Message ID | 20221107134248.864890-3-jarkko.nikula@linux.intel.com |
---|---|
State | New |
Headers | show |
Series | i2c: designware: Slave fixes and generic cleanups | expand |
> 2. i2ctransfer -y 6 w9@0x65 0x00 0xff- Always nice to see 'i2ctransfer' in action! > While at it do not test the return code from i2c_slave_event() for the > I2C_SLAVE_WRITE_RECEIVED since to my understanding this hardware cannot > generate NACK to incoming bytes Not even on the last byte? That would be bad. If a backend encounters a problem, there is no way then to communicate that back to the controller.
On 11/12/22 08:57, Wolfram Sang wrote: > >> 2. i2ctransfer -y 6 w9@0x65 0x00 0xff- > > Always nice to see 'i2ctransfer' in action! > >> While at it do not test the return code from i2c_slave_event() for the >> I2C_SLAVE_WRITE_RECEIVED since to my understanding this hardware cannot >> generate NACK to incoming bytes > > Not even on the last byte? That would be bad. If a backend encounters a > problem, there is no way then to communicate that back to the > controller. > Yeah, that's how I understood it. HW has an optional register (I didn't check is it enabled on our HW) that enable generation of NACK for the incoming data byte but it can be enabled only when the controller is disabled and slave is inactive so it doesn't look very useful. Jarkko
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index dbf6bdc5f01b..6d1df28dd93b 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -108,6 +108,7 @@ #define DW_IC_STATUS_ACTIVITY BIT(0) #define DW_IC_STATUS_TFE BIT(2) +#define DW_IC_STATUS_RFNE BIT(3) #define DW_IC_STATUS_MASTER_ACTIVITY BIT(5) #define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6) diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index 1eac4f4d5573..295774a69b67 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -180,11 +180,13 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev) &val); } - regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); - val = tmp; - if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, - &val)) - dev_vdbg(dev->dev, "Byte %X acked!", val); + do { + regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); + val = tmp; + i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, + &val); + regmap_read(dev->map, DW_IC_STATUS, &tmp); + } while (tmp & DW_IC_STATUS_RFNE); } if (stat & DW_IC_INTR_RD_REQ) {