Commit 907537f5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'i2c-for-6.12-rc1-additional_fixes' of...

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
parents b81b78da 26de8614
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -782,6 +782,7 @@ config I2C_JZ4780
config I2C_KEBA
	tristate "KEBA I2C controller support"
	depends on HAS_IOMEM
	depends on KEBA_CP500 || COMPILE_TEST
	select AUXILIARY_BUS
	help
	  This driver supports the I2C controller found in KEBA system FPGA
+14 −0
Original line number Diff line number Diff line
@@ -523,6 +523,7 @@ int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)

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

	abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
	if (abort_needed) {
		if (!(enable & DW_IC_ENABLE_ENABLE)) {
			regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);
			/*
			 * Wait 10 times the signaling period of the highest I2C
			 * transfer supported by the driver (for 400KHz this is
			 * 25us) to ensure the I2C ENABLE bit is already set
			 * as described in the DesignWare I2C databook.
			 */
			fsleep(DIV_ROUND_CLOSEST_ULL(10 * MICRO, t->bus_freq_hz));
			/* Set ENABLE bit before setting ABORT */
			enable |= DW_IC_ENABLE_ENABLE;
		}

		regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
		ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
					       !(enable & DW_IC_ENABLE_ABORT), 10,
+1 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@
						 DW_IC_INTR_RX_UNDER | \
						 DW_IC_INTR_RD_REQ)

#define DW_IC_ENABLE_ENABLE			BIT(0)
#define DW_IC_ENABLE_ABORT			BIT(1)

#define DW_IC_STATUS_ACTIVITY			BIT(0)
+38 −0
Original line number Diff line number Diff line
@@ -271,6 +271,34 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
	__i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
}

/*
 * This function waits for the controller to be idle before disabling I2C
 * When the controller is not in the IDLE state, the MST_ACTIVITY bit
 * (IC_STATUS[5]) is set.
 *
 * Values:
 * 0x1 (ACTIVE): Controller not idle
 * 0x0 (IDLE): Controller is idle
 *
 * The function is called after completing the current transfer.
 *
 * Returns:
 * False when the controller is in the IDLE state.
 * True when the controller is in the ACTIVE state.
 */
static bool i2c_dw_is_controller_active(struct dw_i2c_dev *dev)
{
	u32 status;

	regmap_read(dev->map, DW_IC_STATUS, &status);
	if (!(status & DW_IC_STATUS_MASTER_ACTIVITY))
		return false;

	return regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
				       !(status & DW_IC_STATUS_MASTER_ACTIVITY),
				       1100, 20000) != 0;
}

static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
{
	u32 val;
@@ -806,6 +834,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
		goto done;
	}

	/*
	 * This happens rarely (~1:500) and is hard to reproduce. Debug trace
	 * showed that IC_STATUS had value of 0x23 when STOP_DET occurred,
	 * if disable IC_ENABLE.ENABLE immediately that can result in
	 * IC_RAW_INTR_STAT.MASTER_ON_HOLD holding SCL low. Check if
	 * controller is still ACTIVE before disabling I2C.
	 */
	if (i2c_dw_is_controller_active(dev))
		dev_err(dev->dev, "controller active\n");

	/*
	 * We must disable the adapter before returning and signaling the end
	 * of the current transfer. Otherwise the hardware might continue
+3 −2
Original line number Diff line number Diff line
@@ -550,11 +550,12 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
	device_property_read_u32(&pdev->dev, "socionext,pclk-rate",
				 &i2c->pclkrate);

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

	if (pclk)
		i2c->pclkrate = clk_get_rate(pclk);

	if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE ||
Loading