Skip to content

Commit 907537f

Browse files
committed
Merge tag 'i2c-for-6.12-rc1-additional_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: - fix DesignWare driver ENABLE-ABORT sequence, ensuring ABORT can always be sent when needed - check for PCLK in the SynQuacer controller as an optional clock, allowing ACPI to directly provide the clock rate - KEBA driver Kconfig dependency fix - fix XIIC driver power suspend sequence * tag 'i2c-for-6.12-rc1-additional_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: xiic: Fix pm_runtime_set_suspended() with runtime pm enabled i2c: keba: I2C_KEBA should depend on KEBA_CP500 i2c: synquacer: Deal with optional PCLK correctly i2c: designware: fix controller is holding SCL low while ENABLE bit is disabled
2 parents b81b78d + 26de861 commit 907537f

File tree

6 files changed

+58
-3
lines changed

6 files changed

+58
-3
lines changed

drivers/i2c/busses/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ config I2C_JZ4780
782782
config I2C_KEBA
783783
tristate "KEBA I2C controller support"
784784
depends on HAS_IOMEM
785+
depends on KEBA_CP500 || COMPILE_TEST
785786
select AUXILIARY_BUS
786787
help
787788
This driver supports the I2C controller found in KEBA system FPGA

drivers/i2c/busses/i2c-designware-common.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
523523

524524
void __i2c_dw_disable(struct dw_i2c_dev *dev)
525525
{
526+
struct i2c_timings *t = &dev->timings;
526527
unsigned int raw_intr_stats;
527528
unsigned int enable;
528529
int timeout = 100;
@@ -535,6 +536,19 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
535536

536537
abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
537538
if (abort_needed) {
539+
if (!(enable & DW_IC_ENABLE_ENABLE)) {
540+
regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);
541+
/*
542+
* Wait 10 times the signaling period of the highest I2C
543+
* transfer supported by the driver (for 400KHz this is
544+
* 25us) to ensure the I2C ENABLE bit is already set
545+
* as described in the DesignWare I2C databook.
546+
*/
547+
fsleep(DIV_ROUND_CLOSEST_ULL(10 * MICRO, t->bus_freq_hz));
548+
/* Set ENABLE bit before setting ABORT */
549+
enable |= DW_IC_ENABLE_ENABLE;
550+
}
551+
538552
regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
539553
ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
540554
!(enable & DW_IC_ENABLE_ABORT), 10,

drivers/i2c/busses/i2c-designware-core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
DW_IC_INTR_RX_UNDER | \
109109
DW_IC_INTR_RD_REQ)
110110

111+
#define DW_IC_ENABLE_ENABLE BIT(0)
111112
#define DW_IC_ENABLE_ABORT BIT(1)
112113

113114
#define DW_IC_STATUS_ACTIVITY BIT(0)

drivers/i2c/busses/i2c-designware-master.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,34 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
271271
__i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
272272
}
273273

274+
/*
275+
* This function waits for the controller to be idle before disabling I2C
276+
* When the controller is not in the IDLE state, the MST_ACTIVITY bit
277+
* (IC_STATUS[5]) is set.
278+
*
279+
* Values:
280+
* 0x1 (ACTIVE): Controller not idle
281+
* 0x0 (IDLE): Controller is idle
282+
*
283+
* The function is called after completing the current transfer.
284+
*
285+
* Returns:
286+
* False when the controller is in the IDLE state.
287+
* True when the controller is in the ACTIVE state.
288+
*/
289+
static bool i2c_dw_is_controller_active(struct dw_i2c_dev *dev)
290+
{
291+
u32 status;
292+
293+
regmap_read(dev->map, DW_IC_STATUS, &status);
294+
if (!(status & DW_IC_STATUS_MASTER_ACTIVITY))
295+
return false;
296+
297+
return regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
298+
!(status & DW_IC_STATUS_MASTER_ACTIVITY),
299+
1100, 20000) != 0;
300+
}
301+
274302
static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
275303
{
276304
u32 val;
@@ -806,6 +834,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
806834
goto done;
807835
}
808836

837+
/*
838+
* This happens rarely (~1:500) and is hard to reproduce. Debug trace
839+
* showed that IC_STATUS had value of 0x23 when STOP_DET occurred,
840+
* if disable IC_ENABLE.ENABLE immediately that can result in
841+
* IC_RAW_INTR_STAT.MASTER_ON_HOLD holding SCL low. Check if
842+
* controller is still ACTIVE before disabling I2C.
843+
*/
844+
if (i2c_dw_is_controller_active(dev))
845+
dev_err(dev->dev, "controller active\n");
846+
809847
/*
810848
* We must disable the adapter before returning and signaling the end
811849
* of the current transfer. Otherwise the hardware might continue

drivers/i2c/busses/i2c-synquacer.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,12 +550,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
550550
device_property_read_u32(&pdev->dev, "socionext,pclk-rate",
551551
&i2c->pclkrate);
552552

553-
pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
553+
pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
554554
if (IS_ERR(pclk))
555555
return dev_err_probe(&pdev->dev, PTR_ERR(pclk),
556556
"failed to get and enable clock\n");
557557

558-
i2c->pclkrate = clk_get_rate(pclk);
558+
if (pclk)
559+
i2c->pclkrate = clk_get_rate(pclk);
559560

560561
if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE ||
561562
i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE)

drivers/i2c/busses/i2c-xiic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,8 +1337,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
13371337
return 0;
13381338

13391339
err_pm_disable:
1340-
pm_runtime_set_suspended(&pdev->dev);
13411340
pm_runtime_disable(&pdev->dev);
1341+
pm_runtime_set_suspended(&pdev->dev);
13421342

13431343
return ret;
13441344
}

0 commit comments

Comments
 (0)