Commit c8d1a46f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i2c fixes from Wolfram Sang:
 "Another bunch of fixes for I2C.

  Jean's i801 patch is a cleanup on top of Volker's i801 patch, but it
  will make dependency handling much easier if those two go together"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: mxs: use MXS_DMA_CTRL_WAIT4END instead of DMA_CTRL_ACK
  i2c: mediatek: Send i2c master code at more than 1MHz
  i2c: mediatek: Fix generic definitions for bus frequency
  i2c: core: Call i2c_acpi_install_space_handler() before i2c_acpi_register_devices()
  i2c: i801: Simplify the suspend callback
  i2c: i801: Fix resume bug
  i2c: aspeed: Mask IRQ status to relevant bits
parents eb5f95f1 6eb158ec
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
 * These share bit definitions, so use the same values for the enable &
 * status bits.
 */
#define ASPEED_I2CD_INTR_RECV_MASK			0xf000ffff
#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT			BIT(14)
#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE		BIT(13)
#define ASPEED_I2CD_INTR_SLAVE_MATCH			BIT(7)
@@ -604,6 +605,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
	writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
	       bus->base + ASPEED_I2C_INTR_STS_REG);
	readl(bus->base + ASPEED_I2C_INTR_STS_REG);
	irq_received &= ASPEED_I2CD_INTR_RECV_MASK;
	irq_remaining = irq_received;

#if IS_ENABLED(CONFIG_I2C_SLAVE)
+16 −10
Original line number Diff line number Diff line
@@ -1709,6 +1709,16 @@ static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
static inline void i801_acpi_remove(struct i801_priv *priv) { }
#endif

static unsigned char i801_setup_hstcfg(struct i801_priv *priv)
{
	unsigned char hstcfg = priv->original_hstcfg;

	hstcfg &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
	hstcfg |= SMBHSTCFG_HST_EN;
	pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
	return hstcfg;
}

static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
	unsigned char temp;
@@ -1830,14 +1840,10 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
		return err;
	}

	pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
	priv->original_hstcfg = temp;
	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
	if (!(temp & SMBHSTCFG_HST_EN)) {
	pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg);
	temp = i801_setup_hstcfg(priv);
	if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN))
		dev_info(&dev->dev, "Enabling SMBus device\n");
		temp |= SMBHSTCFG_HST_EN;
	}
	pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);

	if (temp & SMBHSTCFG_SMB_SMI_EN) {
		dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
@@ -1952,10 +1958,9 @@ static void i801_shutdown(struct pci_dev *dev)
#ifdef CONFIG_PM_SLEEP
static int i801_suspend(struct device *dev)
{
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct i801_priv *priv = pci_get_drvdata(pci_dev);
	struct i801_priv *priv = dev_get_drvdata(dev);

	pci_write_config_byte(pci_dev, SMBHSTCFG, priv->original_hstcfg);
	pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
	return 0;
}

@@ -1963,6 +1968,7 @@ static int i801_resume(struct device *dev)
{
	struct i801_priv *priv = dev_get_drvdata(dev);

	i801_setup_hstcfg(priv);
	i801_enable_host_notify(&priv->adapter);

	return 0;
+3 −3
Original line number Diff line number Diff line
@@ -681,8 +681,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
	unsigned int cnt_mul;
	int ret = -EINVAL;

	if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ)
		target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ;
	if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ)
		target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ;

	max_step_cnt = mtk_i2c_max_step_cnt(target_speed);
	base_step_cnt = max_step_cnt;
@@ -759,7 +759,7 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
	for (clk_div = 1; clk_div <= max_clk_div; clk_div++) {
		clk_src = parent_clk / clk_div;

		if (target_speed > I2C_MAX_FAST_MODE_FREQ) {
		if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
			/* Set master code speed register */
			ret = mtk_i2c_calculate_speed(i2c, clk_src,
						      I2C_MAX_FAST_MODE_FREQ,
+7 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/of_device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/dma/mxs-dma.h>

#define DRIVER_NAME "mxs-i2c"

@@ -200,7 +201,8 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
		dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
					DMA_MEM_TO_DEV,
					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
					DMA_PREP_INTERRUPT |
					MXS_DMA_CTRL_WAIT4END);
		if (!desc) {
			dev_err(i2c->dev,
				"Failed to get DMA data write descriptor.\n");
@@ -228,7 +230,8 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
		dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
					DMA_DEV_TO_MEM,
					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
					DMA_PREP_INTERRUPT |
					MXS_DMA_CTRL_WAIT4END);
		if (!desc) {
			dev_err(i2c->dev,
				"Failed to get DMA data write descriptor.\n");
@@ -260,7 +263,8 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
		dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
		desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
					DMA_MEM_TO_DEV,
					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
					DMA_PREP_INTERRUPT |
					MXS_DMA_CTRL_WAIT4END);
		if (!desc) {
			dev_err(i2c->dev,
				"Failed to get DMA data write descriptor.\n");
+1 −1
Original line number Diff line number Diff line
@@ -1464,8 +1464,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)

	/* create pre-declared device nodes */
	of_i2c_register_devices(adap);
	i2c_acpi_register_devices(adap);
	i2c_acpi_install_space_handler(adap);
	i2c_acpi_register_devices(adap);

	if (adap->nr < __i2c_first_dynamic_bus_num)
		i2c_scan_static_board_info(adap);