Merge branch 'i2c/quirks' into i2c/for-4.1
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
Коммит
9ed1d862d7
|
@ -487,30 +487,10 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* The hardware can handle at most two messages concatenated by a
|
||||
* repeated start via it's internal address feature.
|
||||
*/
|
||||
if (num > 2) {
|
||||
dev_err(dev->dev,
|
||||
"cannot handle more than two concatenated messages.\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else if (num == 2) {
|
||||
if (num == 2) {
|
||||
int internal_address = 0;
|
||||
int i;
|
||||
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
dev_err(dev->dev, "first transfer must be write.\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (msg->len > 3) {
|
||||
dev_err(dev->dev, "first message size must be <= 3.\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 1st msg is put into the internal address, start with 2nd */
|
||||
m_start = &msg[1];
|
||||
for (i = 0; i < msg->len; ++i) {
|
||||
|
@ -540,6 +520,15 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The hardware can handle at most two messages concatenated by a
|
||||
* repeated start via it's internal address feature.
|
||||
*/
|
||||
static struct i2c_adapter_quirks at91_twi_quirks = {
|
||||
.flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
|
||||
.max_comb_1st_msg_len = 3,
|
||||
};
|
||||
|
||||
static u32 at91_twi_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
|
||||
|
@ -777,6 +766,7 @@ static int at91_twi_probe(struct platform_device *pdev)
|
|||
dev->adapter.owner = THIS_MODULE;
|
||||
dev->adapter.class = I2C_CLASS_DEPRECATED;
|
||||
dev->adapter.algo = &at91_twi_algorithm;
|
||||
dev->adapter.quirks = &at91_twi_quirks;
|
||||
dev->adapter.dev.parent = dev->dev;
|
||||
dev->adapter.nr = pdev->id;
|
||||
dev->adapter.timeout = AT91_I2C_TIMEOUT;
|
||||
|
|
|
@ -336,11 +336,6 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
|||
u32 addr_1, addr_2;
|
||||
int ret;
|
||||
|
||||
if (msg->len > 255) {
|
||||
dev_warn(idev->dev, "unsupported length %u\n", msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
idev->msg = msg;
|
||||
idev->msg_xfrd = 0;
|
||||
idev->msg_err = 0;
|
||||
|
@ -454,6 +449,11 @@ static const struct i2c_algorithm axxia_i2c_algo = {
|
|||
.functionality = axxia_i2c_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter_quirks axxia_i2c_quirks = {
|
||||
.max_read_len = 255,
|
||||
.max_write_len = 255,
|
||||
};
|
||||
|
||||
static int axxia_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
@ -511,6 +511,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
|
|||
strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
|
||||
idev->adapter.owner = THIS_MODULE;
|
||||
idev->adapter.algo = &axxia_i2c_algo;
|
||||
idev->adapter.quirks = &axxia_i2c_quirks;
|
||||
idev->adapter.dev.parent = &pdev->dev;
|
||||
idev->adapter.dev.of_node = pdev->dev.of_node;
|
||||
|
||||
|
|
|
@ -160,14 +160,6 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c,
|
|||
u32 val;
|
||||
unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT_MESC);
|
||||
|
||||
/* need to reserve one byte in the FIFO for the slave address */
|
||||
if (msg->len > M_TX_RX_FIFO_SIZE - 1) {
|
||||
dev_err(iproc_i2c->device,
|
||||
"only support data length up to %u bytes\n",
|
||||
M_TX_RX_FIFO_SIZE - 1);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* check if bus is busy */
|
||||
if (!!(readl(iproc_i2c->base + M_CMD_OFFSET) &
|
||||
BIT(M_CMD_START_BUSY_SHIFT))) {
|
||||
|
@ -287,6 +279,12 @@ static const struct i2c_algorithm bcm_iproc_algo = {
|
|||
.functionality = bcm_iproc_i2c_functionality,
|
||||
};
|
||||
|
||||
static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = {
|
||||
/* need to reserve one byte in the FIFO for the slave address */
|
||||
.max_read_len = M_TX_RX_FIFO_SIZE - 1,
|
||||
.max_write_len = M_TX_RX_FIFO_SIZE - 1,
|
||||
};
|
||||
|
||||
static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c)
|
||||
{
|
||||
unsigned int bus_speed;
|
||||
|
@ -413,6 +411,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
|
|||
i2c_set_adapdata(adap, iproc_i2c);
|
||||
strlcpy(adap->name, "Broadcom iProc I2C adapter", sizeof(adap->name));
|
||||
adap->algo = &bcm_iproc_algo;
|
||||
adap->quirks = &bcm_iproc_i2c_quirks;
|
||||
adap->dev.parent = &pdev->dev;
|
||||
adap->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
|
|
|
@ -308,22 +308,12 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
|
||||
struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
|
||||
struct i2c_msg *pmsg;
|
||||
int ret, i;
|
||||
int ret;
|
||||
int tptr;
|
||||
int rptr;
|
||||
cbd_t __iomem *tbdf;
|
||||
cbd_t __iomem *rbdf;
|
||||
|
||||
if (num > CPM_MAXBD)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if we have any oversized READ requests */
|
||||
for (i = 0; i < num; i++) {
|
||||
pmsg = &msgs[i];
|
||||
if (pmsg->len >= CPM_MAX_READ)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Reset to use first buffer */
|
||||
out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
|
||||
out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
|
||||
|
@ -424,10 +414,18 @@ static const struct i2c_algorithm cpm_i2c_algo = {
|
|||
.functionality = cpm_i2c_func,
|
||||
};
|
||||
|
||||
/* CPM_MAX_READ is also limiting writes according to the code! */
|
||||
static struct i2c_adapter_quirks cpm_i2c_quirks = {
|
||||
.max_num_msgs = CPM_MAXBD,
|
||||
.max_read_len = CPM_MAX_READ,
|
||||
.max_write_len = CPM_MAX_READ,
|
||||
};
|
||||
|
||||
static const struct i2c_adapter cpm_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-cpm",
|
||||
.algo = &cpm_i2c_algo,
|
||||
.quirks = &cpm_i2c_quirks,
|
||||
};
|
||||
|
||||
static int cpm_i2c_setup(struct cpm_i2c *cpm)
|
||||
|
|
|
@ -144,7 +144,6 @@ static int dln2_i2c_xfer(struct i2c_adapter *adapter,
|
|||
{
|
||||
struct dln2_i2c *dln2 = i2c_get_adapdata(adapter);
|
||||
struct i2c_msg *pmsg;
|
||||
struct device *dev = &dln2->adapter.dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
|
@ -152,11 +151,6 @@ static int dln2_i2c_xfer(struct i2c_adapter *adapter,
|
|||
|
||||
pmsg = &msgs[i];
|
||||
|
||||
if (pmsg->len > DLN2_I2C_MAX_XFER_SIZE) {
|
||||
dev_warn(dev, "maximum transfer size exceeded\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (pmsg->flags & I2C_M_RD) {
|
||||
ret = dln2_i2c_read(dln2, pmsg->addr, pmsg->buf,
|
||||
pmsg->len);
|
||||
|
@ -187,6 +181,11 @@ static const struct i2c_algorithm dln2_i2c_usb_algorithm = {
|
|||
.functionality = dln2_i2c_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter_quirks dln2_i2c_quirks = {
|
||||
.max_read_len = DLN2_I2C_MAX_XFER_SIZE,
|
||||
.max_write_len = DLN2_I2C_MAX_XFER_SIZE,
|
||||
};
|
||||
|
||||
static int dln2_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
@ -209,6 +208,7 @@ static int dln2_i2c_probe(struct platform_device *pdev)
|
|||
dln2->adapter.owner = THIS_MODULE;
|
||||
dln2->adapter.class = I2C_CLASS_HWMON;
|
||||
dln2->adapter.algo = &dln2_i2c_usb_algorithm;
|
||||
dln2->adapter.quirks = &dln2_i2c_quirks;
|
||||
dln2->adapter.dev.parent = dev;
|
||||
i2c_set_adapdata(&dln2->adapter, dln2);
|
||||
snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",
|
||||
|
|
|
@ -104,18 +104,8 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||
req.buffer_ra = cpu_to_be64(__pa(msgs[0].buf));
|
||||
break;
|
||||
case 2:
|
||||
/* For two messages, we basically support only simple
|
||||
* smbus transactions of a write plus a read. We might
|
||||
* want to allow also two writes but we'd have to bounce
|
||||
* the data into a single buffer.
|
||||
*/
|
||||
if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD))
|
||||
return -EOPNOTSUPP;
|
||||
if (msgs[0].len > 4)
|
||||
return -EOPNOTSUPP;
|
||||
if (msgs[0].addr != msgs[1].addr)
|
||||
return -EOPNOTSUPP;
|
||||
req.type = OPAL_I2C_SM_READ;
|
||||
req.type = (msgs[1].flags & I2C_M_RD) ?
|
||||
OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
|
||||
req.addr = cpu_to_be16(msgs[0].addr);
|
||||
req.subaddr_sz = msgs[0].len;
|
||||
for (i = 0; i < msgs[0].len; i++)
|
||||
|
@ -210,6 +200,15 @@ static const struct i2c_algorithm i2c_opal_algo = {
|
|||
.functionality = i2c_opal_func,
|
||||
};
|
||||
|
||||
/*
|
||||
* For two messages, we basically support simple smbus transactions of a
|
||||
* write-then-anything.
|
||||
*/
|
||||
static struct i2c_adapter_quirks i2c_opal_quirks = {
|
||||
.flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
|
||||
.max_comb_1st_msg_len = 4,
|
||||
};
|
||||
|
||||
static int i2c_opal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_adapter *adapter;
|
||||
|
@ -232,6 +231,7 @@ static int i2c_opal_probe(struct platform_device *pdev)
|
|||
|
||||
adapter->algo = &i2c_opal_algo;
|
||||
adapter->algo_data = (void *)(unsigned long)opal_id;
|
||||
adapter->quirks = &i2c_opal_quirks;
|
||||
adapter->dev.parent = &pdev->dev;
|
||||
adapter->dev.of_node = of_node_get(pdev->dev.of_node);
|
||||
pname = of_get_property(pdev->dev.of_node, "ibm,port-name", NULL);
|
||||
|
|
|
@ -456,14 +456,6 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cmd->read_len > MSP_MAX_BYTES_PER_RW ||
|
||||
cmd->write_len > MSP_MAX_BYTES_PER_RW) {
|
||||
dev_err(&pmcmsptwi_adapter.dev,
|
||||
"%s: Cannot transfer more than %d bytes\n",
|
||||
__func__, MSP_MAX_BYTES_PER_RW);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
dev_dbg(&pmcmsptwi_adapter.dev,
|
||||
"Setting address to 0x%04x\n", cmd->addr);
|
||||
|
@ -520,25 +512,14 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
|
|||
struct pmcmsptwi_cfg oldcfg, newcfg;
|
||||
int ret;
|
||||
|
||||
if (num > 2) {
|
||||
dev_dbg(&adap->dev, "%d messages unsupported\n", num);
|
||||
return -EINVAL;
|
||||
} else if (num == 2) {
|
||||
/* Check for a dual write-then-read command */
|
||||
if (num == 2) {
|
||||
struct i2c_msg *nextmsg = msg + 1;
|
||||
if (!(msg->flags & I2C_M_RD) &&
|
||||
(nextmsg->flags & I2C_M_RD) &&
|
||||
msg->addr == nextmsg->addr) {
|
||||
cmd.type = MSP_TWI_CMD_WRITE_READ;
|
||||
cmd.write_len = msg->len;
|
||||
cmd.write_data = msg->buf;
|
||||
cmd.read_len = nextmsg->len;
|
||||
cmd.read_data = nextmsg->buf;
|
||||
} else {
|
||||
dev_dbg(&adap->dev,
|
||||
"Non write-read dual messages unsupported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd.type = MSP_TWI_CMD_WRITE_READ;
|
||||
cmd.write_len = msg->len;
|
||||
cmd.write_data = msg->buf;
|
||||
cmd.read_len = nextmsg->len;
|
||||
cmd.read_data = nextmsg->buf;
|
||||
} else if (msg->flags & I2C_M_RD) {
|
||||
cmd.type = MSP_TWI_CMD_READ;
|
||||
cmd.read_len = msg->len;
|
||||
|
@ -598,6 +579,14 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
|
|||
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
|
||||
}
|
||||
|
||||
static struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
|
||||
.flags = I2C_AQ_COMB_WRITE_THEN_READ,
|
||||
.max_write_len = MSP_MAX_BYTES_PER_RW,
|
||||
.max_read_len = MSP_MAX_BYTES_PER_RW,
|
||||
.max_comb_1st_msg_len = MSP_MAX_BYTES_PER_RW,
|
||||
.max_comb_2nd_msg_len = MSP_MAX_BYTES_PER_RW,
|
||||
};
|
||||
|
||||
/* -- Initialization -- */
|
||||
|
||||
static struct i2c_algorithm pmcmsptwi_algo = {
|
||||
|
@ -609,6 +598,7 @@ static struct i2c_adapter pmcmsptwi_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.algo = &pmcmsptwi_algo,
|
||||
.quirks = &pmcmsptwi_i2c_quirks,
|
||||
.name = DRV_NAME,
|
||||
};
|
||||
|
||||
|
|
|
@ -153,12 +153,6 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
|
|||
int read;
|
||||
int addrdir;
|
||||
|
||||
if (num != 1) {
|
||||
dev_err(&adap->dev,
|
||||
"Multi-message I2C transactions not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (msgs->flags & I2C_M_TEN)
|
||||
return -EINVAL;
|
||||
read = (msgs->flags & I2C_M_RD) != 0;
|
||||
|
@ -205,6 +199,9 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
|
|||
.functionality = i2c_powermac_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter_quirks i2c_powermac_quirks = {
|
||||
.max_num_msgs = 1,
|
||||
};
|
||||
|
||||
static int i2c_powermac_remove(struct platform_device *dev)
|
||||
{
|
||||
|
@ -434,6 +431,7 @@ static int i2c_powermac_probe(struct platform_device *dev)
|
|||
|
||||
platform_set_drvdata(dev, adapter);
|
||||
adapter->algo = &i2c_powermac_algorithm;
|
||||
adapter->quirks = &i2c_powermac_quirks;
|
||||
i2c_set_adapdata(adapter, bus);
|
||||
adapter->dev.parent = &dev->dev;
|
||||
|
||||
|
|
|
@ -412,17 +412,6 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
|
|||
unsigned long left;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The QUP block will issue a NACK and STOP on the bus when reaching
|
||||
* the end of the read, the length of the read is specified as one byte
|
||||
* which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
|
||||
*/
|
||||
if (msg->len > QUP_READ_LIMIT) {
|
||||
dev_err(qup->dev, "HW not capable of reads over %d bytes\n",
|
||||
QUP_READ_LIMIT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qup->msg = msg;
|
||||
qup->pos = 0;
|
||||
|
||||
|
@ -534,6 +523,15 @@ static const struct i2c_algorithm qup_i2c_algo = {
|
|||
.functionality = qup_i2c_func,
|
||||
};
|
||||
|
||||
/*
|
||||
* The QUP block will issue a NACK and STOP on the bus when reaching
|
||||
* the end of the read, the length of the read is specified as one byte
|
||||
* which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
|
||||
*/
|
||||
static struct i2c_adapter_quirks qup_i2c_quirks = {
|
||||
.max_read_len = QUP_READ_LIMIT,
|
||||
};
|
||||
|
||||
static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
|
||||
{
|
||||
clk_prepare_enable(qup->clk);
|
||||
|
@ -670,6 +668,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
|
||||
i2c_set_adapdata(&qup->adap, qup);
|
||||
qup->adap.algo = &qup_i2c_algo;
|
||||
qup->adap.quirks = &qup_i2c_quirks;
|
||||
qup->adap.dev.parent = qup->dev;
|
||||
qup->adap.dev.of_node = pdev->dev.of_node;
|
||||
strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name));
|
||||
|
|
|
@ -288,10 +288,6 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs,
|
|||
i, pmsg->flags & I2C_M_RD ? "read" : "write",
|
||||
pmsg->flags, pmsg->len, pmsg->addr);
|
||||
|
||||
/* msgs longer than 2048 bytes are not supported by adapter */
|
||||
if (pmsg->len > 2048)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&vb->lock);
|
||||
/* directly send the message */
|
||||
if (pmsg->flags & I2C_M_RD) {
|
||||
|
@ -358,6 +354,11 @@ static const struct i2c_algorithm vprbrd_algorithm = {
|
|||
.functionality = vprbrd_i2c_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter_quirks vprbrd_quirks = {
|
||||
.max_read_len = 2048,
|
||||
.max_write_len = 2048,
|
||||
};
|
||||
|
||||
static int vprbrd_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
|
||||
|
@ -373,6 +374,7 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
|
|||
vb_i2c->i2c.owner = THIS_MODULE;
|
||||
vb_i2c->i2c.class = I2C_CLASS_HWMON;
|
||||
vb_i2c->i2c.algo = &vprbrd_algorithm;
|
||||
vb_i2c->i2c.quirks = &vprbrd_quirks;
|
||||
vb_i2c->i2c.algo_data = vb;
|
||||
/* save the param in usb capabable memory */
|
||||
vb_i2c->bus_freq_param = i2c_bus_param;
|
||||
|
|
|
@ -1929,6 +1929,65 @@ module_exit(i2c_exit);
|
|||
* ----------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Check if val is exceeding the quirk IFF quirk is non 0 */
|
||||
#define i2c_quirk_exceeded(val, quirk) ((quirk) && ((val) > (quirk)))
|
||||
|
||||
static int i2c_quirk_error(struct i2c_adapter *adap, struct i2c_msg *msg, char *err_msg)
|
||||
{
|
||||
dev_err_ratelimited(&adap->dev, "adapter quirk: %s (addr 0x%04x, size %u, %s)\n",
|
||||
err_msg, msg->addr, msg->len,
|
||||
msg->flags & I2C_M_RD ? "read" : "write");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
{
|
||||
const struct i2c_adapter_quirks *q = adap->quirks;
|
||||
int max_num = q->max_num_msgs, i;
|
||||
bool do_len_check = true;
|
||||
|
||||
if (q->flags & I2C_AQ_COMB) {
|
||||
max_num = 2;
|
||||
|
||||
/* special checks for combined messages */
|
||||
if (num == 2) {
|
||||
if (q->flags & I2C_AQ_COMB_WRITE_FIRST && msgs[0].flags & I2C_M_RD)
|
||||
return i2c_quirk_error(adap, &msgs[0], "1st comb msg must be write");
|
||||
|
||||
if (q->flags & I2C_AQ_COMB_READ_SECOND && !(msgs[1].flags & I2C_M_RD))
|
||||
return i2c_quirk_error(adap, &msgs[1], "2nd comb msg must be read");
|
||||
|
||||
if (q->flags & I2C_AQ_COMB_SAME_ADDR && msgs[0].addr != msgs[1].addr)
|
||||
return i2c_quirk_error(adap, &msgs[0], "comb msg only to same addr");
|
||||
|
||||
if (i2c_quirk_exceeded(msgs[0].len, q->max_comb_1st_msg_len))
|
||||
return i2c_quirk_error(adap, &msgs[0], "msg too long");
|
||||
|
||||
if (i2c_quirk_exceeded(msgs[1].len, q->max_comb_2nd_msg_len))
|
||||
return i2c_quirk_error(adap, &msgs[1], "msg too long");
|
||||
|
||||
do_len_check = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i2c_quirk_exceeded(num, max_num))
|
||||
return i2c_quirk_error(adap, &msgs[0], "too many messages");
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
u16 len = msgs[i].len;
|
||||
|
||||
if (msgs[i].flags & I2C_M_RD) {
|
||||
if (do_len_check && i2c_quirk_exceeded(len, q->max_read_len))
|
||||
return i2c_quirk_error(adap, &msgs[i], "msg too long");
|
||||
} else {
|
||||
if (do_len_check && i2c_quirk_exceeded(len, q->max_write_len))
|
||||
return i2c_quirk_error(adap, &msgs[i], "msg too long");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __i2c_transfer - unlocked flavor of i2c_transfer
|
||||
* @adap: Handle to I2C bus
|
||||
|
@ -1946,6 +2005,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
unsigned long orig_jiffies;
|
||||
int ret, try;
|
||||
|
||||
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets
|
||||
* enabled. This is an efficient way of keeping the for-loop from
|
||||
* being executed when not needed.
|
||||
|
|
|
@ -449,6 +449,48 @@ int i2c_recover_bus(struct i2c_adapter *adap);
|
|||
int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
|
||||
int i2c_generic_scl_recovery(struct i2c_adapter *adap);
|
||||
|
||||
/**
|
||||
* struct i2c_adapter_quirks - describe flaws of an i2c adapter
|
||||
* @flags: see I2C_AQ_* for possible flags and read below
|
||||
* @max_num_msgs: maximum number of messages per transfer
|
||||
* @max_write_len: maximum length of a write message
|
||||
* @max_read_len: maximum length of a read message
|
||||
* @max_comb_1st_msg_len: maximum length of the first msg in a combined message
|
||||
* @max_comb_2nd_msg_len: maximum length of the second msg in a combined message
|
||||
*
|
||||
* Note about combined messages: Some I2C controllers can only send one message
|
||||
* per transfer, plus something called combined message or write-then-read.
|
||||
* This is (usually) a small write message followed by a read message and
|
||||
* barely enough to access register based devices like EEPROMs. There is a flag
|
||||
* to support this mode. It implies max_num_msg = 2 and does the length checks
|
||||
* with max_comb_*_len because combined message mode usually has its own
|
||||
* limitations. Because of HW implementations, some controllers can actually do
|
||||
* write-then-anything or other variants. To support that, write-then-read has
|
||||
* been broken out into smaller bits like write-first and read-second which can
|
||||
* be combined as needed.
|
||||
*/
|
||||
|
||||
struct i2c_adapter_quirks {
|
||||
u64 flags;
|
||||
int max_num_msgs;
|
||||
u16 max_write_len;
|
||||
u16 max_read_len;
|
||||
u16 max_comb_1st_msg_len;
|
||||
u16 max_comb_2nd_msg_len;
|
||||
};
|
||||
|
||||
/* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */
|
||||
#define I2C_AQ_COMB BIT(0)
|
||||
/* first combined message must be write */
|
||||
#define I2C_AQ_COMB_WRITE_FIRST BIT(1)
|
||||
/* second combined message must be read */
|
||||
#define I2C_AQ_COMB_READ_SECOND BIT(2)
|
||||
/* both combined messages must have the same target address */
|
||||
#define I2C_AQ_COMB_SAME_ADDR BIT(3)
|
||||
/* convenience macro for typical write-then read case */
|
||||
#define I2C_AQ_COMB_WRITE_THEN_READ (I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \
|
||||
I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)
|
||||
|
||||
/*
|
||||
* i2c_adapter is the structure used to identify a physical i2c bus along
|
||||
* with the access algorithms necessary to access it.
|
||||
|
@ -474,6 +516,7 @@ struct i2c_adapter {
|
|||
struct list_head userspace_clients;
|
||||
|
||||
struct i2c_bus_recovery_info *bus_recovery_info;
|
||||
const struct i2c_adapter_quirks *quirks;
|
||||
};
|
||||
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче