summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-at91-master.c78
-rw-r--r--drivers/i2c/busses/i2c-at91.h4
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c33
-rw-r--r--drivers/i2c/busses/i2c-designware-baytrail.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c36
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h2
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c24
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c4
-rw-r--r--drivers/i2c/busses/i2c-imx.c150
-rw-r--r--drivers/i2c/busses/i2c-mxs.c6
-rw-r--r--drivers/i2c/busses/i2c-omap.c4
-rw-r--r--drivers/i2c/busses/i2c-parport.c12
-rw-r--r--drivers/i2c/busses/i2c-powermac.c15
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c58
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c188
-rw-r--r--drivers/i2c/busses/i2c-thunderx-pcidrv.c11
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c10
-rw-r--r--drivers/i2c/i2c-core-smbus.c26
-rw-r--r--drivers/i2c/i2c-dev.c50
-rw-r--r--drivers/i2c/i2c-slave-eeprom.c4
-rw-r--r--drivers/i2c/i2c-smbus.c2
23 files changed, 505 insertions, 220 deletions
diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c
index 7a862e00b475..0aba51a7df32 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -18,11 +18,13 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/pm_runtime.h>
@@ -478,6 +480,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
unsigned long time_left;
bool has_unre_flag = dev->pdata->has_unre_flag;
bool has_alt_cmd = dev->pdata->has_alt_cmd;
+ struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
/*
* WARNING: the TXCOMP bit in the Status Register is NOT a clear on
@@ -637,6 +640,13 @@ error:
at91_twi_write(dev, AT91_TWI_CR,
AT91_TWI_THRCLR | AT91_TWI_LOCKCLR);
}
+
+ if (rinfo->get_sda && !(rinfo->get_sda(&dev->adapter))) {
+ dev_dbg(dev->dev,
+ "SDA is down; clear bus using gpio\n");
+ i2c_recover_bus(&dev->adapter);
+ }
+
return ret;
}
@@ -806,6 +816,70 @@ error:
return ret;
}
+static void at91_prepare_twi_recovery(struct i2c_adapter *adap)
+{
+ struct at91_twi_dev *dev = i2c_get_adapdata(adap);
+
+ pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
+}
+
+static void at91_unprepare_twi_recovery(struct i2c_adapter *adap)
+{
+ struct at91_twi_dev *dev = i2c_get_adapdata(adap);
+
+ pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
+}
+
+static int at91_init_twi_recovery_info(struct platform_device *pdev,
+ struct at91_twi_dev *dev)
+{
+ struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
+
+ dev->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (!dev->pinctrl || IS_ERR(dev->pinctrl)) {
+ dev_info(dev->dev, "can't get pinctrl, bus recovery not supported\n");
+ return PTR_ERR(dev->pinctrl);
+ }
+
+ dev->pinctrl_pins_default = pinctrl_lookup_state(dev->pinctrl,
+ PINCTRL_STATE_DEFAULT);
+ dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl,
+ "gpio");
+ rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
+ if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl",
+ GPIOD_OUT_HIGH_OPEN_DRAIN);
+ if (PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (IS_ERR(rinfo->sda_gpiod) ||
+ IS_ERR(rinfo->scl_gpiod) ||
+ IS_ERR(dev->pinctrl_pins_default) ||
+ IS_ERR(dev->pinctrl_pins_gpio)) {
+ dev_info(&pdev->dev, "recovery information incomplete\n");
+ if (!IS_ERR(rinfo->sda_gpiod)) {
+ gpiod_put(rinfo->sda_gpiod);
+ rinfo->sda_gpiod = NULL;
+ }
+ if (!IS_ERR(rinfo->scl_gpiod)) {
+ gpiod_put(rinfo->scl_gpiod);
+ rinfo->scl_gpiod = NULL;
+ }
+ return -EINVAL;
+ }
+
+ dev_info(&pdev->dev, "using scl, sda for recovery\n");
+
+ rinfo->prepare_recovery = at91_prepare_twi_recovery;
+ rinfo->unprepare_recovery = at91_unprepare_twi_recovery;
+ rinfo->recover_bus = i2c_generic_scl_recovery;
+ dev->adapter.bus_recovery_info = rinfo;
+
+ return 0;
+}
+
int at91_twi_probe_master(struct platform_device *pdev,
u32 phy_addr, struct at91_twi_dev *dev)
{
@@ -838,6 +912,10 @@ int at91_twi_probe_master(struct platform_device *pdev,
"i2c-analog-filter");
at91_calc_twi_clock(dev);
+ rc = at91_init_twi_recovery_info(pdev, dev);
+ if (rc == -EPROBE_DEFER)
+ return rc;
+
dev->adapter.algo = &at91_twi_algorithm;
dev->adapter.quirks = &at91_twi_quirks;
diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h
index 977a67bc0f88..f57a6cab96b4 100644
--- a/drivers/i2c/busses/i2c-at91.h
+++ b/drivers/i2c/busses/i2c-at91.h
@@ -151,6 +151,10 @@ struct at91_twi_dev {
u32 fifo_size;
struct at91_twi_dma dma;
bool slave_detected;
+ struct i2c_bus_recovery_info rinfo;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_pins_default;
+ struct pinctrl_state *pinctrl_pins_gpio;
#ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL
unsigned smr;
struct i2c_client *slave;
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 506991596b68..169a2836922d 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -580,6 +580,31 @@ static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev)
brcmstb_i2c_set_bus_speed(dev);
}
+#define AUTOI2C_CTRL0 0x26c
+#define AUTOI2C_CTRL0_RELEASE_BSC BIT(1)
+
+static int bcm2711_release_bsc(struct brcmstb_i2c_dev *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev->device);
+ struct resource *iomem;
+ void __iomem *autoi2c;
+
+ /* Map hardware registers */
+ iomem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "auto-i2c");
+ autoi2c = devm_ioremap_resource(&pdev->dev, iomem);
+ if (IS_ERR(autoi2c))
+ return PTR_ERR(autoi2c);
+
+ writel(AUTOI2C_CTRL0_RELEASE_BSC, autoi2c + AUTOI2C_CTRL0);
+ devm_iounmap(&pdev->dev, autoi2c);
+
+ /* We need to reset the controller after the release */
+ dev->bsc_regmap->iic_enable = 0;
+ bsc_writel(dev, dev->bsc_regmap->iic_enable, iic_enable);
+
+ return 0;
+}
+
static int brcmstb_i2c_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -609,6 +634,13 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
goto probe_errorout;
}
+ if (of_device_is_compatible(dev->device->of_node,
+ "brcm,bcm2711-hdmi-i2c")) {
+ rc = bcm2711_release_bsc(dev);
+ if (rc)
+ goto probe_errorout;
+ }
+
rc = of_property_read_string(dev->device->of_node, "interrupt-names",
&int_name);
if (rc < 0)
@@ -705,6 +737,7 @@ static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend,
static const struct of_device_id brcmstb_i2c_of_match[] = {
{.compatible = "brcm,brcmstb-i2c"},
{.compatible = "brcm,brcmper-i2c"},
+ {.compatible = "brcm,bcm2711-hdmi-i2c"},
{},
};
MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match);
diff --git a/drivers/i2c/busses/i2c-designware-baytrail.c b/drivers/i2c/busses/i2c-designware-baytrail.c
index 33da07d64494..c6a7a00e1d52 100644
--- a/drivers/i2c/busses/i2c-designware-baytrail.c
+++ b/drivers/i2c/busses/i2c-designware-baytrail.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Intel BayTrail PMIC I2C bus semaphore implementaion
+ * Intel BayTrail PMIC I2C bus semaphore implementation
* Copyright (c) 2014, Intel Corporation.
*/
#include <linux/device.h>
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index 2de7452fcd6d..c70c6fc09ee3 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -102,7 +102,7 @@ int i2c_dw_set_reg_access(struct dw_i2c_dev *dev)
i2c_dw_release_lock(dev);
if (reg == swab32(DW_IC_COMP_TYPE_VALUE)) {
- /* Configure register endianess access */
+ /* Configure register endianness access */
dev->flags |= ACCESS_SWAP;
} else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
/* Configure register access mode 16bit */
@@ -190,10 +190,10 @@ int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
/*
* Workaround for avoiding TX arbitration lost in case I2C
- * slave pulls SDA down "too quickly" after falling egde of
+ * slave pulls SDA down "too quickly" after falling edge of
* SCL by enabling non-zero SDA RX hold. Specification says it
* extends incoming SDA low to high transition while SCL is
- * high but it apprears to help also above issue.
+ * high but it appears to help also above issue.
*/
if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
@@ -344,6 +344,28 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
return -EIO;
}
+void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
+{
+ u32 param, tx_fifo_depth, rx_fifo_depth;
+
+ /*
+ * Try to detect the FIFO depth if not set by interface driver,
+ * the depth could be from 2 to 256 from HW spec.
+ */
+ param = dw_readl(dev, DW_IC_COMP_PARAM_1);
+ tx_fifo_depth = ((param >> 16) & 0xff) + 1;
+ rx_fifo_depth = ((param >> 8) & 0xff) + 1;
+ if (!dev->tx_fifo_depth) {
+ dev->tx_fifo_depth = tx_fifo_depth;
+ dev->rx_fifo_depth = rx_fifo_depth;
+ } else if (tx_fifo_depth >= 2) {
+ dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
+ tx_fifo_depth);
+ dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
+ rx_fifo_depth);
+ }
+}
+
u32 i2c_dw_func(struct i2c_adapter *adap)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
@@ -356,7 +378,7 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
/* Disable controller */
__i2c_dw_disable(dev);
- /* Disable all interupts */
+ /* Disable all interrupts */
dw_writel(dev, 0, DW_IC_INTR_MASK);
dw_readl(dev, DW_IC_CLR_INTR);
}
@@ -366,11 +388,5 @@ void i2c_dw_disable_int(struct dw_i2c_dev *dev)
dw_writel(dev, 0, DW_IC_INTR_MASK);
}
-u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
-{
- return dw_readl(dev, DW_IC_COMP_PARAM_1);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
-
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 67edbbde1070..b220ad64c38d 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -297,6 +297,7 @@ int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
void i2c_dw_release_lock(struct dw_i2c_dev *dev);
int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
+void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
u32 i2c_dw_func(struct i2c_adapter *adap);
void i2c_dw_disable(struct dw_i2c_dev *dev);
void i2c_dw_disable_int(struct dw_i2c_dev *dev);
@@ -313,7 +314,6 @@ static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
void __i2c_dw_disable(struct dw_i2c_dev *dev);
-extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
extern int i2c_dw_probe(struct dw_i2c_dev *dev);
#if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE)
extern int i2c_dw_probe_slave(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index e8b328242256..3a58eef20936 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -521,7 +521,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
- * Ths unmasked raw version of interrupt status bits are available
+ * The unmasked raw version of interrupt status bits is available
* in the IC_RAW_INTR_STAT register.
*
* That is,
@@ -698,6 +698,8 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
if (ret)
return ret;
+ i2c_dw_set_fifo_size(dev);
+
ret = dev->init(dev);
if (ret)
return ret;
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 050adda7c1bd..656206cf9679 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -109,7 +109,7 @@ static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c)
static int mrfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c)
{
/*
- * On Intel Merrifield the user visible i2c busses are enumerated
+ * On Intel Merrifield the user visible i2c buses are enumerated
* [1..7]. So, we add 1 to shift the default range. Besides that the
* first PCI slot provides 4 functions, that's why we have to add 0 to
* the first slot and 4 to the next one.
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3b7d58c2fe85..cb494273bb60 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -219,28 +219,6 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
dev->mode = DW_IC_SLAVE;
}
-static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev)
-{
- u32 param, tx_fifo_depth, rx_fifo_depth;
-
- /*
- * Try to detect the FIFO depth if not set by interface driver,
- * the depth could be from 2 to 256 from HW spec.
- */
- param = i2c_dw_read_comp_param(dev);
- tx_fifo_depth = ((param >> 16) & 0xff) + 1;
- rx_fifo_depth = ((param >> 8) & 0xff) + 1;
- if (!dev->tx_fifo_depth) {
- dev->tx_fifo_depth = tx_fifo_depth;
- dev->rx_fifo_depth = rx_fifo_depth;
- } else if (tx_fifo_depth >= 2) {
- dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
- tx_fifo_depth);
- dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
- rx_fifo_depth);
- }
-}
-
static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
{
pm_runtime_disable(dev->dev);
@@ -362,8 +340,6 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
}
- dw_i2c_set_fifo_size(dev);
-
adap = &dev->adapter;
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_DEPRECATED;
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index f5f001738df5..f5ecf76c0d02 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -107,7 +107,7 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
- * Ths unmasked raw version of interrupt status bits are available
+ * The unmasked raw version of interrupt status bits is available
* in the IC_RAW_INTR_STAT register.
*
* That is,
@@ -260,6 +260,8 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
if (ret)
return ret;
+ i2c_dw_set_fifo_size(dev);
+
ret = dev->init(dev);
if (ret)
return ret;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index a3b61336fe55..775805616ba3 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -414,7 +415,7 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL;
}
-static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
+static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{
unsigned long orig_jiffies = jiffies;
unsigned int temp;
@@ -444,15 +445,37 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
"<%s> I2C bus is busy\n", __func__);
return -ETIMEDOUT;
}
- schedule();
+ if (atomic)
+ udelay(100);
+ else
+ schedule();
}
return 0;
}
-static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
{
- wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
+ if (atomic) {
+ void __iomem *addr = i2c_imx->base + (IMX_I2C_I2SR << i2c_imx->hwdata->regshift);
+ unsigned int regval;
+
+ /*
+ * The formula for the poll timeout is documented in the RM
+ * Rev.5 on page 1878:
+ * T_min = 10/F_scl
+ * Set the value hard as it is done for the non-atomic use-case.
+ * Use 10 kHz for the calculation since this is the minimum
+ * allowed SMBus frequency. Also add an offset of 100us since it
+ * turned out that the I2SR_IIF bit isn't set correctly within
+ * the minimum timeout in polling mode.
+ */
+ readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100);
+ i2c_imx->i2csr = regval;
+ imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
+ } else {
+ wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
+ }
if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
@@ -530,7 +553,7 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
return NOTIFY_OK;
}
-static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic)
{
unsigned int temp = 0;
int result;
@@ -543,23 +566,29 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR);
/* Wait controller to be stable */
- usleep_range(50, 150);
+ if (atomic)
+ udelay(50);
+ else
+ usleep_range(50, 150);
/* Start I2C transaction */
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_MSTA;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- result = i2c_imx_bus_busy(i2c_imx, 1);
+ result = i2c_imx_bus_busy(i2c_imx, 1, atomic);
if (result)
return result;
temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
+ if (atomic)
+ temp &= ~I2CR_IIEN; /* Disable interrupt */
+
temp &= ~I2CR_DMAEN;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
return result;
}
-static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
+static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
{
unsigned int temp = 0;
@@ -581,7 +610,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
}
if (!i2c_imx->stopped)
- i2c_imx_bus_busy(i2c_imx, 0);
+ i2c_imx_bus_busy(i2c_imx, 0, atomic);
/* Disable I2C controller */
temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
@@ -662,7 +691,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
/* The last data byte must be transferred by the CPU. */
imx_i2c_write_reg(msgs->buf[msgs->len-1],
i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx);
+ result = i2c_imx_trx_complete(i2c_imx, false);
if (result)
return result;
@@ -721,7 +750,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
msgs->buf[msgs->len-2] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
/* read n byte data */
- result = i2c_imx_trx_complete(i2c_imx);
+ result = i2c_imx_trx_complete(i2c_imx, false);
if (result)
return result;
@@ -734,7 +763,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- i2c_imx_bus_busy(i2c_imx, 0);
+ i2c_imx_bus_busy(i2c_imx, 0, false);
} else {
/*
* For i2c master receiver repeat restart operation like:
@@ -752,7 +781,8 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
return 0;
}
-static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
+static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
+ bool atomic)
{
int i, result;
@@ -761,7 +791,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
/* write slave address */
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx);
+ result = i2c_imx_trx_complete(i2c_imx, atomic);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -775,7 +805,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
"<%s> write byte: B%d=0x%X\n",
__func__, i, msgs->buf[i]);
imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx);
+ result = i2c_imx_trx_complete(i2c_imx, atomic);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -785,7 +815,8 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
return 0;
}
-static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg)
+static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
+ bool is_lastmsg, bool atomic)
{
int i, result;
unsigned int temp;
@@ -798,7 +829,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
/* write slave address */
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx);
+ result = i2c_imx_trx_complete(i2c_imx, atomic);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -831,7 +862,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
for (i = 0; i < msgs->len; i++) {
u8 len = 0;
- result = i2c_imx_trx_complete(i2c_imx);
+ result = i2c_imx_trx_complete(i2c_imx, atomic);
if (result)
return result;
/*
@@ -859,7 +890,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- i2c_imx_bus_busy(i2c_imx, 0);
+ i2c_imx_bus_busy(i2c_imx, 0, atomic);
} else {
/*
* For i2c master receiver repeat restart operation like:
@@ -890,8 +921,8 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
return 0;
}
-static int i2c_imx_xfer(struct i2c_adapter *adapter,
- struct i2c_msg *msgs, int num)
+static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs, int num, bool atomic)
{
unsigned int i, temp;
int result;
@@ -900,16 +931,16 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
- if (result < 0)
- goto out;
-
/* Start I2C transfer */
- result = i2c_imx_start(i2c_imx);
+ result = i2c_imx_start(i2c_imx, atomic);
if (result) {
- if (i2c_imx->adapter.bus_recovery_info) {
+ /*
+ * Bus recovery uses gpiod_get_value_cansleep() which is not
+ * allowed within atomic context.
+ */
+ if (!atomic && i2c_imx->adapter.bus_recovery_info) {
i2c_recover_bus(&i2c_imx->adapter);
- result = i2c_imx_start(i2c_imx);
+ result = i2c_imx_start(i2c_imx, atomic);
}
}
@@ -927,7 +958,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_RSTA;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- result = i2c_imx_bus_busy(i2c_imx, 1);
+ result = i2c_imx_bus_busy(i2c_imx, 1, atomic);
if (result)
goto fail0;
}
@@ -951,13 +982,14 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
(temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0),
(temp & I2SR_RXAK ? 1 : 0));
#endif
- if (msgs[i].flags & I2C_M_RD)
- result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg);
- else {
- if (i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD)
+ if (msgs[i].flags & I2C_M_RD) {
+ result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic);
+ } else {
+ if (!atomic &&
+ i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD)
result = i2c_imx_dma_write(i2c_imx, &msgs[i]);
else
- result = i2c_imx_write(i2c_imx, &msgs[i]);
+ result = i2c_imx_write(i2c_imx, &msgs[i], atomic);
}
if (result)
goto fail0;
@@ -965,18 +997,49 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
fail0:
/* Stop I2C transfer */
- i2c_imx_stop(i2c_imx);
-
- pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
- pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
+ i2c_imx_stop(i2c_imx, atomic);
-out:
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
return (result < 0) ? result : num;
}
+static int i2c_imx_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs, int num)
+{
+ struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
+ int result;
+
+ result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
+ if (result < 0)
+ return result;
+
+ result = i2c_imx_xfer_common(adapter, msgs, num, false);
+
+ pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
+ pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
+
+ return result;
+}
+
+static int i2c_imx_xfer_atomic(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs, int num)
+{
+ struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
+ int result;
+
+ result = clk_enable(i2c_imx->clk);
+ if (result)
+ return result;
+
+ result = i2c_imx_xfer_common(adapter, msgs, num, true);
+
+ clk_disable(i2c_imx->clk);
+
+ return result;
+}
+
static void i2c_imx_prepare_recovery(struct i2c_adapter *adap)
{
struct imx_i2c_struct *i2c_imx;
@@ -1049,8 +1112,9 @@ static u32 i2c_imx_func(struct i2c_adapter *adapter)
}
static const struct i2c_algorithm i2c_imx_algo = {
- .master_xfer = i2c_imx_xfer,
- .functionality = i2c_imx_func,
+ .master_xfer = i2c_imx_xfer,
+ .master_xfer_atomic = i2c_imx_xfer_atomic,
+ .functionality = i2c_imx_func,
};
static int i2c_imx_probe(struct platform_device *pdev)
@@ -1066,10 +1130,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "<%s>\n", __func__);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "can't get irq number\n");
+ if (irq < 0)
return irq;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 89224913f578..03f5eee9883a 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -836,10 +836,10 @@ static int mxs_i2c_probe(struct platform_device *pdev)
}
/* Setup the DMA */
- i2c->dmach = dma_request_slave_channel(dev, "rx-tx");
- if (!i2c->dmach) {
+ i2c->dmach = dma_request_chan(dev, "rx-tx");
+ if (IS_ERR(i2c->dmach)) {
dev_err(dev, "Failed to request dma\n");
- return -ENODEV;
+ return PTR_ERR(i2c->dmach);
}
platform_set_drvdata(pdev, i2c);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 2dfea357b131..47d994a7c473 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1355,7 +1355,6 @@ omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *omap;
struct i2c_adapter *adap;
- struct resource *mem;
const struct omap_i2c_bus_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct device_node *node = pdev->dev.of_node;
@@ -1375,8 +1374,7 @@ omap_i2c_probe(struct platform_device *pdev)
if (!omap)
return -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- omap->base = devm_ioremap_resource(&pdev->dev, mem);
+ omap->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(omap->base))
return PTR_ERR(omap->base);
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 81eb441b2387..a535889acca6 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -333,13 +333,17 @@ static void i2c_parport_attach(struct parport *port)
/* Setup SMBus alert if supported */
if (adapter_parm[type].smbus_alert) {
- adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
- &adapter->alert_data);
- if (adapter->ara)
+ struct i2c_client *ara;
+