summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-23 16:45:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-23 16:45:17 -0700
commite8df5a0c0d041588e7f02781822d637d226cdbe8 (patch)
treeaeb7d43c945caf4bd87c6d2c9945e67cd24545af /drivers
parent5fb4fde3b287fdd9097c53fee7126c2f74698073 (diff)
parent79fc229e8a471356ddfea225f42e02f4fb73c469 (diff)
Merge tag 'i2c-for-7.1-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull more i2c updates from Wolfram Sang: - cx92755: convert I2C bindings to DT schema - mediatek: add optional bus power management during transfers - pxa: handle early bus busy condition - MAINTAINERS: update I2C RUST entry * tag 'i2c-for-7.1-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: MAINTAINERS: add Rust I2C tree and update Igor Korotin's email i2c: mediatek: add bus regulator control for power saving dt-bindings: i2c: cnxt,cx92755-i2c: Convert to DT schema i2c: pxa: handle 'Early Bus Busy' condition on Armada 3700
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c13
-rw-r--r--drivers/i2c/busses/i2c-pxa.c18
2 files changed, 24 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index cb4d3aa709d0..126040ca05f1 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -1244,9 +1245,15 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
bool write_then_read_en = false;
struct mtk_i2c *i2c = i2c_get_adapdata(adap);
+ if (i2c->adap.bus_regulator) {
+ ret = regulator_enable(i2c->adap.bus_regulator);
+ if (ret)
+ return ret;
+ }
+
ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
if (ret)
- return ret;
+ goto err_regulator;
i2c->auto_restart = i2c->dev_comp->auto_restart;
@@ -1301,6 +1308,10 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
err_exit:
clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+err_regulator:
+ if (i2c->adap.bus_regulator)
+ regulator_disable(i2c->adap.bus_regulator);
+
return ret;
}
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index f55840b2eb9a..9a8b154ab69e 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -71,6 +71,7 @@
#define ISR_GCAD (1 << 8) /* general call address detected */
#define ISR_SAD (1 << 9) /* slave address detected */
#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
+#define ISR_A3700_EBB (1 << 11) /* early bus busy for armada 3700 */
#define ILCR_SLV_SHIFT 0
#define ILCR_SLV_MASK (0x1FF << ILCR_SLV_SHIFT)
@@ -263,6 +264,7 @@ struct pxa_i2c {
bool highmode_enter;
u32 fm_mask;
u32 hs_mask;
+ u32 busy_mask;
struct i2c_bus_recovery_info recovery;
struct pinctrl *pinctrl;
@@ -430,7 +432,7 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
while (1) {
isr = readl(_ISR(i2c));
- if (!(isr & (ISR_IBB | ISR_UB)))
+ if (!(isr & i2c->busy_mask))
return 0;
if (isr & ISR_SAD)
@@ -467,7 +469,7 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
* quick check of the i2c lines themselves to ensure they've
* gone high...
*/
- if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 &&
+ if ((readl(_ISR(i2c)) & i2c->busy_mask) == 0 &&
readl(_IBMR(i2c)) == (IBMR_SCLS | IBMR_SDAS)) {
if (i2c_debug > 0)
dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
@@ -488,7 +490,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
if (i2c_debug)
dev_dbg(&i2c->adap.dev, "setting to bus master\n");
- if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) {
+ if ((readl(_ISR(i2c)) & i2c->busy_mask) != 0) {
dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
if (!i2c_pxa_wait_master(i2c)) {
dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
@@ -514,7 +516,7 @@ static int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
__func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
- if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 ||
+ if ((readl(_ISR(i2c)) & i2c->busy_mask) == 0 ||
(readl(_ISR(i2c)) & ISR_SAD) != 0 ||
(readl(_ICR(i2c)) & ICR_SCLE) == 0) {
if (i2c_debug > 1)
@@ -1177,7 +1179,7 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
/*
* Wait for the bus to become free.
*/
- while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB))
+ while (timeout-- && readl(_ISR(i2c)) & i2c->busy_mask)
udelay(1000);
if (timeout < 0) {
@@ -1322,7 +1324,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
* handing control of the bus back to avoid the bus changing state.
*/
isr = readl(_ISR(i2c));
- if (isr & (ISR_UB | ISR_IBB)) {
+ if (isr & i2c->busy_mask) {
dev_dbg(&i2c->adap.dev,
"recovery: resetting controller, ISR=0x%08x\n", isr);
i2c_pxa_do_reset(i2c);
@@ -1479,6 +1481,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->fm_mask = pxa_reg_layout[i2c_type].fm;
i2c->hs_mask = pxa_reg_layout[i2c_type].hs;
+ i2c->busy_mask = ISR_UB | ISR_IBB;
+ if (i2c_type == REGS_A3700)
+ i2c->busy_mask |= ISR_A3700_EBB;
+
if (i2c_type != REGS_CE4100)
i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;