All of lore.kernel.org
 help / color / mirror / Atom feed
* [v3] i2c: imx: support slave mode for imx I2C driver
@ 2019-10-25  9:37 ` Biwen Li
  0 siblings, 0 replies; 6+ messages in thread
From: Biwen Li @ 2019-10-25  9:37 UTC (permalink / raw)
  To: shawnguo, s.hauer, kernel, festevam, linux-imx, wsa, leoyang.li,
	aisheng.dong, xiaoning.wang, o.rempel
  Cc: linux-i2c, linux-kernel, linux-arm-kernel, laurentiu.tudor,
	jiafei.pan, xiaobo.xie, Biwen Li

The patch supports slave mode for imx I2C driver

Signed-off-by: Biwen Li <biwen.li@nxp.com>
---
Change in v3:
    - support layerscape and i.mx platform

Change in v2:
	- remove MACRO CONFIG_I2C_SLAVE

 drivers/i2c/busses/i2c-imx.c | 209 ++++++++++++++++++++++++++++++++---
 1 file changed, 191 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index a3b61336fe55..a91bf122f66c 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -203,6 +203,7 @@ struct imx_i2c_struct {
 	struct pinctrl_state *pinctrl_pins_gpio;
 
 	struct imx_i2c_dma	*dma;
+	struct i2c_client	*slave;
 };
 
 static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
@@ -279,6 +280,14 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
 	return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
 }
 
+/* Set up i2c controller register and i2c status register to default value. */
+static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
+{
+	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+			i2c_imx, IMX_I2C_I2CR);
+	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
+}
+
 /* Functions for DMA support */
 static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
 						dma_addr_t phy_addr)
@@ -588,23 +597,33 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
 	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
 }
 
-static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
+/* Clear interrupt flag bit */
+static void i2c_imx_clr_if_bit(unsigned int status, struct imx_i2c_struct *i2c_imx)
 {
-	struct imx_i2c_struct *i2c_imx = dev_id;
-	unsigned int temp;
+	status &= ~I2SR_IIF;
+	status |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
+	imx_i2c_write_reg(status, i2c_imx, IMX_I2C_I2SR);
+}
 
-	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
-	if (temp & I2SR_IIF) {
-		/* save status register */
-		i2c_imx->i2csr = temp;
-		temp &= ~I2SR_IIF;
-		temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
-		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
-		wake_up(&i2c_imx->queue);
-		return IRQ_HANDLED;
-	}
+/* Clear arbitration lost bit */
+static void i2c_imx_clr_al_bit(unsigned int status, struct imx_i2c_struct *i2c_imx)
+{
+	status &= ~I2SR_IAL;
+	status |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IAL);
+	imx_i2c_write_reg(status, i2c_imx, IMX_I2C_I2SR);
+}
+
+static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx)
+{
+	unsigned int status;
+
+	/* Save status register */
+	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+	i2c_imx->i2csr = status | I2SR_IIF;
 
-	return IRQ_NONE;
+	wake_up(&i2c_imx->queue);
+
+	return IRQ_HANDLED;
 }
 
 static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
@@ -900,6 +919,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
+	if (i2c_imx->slave) {
+		dev_err(&i2c_imx->adapter.dev, "Please not do operations of master mode in slave mode");
+		return -EBUSY;
+	}
+
 	result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
 	if (result < 0)
 		goto out;
@@ -1048,11 +1072,163 @@ static u32 i2c_imx_func(struct i2c_adapter *adapter)
 		| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
 }
 
+static int i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
+{
+	int temp;
+
+	/* Resume */
+	temp = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
+	if (temp < 0) {
+		dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller");
+		return temp;
+	}
+
+	/* Set slave addr. */
+	imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR);
+
+	i2c_imx_reset_regs(i2c_imx);
+
+	/* Enable module */
+	temp = i2c_imx->hwdata->i2cr_ien_opcode;
+	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+
+	/* Enable interrupt from i2c module */
+	temp |= I2CR_IIEN;
+	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+
+	/* Wait controller to be stable */
+	usleep_range(50, 150);
+	return 0;
+}
+
+static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx)
+{
+	unsigned int status, ctl;
+	u8 value;
+
+	if (!i2c_imx->slave) {
+		dev_err(&i2c_imx->adapter.dev, "cannot deal with slave irq,i2c_imx->slave is null");
+		return IRQ_NONE;
+	}
+
+	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+	if (status & I2SR_IAL) { /* Arbitration lost */
+		i2c_imx_clr_al_bit(status, i2c_imx);
+	} else if (status & I2SR_IAAS) { /* Addressed as a slave */
+		if (status & I2SR_SRW) { /* Master wants to read from us*/
+			dev_dbg(&i2c_imx->adapter.dev, "read requested");
+			i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
+
+			/* Slave transmit */
+			ctl |= I2CR_MTX;
+			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+
+			/* Send data */
+			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
+		} else { /* Master wants to write to us */
+			dev_dbg(&i2c_imx->adapter.dev, "write requested");
+			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value);
+
+			/* Slave receive */
+			ctl &= ~I2CR_MTX;
+			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+			/* Dummy read */
+			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+		}
+	} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
+			if (status & I2SR_IBB) { /* No STOP signal detected */
+				ctl &= ~I2CR_MTX;
+				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+
+				value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+				i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value);
+			} else { /* STOP signal is detected */
+				dev_dbg(&i2c_imx->adapter.dev,
+					"STOP signal detected");
+				i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
+			}
+	} else if (!(status & I2SR_RXAK)) {	/* Transmit mode received ACK */
+		ctl |= I2CR_MTX;
+		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+
+		i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value);
+
+		imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
+	} else { /* Transmit mode received NAK */
+		ctl &= ~I2CR_MTX;
+		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+		imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+	}
+	return IRQ_HANDLED;
+}
+
+static int i2c_imx_reg_slave(struct i2c_client *client)
+{
+	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
+	int ret;
+	if (i2c_imx->slave)
+		return -EBUSY;
+
+	i2c_imx->slave = client;
+
+	ret = i2c_imx_slave_init(i2c_imx);
+	if (ret < 0)
+		dev_err(&i2c_imx->adapter.dev, "failed to switch to slave mode");
+
+	return ret;
+}
+
+static int i2c_imx_unreg_slave(struct i2c_client *client)
+{
+	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
+	int ret;
+
+	if (!i2c_imx->slave)
+		return -EINVAL;
+
+	/* Reset slave address. */
+	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
+
+	i2c_imx_reset_regs(i2c_imx);
+
+	i2c_imx->slave = NULL;
+
+	/* Suspend */
+	ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
+	if (ret < 0)
+		dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
+
+	return ret;
+}
+
 static const struct i2c_algorithm i2c_imx_algo = {
 	.master_xfer	= i2c_imx_xfer,
 	.functionality	= i2c_imx_func,
+	.reg_slave	= i2c_imx_reg_slave,
+	.unreg_slave	= i2c_imx_unreg_slave,
 };
 
+static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
+{
+	struct imx_i2c_struct *i2c_imx = dev_id;
+	unsigned int status, ctl;
+	irqreturn_t irq_status = IRQ_NONE;
+
+	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+
+	if (status & I2SR_IIF) {
+		i2c_imx_clr_if_bit(status, i2c_imx);
+		if (ctl & I2CR_MSTA)
+			irq_status = i2c_imx_master_isr(i2c_imx);
+		else
+			irq_status = i2c_imx_slave_isr(i2c_imx);
+	}
+
+	return irq_status;
+}
+
 static int i2c_imx_probe(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx;
@@ -1148,10 +1324,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
 	clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
 	i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
 
-	/* Set up chip registers to defaults */
-	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
-			i2c_imx, IMX_I2C_I2CR);
-	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
+	i2c_imx_reset_regs(i2c_imx);
 
 	/* Init optional bus recovery function */
 	ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [v3] i2c: imx: support slave mode for imx I2C driver
@ 2019-10-25  9:37 ` Biwen Li
  0 siblings, 0 replies; 6+ messages in thread
From: Biwen Li @ 2019-10-25  9:37 UTC (permalink / raw)
  To: shawnguo, s.hauer, kernel, festevam, linux-imx, wsa, leoyang.li,
	aisheng.dong, xiaoning.wang, o.rempel
  Cc: Biwen Li, xiaobo.xie, linux-kernel, linux-i2c, jiafei.pan,
	linux-arm-kernel, laurentiu.tudor

The patch supports slave mode for imx I2C driver

Signed-off-by: Biwen Li <biwen.li@nxp.com>
---
Change in v3:
    - support layerscape and i.mx platform

Change in v2:
	- remove MACRO CONFIG_I2C_SLAVE

 drivers/i2c/busses/i2c-imx.c | 209 ++++++++++++++++++++++++++++++++---
 1 file changed, 191 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index a3b61336fe55..a91bf122f66c 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -203,6 +203,7 @@ struct imx_i2c_struct {
 	struct pinctrl_state *pinctrl_pins_gpio;
 
 	struct imx_i2c_dma	*dma;
+	struct i2c_client	*slave;
 };
 
 static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
@@ -279,6 +280,14 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
 	return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
 }
 
+/* Set up i2c controller register and i2c status register to default value. */
+static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
+{
+	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+			i2c_imx, IMX_I2C_I2CR);
+	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
+}
+
 /* Functions for DMA support */
 static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
 						dma_addr_t phy_addr)
@@ -588,23 +597,33 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
 	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
 }
 
-static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
+/* Clear interrupt flag bit */
+static void i2c_imx_clr_if_bit(unsigned int status, struct imx_i2c_struct *i2c_imx)
 {
-	struct imx_i2c_struct *i2c_imx = dev_id;
-	unsigned int temp;
+	status &= ~I2SR_IIF;
+	status |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
+	imx_i2c_write_reg(status, i2c_imx, IMX_I2C_I2SR);
+}
 
-	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
-	if (temp & I2SR_IIF) {
-		/* save status register */
-		i2c_imx->i2csr = temp;
-		temp &= ~I2SR_IIF;
-		temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
-		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
-		wake_up(&i2c_imx->queue);
-		return IRQ_HANDLED;
-	}
+/* Clear arbitration lost bit */
+static void i2c_imx_clr_al_bit(unsigned int status, struct imx_i2c_struct *i2c_imx)
+{
+	status &= ~I2SR_IAL;
+	status |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IAL);
+	imx_i2c_write_reg(status, i2c_imx, IMX_I2C_I2SR);
+}
+
+static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx)
+{
+	unsigned int status;
+
+	/* Save status register */
+	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+	i2c_imx->i2csr = status | I2SR_IIF;
 
-	return IRQ_NONE;
+	wake_up(&i2c_imx->queue);
+
+	return IRQ_HANDLED;
 }
 
 static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
@@ -900,6 +919,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 
 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
+	if (i2c_imx->slave) {
+		dev_err(&i2c_imx->adapter.dev, "Please not do operations of master mode in slave mode");
+		return -EBUSY;
+	}
+
 	result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
 	if (result < 0)
 		goto out;
@@ -1048,11 +1072,163 @@ static u32 i2c_imx_func(struct i2c_adapter *adapter)
 		| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
 }
 
+static int i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
+{
+	int temp;
+
+	/* Resume */
+	temp = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
+	if (temp < 0) {
+		dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller");
+		return temp;
+	}
+
+	/* Set slave addr. */
+	imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR);
+
+	i2c_imx_reset_regs(i2c_imx);
+
+	/* Enable module */
+	temp = i2c_imx->hwdata->i2cr_ien_opcode;
+	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+
+	/* Enable interrupt from i2c module */
+	temp |= I2CR_IIEN;
+	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+
+	/* Wait controller to be stable */
+	usleep_range(50, 150);
+	return 0;
+}
+
+static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx)
+{
+	unsigned int status, ctl;
+	u8 value;
+
+	if (!i2c_imx->slave) {
+		dev_err(&i2c_imx->adapter.dev, "cannot deal with slave irq,i2c_imx->slave is null");
+		return IRQ_NONE;
+	}
+
+	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+	if (status & I2SR_IAL) { /* Arbitration lost */
+		i2c_imx_clr_al_bit(status, i2c_imx);
+	} else if (status & I2SR_IAAS) { /* Addressed as a slave */
+		if (status & I2SR_SRW) { /* Master wants to read from us*/
+			dev_dbg(&i2c_imx->adapter.dev, "read requested");
+			i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
+
+			/* Slave transmit */
+			ctl |= I2CR_MTX;
+			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+
+			/* Send data */
+			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
+		} else { /* Master wants to write to us */
+			dev_dbg(&i2c_imx->adapter.dev, "write requested");
+			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value);
+
+			/* Slave receive */
+			ctl &= ~I2CR_MTX;
+			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+			/* Dummy read */
+			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+		}
+	} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
+			if (status & I2SR_IBB) { /* No STOP signal detected */
+				ctl &= ~I2CR_MTX;
+				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+
+				value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+				i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value);
+			} else { /* STOP signal is detected */
+				dev_dbg(&i2c_imx->adapter.dev,
+					"STOP signal detected");
+				i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
+			}
+	} else if (!(status & I2SR_RXAK)) {	/* Transmit mode received ACK */
+		ctl |= I2CR_MTX;
+		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+
+		i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value);
+
+		imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
+	} else { /* Transmit mode received NAK */
+		ctl &= ~I2CR_MTX;
+		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+		imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+	}
+	return IRQ_HANDLED;
+}
+
+static int i2c_imx_reg_slave(struct i2c_client *client)
+{
+	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
+	int ret;
+	if (i2c_imx->slave)
+		return -EBUSY;
+
+	i2c_imx->slave = client;
+
+	ret = i2c_imx_slave_init(i2c_imx);
+	if (ret < 0)
+		dev_err(&i2c_imx->adapter.dev, "failed to switch to slave mode");
+
+	return ret;
+}
+
+static int i2c_imx_unreg_slave(struct i2c_client *client)
+{
+	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
+	int ret;
+
+	if (!i2c_imx->slave)
+		return -EINVAL;
+
+	/* Reset slave address. */
+	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
+
+	i2c_imx_reset_regs(i2c_imx);
+
+	i2c_imx->slave = NULL;
+
+	/* Suspend */
+	ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
+	if (ret < 0)
+		dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
+
+	return ret;
+}
+
 static const struct i2c_algorithm i2c_imx_algo = {
 	.master_xfer	= i2c_imx_xfer,
 	.functionality	= i2c_imx_func,
+	.reg_slave	= i2c_imx_reg_slave,
+	.unreg_slave	= i2c_imx_unreg_slave,
 };
 
+static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
+{
+	struct imx_i2c_struct *i2c_imx = dev_id;
+	unsigned int status, ctl;
+	irqreturn_t irq_status = IRQ_NONE;
+
+	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+
+	if (status & I2SR_IIF) {
+		i2c_imx_clr_if_bit(status, i2c_imx);
+		if (ctl & I2CR_MSTA)
+			irq_status = i2c_imx_master_isr(i2c_imx);
+		else
+			irq_status = i2c_imx_slave_isr(i2c_imx);
+	}
+
+	return irq_status;
+}
+
 static int i2c_imx_probe(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx;
@@ -1148,10 +1324,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
 	clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
 	i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
 
-	/* Set up chip registers to defaults */
-	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
-			i2c_imx, IMX_I2C_I2CR);
-	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
+	i2c_imx_reset_regs(i2c_imx);
 
 	/* Init optional bus recovery function */
 	ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [v3] i2c: imx: support slave mode for imx I2C driver
  2019-10-25  9:37 ` Biwen Li
  (?)
  (?)
@ 2019-10-28  7:23   ` kbuild test robot
  -1 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2019-10-28  7:23 UTC (permalink / raw)
  To: Biwen Li
  Cc: kbuild-all, shawnguo, s.hauer, kernel, festevam, linux-imx, wsa,
	leoyang.li, aisheng.dong, xiaoning.wang, o.rempel, linux-i2c,
	linux-kernel, linux-arm-kernel, laurentiu.tudor, jiafei.pan,
	xiaobo.xie, Biwen Li

[-- Attachment #1: Type: text/plain, Size: 8316 bytes --]

Hi Biwen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v5.4-rc5 next-20191025]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Biwen-Li/i2c-imx-support-slave-mode-for-imx-I2C-driver/20191028-135008
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: arm-imx_v6_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   drivers/i2c/busses/i2c-imx.c: In function 'i2c_imx_slave_isr':
>> drivers/i2c/busses/i2c-imx.c:1121:4: error: implicit declaration of function 'i2c_slave_event'; did you mean 'io_wait_event'? [-Werror=implicit-function-declaration]
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
       ^~~~~~~~~~~~~~~
       io_wait_event
>> drivers/i2c/busses/i2c-imx.c:1121:36: error: 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function); did you mean 'I2C_CLASS_DEPRECATED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_CLASS_DEPRECATED
   drivers/i2c/busses/i2c-imx.c:1121:36: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-imx.c:1131:36: error: 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_SLAVE_READ_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1145:37: error: 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function); did you mean 'I2C_SLAVE_WRITE_REQUESTED'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
                                        ^~~~~~~~~~~~~~~~~~~~~~~~
                                        I2C_SLAVE_WRITE_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1149:37: error: 'I2C_SLAVE_STOP' undeclared (first use in this function); did you mean 'I2C_M_STOP'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
                                        ^~~~~~~~~~~~~~
                                        I2C_M_STOP
>> drivers/i2c/busses/i2c-imx.c:1155:35: error: 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
      i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
                                      ^~~~~~~~~~~~~~~~~~~~~~~~
                                      I2C_SLAVE_READ_REQUESTED
   drivers/i2c/busses/i2c-imx.c: At top level:
>> drivers/i2c/busses/i2c-imx.c:1208:3: error: 'const struct i2c_algorithm' has no member named 'reg_slave'
     .reg_slave = i2c_imx_reg_slave,
      ^~~~~~~~~
>> drivers/i2c/busses/i2c-imx.c:1208:15: warning: excess elements in struct initializer
     .reg_slave = i2c_imx_reg_slave,
                  ^~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1208:15: note: (near initialization for 'i2c_imx_algo')
>> drivers/i2c/busses/i2c-imx.c:1209:3: error: 'const struct i2c_algorithm' has no member named 'unreg_slave'
     .unreg_slave = i2c_imx_unreg_slave,
      ^~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: warning: excess elements in struct initializer
     .unreg_slave = i2c_imx_unreg_slave,
                    ^~~~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: note: (near initialization for 'i2c_imx_algo')
   cc1: some warnings being treated as errors

vim +1121 drivers/i2c/busses/i2c-imx.c

  1103	
  1104	static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx)
  1105	{
  1106		unsigned int status, ctl;
  1107		u8 value;
  1108	
  1109		if (!i2c_imx->slave) {
  1110			dev_err(&i2c_imx->adapter.dev, "cannot deal with slave irq,i2c_imx->slave is null");
  1111			return IRQ_NONE;
  1112		}
  1113	
  1114		status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
  1115		ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
  1116		if (status & I2SR_IAL) { /* Arbitration lost */
  1117			i2c_imx_clr_al_bit(status, i2c_imx);
  1118		} else if (status & I2SR_IAAS) { /* Addressed as a slave */
  1119			if (status & I2SR_SRW) { /* Master wants to read from us*/
  1120				dev_dbg(&i2c_imx->adapter.dev, "read requested");
> 1121				i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
  1122	
  1123				/* Slave transmit */
  1124				ctl |= I2CR_MTX;
  1125				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1126	
  1127				/* Send data */
  1128				imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1129			} else { /* Master wants to write to us */
  1130				dev_dbg(&i2c_imx->adapter.dev, "write requested");
> 1131				i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value);
  1132	
  1133				/* Slave receive */
  1134				ctl &= ~I2CR_MTX;
  1135				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1136				/* Dummy read */
  1137				imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1138			}
  1139		} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
  1140				if (status & I2SR_IBB) { /* No STOP signal detected */
  1141					ctl &= ~I2CR_MTX;
  1142					imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1143	
  1144					value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
> 1145					i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value);
  1146				} else { /* STOP signal is detected */
  1147					dev_dbg(&i2c_imx->adapter.dev,
  1148						"STOP signal detected");
> 1149					i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
  1150				}
  1151		} else if (!(status & I2SR_RXAK)) {	/* Transmit mode received ACK */
  1152			ctl |= I2CR_MTX;
  1153			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1154	
> 1155			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value);
  1156	
  1157			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1158		} else { /* Transmit mode received NAK */
  1159			ctl &= ~I2CR_MTX;
  1160			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1161			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1162		}
  1163		return IRQ_HANDLED;
  1164	}
  1165	
  1166	static int i2c_imx_reg_slave(struct i2c_client *client)
  1167	{
  1168		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1169		int ret;
  1170		if (i2c_imx->slave)
  1171			return -EBUSY;
  1172	
  1173		i2c_imx->slave = client;
  1174	
  1175		ret = i2c_imx_slave_init(i2c_imx);
  1176		if (ret < 0)
  1177			dev_err(&i2c_imx->adapter.dev, "failed to switch to slave mode");
  1178	
  1179		return ret;
  1180	}
  1181	
  1182	static int i2c_imx_unreg_slave(struct i2c_client *client)
  1183	{
  1184		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1185		int ret;
  1186	
  1187		if (!i2c_imx->slave)
  1188			return -EINVAL;
  1189	
  1190		/* Reset slave address. */
  1191		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
  1192	
  1193		i2c_imx_reset_regs(i2c_imx);
  1194	
  1195		i2c_imx->slave = NULL;
  1196	
  1197		/* Suspend */
  1198		ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
  1199		if (ret < 0)
  1200			dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
  1201	
  1202		return ret;
  1203	}
  1204	
  1205	static const struct i2c_algorithm i2c_imx_algo = {
  1206		.master_xfer	= i2c_imx_xfer,
  1207		.functionality	= i2c_imx_func,
> 1208		.reg_slave	= i2c_imx_reg_slave,
> 1209		.unreg_slave	= i2c_imx_unreg_slave,
  1210	};
  1211	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36577 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [v3] i2c: imx: support slave mode for imx I2C driver
@ 2019-10-28  7:23   ` kbuild test robot
  0 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2019-10-28  7:23 UTC (permalink / raw)
  Cc: kbuild-all, shawnguo, s.hauer, kernel, festevam, linux-imx, wsa,
	leoyang.li, aisheng.dong, xiaoning.wang, o.rempel, linux-i2c,
	linux-kernel, linux-arm-kernel, laurentiu.tudor, jiafei.pan,
	xiaobo.xie, Biwen Li

[-- Attachment #1: Type: text/plain, Size: 8316 bytes --]

Hi Biwen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v5.4-rc5 next-20191025]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Biwen-Li/i2c-imx-support-slave-mode-for-imx-I2C-driver/20191028-135008
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: arm-imx_v6_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   drivers/i2c/busses/i2c-imx.c: In function 'i2c_imx_slave_isr':
>> drivers/i2c/busses/i2c-imx.c:1121:4: error: implicit declaration of function 'i2c_slave_event'; did you mean 'io_wait_event'? [-Werror=implicit-function-declaration]
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
       ^~~~~~~~~~~~~~~
       io_wait_event
>> drivers/i2c/busses/i2c-imx.c:1121:36: error: 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function); did you mean 'I2C_CLASS_DEPRECATED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_CLASS_DEPRECATED
   drivers/i2c/busses/i2c-imx.c:1121:36: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-imx.c:1131:36: error: 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_SLAVE_READ_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1145:37: error: 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function); did you mean 'I2C_SLAVE_WRITE_REQUESTED'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
                                        ^~~~~~~~~~~~~~~~~~~~~~~~
                                        I2C_SLAVE_WRITE_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1149:37: error: 'I2C_SLAVE_STOP' undeclared (first use in this function); did you mean 'I2C_M_STOP'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
                                        ^~~~~~~~~~~~~~
                                        I2C_M_STOP
>> drivers/i2c/busses/i2c-imx.c:1155:35: error: 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
      i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
                                      ^~~~~~~~~~~~~~~~~~~~~~~~
                                      I2C_SLAVE_READ_REQUESTED
   drivers/i2c/busses/i2c-imx.c: At top level:
>> drivers/i2c/busses/i2c-imx.c:1208:3: error: 'const struct i2c_algorithm' has no member named 'reg_slave'
     .reg_slave = i2c_imx_reg_slave,
      ^~~~~~~~~
>> drivers/i2c/busses/i2c-imx.c:1208:15: warning: excess elements in struct initializer
     .reg_slave = i2c_imx_reg_slave,
                  ^~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1208:15: note: (near initialization for 'i2c_imx_algo')
>> drivers/i2c/busses/i2c-imx.c:1209:3: error: 'const struct i2c_algorithm' has no member named 'unreg_slave'
     .unreg_slave = i2c_imx_unreg_slave,
      ^~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: warning: excess elements in struct initializer
     .unreg_slave = i2c_imx_unreg_slave,
                    ^~~~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: note: (near initialization for 'i2c_imx_algo')
   cc1: some warnings being treated as errors

vim +1121 drivers/i2c/busses/i2c-imx.c

  1103	
  1104	static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx)
  1105	{
  1106		unsigned int status, ctl;
  1107		u8 value;
  1108	
  1109		if (!i2c_imx->slave) {
  1110			dev_err(&i2c_imx->adapter.dev, "cannot deal with slave irq,i2c_imx->slave is null");
  1111			return IRQ_NONE;
  1112		}
  1113	
  1114		status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
  1115		ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
  1116		if (status & I2SR_IAL) { /* Arbitration lost */
  1117			i2c_imx_clr_al_bit(status, i2c_imx);
  1118		} else if (status & I2SR_IAAS) { /* Addressed as a slave */
  1119			if (status & I2SR_SRW) { /* Master wants to read from us*/
  1120				dev_dbg(&i2c_imx->adapter.dev, "read requested");
> 1121				i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
  1122	
  1123				/* Slave transmit */
  1124				ctl |= I2CR_MTX;
  1125				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1126	
  1127				/* Send data */
  1128				imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1129			} else { /* Master wants to write to us */
  1130				dev_dbg(&i2c_imx->adapter.dev, "write requested");
> 1131				i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value);
  1132	
  1133				/* Slave receive */
  1134				ctl &= ~I2CR_MTX;
  1135				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1136				/* Dummy read */
  1137				imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1138			}
  1139		} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
  1140				if (status & I2SR_IBB) { /* No STOP signal detected */
  1141					ctl &= ~I2CR_MTX;
  1142					imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1143	
  1144					value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
> 1145					i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value);
  1146				} else { /* STOP signal is detected */
  1147					dev_dbg(&i2c_imx->adapter.dev,
  1148						"STOP signal detected");
> 1149					i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
  1150				}
  1151		} else if (!(status & I2SR_RXAK)) {	/* Transmit mode received ACK */
  1152			ctl |= I2CR_MTX;
  1153			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1154	
> 1155			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value);
  1156	
  1157			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1158		} else { /* Transmit mode received NAK */
  1159			ctl &= ~I2CR_MTX;
  1160			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1161			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1162		}
  1163		return IRQ_HANDLED;
  1164	}
  1165	
  1166	static int i2c_imx_reg_slave(struct i2c_client *client)
  1167	{
  1168		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1169		int ret;
  1170		if (i2c_imx->slave)
  1171			return -EBUSY;
  1172	
  1173		i2c_imx->slave = client;
  1174	
  1175		ret = i2c_imx_slave_init(i2c_imx);
  1176		if (ret < 0)
  1177			dev_err(&i2c_imx->adapter.dev, "failed to switch to slave mode");
  1178	
  1179		return ret;
  1180	}
  1181	
  1182	static int i2c_imx_unreg_slave(struct i2c_client *client)
  1183	{
  1184		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1185		int ret;
  1186	
  1187		if (!i2c_imx->slave)
  1188			return -EINVAL;
  1189	
  1190		/* Reset slave address. */
  1191		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
  1192	
  1193		i2c_imx_reset_regs(i2c_imx);
  1194	
  1195		i2c_imx->slave = NULL;
  1196	
  1197		/* Suspend */
  1198		ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
  1199		if (ret < 0)
  1200			dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
  1201	
  1202		return ret;
  1203	}
  1204	
  1205	static const struct i2c_algorithm i2c_imx_algo = {
  1206		.master_xfer	= i2c_imx_xfer,
  1207		.functionality	= i2c_imx_func,
> 1208		.reg_slave	= i2c_imx_reg_slave,
> 1209		.unreg_slave	= i2c_imx_unreg_slave,
  1210	};
  1211	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36577 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [v3] i2c: imx: support slave mode for imx I2C driver
@ 2019-10-28  7:23   ` kbuild test robot
  0 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2019-10-28  7:23 UTC (permalink / raw)
  To: Biwen Li
  Cc: aisheng.dong, Biwen Li, kbuild-all, wsa, festevam, s.hauer,
	linux-kernel, leoyang.li, xiaobo.xie, o.rempel, xiaoning.wang,
	linux-imx, kernel, jiafei.pan, laurentiu.tudor, shawnguo,
	linux-arm-kernel, linux-i2c

[-- Attachment #1: Type: text/plain, Size: 8316 bytes --]

Hi Biwen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v5.4-rc5 next-20191025]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Biwen-Li/i2c-imx-support-slave-mode-for-imx-I2C-driver/20191028-135008
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: arm-imx_v6_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   drivers/i2c/busses/i2c-imx.c: In function 'i2c_imx_slave_isr':
>> drivers/i2c/busses/i2c-imx.c:1121:4: error: implicit declaration of function 'i2c_slave_event'; did you mean 'io_wait_event'? [-Werror=implicit-function-declaration]
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
       ^~~~~~~~~~~~~~~
       io_wait_event
>> drivers/i2c/busses/i2c-imx.c:1121:36: error: 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function); did you mean 'I2C_CLASS_DEPRECATED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_CLASS_DEPRECATED
   drivers/i2c/busses/i2c-imx.c:1121:36: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-imx.c:1131:36: error: 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_SLAVE_READ_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1145:37: error: 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function); did you mean 'I2C_SLAVE_WRITE_REQUESTED'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
                                        ^~~~~~~~~~~~~~~~~~~~~~~~
                                        I2C_SLAVE_WRITE_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1149:37: error: 'I2C_SLAVE_STOP' undeclared (first use in this function); did you mean 'I2C_M_STOP'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
                                        ^~~~~~~~~~~~~~
                                        I2C_M_STOP
>> drivers/i2c/busses/i2c-imx.c:1155:35: error: 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
      i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
                                      ^~~~~~~~~~~~~~~~~~~~~~~~
                                      I2C_SLAVE_READ_REQUESTED
   drivers/i2c/busses/i2c-imx.c: At top level:
>> drivers/i2c/busses/i2c-imx.c:1208:3: error: 'const struct i2c_algorithm' has no member named 'reg_slave'
     .reg_slave = i2c_imx_reg_slave,
      ^~~~~~~~~
>> drivers/i2c/busses/i2c-imx.c:1208:15: warning: excess elements in struct initializer
     .reg_slave = i2c_imx_reg_slave,
                  ^~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1208:15: note: (near initialization for 'i2c_imx_algo')
>> drivers/i2c/busses/i2c-imx.c:1209:3: error: 'const struct i2c_algorithm' has no member named 'unreg_slave'
     .unreg_slave = i2c_imx_unreg_slave,
      ^~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: warning: excess elements in struct initializer
     .unreg_slave = i2c_imx_unreg_slave,
                    ^~~~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: note: (near initialization for 'i2c_imx_algo')
   cc1: some warnings being treated as errors

vim +1121 drivers/i2c/busses/i2c-imx.c

  1103	
  1104	static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx)
  1105	{
  1106		unsigned int status, ctl;
  1107		u8 value;
  1108	
  1109		if (!i2c_imx->slave) {
  1110			dev_err(&i2c_imx->adapter.dev, "cannot deal with slave irq,i2c_imx->slave is null");
  1111			return IRQ_NONE;
  1112		}
  1113	
  1114		status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
  1115		ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
  1116		if (status & I2SR_IAL) { /* Arbitration lost */
  1117			i2c_imx_clr_al_bit(status, i2c_imx);
  1118		} else if (status & I2SR_IAAS) { /* Addressed as a slave */
  1119			if (status & I2SR_SRW) { /* Master wants to read from us*/
  1120				dev_dbg(&i2c_imx->adapter.dev, "read requested");
> 1121				i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
  1122	
  1123				/* Slave transmit */
  1124				ctl |= I2CR_MTX;
  1125				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1126	
  1127				/* Send data */
  1128				imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1129			} else { /* Master wants to write to us */
  1130				dev_dbg(&i2c_imx->adapter.dev, "write requested");
> 1131				i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value);
  1132	
  1133				/* Slave receive */
  1134				ctl &= ~I2CR_MTX;
  1135				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1136				/* Dummy read */
  1137				imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1138			}
  1139		} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
  1140				if (status & I2SR_IBB) { /* No STOP signal detected */
  1141					ctl &= ~I2CR_MTX;
  1142					imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1143	
  1144					value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
> 1145					i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value);
  1146				} else { /* STOP signal is detected */
  1147					dev_dbg(&i2c_imx->adapter.dev,
  1148						"STOP signal detected");
> 1149					i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
  1150				}
  1151		} else if (!(status & I2SR_RXAK)) {	/* Transmit mode received ACK */
  1152			ctl |= I2CR_MTX;
  1153			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1154	
> 1155			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value);
  1156	
  1157			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1158		} else { /* Transmit mode received NAK */
  1159			ctl &= ~I2CR_MTX;
  1160			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1161			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1162		}
  1163		return IRQ_HANDLED;
  1164	}
  1165	
  1166	static int i2c_imx_reg_slave(struct i2c_client *client)
  1167	{
  1168		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1169		int ret;
  1170		if (i2c_imx->slave)
  1171			return -EBUSY;
  1172	
  1173		i2c_imx->slave = client;
  1174	
  1175		ret = i2c_imx_slave_init(i2c_imx);
  1176		if (ret < 0)
  1177			dev_err(&i2c_imx->adapter.dev, "failed to switch to slave mode");
  1178	
  1179		return ret;
  1180	}
  1181	
  1182	static int i2c_imx_unreg_slave(struct i2c_client *client)
  1183	{
  1184		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1185		int ret;
  1186	
  1187		if (!i2c_imx->slave)
  1188			return -EINVAL;
  1189	
  1190		/* Reset slave address. */
  1191		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
  1192	
  1193		i2c_imx_reset_regs(i2c_imx);
  1194	
  1195		i2c_imx->slave = NULL;
  1196	
  1197		/* Suspend */
  1198		ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
  1199		if (ret < 0)
  1200			dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
  1201	
  1202		return ret;
  1203	}
  1204	
  1205	static const struct i2c_algorithm i2c_imx_algo = {
  1206		.master_xfer	= i2c_imx_xfer,
  1207		.functionality	= i2c_imx_func,
> 1208		.reg_slave	= i2c_imx_reg_slave,
> 1209		.unreg_slave	= i2c_imx_unreg_slave,
  1210	};
  1211	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36577 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [v3] i2c: imx: support slave mode for imx I2C driver
@ 2019-10-28  7:23   ` kbuild test robot
  0 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2019-10-28  7:23 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 8499 bytes --]

Hi Biwen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v5.4-rc5 next-20191025]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Biwen-Li/i2c-imx-support-slave-mode-for-imx-I2C-driver/20191028-135008
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: arm-imx_v6_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   drivers/i2c/busses/i2c-imx.c: In function 'i2c_imx_slave_isr':
>> drivers/i2c/busses/i2c-imx.c:1121:4: error: implicit declaration of function 'i2c_slave_event'; did you mean 'io_wait_event'? [-Werror=implicit-function-declaration]
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
       ^~~~~~~~~~~~~~~
       io_wait_event
>> drivers/i2c/busses/i2c-imx.c:1121:36: error: 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function); did you mean 'I2C_CLASS_DEPRECATED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_CLASS_DEPRECATED
   drivers/i2c/busses/i2c-imx.c:1121:36: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-imx.c:1131:36: error: 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
       i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
                                       I2C_SLAVE_READ_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1145:37: error: 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function); did you mean 'I2C_SLAVE_WRITE_REQUESTED'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
                                        ^~~~~~~~~~~~~~~~~~~~~~~~
                                        I2C_SLAVE_WRITE_REQUESTED
>> drivers/i2c/busses/i2c-imx.c:1149:37: error: 'I2C_SLAVE_STOP' undeclared (first use in this function); did you mean 'I2C_M_STOP'?
        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
                                        ^~~~~~~~~~~~~~
                                        I2C_M_STOP
>> drivers/i2c/busses/i2c-imx.c:1155:35: error: 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function); did you mean 'I2C_SLAVE_READ_REQUESTED'?
      i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
                                      ^~~~~~~~~~~~~~~~~~~~~~~~
                                      I2C_SLAVE_READ_REQUESTED
   drivers/i2c/busses/i2c-imx.c: At top level:
>> drivers/i2c/busses/i2c-imx.c:1208:3: error: 'const struct i2c_algorithm' has no member named 'reg_slave'
     .reg_slave = i2c_imx_reg_slave,
      ^~~~~~~~~
>> drivers/i2c/busses/i2c-imx.c:1208:15: warning: excess elements in struct initializer
     .reg_slave = i2c_imx_reg_slave,
                  ^~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1208:15: note: (near initialization for 'i2c_imx_algo')
>> drivers/i2c/busses/i2c-imx.c:1209:3: error: 'const struct i2c_algorithm' has no member named 'unreg_slave'
     .unreg_slave = i2c_imx_unreg_slave,
      ^~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: warning: excess elements in struct initializer
     .unreg_slave = i2c_imx_unreg_slave,
                    ^~~~~~~~~~~~~~~~~~~
   drivers/i2c/busses/i2c-imx.c:1209:17: note: (near initialization for 'i2c_imx_algo')
   cc1: some warnings being treated as errors

vim +1121 drivers/i2c/busses/i2c-imx.c

  1103	
  1104	static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx)
  1105	{
  1106		unsigned int status, ctl;
  1107		u8 value;
  1108	
  1109		if (!i2c_imx->slave) {
  1110			dev_err(&i2c_imx->adapter.dev, "cannot deal with slave irq,i2c_imx->slave is null");
  1111			return IRQ_NONE;
  1112		}
  1113	
  1114		status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
  1115		ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
  1116		if (status & I2SR_IAL) { /* Arbitration lost */
  1117			i2c_imx_clr_al_bit(status, i2c_imx);
  1118		} else if (status & I2SR_IAAS) { /* Addressed as a slave */
  1119			if (status & I2SR_SRW) { /* Master wants to read from us*/
  1120				dev_dbg(&i2c_imx->adapter.dev, "read requested");
> 1121				i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
  1122	
  1123				/* Slave transmit */
  1124				ctl |= I2CR_MTX;
  1125				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1126	
  1127				/* Send data */
  1128				imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1129			} else { /* Master wants to write to us */
  1130				dev_dbg(&i2c_imx->adapter.dev, "write requested");
> 1131				i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value);
  1132	
  1133				/* Slave receive */
  1134				ctl &= ~I2CR_MTX;
  1135				imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1136				/* Dummy read */
  1137				imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1138			}
  1139		} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
  1140				if (status & I2SR_IBB) { /* No STOP signal detected */
  1141					ctl &= ~I2CR_MTX;
  1142					imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1143	
  1144					value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
> 1145					i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value);
  1146				} else { /* STOP signal is detected */
  1147					dev_dbg(&i2c_imx->adapter.dev,
  1148						"STOP signal detected");
> 1149					i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
  1150				}
  1151		} else if (!(status & I2SR_RXAK)) {	/* Transmit mode received ACK */
  1152			ctl |= I2CR_MTX;
  1153			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1154	
> 1155			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value);
  1156	
  1157			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
  1158		} else { /* Transmit mode received NAK */
  1159			ctl &= ~I2CR_MTX;
  1160			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
  1161			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
  1162		}
  1163		return IRQ_HANDLED;
  1164	}
  1165	
  1166	static int i2c_imx_reg_slave(struct i2c_client *client)
  1167	{
  1168		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1169		int ret;
  1170		if (i2c_imx->slave)
  1171			return -EBUSY;
  1172	
  1173		i2c_imx->slave = client;
  1174	
  1175		ret = i2c_imx_slave_init(i2c_imx);
  1176		if (ret < 0)
  1177			dev_err(&i2c_imx->adapter.dev, "failed to switch to slave mode");
  1178	
  1179		return ret;
  1180	}
  1181	
  1182	static int i2c_imx_unreg_slave(struct i2c_client *client)
  1183	{
  1184		struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter);
  1185		int ret;
  1186	
  1187		if (!i2c_imx->slave)
  1188			return -EINVAL;
  1189	
  1190		/* Reset slave address. */
  1191		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
  1192	
  1193		i2c_imx_reset_regs(i2c_imx);
  1194	
  1195		i2c_imx->slave = NULL;
  1196	
  1197		/* Suspend */
  1198		ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent);
  1199		if (ret < 0)
  1200			dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller");
  1201	
  1202		return ret;
  1203	}
  1204	
  1205	static const struct i2c_algorithm i2c_imx_algo = {
  1206		.master_xfer	= i2c_imx_xfer,
  1207		.functionality	= i2c_imx_func,
> 1208		.reg_slave	= i2c_imx_reg_slave,
> 1209		.unreg_slave	= i2c_imx_unreg_slave,
  1210	};
  1211	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 36577 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-10-28  7:24 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-25  9:37 [v3] i2c: imx: support slave mode for imx I2C driver Biwen Li
2019-10-25  9:37 ` Biwen Li
2019-10-28  7:23 ` kbuild test robot
2019-10-28  7:23   ` kbuild test robot
2019-10-28  7:23   ` kbuild test robot
2019-10-28  7:23   ` kbuild test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.