Merge "Adding parrot support in mosys"
diff --git a/core/command/i2c.c b/core/command/i2c.c
index e609f70..17ab7c8 100644
--- a/core/command/i2c.c
+++ b/core/command/i2c.c
@@ -69,8 +69,10 @@
/* read in block of 256 bytes */
memset(i2c_data, 0, sizeof(i2c_data));
- length = intf->op->i2c->read_reg(intf, bus, address,
- start, length, i2c_data);
+ /* FIXME: historically we have only worried about SMBus devices here
+ (e.g. SPDs), but this does not seem like a great general solution */
+ length = intf->op->i2c->smbus_read_reg(intf, bus, address,
+ start, length, i2c_data);
if (length < 0) {
lprintf(LOG_ERR, "Failed to read from I2C (not present?)\n");
diff --git a/drivers/cypress/cypress_apa.c b/drivers/cypress/cypress_apa.c
index eee8f87..dd9bf44 100644
--- a/drivers/cypress/cypress_apa.c
+++ b/drivers/cypress/cypress_apa.c
@@ -133,12 +133,14 @@
uint8_t major, minor;
size_t max_len = 8;
- if (intf->op->i2c->read_reg(intf, bus, addr,
- CYAPA_REG_FIRMWARE_MAJOR, 1, &major) != 1)
+ if (intf->op->i2c->smbus_read_reg(intf, bus, addr,
+ CYAPA_REG_FIRMWARE_MAJOR,
+ 1, &major) != 1)
return -1;
- if (intf->op->i2c->read_reg(intf, bus, addr,
- CYAPA_REG_FIRMWARE_MINOR, 1, &minor) != 1)
+ if (intf->op->i2c->smbus_read_reg(intf, bus, addr,
+ CYAPA_REG_FIRMWARE_MINOR,
+ 1, &minor) != 1)
return -1;
*buf = mosys_zalloc(max_len);
@@ -152,12 +154,14 @@
uint8_t major, minor;
size_t max_len = 8;
- if (intf->op->i2c->read_reg(intf, bus, addr,
- CYAPA_REG_HARDWARE_MAJOR, 1, &major) != 1)
+ if (intf->op->i2c->smbus_read_reg(intf, bus, addr,
+ CYAPA_REG_HARDWARE_MAJOR,
+ 1, &major) != 1)
return -1;
- if (intf->op->i2c->read_reg(intf, bus, addr,
- CYAPA_REG_HARDWARE_MINOR, 1, &minor) != 1)
+ if (intf->op->i2c->smbus_read_reg(intf, bus, addr,
+ CYAPA_REG_HARDWARE_MINOR,
+ 1, &minor) != 1)
return -1;
*buf = mosys_zalloc(max_len);
@@ -172,9 +176,9 @@
*buf = mosys_zalloc(CYAPA_REG_PRODUCT_ID_LEN + 1);
for (i = 0; i < CYAPA_REG_PRODUCT_ID_LEN; i++) {
- if (intf->op->i2c->read_reg(intf, bus, addr,
- CYAPA_REG_PRODUCT_ID + i,
- 1, *buf + i) != 1)
+ if (intf->op->i2c->smbus_read_reg(intf, bus, addr,
+ CYAPA_REG_PRODUCT_ID + i,
+ 1, *buf + i) != 1)
return -1;
}
diff --git a/include/intf/i2c.h b/include/intf/i2c.h
index 87dc9b6..2f804dc 100644
--- a/include/intf/i2c.h
+++ b/include/intf/i2c.h
@@ -49,7 +49,7 @@
const char *dev_root;
/*
- * setup - prepare interface
+ * setup - prepare interface
*
* @intf: platform interface
*
@@ -59,14 +59,33 @@
int (*setup)(struct platform_intf *intf);
/*
- * destroy - teardown interface
+ * destroy - teardown interface
*
* @intf: platform interface
*/
void (*destroy)(struct platform_intf *intf);
+
/*
- * read - Read bytes from I2C device
+ * i2c_transfer - Single or combined transfer using I2C_RDWR ioctl
+ *
+ * @intf: platform interface
+ * @bus: I2C bus/adapter
+ * @address: I2C slave address
+ * @outdata: buffer containing output data
+ * @outsize: number of bytes to send
+ * @indata: buffer to store input data
+ * @insize: number of bytes expected to be received
+ *
+ * returns 0 to indicate success
+ * returns <0 to indicate failure
+ */
+ int (*i2c_transfer)(struct platform_intf *intf, int bus, int address,
+ const void *outdata, int outsize,
+ const void *indata, int insize);
+
+ /*
+ * smbus_read_reg - Read from a register addressable SMBus device
*
* @intf: platform interface
* @bus: I2C bus/adapter
@@ -76,80 +95,79 @@
* @data: data buffer
*
* returns number of bytes read
- * returns <0 to indicate error
- */
- int (*read_reg)(struct platform_intf *intf,
- int bus, int address, int reg,
- int length, void *data);
-
- /*
- * write - Write bytes to I2C device
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes written
- * returns <0 to indicate error
- */
- int (*write_reg)(struct platform_intf *intf,
- int bus, int address, int reg,
- int length, const void *data);
-
- /*
- * read16 - Read bytes from I2C device using 16-bit address
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset (16-bit)
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes read
- * returns <0 to indicate error
- */
- int (*read16)(struct platform_intf *intf,
- int bus, int address, int reg,
- int length, void *data);
-
- /*
- * write16 - Write bytes to I2C device using 16-bit address
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset (16-bit)
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes written
- * returns <0 to indicate error
- */
- int (*write16)(struct platform_intf *intf,
- int bus, int address, int reg,
- int length, const void *data);
-
- /*
- * read_raw - read byte(s) from device without register addressing
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @length: number of bytes to read (1-256)
- * @data: data buffer
- *
- * returns number of bytes read
* returns <0 to indicate failure
*/
- int (*read_raw)(struct platform_intf *intf,
- int bus, int address, int length, void *data);
+ int (*smbus_read_reg)(struct platform_intf *intf,
+ int bus, int address, int reg,
+ int length, void *data);
/*
- * write_raw - write byte(s) to device without register addressing
+ * smbus_write_reg - Write bytes to SMBus slave address
+ *
+ * @intf: platform interface
+ * @bus: I2C bus/adapter
+ * @address: I2C slave address
+ * @reg: I2C register offset
+ * @length: number of bytes to read (1-255)
+ * @data: data buffer
+ *
+ * returns number of bytes written
+ * returns <0 to indicate error
+ */
+ int (*smbus_write_reg)(struct platform_intf *intf,
+ int bus, int address, int reg,
+ int length, const void *data);
+
+ /*
+ * smbus_read16_dev - Read SMBus device using 16-bit register offset
+ *
+ * @intf: platform interface
+ * @bus: I2C bus/adapter
+ * @address: I2C slave address
+ * @reg: I2C register offset (16-bit)
+ * @length: number of bytes to read (1-255)
+ * @data: data buffer
+ *
+ * returns number of bytes read
+ * returns <0 to indicate failure
+ */
+ int (*smbus_read16)(struct platform_intf *intf,
+ int bus, int address, int reg,
+ int length, void *data);
+
+
+ /*
+ * smbus_write16_buf - Write to SMBus device using 16-bit offset
+ *
+ * @handle: I2C device handle
+ * @reg: I2C register offset (16-bit)
+ * @dp: data buffer
+ * @len: number of bytes to write (1-32)
+ *
+ * returns number of bytes written
+ * returns <0 to indicate error
+ */
+ int (*smbus_write16)(struct platform_intf *intf,
+ int bus, int address, int reg,
+ int length, const void *data);
+
+ /*
+ * smbus_read_raw - bytewise SMBus read without register addressing
+ *
+ * @intf: platform interface
+ * @bus: I2C bus/adapter
+ * @address: I2C slave address
+ * @length: number of bytes to read
+ * @data: data buffer
+ *
+ * returns number of bytes read
+ * returns <0 to indicate failure
+ */
+ int (*smbus_read_raw)(struct platform_intf *intf,
+ int bus, int address, int length, void *data);
+
+ /*
+ * smbus_write_raw - write to device without register addressing
*
* @intf: platform interface
* @bus: I2C bus/adapter
@@ -160,35 +178,35 @@
* returns number of bytes written
* returns <0 to indicate failure
*/
- int (*write_raw)(struct platform_intf *intf,
- int bus, int address, int length, void *data);
+ int (*smbus_write_raw)(struct platform_intf *intf,
+ int bus, int address, int length, void *data);
/*
- * find_driver - Find I2C driver
+ * find_driver - Determine if driver is loaded
*
- * @intf: platform interface
- * @name: i2c driver name
+ * @intf: Platform interface
+ * @module: The name of the module to search for
*
- * returns 0 if the module is not found
- * returns 1 if the module is found
+ * returns 0 if the module is not found or if /proc/modules does not exist
+ * returns > 0 if the module is found
*/
int (*find_driver)(struct platform_intf *intf,
const char *name);
/*
- * find_dir - Find I2C directory for device
+ * find_sysfs_dir - Find sysfs directory for device
*
* @intf: platform interface
* @name: i2c driver name
*
* returns the head of a linked list of matching devices
- * returns NULL if no device found
+ * returns NULL if no device found or error
*/
- struct ll_node *(*find_dir)(struct platform_intf *intf,
- const char *name);
+ struct ll_node *(*find_sysfs_dir)(struct platform_intf *intf,
+ const char *name);
/*
- * match_bus - Look for bus name
+ * i2c_match_bus_name - Look for bus name
*
* @intf: platform interface
* @name: bus name
diff --git a/include/intf/linux-i2c-dev.h b/include/intf/linux-i2c-dev.h
index 8204852..45971a5 100644
--- a/include/intf/linux-i2c-dev.h
+++ b/include/intf/linux-i2c-dev.h
@@ -36,17 +36,16 @@
*/
struct i2c_msg {
__u16 addr; /* slave address */
- unsigned short flags;
+ __u16 flags;
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
#define I2C_M_RD 0x01
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000
#define I2C_M_IGNORE_NAK 0x1000
#define I2C_M_NO_RD_ACK 0x0800
- short len; /* msg length */
- char *buf; /* pointer to msg data */
- int err;
- short done;
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+ __u16 len; /* msg length */
+ __u8 *buf; /* pointer to msg data */
};
/* To determine what functionality is present */
@@ -189,9 +188,10 @@
/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
struct i2c_msg *msgs; /* pointers to i2c_msgs */
- int nmsgs; /* number of i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
};
+#define I2C_RDRW_IOCTL_MAX_MSGS 42
static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
int size, union i2c_smbus_data *data)
diff --git a/intf/i2c.c b/intf/i2c.c
index 7afd648..456675a 100644
--- a/intf/i2c.c
+++ b/intf/i2c.c
@@ -38,6 +38,7 @@
#include <inttypes.h>
#include <string.h>
#include <dirent.h>
+#include <sys/ioctl.h>
#include "mosys/alloc.h"
#include "mosys/globals.h"
@@ -155,21 +156,66 @@
free((char *)intf->op->i2c->dev_root);
}
-/*
- * i2c_read_reg - Read bytes from a register addressable I2C device
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes read
- * returns <0 to indicate failure
- */
-static int i2c_read_reg(struct platform_intf *intf,
- int bus, int address, int reg, int length, void *data)
+static int i2c_transfer(struct platform_intf *intf, int bus, int address,
+ const void *outdata, int outsize,
+ const void *indata, int insize)
+{
+ int ret = -1;
+ struct i2c_rdwr_ioctl_data data;
+ struct i2c_msg *msg = NULL;
+ int handle, fd;
+
+ /* open connection to i2c slave */
+ handle = i2c_open_dev(intf, bus, address);
+ if (handle < 0)
+ return -1;
+ fd = i2c_handles[handle].fd;
+
+ data.nmsgs = 0;
+
+ if (outsize) {
+ msg = mosys_realloc(msg, sizeof(*msg) * (data.nmsgs + 1));
+ msg[data.nmsgs].addr = address;
+ msg[data.nmsgs].flags = 0;
+ msg[data.nmsgs].len = outsize;
+ msg[data.nmsgs].buf = (char *)outdata;
+ data.nmsgs++;
+ }
+
+ if (insize) {
+ msg = mosys_realloc(msg, sizeof(*msg) * (data.nmsgs + 1));
+ msg[data.nmsgs].addr = address;
+ msg[data.nmsgs].flags = I2C_M_RD;
+ msg[data.nmsgs].len = insize;
+ msg[data.nmsgs].buf = (char *)indata;
+ data.nmsgs++;
+ }
+
+ data.msgs = msg;
+ /* send command to EC and read answer */
+#if defined (__linux__)
+ /* ioctl returns negative errno, else the number of messages executed */
+ ret = ioctl(fd, I2C_RDWR, &data);
+#else
+ ret = -ENOSYS;
+#endif
+
+ if (ret < 0) {
+ lperror(LOG_ERR, "i2c transfer failed");
+ ret = -1;
+ } else if (ret != data.nmsgs) {
+ lprintf(LOG_ERR, "ioctl executed wrong number of messages\n");
+ ret = -1;
+ } else {
+ ret = 0;
+ }
+
+ free(msg);
+ return ret;
+}
+
+static int smbus_read_reg(struct platform_intf *intf, int bus,
+ int address, int reg, int length, void *data)
{
int handle, fd, i;
int32_t result;
@@ -234,25 +280,13 @@
}
/*
- * i2c_read16_dev - Read bytes from I2C device using 16-bit register offset
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset (16-bit)
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes read
- * returns <0 to indicate failure
- *
* We can't actually use i2c_smbus_read_block_data() because the driver
* doesn't know how to do the 2-byte address write. So we do the best we can
* by performing the address write once, then calling i2c_smbus_read_byte()
* repeatedly to keep the overhead to a minimum.
*/
-static int i2c_read16_dev(struct platform_intf *intf,
- int bus, int address, int reg, int length, void *data)
+static int smbus_read16_dev(struct platform_intf *intf, int bus,
+ int address, int reg, int length, void *data)
{
uint8_t hi, lo;
int fd, handle, i;
@@ -297,20 +331,8 @@
return i;
}
-/*
- * i2c_read_raw - read byte(s) from device without register addressing
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @length: number of bytes to read
- * @data: data buffer
- *
- * returns number of bytes read
- * returns <0 to indicate failure
- */
-static int i2c_read_raw(struct platform_intf *intf,
- int bus, int address, int length, void *data)
+static int smbus_read_raw(struct platform_intf *intf,
+ int bus, int address, int length, void *data)
{
int result, count;
int fd, handle;
@@ -342,22 +364,8 @@
return count;
}
-/*
- * i2c_write_reg - Write bytes to I2C slave address
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes written
- * returns <0 to indicate error
- */
-static int i2c_write_reg(struct platform_intf *intf,
- int bus,
- int address, int reg, int length, const void *data)
+static int smbus_write_reg(struct platform_intf *intf, int bus,
+ int address, int reg, int length, const void *data)
{
int handle, fd, i;
int32_t result;
@@ -394,22 +402,12 @@
}
/*
- * i2c_write16_buf - Write a buffer to I2C slave address using 16-bit offset
- *
- * @handle: I2C device handle
- * @reg: I2C register offset (16-bit)
- * @dp: data buffer
- * @len: number of bytes to write (1-32)
- *
- * returns number of bytes written
- * returns <0 to indicate error
- *
* The LSByte of the 16-bit register offset is sent as the first byte of
* the transfer buffer. Note the driver won't let us transfer more than
* 32 bytes, and since we're using one data byte as the low byte of the
* offset address, we have to perform the write in 31-byte chunks. Ugh.
*/
-static int i2c_write16_buf(int handle, int reg, const uint8_t *dp, int len)
+static int smbus_write16_buf(int handle, int reg, const uint8_t *dp, int len)
{
uint8_t buf[32];
int32_t result;
@@ -450,23 +448,9 @@
return result;
}
-/*
- * i2c_write16_dev - Write bytes to I2C slave address using 16-bit reg offset
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @reg: I2C register offset (16-bit)
- * @length: number of bytes to read (1-255)
- * @data: data buffer
- *
- * returns number of bytes written
- * returns <0 to indicate error
- *
- */
-static int i2c_write16_dev(struct platform_intf *intf,
- int bus, int address, int reg,
- int length, const void *data)
+static int smbus_write16_dev(struct platform_intf *intf,
+ int bus, int address, int reg,
+ int length, const void *data)
{
int handle, written = 0;
const uint8_t *data_ptr = (uint8_t *)data;
@@ -479,12 +463,12 @@
if (length == 0) {
/* useful for setting internal address counters in devices */
- written = i2c_write16_buf(handle, reg, NULL, 0);
+ written = smbus_write16_buf(handle, reg, NULL, 0);
}
while (length) {
buf_len = __min(length, 31);
- count = i2c_write16_buf(handle, reg, data_ptr, buf_len);
+ count = smbus_write16_buf(handle, reg, data_ptr, buf_len);
if (count != buf_len)
return written;
length -= count;
@@ -496,7 +480,7 @@
return written;
buf_len = 1;
- count = i2c_write16_buf(handle, reg, data_ptr, buf_len);
+ count = smbus_write16_buf(handle, reg, data_ptr, buf_len);
if (count != buf_len)
return written;
length -= buf_len;
@@ -507,19 +491,8 @@
return written;
}
-/*
- * i2c_write_raw - write byte(s) to device without register addressing
- *
- * @intf: platform interface
- * @bus: I2C bus/adapter
- * @address: I2C slave address
- * @data: data buffer
- *
- * returns number of bytes written
- * returns <0 to indicate failure
- */
-static int i2c_write_raw(struct platform_intf *intf,
- int bus, int address, int length, void *data)
+static int smbus_write_raw(struct platform_intf *intf,
+ int bus, int address, int length, void *data)
{
int handle, fd, count;
int32_t result;
@@ -549,16 +522,6 @@
return count;
}
-/*
- * i2c_find_driver - Determine if i2c driver is loaded by scanning
- * /proc/modules.
- *
- * @intf: Platform interface
- * @module: The name of the module to search for
- *
- * returns 0 if the module is not found or if /proc/modules does not exist
- * returns > 0 if the module is found
- */
static int i2c_find_driver(struct platform_intf *intf, const char *module)
{
char *path;
@@ -584,16 +547,6 @@
return ret;
}
-/*
- * i2c_match_bus_name - Look for bus name
- *
- * @intf: platform interface
- * @name: bus name
- * @bus: bus number
- *
- * returns 1 if bus name does match
- * returns 0 if bus name does not match
- */
static int i2c_match_bus_name(struct platform_intf *intf,
int bus, const char *name)
{
@@ -625,15 +578,9 @@
* i2c_find_dir - Find a /sys directory or directories for a device's
* description as printed in the /sys/bus/i2c/devices/<bus-addr>/name file.
* All matching descriptions are inserted into a linked list.
- *
- * @intf: Platform interface
- * @name: The device name to search for, eg "eeprom"
- *
- * returns the head of a linked list of matching devices if found.
- * returns NULL if no device found or if an error has occured.
*/
-static struct ll_node *i2c_find_dir(struct platform_intf *intf,
- const char *name)
+static struct ll_node *i2c_find_sysfs_dir(struct platform_intf *intf,
+ const char *name)
{
char *path;
char s[32];
@@ -699,15 +646,16 @@
/* I2C operations based on Linux /dev interface */
struct i2c_intf i2c_dev_intf = {
- .setup = i2c_setup_dev,
- .destroy = i2c_close_dev,
- .read_reg = i2c_read_reg,
- .write_reg = i2c_write_reg,
- .read16 = i2c_read16_dev,
- .write16 = i2c_write16_dev,
- .read_raw = i2c_read_raw,
- .write_raw = i2c_write_raw,
- .find_driver = i2c_find_driver,
- .find_dir = i2c_find_dir,
- .match_bus = i2c_match_bus_name,
+ .setup = i2c_setup_dev,
+ .destroy = i2c_close_dev,
+ .i2c_transfer = i2c_transfer,
+ .smbus_read_reg = smbus_read_reg,
+ .smbus_write_reg = smbus_write_reg,
+ .smbus_read16 = smbus_read16_dev,
+ .smbus_write16 = smbus_write16_dev,
+ .smbus_read_raw = smbus_read_raw,
+ .smbus_write_raw = smbus_write_raw,
+ .find_driver = i2c_find_driver,
+ .find_sysfs_dir = i2c_find_sysfs_dir,
+ .match_bus = i2c_match_bus_name,
};
diff --git a/lib/spd/spd.c b/lib/spd/spd.c
index 217231e..4cda4c8 100644
--- a/lib/spd/spd.c
+++ b/lib/spd/spd.c
@@ -74,11 +74,11 @@
switch (rw) {
case SPD_READ:
- return intf->op->i2c->read_reg(intf, bus, address,
- reg, length, data);
+ return intf->op->i2c->smbus_read_reg(intf, bus, address,
+ reg, length, data);
case SPD_WRITE:
- return intf->op->i2c->write_reg(intf, bus, address,
- reg, length, data);
+ return intf->op->i2c->smbus_write_reg(intf, bus, address,
+ reg, length, data);
}
return -1;
diff --git a/platform/experimental/kaen/ec.c b/platform/experimental/kaen/ec.c
index 48320dd..7b32c51 100644
--- a/platform/experimental/kaen/ec.c
+++ b/platform/experimental/kaen/ec.c
@@ -56,7 +56,7 @@
if (version)
return version;
- if (intf->op->i2c->read_reg(intf, 2, 0x1b, 0xf1, 2, buf) != 2) {
+ if (intf->op->i2c->smbus_read_reg(intf, 2, 0x1b, 0xf1, 2, buf) != 2) {
lprintf(LOG_ERR, "%s: failed to read EC firmware "
"version\n", __func__);
return NULL;