@@ -33,6 +33,7 @@
#define DRIVER_NAME "xiic-i2c"
#define DYNAMIC_MODE_READ_BROKEN_BIT BIT(0)
+#define SMBUS_BLOCK_READ_MIN_LEN 3
enum xilinx_i2c_state {
STATE_DONE,
@@ -64,6 +65,7 @@ enum xiic_endian {
* @dynamic: Mode of controller
* @prev_msg_tx: Previous message is Tx
* @quirks: To hold platform specific bug info
+ * @smbus_block_read: Flag to handle block read
*/
struct xiic_i2c {
struct device *dev;
@@ -83,6 +85,7 @@ struct xiic_i2c {
bool dynamic;
bool prev_msg_tx;
u32 quirks;
+ bool smbus_block_read;
};
struct xiic_version_data {
@@ -346,6 +349,62 @@ static void xiic_deinit(struct xiic_i2c *i2c)
xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK);
}
+static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
+{
+ u8 rxmsg_len, rfd_set = 0;
+
+ /*
+ * Clear the I2C_M_RECV_LEN flag to avoid setting
+ * message length again
+ */
+ i2c->rx_msg->flags &= ~I2C_M_RECV_LEN;
+
+ /* Set smbus_block_read flag to identify in isr */
+ i2c->smbus_block_read = true;
+
+ /* Read byte from rx fifo and set message length */
+ rxmsg_len = xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+
+ i2c->rx_msg->buf[i2c->rx_pos++] = rxmsg_len;
+
+ /* Check if received length is valid */
+ if (rxmsg_len <= I2C_SMBUS_BLOCK_MAX) {
+ /* Set Receive fifo depth */
+ if (rxmsg_len > IIC_RX_FIFO_DEPTH) {
+ /*
+ * When Rx msg len greater than or equal to Rx fifo capacity
+ * Receive fifo depth should set to Rx fifo capacity minus 1
+ */
+ rfd_set = IIC_RX_FIFO_DEPTH - 1;
+ i2c->rx_msg->len = rxmsg_len + 1;
+ } else if ((rxmsg_len == 1) ||
+ (rxmsg_len == 0)) {
+ /*
+ * Minimum of 3 bytes required to exit cleanly. 1 byte
+ * already received, Second byte is being received. Have
+ * to set NACK in read_rx before receiving the last byte
+ */
+ rfd_set = 0;
+ i2c->rx_msg->len = SMBUS_BLOCK_READ_MIN_LEN;
+ } else {
+ /*
+ * When Rx msg len less than Rx fifo capacity
+ * Receive fifo depth should set to Rx msg len minus 2
+ */
+ rfd_set = rxmsg_len - 2;
+ i2c->rx_msg->len = rxmsg_len + 1;
+ }
+ xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
+
+ return;
+ }
+
+ /* Invalid message length, trigger STATE_ERROR with tx_msg_len in ISR */
+ i2c->tx_msg->len = 3;
+ i2c->smbus_block_read = false;
+ dev_err(i2c->adap.dev.parent, "smbus_block_read Invalid msg length\n");
+}
+
static void xiic_read_rx(struct xiic_i2c *i2c)
{
u8 bytes_in_fifo, cr = 0, bytes_to_read = 0;
@@ -368,6 +427,12 @@ static void xiic_read_rx(struct xiic_i2c *i2c)
if (!i2c->dynamic) {
bytes_rem = xiic_rx_space(i2c) - bytes_in_fifo;
+ /* Set msg length if smbus_block_read */
+ if (i2c->rx_msg->flags & I2C_M_RECV_LEN) {
+ xiic_smbus_block_read_setup(i2c);
+ return;
+ }
+
if (bytes_rem > IIC_RX_FIFO_DEPTH) {
bytes_to_read = bytes_in_fifo;
} else if (bytes_rem > 1) {
@@ -601,6 +666,12 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
/* The bus is not busy, disable BusNotBusy interrupt */
xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
+ if (i2c->tx_msg && i2c->smbus_block_read) {
+ i2c->smbus_block_read = false;
+ /* Set requested message len=1 to indicate STATE_DONE */
+ i2c->tx_msg->len = 1;
+ }
+
if (!i2c->tx_msg)
goto out;
@@ -741,11 +812,14 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
rfd_set = IIC_RX_FIFO_DEPTH - 1;
} else if (rx_watermark == 1) {
rfd_set = rx_watermark - 1;
- /* Handle single byte transfer separately */
- cr |= XIIC_CR_NO_ACK_MASK;
+
+ /* Set No_ACK, except for smbus_block_read */
+ if (!(i2c->rx_msg->flags & I2C_M_RECV_LEN)) {
+ /* Handle single byte transfer separately */
+ cr |= XIIC_CR_NO_ACK_MASK;
+ }
} else if (rx_watermark == 0) {
rfd_set = rx_watermark;
- cr |= XIIC_CR_NO_ACK_MASK;
} else {
rfd_set = rx_watermark - 2;
}
@@ -984,7 +1058,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
static u32 xiic_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
}
static const struct i2c_algorithm xiic_algorithm = {