Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f5de42d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i2c fixes from Wolfram Sang:
 "I2C has some bugfixes for you: mainly Jarkko fixed up a few things in
  the designware driver regarding the new slave mode. But Ulf also fixed
  a long-standing and now agreed suspend problem. Plus, some simple
  stuff which nonetheless needs fixing"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: designware: Fix runtime PM for I2C slave mode
  i2c: designware: Remove needless pm_runtime_put_noidle() call
  i2c: aspeed: fixed potential null pointer dereference
  i2c: simtec: use release_mem_region instead of release_resource
  i2c: core: Make comment about I2C table requirement to reflect the code
  i2c: designware: Fix standard mode speed when configuring the slave mode
  i2c: designware: Fix oops from i2c_dw_irq_handler_slave
  i2c: designware: Fix system suspend
parents 299c4608 2a86cdd2
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -410,9 +410,10 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
	}
	}


	/* We are in an invalid state; reset bus to a known state. */
	/* We are in an invalid state; reset bus to a known state. */
	if (!bus->msgs && bus->master_state != ASPEED_I2C_MASTER_STOP) {
	if (!bus->msgs) {
		dev_err(bus->dev, "bus in unknown state");
		dev_err(bus->dev, "bus in unknown state");
		bus->cmd_err = -EIO;
		bus->cmd_err = -EIO;
		if (bus->master_state != ASPEED_I2C_MASTER_STOP)
			aspeed_i2c_do_stop(bus);
			aspeed_i2c_do_stop(bus);
		goto out_no_complete;
		goto out_no_complete;
	}
	}
+13 −4
Original line number Original line Diff line number Diff line
@@ -198,8 +198,7 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
	dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY;
	dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY;


	dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
	dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
			 DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED |
			 DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;
			 DW_IC_CON_SPEED_FAST;


	dev->mode = DW_IC_SLAVE;
	dev->mode = DW_IC_SLAVE;


@@ -430,7 +429,7 @@ static void dw_i2c_plat_complete(struct device *dev)
#endif
#endif


#ifdef CONFIG_PM
#ifdef CONFIG_PM
static int dw_i2c_plat_suspend(struct device *dev)
static int dw_i2c_plat_runtime_suspend(struct device *dev)
{
{
	struct platform_device *pdev = to_platform_device(dev);
	struct platform_device *pdev = to_platform_device(dev);
	struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
	struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
@@ -452,11 +451,21 @@ static int dw_i2c_plat_resume(struct device *dev)
	return 0;
	return 0;
}
}


#ifdef CONFIG_PM_SLEEP
static int dw_i2c_plat_suspend(struct device *dev)
{
	pm_runtime_resume(dev);
	return dw_i2c_plat_runtime_suspend(dev);
}
#endif

static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
	.prepare = dw_i2c_plat_prepare,
	.prepare = dw_i2c_plat_prepare,
	.complete = dw_i2c_plat_complete,
	.complete = dw_i2c_plat_complete,
	SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
	SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
	SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
	SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend,
			   dw_i2c_plat_resume,
			   NULL)
};
};


#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
+4 −2
Original line number Original line Diff line number Diff line
@@ -177,6 +177,8 @@ static int i2c_dw_reg_slave(struct i2c_client *slave)
		return -EBUSY;
		return -EBUSY;
	if (slave->flags & I2C_CLIENT_TEN)
	if (slave->flags & I2C_CLIENT_TEN)
		return -EAFNOSUPPORT;
		return -EAFNOSUPPORT;
	pm_runtime_get_sync(dev->dev);

	/*
	/*
	 * Set slave address in the IC_SAR register,
	 * Set slave address in the IC_SAR register,
	 * the address to which the DW_apb_i2c responds.
	 * the address to which the DW_apb_i2c responds.
@@ -205,6 +207,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
	dev->disable_int(dev);
	dev->disable_int(dev);
	dev->disable(dev);
	dev->disable(dev);
	dev->slave = NULL;
	dev->slave = NULL;
	pm_runtime_put(dev->dev);


	return 0;
	return 0;
}
}
@@ -272,7 +275,7 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
	slave_activity = ((dw_readl(dev, DW_IC_STATUS) &
	slave_activity = ((dw_readl(dev, DW_IC_STATUS) &
		DW_IC_STATUS_SLAVE_ACTIVITY) >> 6);
		DW_IC_STATUS_SLAVE_ACTIVITY) >> 6);


	if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY))
	if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave)
		return 0;
		return 0;


	dev_dbg(dev->dev,
	dev_dbg(dev->dev,
@@ -382,7 +385,6 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
	ret = i2c_add_numbered_adapter(adap);
	ret = i2c_add_numbered_adapter(adap);
	if (ret)
	if (ret)
		dev_err(dev->dev, "failure adding adapter: %d\n", ret);
		dev_err(dev->dev, "failure adding adapter: %d\n", ret);
	pm_runtime_put_noidle(dev->dev);


	return ret;
	return ret;
}
}
+2 −4
Original line number Original line Diff line number Diff line
@@ -127,8 +127,7 @@ static int simtec_i2c_probe(struct platform_device *dev)
	iounmap(pd->reg);
	iounmap(pd->reg);


 err_res:
 err_res:
	release_resource(pd->ioarea);
	release_mem_region(pd->ioarea->start, size);
	kfree(pd->ioarea);


 err:
 err:
	kfree(pd);
	kfree(pd);
@@ -142,8 +141,7 @@ static int simtec_i2c_remove(struct platform_device *dev)
	i2c_del_adapter(&pd->adap);
	i2c_del_adapter(&pd->adap);


	iounmap(pd->reg);
	iounmap(pd->reg);
	release_resource(pd->ioarea);
	release_mem_region(pd->ioarea->start, resource_size(pd->ioarea));
	kfree(pd->ioarea);
	kfree(pd);
	kfree(pd);


	return 0;
	return 0;
+2 −2
Original line number Original line Diff line number Diff line
@@ -353,8 +353,8 @@ static int i2c_device_probe(struct device *dev)
	}
	}


	/*
	/*
	 * An I2C ID table is not mandatory, if and only if, a suitable Device
	 * An I2C ID table is not mandatory, if and only if, a suitable OF
	 * Tree match table entry is supplied for the probing device.
	 * or ACPI ID table is supplied for the probing device.
	 */
	 */
	if (!driver->id_table &&
	if (!driver->id_table &&
	    !i2c_acpi_match_device(dev->driver->acpi_match_table, client) &&
	    !i2c_acpi_match_device(dev->driver->acpi_match_table, client) &&