Skip to contentSkip to conversation

i2c: npcm: Bug fixes timeout, spurious interrupts

PATCH Applied Tyrone Ting 4 participants 33 messages May 17, 2022 – May 22, 2022

Subsystems (3)

v5 of 6 Applied Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v5 cover i2c: npcm: Bug fixes timeout, spurious interrupts

From: Tyrone Ting <[email protected]>

This patchset includes the following fixes:

- Add dt-bindings description for NPCM845.
- Bug fix for timeout calculation.
- Better handling of spurious interrupts.
- Fix for event type in slave mode.
- Removal of own slave addresses [2:10].
- Support for next gen BMC (NPCM845).

The NPCM I2C driver is tested on NPCM750 and NPCM845 evaluation boards.

Addressed comments from:
- Krzysztof Kozlowski : https://www.spinics.net/lists/linux-i2c/
msg56795.html
- Andy Shevchenko : https://lkml.org/lkml/2022/5/10/297
- Wolfram Sang : https://lkml.org/lkml/2022/5/17/38
- Andy Shevchenko : https://lkml.org/lkml/2022/5/10/306
- Andy Shevchenko : https://lkml.org/lkml/2022/5/10/309

Changes since version 4:
- Remove quotes around ref handle to nuvoton,sys-mgr in i2c binding document.
- Keep the "longer line first" order.
- Correct the SoB chain.
- Modify the if statement in one line and add new line characters.
- Modify the commit message format in the patch Remove own slave addresses 2:10. Correct the if statement in one line and shorten the debug messages.
- Create a new patch to capitalize the one-line comment in the driver.

Changes since version 3:
- Correct the const format in if condition in i2c binding document.
- Add the oops message statement and register information in register access width patch.
- Add the occurring rate of the i2c spurious interrupt issue and more details in driver's behavior to overcome this issue.
- Address Andy's comments in the patch to support NPCM845.

Changes since version 2:
- Keep old code as fallback, if getting nuvoton,sys-mgr property fails.
- Fix the error reported by running 'make DT_CHECKER_FLAGS=-m dt_binding_check'.
- Make nuvoton,sys-mgr required for nuvoton,npcm845-i2c.
- Correct the patch's subject about changing the way of getting GCR regmap and add the description about keeping old code as fallback if getting nuvoton,sys-mgr property fails.
- Correct the patch title and description about removing the unused variable clk_regmap.
- Use the data field directly instead of the macros since macros are not constants anymore in this patch.

Changes since version 1:
- Add nuvoton,sys-mgr property in NPCM devicetree.
- Describe the commit message in imperative mood.
- Modify the description in i2c binding document to cover NPCM series.
- Add new property in i2c binding document.
- Create a new patch for client address calculation.
- Create a new patch for updating gcr property name.
- Create a new patch for removing unused clock node.
- Explain EOB in the commit description.
- Create a new patch for correcting NPCM register access width.
- Remove some comment since the corresponding logic no longer exists.
- Remove fixes tag while the patch adds an additional feature.
- Use devicetree data field to support NPCM845.

Tali Perry (6):
i2c: npcm: Change the way of getting GCR regmap
i2c: npcm: Remove unused variable clk_regmap
i2c: npcm: Fix timeout calculation
i2c: npcm: Add tx complete counter
i2c: npcm: Handle spurious interrupts
i2c: npcm: Remove own slave addresses 2:10

Tyrone Ting (4):
dt-bindings: i2c: npcm: support NPCM845
i2c: npcm: Correct register access width
i2c: npcm: Support NPCM845
i2c: npcm: Capitalize the one-line comment

 .../bindings/i2c/nuvoton,npcm7xx-i2c.yaml     |  25 +-
 drivers/i2c/busses/Kconfig                    |   8 +-
 drivers/i2c/busses/Makefile                   |   2 +-
 drivers/i2c/busses/i2c-npcm7xx.c              | 277 +++++++++++-------
 4 files changed, 194 insertions(+), 118 deletions(-)
Signature · 1 line
2.17.1
#1 lore raw

PATCH v5 1/10 dt-bindings: i2c: npcm: support NPCM845

From: Tyrone Ting <[email protected]>

Add compatible and nuvoton,sys-mgr description for NPCM i2c module.

---
 .../bindings/i2c/nuvoton,npcm7xx-i2c.yaml     | 25 +++++++++++++++----
 1 file changed, 20 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/i2c/nuvoton,npcm7xx-i2c.yaml +20 -5
index 128444942aec..09d2591e1fa3 100644
@@ -7,17 +7,18 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: nuvoton NPCM7XX I2C Controller Device Tree Bindings
 
 description: |
-  The NPCM750x includes sixteen I2C bus controllers. All Controllers support
-  both master and slave mode. Each controller can switch between master and slave
-  at run time (i.e. IPMB mode). Each controller has two 16 byte HW FIFO for TX and
-  RX.
+  I2C bus controllers of the NPCM series support both master and
+  slave mode. Each controller can switch between master and slave at run time
+  (i.e. IPMB mode). HW FIFO for TX and RX are supported.
 
 maintainers:
   - Tali Perry <[email protected]>
 
 properties:
   compatible:
-    const: nuvoton,npcm750-i2c
+    enum:
+      - nuvoton,npcm750-i2c
+      - nuvoton,npcm845-i2c
 
   reg:
     maxItems: 1
@@ -36,6 +37,10 @@ properties:
     default: 100000
     enum: [100000, 400000, 1000000]
 
+  nuvoton,sys-mgr:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: The phandle of system manager register node.
+
 required:
   - compatible
   - reg
@@ -44,6 +49,15 @@ required:
 
 allOf:
   - $ref: /schemas/i2c/i2c-controller.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: nuvoton,npcm845-i2c
+
+    then:
+      required:
+        - nuvoton,sys-mgr
 
 unevaluatedProperties: false
 
@@ -57,6 +71,7 @@ examples:
         clock-frequency = <100000>;
         interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
         compatible = "nuvoton,npcm750-i2c";
+        nuvoton,sys-mgr = <&gcr>;
     };
 
 ...
Signature · 1 line
2.17.1
#3 lore raw

Re: [PATCH v5 01/10] dt-bindings: i2c: npcm: support NPCM845

Hi Wolfram:

Thank you for your help.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午2:03寫道:

Quoted 12 lines · Tyrone Ting
Quoted 7 lines

From: Tyrone Ting <[email protected]>

Add compatible and nuvoton,sys-mgr description for NPCM i2c module.

Needs to wait until comments to patches 8+9 are addressed.

Best Regards,
Tyrone

#4 lore raw

PATCH v5 2/10 i2c: npcm: Change the way of getting GCR regmap

In reply to Tyrone Ting

From: Tali Perry <[email protected]>

Change the way of getting NPCM system manager reigster (GCR) and still maintain the old mechanism as a fallback if getting nuvoton,sys-mgr fails while working with the legacy devicetree file.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +8 -4
index 71aad029425d..de4e5f2f3e5a 100644
@@ -2229,11 +2229,12 @@ static void npcm_i2c_init_debugfs(struct platform_device *pdev,
 
 static int npcm_i2c_probe_bus(struct platform_device *pdev)
 {
-	struct npcm_i2c *bus;
-	struct i2c_adapter *adap;
-	struct clk *i2c_clk;
+	struct device_node *np = pdev->dev.of_node;
 	static struct regmap *gcr_regmap;
 	static struct regmap *clk_regmap;
+	struct i2c_adapter *adap;
+	struct npcm_i2c *bus;
+	struct clk *i2c_clk;
 	int irq;
 	int ret;
 
@@ -2250,7 +2251,10 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
 		return PTR_ERR(i2c_clk);
 	bus->apb_clk = clk_get_rate(i2c_clk);
 
-	gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
+	gcr_regmap = syscon_regmap_lookup_by_phandle(np, "nuvoton,sys-mgr");
+	if (IS_ERR(gcr_regmap))
+		gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
+
 	if (IS_ERR(gcr_regmap))
 		return PTR_ERR(gcr_regmap);
 	regmap_write(gcr_regmap, NPCM_I2CSEGCTL, NPCM_I2CSEGCTL_INIT_VAL);
Signature · 1 line
2.17.1
Applied
#5 lore raw

Re: [PATCH v5 02/10] i2c: npcm: Change the way of getting GCR regmap

Quoted 11 lines · Tyrone Ting

From: Tali Perry <[email protected]>

Change the way of getting NPCM system manager reigster (GCR) and still maintain the old mechanism as a fallback if getting nuvoton,sys-mgr fails while working with the legacy devicetree file.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Fixes tag, doesn't look like a bugfix to me.

#6 lore raw

Re: [PATCH v5 02/10] i2c: npcm: Change the way of getting GCR regmap

Hi Wolfram:

Got it and thank you for your review.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午1:51寫道:

Quoted 9 lines · Tyrone Ting
Quoted 7 lines

From: Tali Perry <[email protected]>

Change the way of getting NPCM system manager reigster (GCR) and still maintain the old mechanism as a fallback if getting nuvoton,sys-mgr fails while working with the legacy devicetree file.

Quoted 9 lines
Quoted 4 lines
Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Fixes tag, doesn't look like a bugfix to me.

Best Regards,
Tyrone

#7 lore raw

PATCH v5 3/10 i2c: npcm: Remove unused variable clk_regmap

In reply to Tyrone Ting

From: Tali Perry <[email protected]>

Remove unused variable clk_regmap.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 5 -----
 1 file changed, 5 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +0 -5
index de4e5f2f3e5a..550e4a4d1e01 100644
@@ -2231,7 +2231,6 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	static struct regmap *gcr_regmap;
-	static struct regmap *clk_regmap;
 	struct i2c_adapter *adap;
 	struct npcm_i2c *bus;
 	struct clk *i2c_clk;
@@ -2259,10 +2258,6 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
 		return PTR_ERR(gcr_regmap);
 	regmap_write(gcr_regmap, NPCM_I2CSEGCTL, NPCM_I2CSEGCTL_INIT_VAL);
 
-	clk_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-clk");
-	if (IS_ERR(clk_regmap))
-		return PTR_ERR(clk_regmap);
-
 	bus->reg = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(bus->reg))
 		return PTR_ERR(bus->reg);
Signature · 1 line
2.17.1
Applied
#8 lore raw

Re: [PATCH v5 03/10] i2c: npcm: Remove unused variable clk_regmap

Quoted 8 lines · Tyrone Ting

From: Tali Perry <[email protected]>

Remove unused variable clk_regmap.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Fixes tag, doesn't look like a bugfix to me.

#9 lore raw

Re: [PATCH v5 03/10] i2c: npcm: Remove unused variable clk_regmap

Hi Wolfram:

Thank you for your help and review.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午1:51寫道:

Quoted 6 lines · Tyrone Ting
Quoted 4 lines

From: Tali Perry <[email protected]>

Remove unused variable clk_regmap.

Quoted 9 lines
Quoted 4 lines
Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Fixes tag, doesn't look like a bugfix to me.

Best Regards,
Tyrone

#10 lore raw

PATCH v5 4/10 i2c: npcm: Fix timeout calculation

In reply to Tyrone Ting

From: Tali Perry <[email protected]>

Use adap.timeout for timeout calculation instead of hard-coded value of 35ms.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +4 -4
index 550e4a4d1e01..489b4c8ad0ee 100644
@@ -2047,7 +2047,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 	u16 nwrite, nread;
 	u8 *write_data, *read_data;
 	u8 slave_addr;
-	int timeout;
+	unsigned long timeout;
 	int ret = 0;
 	bool read_block = false;
 	bool read_PEC = false;
@@ -2099,13 +2099,13 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 	 * 9: bits per transaction (including the ack/nack)
 	 */
 	timeout_usec = (2 * 9 * USEC_PER_SEC / bus->bus_freq) * (2 + nread + nwrite);
-	timeout = max(msecs_to_jiffies(35), usecs_to_jiffies(timeout_usec));
+	timeout = max_t(unsigned long, bus->adap.timeout, usecs_to_jiffies(timeout_usec));
 	if (nwrite >= 32 * 1024 || nread >= 32 * 1024) {
 		dev_err(bus->dev, "i2c%d buffer too big\n", bus->num);
 		return -EINVAL;
 	}
 
-	time_left = jiffies + msecs_to_jiffies(DEFAULT_STALL_COUNT) + 1;
+	time_left = jiffies + timeout + 1;
 	do {
 		/*
 		 * we must clear slave address immediately when the bus is not
@@ -2268,7 +2268,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
 	adap = &bus->adap;
 	adap->owner = THIS_MODULE;
 	adap->retries = 3;
-	adap->timeout = HZ;
+	adap->timeout = msecs_to_jiffies(35);
 	adap->algo = &npcm_i2c_algo;
 	adap->quirks = &npcm_i2c_quirks;
 	adap->algo_data = bus;
Signature · 1 line
2.17.1
Applied
#11 lore raw

Re: [PATCH v5 04/10] i2c: npcm: Fix timeout calculation

Quoted 8 lines · Tyrone Ting

From: Tali Perry <[email protected]>

Use adap.timeout for timeout calculation instead of hard-coded value of 35ms.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Reported-by tag, doesn't look like test robot found this issue.

#12 lore raw

Re: [PATCH v5 04/10] i2c: npcm: Fix timeout calculation

Hi Wolfram:

Thank you for your review.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午1:52寫道:

Quoted 7 lines · Tyrone Ting
Quoted 5 lines

From: Tali Perry <[email protected]>

Use adap.timeout for timeout calculation instead of hard-coded value of 35ms.

Quoted 9 lines
Quoted 3 lines
Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Reported-by tag, doesn't look like test robot found this issue.

Best Regards,
Tyrone

#13 lore raw

PATCH v5 5/10 i2c: npcm: Add tx complete counter

In reply to Tyrone Ting

From: Tali Perry <[email protected]>

tx_complete counter is used to indicate successful transaction count.
Similar counters for failed tx were previously added.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/i2c/busses/i2c-npcm7xx.c +4 -0
index 489b4c8ad0ee..36f8aa7ab106 100644
@@ -314,6 +314,7 @@ struct npcm_i2c {
 	u64 rec_fail_cnt;
 	u64 nack_cnt;
 	u64 timeout_cnt;
+	u64 tx_complete_cnt;
 };
 
 static inline void npcm_i2c_select_bank(struct npcm_i2c *bus,
@@ -684,6 +685,8 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
 	switch (op_status) {
 	case I2C_MASTER_DONE_IND:
 		bus->cmd_err = bus->msgs_num;
+		if (bus->tx_complete_cnt < ULLONG_MAX)
+			bus->tx_complete_cnt++;
 		fallthrough;
 	case I2C_BLOCK_BYTES_ERR_IND:
 		/* Master tx finished and all transmit bytes were sent */
@@ -2223,6 +2226,7 @@ static void npcm_i2c_init_debugfs(struct platform_device *pdev,
 	debugfs_create_u64("rec_succ_cnt", 0444, d, &bus->rec_succ_cnt);
 	debugfs_create_u64("rec_fail_cnt", 0444, d, &bus->rec_fail_cnt);
 	debugfs_create_u64("timeout_cnt", 0444, d, &bus->timeout_cnt);
+	debugfs_create_u64("tx_complete_cnt", 0444, d, &bus->tx_complete_cnt);
 
 	bus->debugfs = d;
 }
Signature · 1 line
2.17.1
Applied
#14 lore raw

Re: [PATCH v5 05/10] i2c: npcm: Add tx complete counter

Quoted 9 lines · Tyrone Ting

From: Tali Perry <[email protected]>

tx_complete counter is used to indicate successful transaction count.
Similar counters for failed tx were previously added.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Fixes tag, doesn't look like a bugfix to me.

#15 lore raw

Re: [PATCH v5 05/10] i2c: npcm: Add tx complete counter

Hi Wolfram:

Thank you for your help and review.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午1:52寫道:

Quoted 8 lines · Tyrone Ting
Quoted 6 lines

From: Tali Perry <[email protected]>

tx_complete counter is used to indicate successful transaction count.
Similar counters for failed tx were previously added.

Quoted 8 lines
Quoted 3 lines
Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

I dropped the Fixes tag, doesn't look like a bugfix to me.

Best Regards,
Tyrone

#16 lore raw

PATCH v5 6/10 i2c: npcm: Correct register access width

In reply to Tyrone Ting

From: Tyrone Ting <[email protected]>

The SMBnCTL3 register is 8-bit wide and the 32-bit access was always incorrect, but simply didn't cause a visible error on the 32-bit machine.

On the 64-bit machine, the kernel message reports that ESR value is 0x96000021. Checking Arm Architecture Reference Manual Armv8 suggests that it's the alignment fault.

SMBnCTL3's address is 0xE.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +2 -2
index 36f8aa7ab106..58d7175f0362 100644
@@ -360,14 +360,14 @@ static int npcm_i2c_get_SCL(struct i2c_adapter *_adap)
 {
 	struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap);
 
-	return !!(I2CCTL3_SCL_LVL & ioread32(bus->reg + NPCM_I2CCTL3));
+	return !!(I2CCTL3_SCL_LVL & ioread8(bus->reg + NPCM_I2CCTL3));
 }
 
 static int npcm_i2c_get_SDA(struct i2c_adapter *_adap)
 {
 	struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap);
 
-	return !!(I2CCTL3_SDA_LVL & ioread32(bus->reg + NPCM_I2CCTL3));
+	return !!(I2CCTL3_SDA_LVL & ioread8(bus->reg + NPCM_I2CCTL3));
 }
 
 static inline u16 npcm_i2c_get_index(struct npcm_i2c *bus)
Signature · 1 line
2.17.1
Applied
#17 lore raw

Re: [PATCH v5 06/10] i2c: npcm: Correct register access width

Quoted 9 lines · Tyrone Ting

From: Tyrone Ting <[email protected]>

The SMBnCTL3 register is 8-bit wide and the 32-bit access was always incorrect, but simply didn't cause a visible error on the 32-bit machine.

On the 64-bit machine, the kernel message reports that ESR value is 0x96000021. Checking Arm Architecture Reference Manual Armv8 suggests that it's the alignment fault.

Quoted 5 lines

SMBnCTL3's address is 0xE.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

#18 lore raw

Re: [PATCH v5 06/10] i2c: npcm: Correct register access width

Hi Wolfram:

Thank you for your help.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午1:53寫道:

Quoted 11 lines · Tyrone Ting
Quoted 9 lines

From: Tyrone Ting <[email protected]>

The SMBnCTL3 register is 8-bit wide and the 32-bit access was always incorrect, but simply didn't cause a visible error on the 32-bit machine.

On the 64-bit machine, the kernel message reports that ESR value is 0x96000021. Checking Arm Architecture Reference Manual Armv8 suggests that it's the alignment fault.

Quoted 8 lines
Quoted 5 lines

SMBnCTL3's address is 0xE.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

Best Regards,
Tyrone

#19 lore raw

PATCH v5 7/10 i2c: npcm: Handle spurious interrupts

In reply to Tyrone Ting

From: Tali Perry <[email protected]>

On some platforms in rare cases (1 to 100,000 transactions), the i2c gets a spurious interrupt which means that we enter an interrupt but in the interrupt handler we don't find any status bit that points to the reason we got this interrupt.

This may be a case of a rare HW issue or signal integrity issue that is still under investigation.

In order to overcome this we are doing the following:
1. Disable incoming interrupts in master mode only when slave mode is not enabled.
2. Clear end of busy (EOB) after every interrupt.
3. Clear other status bits (just in case since we found them cleared)
4. Return correct status during the interrupt that will finish the transaction.

On next xmit transaction if the bus is still busy the master will issue a recovery process before issuing the new transaction.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 91 ++++++++++++++++++++++----------
 1 file changed, 62 insertions(+), 29 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +62 -29
index 58d7175f0362..5960ccde6574 100644
@@ -564,6 +564,15 @@ static inline void npcm_i2c_nack(struct npcm_i2c *bus)
 	iowrite8(val, bus->reg + NPCM_I2CCTL1);
 }
 
+static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus)
+{
+	u8 val;
+
+	/* Clear NEGACK, STASTR and BER bits */
+	val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR;
+	iowrite8(val, bus->reg + NPCM_I2CST);
+}
+
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
 static void npcm_i2c_slave_int_enable(struct npcm_i2c *bus, bool enable)
 {
@@ -643,8 +652,8 @@ static void npcm_i2c_reset(struct npcm_i2c *bus)
 	iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
 	iowrite8(0xFF, bus->reg + NPCM_I2CST);
 
-	/* Clear EOB bit */
-	iowrite8(NPCM_I2CCST3_EO_BUSY, bus->reg + NPCM_I2CCST3);
+	/* Clear and disable EOB */
+	npcm_i2c_eob_int(bus, false);
 
 	/* Clear all fifo bits: */
 	iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS);
@@ -656,6 +665,9 @@ static void npcm_i2c_reset(struct npcm_i2c *bus)
 	}
 #endif
 
+	/* clear status bits for spurious interrupts */
+	npcm_i2c_clear_master_status(bus);
+
 	bus->state = I2C_IDLE;
 }
 
@@ -818,15 +830,6 @@ static void npcm_i2c_read_fifo(struct npcm_i2c *bus, u8 bytes_in_fifo)
 	}
 }
 
-static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus)
-{
-	u8 val;
-
-	/* Clear NEGACK, STASTR and BER bits */
-	val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR;
-	iowrite8(val, bus->reg + NPCM_I2CST);
-}
-
 static void npcm_i2c_master_abort(struct npcm_i2c *bus)
 {
 	/* Only current master is allowed to issue a stop condition */
@@ -1234,7 +1237,16 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
 		ret = IRQ_HANDLED;
 	} /* SDAST */
 
-	return ret;
+	/*
+	 * if irq is not one of the above, make sure EOB is disabled and all
+	 * status bits are cleared.
+	 */
+	if (ret == IRQ_NONE) {
+		npcm_i2c_eob_int(bus, false);
+		npcm_i2c_clear_master_status(bus);
+	}
+
+	return IRQ_HANDLED;
 }
 
 static int npcm_i2c_reg_slave(struct i2c_client *client)
@@ -1470,6 +1482,9 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
 		npcm_i2c_eob_int(bus, false);
 		npcm_i2c_master_stop(bus);
 
+		/* Clear SDA Status bit (by reading dummy byte) */
+		npcm_i2c_rd_byte(bus);
+
 		/*
 		 * The bus is released from stall only after the SW clears
 		 * NEGACK bit. Then a Stop condition is sent.
@@ -1477,6 +1492,8 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
 		npcm_i2c_clear_master_status(bus);
 		readx_poll_timeout_atomic(ioread8, bus->reg + NPCM_I2CCST, val,
 					  !(val & NPCM_I2CCST_BUSY), 10, 200);
+		/* verify no status bits are still set after bus is released */
+		npcm_i2c_clear_master_status(bus);
 	}
 	bus->state = I2C_IDLE;
 
@@ -1675,10 +1692,10 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
 	int              iter = 27;
 
 	if ((npcm_i2c_get_SDA(_adap) == 1) && (npcm_i2c_get_SCL(_adap) == 1)) {
-		dev_dbg(bus->dev, "bus%d recovery skipped, bus not stuck",
-			bus->num);
+		dev_dbg(bus->dev, "bus%d-0x%x recovery skipped, bus not stuck",
+			bus->num, bus->dest_addr);
 		npcm_i2c_reset(bus);
-		return status;
+		return 0;
 	}
 
 	npcm_i2c_int_enable(bus, false);
@@ -1912,6 +1929,7 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
 	    bus_freq_hz < I2C_FREQ_MIN_HZ || bus_freq_hz > I2C_FREQ_MAX_HZ)
 		return -EINVAL;
 
+	npcm_i2c_int_enable(bus, false);
 	npcm_i2c_disable(bus);
 
 	/* Configure FIFO mode : */
@@ -1940,10 +1958,17 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
 	val = (val | NPCM_I2CCTL1_NMINTE) & ~NPCM_I2CCTL1_RWS;
 	iowrite8(val, bus->reg + NPCM_I2CCTL1);
 
-	npcm_i2c_int_enable(bus, true);
-
 	npcm_i2c_reset(bus);
 
+	/* check HW is OK: SDA and SCL should be high at this point. */
+	if ((npcm_i2c_get_SDA(&bus->adap) == 0) || (npcm_i2c_get_SCL(&bus->adap) == 0)) {
+		dev_err(bus->dev, "I2C%d init fail: lines are low\n", bus->num);
+		dev_err(bus->dev, "SDA=%d SCL=%d\n", npcm_i2c_get_SDA(&bus->adap),
+			npcm_i2c_get_SCL(&bus->adap));
+		return -ENXIO;
+	}
+
+	npcm_i2c_int_enable(bus, true);
 	return 0;
 }
 
@@ -1991,10 +2016,14 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
 	if (bus->slave) {
 		bus->master_or_slave = I2C_SLAVE;
-		return npcm_i2c_int_slave_handler(bus);
+		if (npcm_i2c_int_slave_handler(bus))
+			return IRQ_HANDLED;
 	}
 #endif
-	return IRQ_NONE;
+	/* clear status bits for spurious interrupts */
+	npcm_i2c_clear_master_status(bus);
+
+	return IRQ_HANDLED;
 }
 
 static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
@@ -2051,7 +2080,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 	u8 *write_data, *read_data;
 	u8 slave_addr;
 	unsigned long timeout;
-	int ret = 0;
 	bool read_block = false;
 	bool read_PEC = false;
 	u8 bus_busy;
@@ -2141,12 +2169,12 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 	bus->read_block_use = read_block;
 
 	reinit_completion(&bus->cmd_complete);
-	if (!npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread,
-					write_data, read_data, read_PEC,
-					read_block))
-		ret = -EBUSY;
 
-	if (ret != -EBUSY) {
+	npcm_i2c_int_enable(bus, true);
+
+	if (npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread,
+				       write_data, read_data, read_PEC,
+				       read_block)) {
 		time_left = wait_for_completion_timeout(&bus->cmd_complete,
 							timeout);
 
@@ -2160,26 +2188,31 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 			}
 		}
 	}
-	ret = bus->cmd_err;
 
 	/* if there was BER, check if need to recover the bus: */
 	if (bus->cmd_err == -EAGAIN)
-		ret = i2c_recover_bus(adap);
+		bus->cmd_err = i2c_recover_bus(adap);
 
 	/*
 	 * After any type of error, check if LAST bit is still set,
 	 * due to a HW issue.
 	 * It cannot be cleared without resetting the module.
 	 */
-	if (bus->cmd_err &&
-	    (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
+	else if (bus->cmd_err &&
+		 (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
 		npcm_i2c_reset(bus);
 
+	/* after any xfer, successful or not, stall and EOB must be disabled */
+	npcm_i2c_stall_after_start(bus, false);
+	npcm_i2c_eob_int(bus, false);
+
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
 	/* reenable slave if it was enabled */
 	if (bus->slave)
 		iowrite8((bus->slave->addr & 0x7F) | NPCM_I2CADDR_SAEN,
 			 bus->reg + NPCM_I2CADDR1);
+#else
+	npcm_i2c_int_enable(bus, false);
 #endif
 	return bus->cmd_err;
 }
Signature · 1 line
2.17.1
Applied
#20 lore raw

Re: [PATCH v5 07/10] i2c: npcm: Handle spurious interrupts

Quoted 18 lines · Tyrone Ting

From: Tali Perry <[email protected]>

On some platforms in rare cases (1 to 100,000 transactions), the i2c gets a spurious interrupt which means that we enter an interrupt but in the interrupt handler we don't find any status bit that points to the reason we got this interrupt.

This may be a case of a rare HW issue or signal integrity issue that is still under investigation.

In order to overcome this we are doing the following:
1. Disable incoming interrupts in master mode only when slave mode is not enabled.
2. Clear end of busy (EOB) after every interrupt.
3. Clear other status bits (just in case since we found them cleared)
4. Return correct status during the interrupt that will finish the transaction.

Quoted 6 lines

On next xmit transaction if the bus is still busy the master will issue a recovery process before issuing the new transaction.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

#21 lore raw

Re: [PATCH v5 07/10] i2c: npcm: Handle spurious interrupts

Hi Wolfram:

Thank you for your review.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午1:53寫道:

Quoted 20 lines · Tyrone Ting
Quoted 18 lines

From: Tali Perry <[email protected]>

On some platforms in rare cases (1 to 100,000 transactions), the i2c gets a spurious interrupt which means that we enter an interrupt but in the interrupt handler we don't find any status bit that points to the reason we got this interrupt.

This may be a case of a rare HW issue or signal integrity issue that is still under investigation.

In order to overcome this we are doing the following:
1. Disable incoming interrupts in master mode only when slave mode is not enabled.
2. Clear end of busy (EOB) after every interrupt.
3. Clear other status bits (just in case since we found them cleared)
4. Return correct status during the interrupt that will finish the transaction.

Quoted 9 lines
Quoted 6 lines

On next xmit transaction if the bus is still busy the master will issue a recovery process before issuing the new transaction.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Applied to for-next, thanks!

Best Regards,
Tyrone

#22 lore raw

PATCH v5 8/10 i2c: npcm: Remove own slave addresses 2:10

In reply to Tyrone Ting

From: Tali Perry <[email protected]>

NPCM can support up to 10 own slave addresses. In practice, only one address is actually being used. In order to access addresses 2 and above, need to switch register banks. The switch needs spinlock.
To avoid using spinlock for this useless feature removed support of SA >=
2. Also fix returned slave event enum.

Remove some comment since the bank selection is not required. The bank selection is not required since the supported slave addresses are reduced.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 43 +++++++++++++++-----------------
 1 file changed, 20 insertions(+), 23 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +20 -23
index 5960ccde6574..3f86895f5e64 100644
@@ -124,6 +124,8 @@ enum i2c_addr {
  * use this array to get the address or each register.
  */
 #define I2C_NUM_OWN_ADDR 10
+#define I2C_NUM_OWN_ADDR_SUPPORTED 2
+
 static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
 	NPCM_I2CADDR1, NPCM_I2CADDR2, NPCM_I2CADDR3, NPCM_I2CADDR4,
 	NPCM_I2CADDR5, NPCM_I2CADDR6, NPCM_I2CADDR7, NPCM_I2CADDR8,
@@ -392,14 +394,10 @@ static void npcm_i2c_disable(struct npcm_i2c *bus)
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
 	int i;
 
-	/* select bank 0 for I2C addresses */
-	npcm_i2c_select_bank(bus, I2C_BANK_0);
-
 	/* Slave addresses removal */
-	for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR; i++)
+	for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR_SUPPORTED; i++)
 		iowrite8(0, bus->reg + npcm_i2caddr[i]);
 
-	npcm_i2c_select_bank(bus, I2C_BANK_1);
 #endif
 	/* Disable module */
 	i2cctl2 = ioread8(bus->reg + NPCM_I2CCTL2);
@@ -604,8 +602,7 @@ static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type,
 			i2cctl1 &= ~NPCM_I2CCTL1_GCMEN;
 		iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1);
 		return 0;
-	}
-	if (addr_type == I2C_ARP_ADDR) {
+	} else if (addr_type == I2C_ARP_ADDR) {
 		i2cctl3 = ioread8(bus->reg + NPCM_I2CCTL3);
 		if (enable)
 			i2cctl3 |= I2CCTL3_ARPMEN;
@@ -614,16 +611,17 @@ static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type,
 		iowrite8(i2cctl3, bus->reg + NPCM_I2CCTL3);
 		return 0;
 	}
+	if (addr_type > I2C_SLAVE_ADDR2 && addr_type <= I2C_SLAVE_ADDR10)
+		dev_err(bus->dev, "try to enable more than 2 SA not supported\n");
+
 	if (addr_type >= I2C_ARP_ADDR)
 		return -EFAULT;
 	/* select bank 0 for address 3 to 10 */
-	if (addr_type > I2C_SLAVE_ADDR2)
-		npcm_i2c_select_bank(bus, I2C_BANK_0);
+
 	/* Set and enable the address */
 	iowrite8(sa_reg, bus->reg + npcm_i2caddr[addr_type]);
 	npcm_i2c_slave_int_enable(bus, enable);
-	if (addr_type > I2C_SLAVE_ADDR2)
-		npcm_i2c_select_bank(bus, I2C_BANK_1);
+
 	return 0;
 }
 #endif
@@ -846,15 +844,11 @@ static u8 npcm_i2c_get_slave_addr(struct npcm_i2c *bus, enum i2c_addr addr_type)
 {
 	u8 slave_add;
 
-	/* select bank 0 for address 3 to 10 */
-	if (addr_type > I2C_SLAVE_ADDR2)
-		npcm_i2c_select_bank(bus, I2C_BANK_0);
+	if (addr_type > I2C_SLAVE_ADDR2 && addr_type <= I2C_SLAVE_ADDR10)
+		dev_err(bus->dev, "get slave: try to use more than 2 SA not supported\n");
 
 	slave_add = ioread8(bus->reg + npcm_i2caddr[(int)addr_type]);
 
-	if (addr_type > I2C_SLAVE_ADDR2)
-		npcm_i2c_select_bank(bus, I2C_BANK_1);
-
 	return slave_add;
 }
 
@@ -864,12 +858,12 @@ static int npcm_i2c_remove_slave_addr(struct npcm_i2c *bus, u8 slave_add)
 
 	/* Set the enable bit */
 	slave_add |= 0x80;
-	npcm_i2c_select_bank(bus, I2C_BANK_0);
-	for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR; i++) {
+
+	for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR_SUPPORTED; i++) {
 		if (ioread8(bus->reg + npcm_i2caddr[i]) == slave_add)
 			iowrite8(0, bus->reg + npcm_i2caddr[i]);
 	}
-	npcm_i2c_select_bank(bus, I2C_BANK_1);
+
 	return 0;
 }
 
@@ -924,11 +918,15 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
 	for (i = 0; i < I2C_HW_FIFO_SIZE; i++) {
 		if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
 			break;
-		i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
+		if (bus->state == I2C_SLAVE_MATCH) {
+			i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
+			bus->state = I2C_OPER_STARTED;
+		} else {
+			i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
+		}
 		ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE;
 		bus->slv_wr_buf[ind] = value;
 		bus->slv_wr_size++;
-		i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
 	}
 	return I2C_HW_FIFO_SIZE - ret;
 }
@@ -976,7 +974,6 @@ static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite,
 	if (nwrite == 0)
 		return;
 
-	bus->state = I2C_OPER_STARTED;
 	bus->operation = I2C_WRITE_OPER;
 
 	/* get the next buffer */
Signature · 1 line
2.17.1
#23 lore raw

Re: [PATCH v5 08/10] i2c: npcm: Remove own slave addresses 2:10

Quoted 6 lines

NPCM can support up to 10 own slave addresses. In practice, only one address is actually being used. In order to access addresses 2 and above, need to switch register banks. The switch needs spinlock.
To avoid using spinlock for this useless feature removed support of SA >=
2. Also fix returned slave event enum.

Is the spinlock contention so high? The code paths do not really look like hot paths to me. A bit sad to see this feature go.

drivers/i2c/busses/i2c-npcm7xx.c enum i2c_addr { · line 131

Quoted 3 lines

static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {

drivers/i2c/busses/i2c-npcm7xx.c +0 -0
 	NPCM_I2CADDR1, NPCM_I2CADDR2, NPCM_I2CADDR3, NPCM_I2CADDR4,
 	NPCM_I2CADDR5, NPCM_I2CADDR6, NPCM_I2CADDR7, NPCM_I2CADDR8,

Why do we keep this array if we drop the support?

drivers/i2c/busses/i2c-npcm7xx.c static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type, · line 605

Quoted 7 lines
drivers/i2c/busses/i2c-npcm7xx.c +1 -2
@@ -604,8 +602,7 @@ static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type,
 			i2cctl1 &= ~NPCM_I2CCTL1_GCMEN;
 		iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1);
 		return 0;
-	}
-	if (addr_type == I2C_ARP_ADDR) {
+	} else if (addr_type == I2C_ARP_ADDR) {

I might be wrong but this looks like a seperate change?

Quoted 19 lines
drivers/i2c/busses/i2c-npcm7xx.c +6 -2
@@ -924,11 +918,15 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
 	for (i = 0; i < I2C_HW_FIFO_SIZE; i++) {
 		if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
 			break;
-		i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
+		if (bus->state == I2C_SLAVE_MATCH) {
+			i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
+			bus->state = I2C_OPER_STARTED;
+		} else {
+			i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
+		}
 		ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE;
 		bus->slv_wr_buf[ind] = value;
 		bus->slv_wr_size++;
-		i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
 	}
 	return I2C_HW_FIFO_SIZE - ret;
 }

drivers/i2c/busses/i2c-npcm7xx.c static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite, · line 977

Quoted 5 lines
drivers/i2c/busses/i2c-npcm7xx.c +0 -1
@@ -976,7 +974,6 @@ static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite,
 	if (nwrite == 0)
 		return;
 
-	bus->state = I2C_OPER_STARTED;
 	bus->operation = I2C_WRITE_OPER;

This is definately a seperate change!

All the best!

maintainer
#24 lore raw

Re: [PATCH v5 08/10] i2c: npcm: Remove own slave addresses 2:10

Quoted 11 lines · Wolfram Sang
Quoted 6 lines

NPCM can support up to 10 own slave addresses. In practice, only one address is actually being used. In order to access addresses 2 and above, need to switch register banks. The switch needs spinlock.
To avoid using spinlock for this useless feature removed support of SA >=
2. Also fix returned slave event enum.

Is the spinlock contention so high? The code paths do not really look like hot paths to me. A bit sad to see this feature go.

The module has two seperate banks, accessible with a bit change. The first one is used
for most of the runtime operations. Second bank is used mostly during init. Unfortunetly, the first two own slave addresses are in the first bank and the other
8 are in the second bank.

Every time the module switchs from master to slave mode, those registers are accessed.
In theory, a spinlock can be used to protect those registers. In practice, none of our customers use the extra addresses. In fact they only need one.

The driver also does not allow you to register more then one slave per bus, so this HW feature was not fully available to begin with.

So when we encounter a deadlock with this spinlock we decided to get rid of this unused feature and get both a stable fix for the issue + performance benefits. We work closely with all our customers so we know that this HW feature is useless to them.

Quoted 6 lines
Quoted 3 lines
 static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
      NPCM_I2CADDR1, NPCM_I2CADDR2, NPCM_I2CADDR3, NPCM_I2CADDR4,
      NPCM_I2CADDR5, NPCM_I2CADDR6, NPCM_I2CADDR7, NPCM_I2CADDR8,

Why do we keep this array if we drop the support?

This array represents the HW so we left it as-is. But I agree it can be shortened to one\two.

Quoted 8 lines

drivers/i2c/busses/i2c-npcm7xx.c static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type, · line 605

Quoted 7 lines
drivers/i2c/busses/i2c-npcm7xx.c +1 -2
@@ -604,8 +602,7 @@ static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type,
                      i2cctl1 &= ~NPCM_I2CCTL1_GCMEN;
              iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1);
              return 0;
-     }
-     if (addr_type == I2C_ARP_ADDR) {
+     } else if (addr_type == I2C_ARP_ADDR) {

addr_type type can be one of several options.
The code was
if (addr_type is 1st option)
...
if (addr_type is 2st option)
...
etc.

Adding that else is more accurate, but ommiting this change works as well.

Quoted 24 lines

I might be wrong but this looks like a seperate change?

Quoted 22 lines
drivers/i2c/busses/i2c-npcm7xx.c +6 -2
@@ -924,11 +918,15 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
      for (i = 0; i < I2C_HW_FIFO_SIZE; i++) {
              if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
                      break;
-             i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
+             if (bus->state == I2C_SLAVE_MATCH) {
+                     i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
+                     bus->state = I2C_OPER_STARTED;
+             } else {
+                     i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
+             }
              ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE;
              bus->slv_wr_buf[ind] = value;
              bus->slv_wr_size++;
-             i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
      }
      return I2C_HW_FIFO_SIZE - ret;
 }
@@ -976,7 +974,6 @@ static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite,
      if (nwrite == 0)
              return;
 
Quoted 5 lines

drivers/i2c/busses/i2c-npcm7xx.c static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite, · line 977

Quoted 2 lines
drivers/i2c/busses/i2c-npcm7xx.c +0 -1
-     bus->state = I2C_OPER_STARTED;
      bus->operation = I2C_WRITE_OPER;

This is definately a seperate change!

OK, we will move the last two to a separate patch. BTW, this change appears in the title as well.

But now I'm not sure: if you already apply for-next patches [1:7], and we change patch [8:10]
do we need to re-submit [1:7]?

Quoted 1 line

All the best!

Thanks, Wolfram, for your review!
Much appreciated

Tali

#25 lore raw

Re: [PATCH v5 08/10] i2c: npcm: Remove own slave addresses 2:10

Hi Tali,

Quoted 4 lines

So when we encounter a deadlock with this spinlock we decided to get rid of this unused feature and get both a stable fix for the issue + performance benefits. We work closely with all our customers so we know that this HW feature is useless to them.

Okay, fair enough. Thanks for the detailed explanation!

Quoted 4 lines
Quoted 2 lines

Why do we keep this array if we drop the support?

This array represents the HW so we left it as-is. But I agree it can be shortened to one\two.

Would be nice, I think.

Quoted 2 lines

OK, we will move the last two to a separate patch. BTW, this change appears in the title as well.

Yes, but I still think it should be a seperate change.

Quoted 3 lines

But now I'm not sure: if you already apply for-next patches [1:7], and we change patch [8:10]
do we need to re-submit [1:7]?

Nope, they are already in linux-next. They seemed like good fixes even without the support for the new SoC, so I applied them right away. I hope this was okay.

Quoted 2 lines

Thanks, Wolfram, for your review!
Much appreciated

You are welcome :)

Happy hacking,

Wolfram

#26 lore raw

PATCH v5 9/10 i2c: npcm: Support NPCM845

In reply to Tyrone Ting

From: Tyrone Ting <[email protected]>

Add NPCM8XX I2C support.
The NPCM8XX uses a similar i2c module as NPCM7XX.
The internal HW FIFO is larger in NPCM8XX.

---
 drivers/i2c/busses/Kconfig       |   8 +--
 drivers/i2c/busses/Makefile      |   2 +-
 drivers/i2c/busses/i2c-npcm7xx.c | 114 +++++++++++++++++++------------
 3 files changed, 76 insertions(+), 48 deletions(-)
drivers/i2c/busses/Kconfig +4 -4
index a1bae59208e3..b1d7069dd377 100644
@@ -838,13 +838,13 @@ config I2C_NOMADIK
 	  I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
 	  as well as the STA2X11 PCIe I/O HUB.
 
-config I2C_NPCM7XX
+config I2C_NPCM
 	tristate "Nuvoton I2C Controller"
-	depends on ARCH_NPCM7XX || COMPILE_TEST
+	depends on ARCH_NPCM || COMPILE_TEST
 	help
 	  If you say yes to this option, support will be included for the
-	  Nuvoton I2C controller, which is available on the NPCM7xx BMC
-	  controller.
+	  Nuvoton I2C controller, which is available on the NPCM BMC
+	  controllers.
 	  Driver can also support slave mode (select I2C_SLAVE).
 
 config I2C_OCORES
drivers/i2c/busses/Makefile +1 -1
index 479f60e4ee3d..b0a10e5d9ee9 100644
@@ -84,7 +84,7 @@ obj-$(CONFIG_I2C_MT7621)	+= i2c-mt7621.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
-obj-$(CONFIG_I2C_NPCM7XX)	+= i2c-npcm7xx.o
+obj-$(CONFIG_I2C_NPCM)		+= i2c-npcm7xx.o
 obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
 obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
 obj-$(CONFIG_I2C_OWL)		+= i2c-owl.o
drivers/i2c/busses/i2c-npcm7xx.c +71 -43

304 lines not on this page · raw message

Signature · 1 line
2.17.1
#27 lore raw

Re: [PATCH v5 09/10] i2c: npcm: Support NPCM845

Quoted 7 lines · Tyrone Ting

From: Tyrone Ting <[email protected]>

Add NPCM8XX I2C support.
The NPCM8XX uses a similar i2c module as NPCM7XX.
The internal HW FIFO is larger in NPCM8XX.

Would be great to get an ack from one of the listed Nuvoton maintainers.

#28 lore raw

Re: [PATCH v5 09/10] i2c: npcm: Support NPCM845

Hi Wolfram:

Thank you for your reminder.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午2:01寫道:

Quoted 12 lines · Tyrone Ting
Quoted 7 lines

From: Tyrone Ting <[email protected]>

Add NPCM8XX I2C support.
The NPCM8XX uses a similar i2c module as NPCM7XX.
The internal HW FIFO is larger in NPCM8XX.

Would be great to get an ack from one of the listed Nuvoton maintainers.

Best Regards,
Tyrone

maintainer Acked-by
#29 lore raw

Re: [PATCH v5 09/10] i2c: npcm: Support NPCM845

Hi Wolfram,

Appreciate your review!

Quoted 14 lines · Tyrone Ting

Hi Wolfram:

Thank you for your reminder.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午2:01寫道:

Quoted 8 lines · Tyrone Ting
Quoted 6 lines

From: Tyrone Ting <[email protected]>

Add NPCM8XX I2C support.
The NPCM8XX uses a similar i2c module as NPCM7XX.
The internal HW FIFO is larger in NPCM8XX.

Quoted 9 lines
Quoted 5 lines
Quoted 1 line

Would be great to get an ack from one of the listed Nuvoton maintainers.

Best Regards,
Tyrone

Best Regards,

Tomer

#30 lore raw

PATCH v5 10/10 i2c: npcm: Capitalize the one-line comment

In reply to Tyrone Ting

From: Tyrone Ting <[email protected]>

Make the one-line comments capital in the driver to get the comment style consistent.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")
---
 drivers/i2c/busses/i2c-npcm7xx.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/i2c/busses/i2c-npcm7xx.c +6 -6
index a032b407f104..a60e392dda50 100644
@@ -683,7 +683,7 @@ static void npcm_i2c_reset(struct npcm_i2c *bus)
 	}
 #endif
 
-	/* clear status bits for spurious interrupts */
+	/* Clear status bits for spurious interrupts */
 	npcm_i2c_clear_master_status(bus);
 
 	bus->state = I2C_IDLE;
@@ -1255,7 +1255,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
 	} /* SDAST */
 
 	/*
-	 * if irq is not one of the above, make sure EOB is disabled and all
+	 * If irq is not one of the above, make sure EOB is disabled and all
 	 * status bits are cleared.
 	 */
 	if (ret == IRQ_NONE) {
@@ -1509,7 +1509,7 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
 		npcm_i2c_clear_master_status(bus);
 		readx_poll_timeout_atomic(ioread8, bus->reg + NPCM_I2CCST, val,
 					  !(val & NPCM_I2CCST_BUSY), 10, 200);
-		/* verify no status bits are still set after bus is released */
+		/* Verify no status bits are still set after bus is released */
 		npcm_i2c_clear_master_status(bus);
 	}
 	bus->state = I2C_IDLE;
@@ -1977,7 +1977,7 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
 
 	npcm_i2c_reset(bus);
 
-	/* check HW is OK: SDA and SCL should be high at this point. */
+	/* Check HW is OK: SDA and SCL should be high at this point. */
 	if ((npcm_i2c_get_SDA(&bus->adap) == 0) || (npcm_i2c_get_SCL(&bus->adap) == 0)) {
 		dev_err(bus->dev, "I2C%d init fail: lines are low\n", bus->num);
 		dev_err(bus->dev, "SDA=%d SCL=%d\n", npcm_i2c_get_SDA(&bus->adap),
@@ -2037,7 +2037,7 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
 			return IRQ_HANDLED;
 	}
 #endif
-	/* clear status bits for spurious interrupts */
+	/* Clear status bits for spurious interrupts */
 	npcm_i2c_clear_master_status(bus);
 
 	return IRQ_HANDLED;
@@ -2219,7 +2219,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 		 (bus->data->rxf_ctl_last_pec & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
 		npcm_i2c_reset(bus);
 
-	/* after any xfer, successful or not, stall and EOB must be disabled */
+	/* After any xfer, successful or not, stall and EOB must be disabled */
 	npcm_i2c_stall_after_start(bus, false);
 	npcm_i2c_eob_int(bus, false);
 
Signature · 1 line
2.17.1
#31 lore raw

Re: [PATCH v5 10/10] i2c: npcm: Capitalize the one-line comment

Quoted 7 lines · Tyrone Ting

From: Tyrone Ting <[email protected]>

Make the one-line comments capital in the driver to get the comment style consistent.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Needs to wait until comments to patches 8+9 are addressed.

#32 lore raw

Re: [PATCH v5 10/10] i2c: npcm: Capitalize the one-line comment

Hi Wolfram:

Got it and thank you for your help.

Wolfram Sang <[email protected]> 於 2022年5月21日 週六 下午2:03寫道:

Quoted 12 lines · Tyrone Ting
Quoted 7 lines

From: Tyrone Ting <[email protected]>

Make the one-line comments capital in the driver to get the comment style consistent.

Fixes 56a1485b102e ("i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver")

Needs to wait until comments to patches 8+9 are addressed.

Best Regards,
Tyrone