aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/busses/Kconfig16
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-imx.c92
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c7
-rw-r--r--drivers/i2c/busses/i2c-xlr.c470
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c53
6 files changed, 84 insertions, 555 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index dce392839017..2f0a440ec446 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -1159,22 +1159,12 @@ config I2C_XILINX
This driver can also be built as a module. If so, the module
will be called xilinx_i2c.
-config I2C_XLR
- tristate "Netlogic XLR I2C support"
- depends on CPU_XLR || COMPILE_TEST
- help
- This driver enables support for the on-chip I2C interface of
- the Netlogic XLR/XLS MIPS processors and Sigma Designs SOCs.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-xlr.
-
config I2C_XLP9XX
- tristate "XLP9XX I2C support"
- depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST
+ tristate "Cavium ThunderX2 I2C support"
+ depends on ARCH_THUNDER2 || COMPILE_TEST
help
This driver enables support for the on-chip I2C interface of
- the Broadcom XLP9xx/XLP5xx MIPS and Vulcan ARM64 processors.
+ the Cavium ThunderX2 processors. (Originally on Netlogic XLP SoCs.)
This driver can also be built as a module. If so, the module will
be called i2c-xlp9xx.
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index d85899fef8c7..1d00dce77098 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -119,7 +119,6 @@ obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o
obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o
obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
-obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o
obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 3576b63a6c03..27f969b3dc07 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -37,6 +37,8 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -51,6 +53,8 @@
/* This will be the driver name the kernel reports */
#define DRIVER_NAME "imx-i2c"
+#define I2C_IMX_CHECK_DELAY 30000 /* Time to check for bus idle, in NS */
+
/*
* Enable DMA if transfer byte size is bigger than this threshold.
* As the hardware request, it must bigger than 4 bytes.\
@@ -210,6 +214,10 @@ struct imx_i2c_struct {
struct imx_i2c_dma *dma;
struct i2c_client *slave;
enum i2c_slave_event last_slave_event;
+
+ /* For checking slave events. */
+ spinlock_t slave_lock;
+ struct hrtimer slave_timer;
};
static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
@@ -680,7 +688,7 @@ static void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx,
static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)
{
- u8 val;
+ u8 val = 0;
while (i2c_imx->last_slave_event != I2C_SLAVE_STOP) {
switch (i2c_imx->last_slave_event) {
@@ -701,10 +709,11 @@ static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)
}
}
-static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
- unsigned int status, unsigned int ctl)
+/* Returns true if the timer should be restarted, false if not. */
+static irqreturn_t i2c_imx_slave_handle(struct imx_i2c_struct *i2c_imx,
+ unsigned int status, unsigned int ctl)
{
- u8 value;
+ u8 value = 0;
if (status & I2SR_IAL) { /* Arbitration lost */
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
@@ -712,6 +721,16 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
return IRQ_HANDLED;
}
+ if (!(status & I2SR_IBB)) {
+ /* No master on the bus, that could mean a stop condition. */
+ i2c_imx_slave_finish_op(i2c_imx);
+ return IRQ_HANDLED;
+ }
+
+ if (!(status & I2SR_ICF))
+ /* Data transfer still in progress, ignore this. */
+ goto out;
+
if (status & I2SR_IAAS) { /* Addressed as a slave */
i2c_imx_slave_finish_op(i2c_imx);
if (status & I2SR_SRW) { /* Master wants to read from us*/
@@ -737,16 +756,9 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
}
} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
- if (status & I2SR_IBB) { /* No STOP signal detected */
- value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
- i2c_imx_slave_event(i2c_imx,
- I2C_SLAVE_WRITE_RECEIVED, &value);
- } else { /* STOP signal is detected */
- dev_dbg(&i2c_imx->adapter.dev,
- "STOP signal detected");
- i2c_imx_slave_event(i2c_imx,
- I2C_SLAVE_STOP, &value);
- }
+ value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+ i2c_imx_slave_event(i2c_imx,
+ I2C_SLAVE_WRITE_RECEIVED, &value);
} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */
ctl |= I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
@@ -755,15 +767,43 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
I2C_SLAVE_READ_PROCESSED, &value);
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
- } else { /* Transmit mode received NAK */
+ } else { /* Transmit mode received NAK, operation is done */
ctl &= ~I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+ i2c_imx_slave_finish_op(i2c_imx);
+ return IRQ_HANDLED;
}
+out:
+ /*
+ * No need to check the return value here. If it returns 0 or
+ * 1, then everything is fine. If it returns -1, then the
+ * timer is running in the handler. This will still work,
+ * though it may be redone (or already have been done) by the
+ * timer function.
+ */
+ hrtimer_try_to_cancel(&i2c_imx->slave_timer);
+ hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY);
+ hrtimer_restart(&i2c_imx->slave_timer);
return IRQ_HANDLED;
}
+static enum hrtimer_restart i2c_imx_slave_timeout(struct hrtimer *t)
+{
+ struct imx_i2c_struct *i2c_imx = container_of(t, struct imx_i2c_struct,
+ slave_timer);
+ unsigned int ctl, status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2c_imx->slave_lock, flags);
+ status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+ ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ i2c_imx_slave_handle(i2c_imx, status, ctl);
+ spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);
+ return HRTIMER_NORESTART;
+}
+
static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)
{
int temp;
@@ -843,7 +883,9 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
{
struct imx_i2c_struct *i2c_imx = dev_id;
unsigned int ctl, status;
+ unsigned long flags;
+ spin_lock_irqsave(&i2c_imx->slave_lock, flags);
status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
@@ -851,14 +893,20 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
if (i2c_imx->slave) {
if (!(ctl & I2CR_MSTA)) {
- return i2c_imx_slave_isr(i2c_imx, status, ctl);
- } else if (i2c_imx->last_slave_event !=
- I2C_SLAVE_STOP) {
- i2c_imx_slave_finish_op(i2c_imx);
+ irqreturn_t ret;
+
+ ret = i2c_imx_slave_handle(i2c_imx,
+ status, ctl);
+ spin_unlock_irqrestore(&i2c_imx->slave_lock,
+ flags);
+ return ret;
}
+ i2c_imx_slave_finish_op(i2c_imx);
}
+ spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);
return i2c_imx_master_isr(i2c_imx, status);
}
+ spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);
return IRQ_NONE;
}
@@ -1378,6 +1426,10 @@ static int i2c_imx_probe(struct platform_device *pdev)
if (!i2c_imx)
return -ENOMEM;
+ spin_lock_init(&i2c_imx->slave_lock);
+ hrtimer_init(&i2c_imx->slave_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ i2c_imx->slave_timer.function = i2c_imx_slave_timeout;
+
match = device_get_match_data(&pdev->dev);
if (match)
i2c_imx->hwdata = match;
@@ -1491,6 +1543,8 @@ static int i2c_imx_remove(struct platform_device *pdev)
if (ret < 0)
return ret;
+ hrtimer_cancel(&i2c_imx->slave_timer);
+
/* remove adapter */
dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
i2c_del_adapter(&i2c_imx->adapter);
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index 6d24dc385522..4e3b11c0f732 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -572,12 +572,6 @@ static int xlp9xx_i2c_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id xlp9xx_i2c_of_match[] = {
- { .compatible = "netlogic,xlp980-i2c", },
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, xlp9xx_i2c_of_match);
-
#ifdef CONFIG_ACPI
static const struct acpi_device_id xlp9xx_i2c_acpi_ids[] = {
{"BRCM9007", 0},
@@ -592,7 +586,6 @@ static struct platform_driver xlp9xx_i2c_driver = {
.remove = xlp9xx_i2c_remove,
.driver = {
.name = "xlp9xx-i2c",
- .of_match_table = xlp9xx_i2c_of_match,
.acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids),
},
};
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
deleted file mode 100644
index 9ce20652d494..000000000000
--- a/drivers/i2c/busses/i2c-xlr.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright 2011, Netlogic Microsystems Inc.
- * Copyright 2004, Matt Porter <[email protected]>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_device.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-
-/* XLR I2C REGISTERS */
-#define XLR_I2C_CFG 0x00
-#define XLR_I2C_CLKDIV 0x01
-#define XLR_I2C_DEVADDR 0x02
-#define XLR_I2C_ADDR 0x03
-#define XLR_I2C_DATAOUT 0x04
-#define XLR_I2C_DATAIN 0x05
-#define XLR_I2C_STATUS 0x06
-#define XLR_I2C_STARTXFR 0x07
-#define XLR_I2C_BYTECNT 0x08
-#define XLR_I2C_HDSTATIM 0x09
-
-/* Sigma Designs additional registers */
-#define XLR_I2C_INT_EN 0x09
-#define XLR_I2C_INT_STAT 0x0a
-
-/* XLR I2C REGISTERS FLAGS */
-#define XLR_I2C_BUS_BUSY 0x01
-#define XLR_I2C_SDOEMPTY 0x02
-#define XLR_I2C_RXRDY 0x04
-#define XLR_I2C_ACK_ERR 0x08
-#define XLR_I2C_ARB_STARTERR 0x30
-
-/* Register Values */
-#define XLR_I2C_CFG_ADDR 0xF8
-#define XLR_I2C_CFG_NOADDR 0xFA
-#define XLR_I2C_STARTXFR_ND 0x02 /* No Data */
-#define XLR_I2C_STARTXFR_RD 0x01 /* Read */
-#define XLR_I2C_STARTXFR_WR 0x00 /* Write */
-
-#define XLR_I2C_TIMEOUT 10 /* timeout per byte in msec */
-
-/*
- * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
- * because they are in the big-endian MMIO area on the SoC.
- *
- * The readl/writel implementation on XLR/XLS byteswaps, because
- * those are for its little-endian PCI space (see arch/mips/Kconfig).
- */
-static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
-{
- __raw_writel(val, base + reg);
-}
-
-static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
-{
- return __raw_readl(base + reg);
-}
-
-#define XLR_I2C_FLAG_IRQ 1
-
-struct xlr_i2c_config {
- u32 flags; /* optional feature support */
- u32 status_busy; /* value of STATUS[0] when busy */
- u32 cfg_extra; /* extra CFG bits to set */
-};
-
-struct xlr_i2c_private {
- struct i2c_adapter adap;
- u32 __iomem *iobase;
- int irq;
- int pos;
- struct i2c_msg *msg;
- const struct xlr_i2c_config *cfg;
- wait_queue_head_t wait;
- struct clk *clk;
-};
-
-static int xlr_i2c_busy(struct xlr_i2c_private *priv, u32 status)
-{
- return (status & XLR_I2C_BUS_BUSY) == priv->cfg->status_busy;
-}
-
-static int xlr_i2c_idle(struct xlr_i2c_private *priv)
-{
- return !xlr_i2c_busy(priv, xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS));
-}
-
-static int xlr_i2c_wait(struct xlr_i2c_private *priv, unsigned long timeout)
-{
- int status;
- int t;
-
- t = wait_event_timeout(priv->wait, xlr_i2c_idle(priv),
- msecs_to_jiffies(timeout));
- if (!t)
- return -ETIMEDOUT;
-
- status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
-
- return status & XLR_I2C_ACK_ERR ? -EIO : 0;
-}
-
-static void xlr_i2c_tx_irq(struct xlr_i2c_private *priv, u32 status)
-{
- struct i2c_msg *msg = priv->msg;
-
- if (status & XLR_I2C_SDOEMPTY)
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT,
- msg->buf[priv->pos++]);
-}
-
-static void xlr_i2c_rx_irq(struct xlr_i2c_private *priv, u32 status)
-{
- struct i2c_msg *msg = priv->msg;
-
- if (status & XLR_I2C_RXRDY)
- msg->buf[priv->pos++] =
- xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
-}
-
-static irqreturn_t xlr_i2c_irq(int irq, void *dev_id)
-{
- struct xlr_i2c_private *priv = dev_id;
- struct i2c_msg *msg = priv->msg;
- u32 int_stat, status;
-
- int_stat = xlr_i2c_rdreg(priv->iobase, XLR_I2C_INT_STAT);
- if (!int_stat)
- return IRQ_NONE;
-
- xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, int_stat);
-
- if (!msg)
- return IRQ_HANDLED;
-
- status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
-
- if (priv->pos < msg->len) {
- if (msg->flags & I2C_M_RD)
- xlr_i2c_rx_irq(priv, status);
- else
- xlr_i2c_tx_irq(priv, status);
- }
-
- if (!xlr_i2c_busy(priv, status))
- wake_up(&priv->wait);
-
- return IRQ_HANDLED;
-}
-
-static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
- u8 *buf, u16 addr)
-{
- struct i2c_adapter *adap = &priv->adap;
- unsigned long timeout, stoptime, checktime;
- u32 i2c_status;
- int pos, timedout;
- u8 offset;
- u32 xfer;
-
- offset = buf[0];
- xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
- XLR_I2C_CFG_ADDR | priv->cfg->cfg_extra);
-
- timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
- stoptime = jiffies + timeout;
- timedout = 0;
-
- if (len == 1) {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
- xfer = XLR_I2C_STARTXFR_ND;
- pos = 1;
- } else {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 2);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[1]);
- xfer = XLR_I2C_STARTXFR_WR;
- pos = 2;
- }
-
- priv->pos = pos;
-
-retry:
- /* retry can only happen on the first byte */
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, xfer);
-
- if (priv->irq > 0)
- return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
-
- while (!timedout) {
- checktime = jiffies;
- i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
-
- if ((i2c_status & XLR_I2C_SDOEMPTY) && pos < len) {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos++]);
-
- /* reset timeout on successful xmit */
- stoptime = jiffies + timeout;
- }
- timedout = time_after(checktime, stoptime);
-
- if (i2c_status & XLR_I2C_ARB_STARTERR) {
- if (timedout)
- break;
- goto retry;
- }
-
- if (i2c_status & XLR_I2C_ACK_ERR)
- return -EIO;
-
- if (!xlr_i2c_busy(priv, i2c_status) && pos >= len)
- return 0;
- }
- dev_err(&adap->dev, "I2C transmit timeout\n");
- return -ETIMEDOUT;
-}
-
-static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
-{
- struct i2c_adapter *adap = &priv->adap;
- u32 i2c_status;
- unsigned long timeout, stoptime, checktime;
- int nbytes, timedout;
-
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
- XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
-
- priv->pos = 0;
-
- timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
- stoptime = jiffies + timeout;
- timedout = 0;
- nbytes = 0;
-retry:
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
-
- if (priv->irq > 0)
- return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
-
- while (!timedout) {
- checktime = jiffies;
- i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
- if (i2c_status & XLR_I2C_RXRDY) {
- if (nbytes >= len)
- return -EIO; /* should not happen */
-
- buf[nbytes++] =
- xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
-
- /* reset timeout on successful read */
- stoptime = jiffies + timeout;
- }
-
- timedout = time_after(checktime, stoptime);
- if (i2c_status & XLR_I2C_ARB_STARTERR) {
- if (timedout)
- break;
- goto retry;
- }
-
- if (i2c_status & XLR_I2C_ACK_ERR)
- return -EIO;
-
- if (!xlr_i2c_busy(priv, i2c_status))
- return 0;
- }
-
- dev_err(&adap->dev, "I2C receive timeout\n");
- return -ETIMEDOUT;
-}
-
-static int xlr_i2c_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct i2c_msg *msg;
- int i;
- int ret = 0;
- struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
-
- ret = clk_enable(priv->clk);
- if (ret)
- return ret;
-
- if (priv->irq)
- xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0xf);
-
-
- for (i = 0; ret == 0 && i < num; i++) {
- msg = &msgs[i];
- priv->msg = msg;
- if (msg->flags & I2C_M_RD)
- ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
- msg->addr);
- else
- ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
- msg->addr);
- }
-
- if (priv->irq)
- xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
-
- clk_disable(priv->clk);
- priv->msg = NULL;
-
- return (ret != 0) ? ret : num;
-}
-
-static u32 xlr_func(struct i2c_adapter *adap)
-{
- /* Emulate SMBUS over I2C */
- return (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_I2C;
-}
-
-static const struct i2c_algorithm xlr_i2c_algo = {
- .master_xfer = xlr_i2c_xfer,
- .functionality = xlr_func,
-};
-
-static const struct i2c_adapter_quirks xlr_i2c_quirks = {
- .flags = I2C_AQ_NO_ZERO_LEN,
-};
-
-static const struct xlr_i2c_config xlr_i2c_config_default = {
- .status_busy = XLR_I2C_BUS_BUSY,
- .cfg_extra = 0,
-};
-
-static const struct xlr_i2c_config xlr_i2c_config_tangox = {
- .flags = XLR_I2C_FLAG_IRQ,
- .status_busy = 0,
- .cfg_extra = 1 << 8,
-};
-
-static const struct of_device_id xlr_i2c_dt_ids[] = {
- {
- .compatible = "sigma,smp8642-i2c",
- .data = &xlr_i2c_config_tangox,
- },
- { }
-};
-MODULE_DEVICE_TABLE(of, xlr_i2c_dt_ids);
-
-static int xlr_i2c_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match;
- struct xlr_i2c_private *priv;
- struct clk *clk;
- unsigned long clk_rate;
- unsigned long clk_div;
- u32 busfreq;
- int irq;
- int ret;
-
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- match = of_match_device(xlr_i2c_dt_ids, &pdev->dev);
- if (match)
- priv->cfg = match->data;
- else
- priv->cfg = &xlr_i2c_config_default;
-
- priv->iobase = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(priv->iobase))
- return PTR_ERR(priv->iobase);
-
- irq = platform_get_irq(pdev, 0);
-
- if (irq > 0 && (priv->cfg->flags & XLR_I2C_FLAG_IRQ)) {
- priv->irq = irq;
-
- xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, 0xf);
-
- ret = devm_request_irq(&pdev->dev, priv->irq, xlr_i2c_irq,
- IRQF_SHARED, dev_name(&pdev->dev),
- priv);
- if (ret)
- return ret;
-
- init_waitqueue_head(&priv->wait);
- }
-
- if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
- &busfreq))
- busfreq = I2C_MAX_STANDARD_MODE_FREQ;
-
- clk = devm_clk_get(&pdev->dev, NULL);
- if (!IS_ERR(clk)) {
- ret = clk_prepare_enable(clk);
- if (ret)
- return ret;
-
- clk_rate = clk_get_rate(clk);
- clk_div = DIV_ROUND_UP(clk_rate, 2 * busfreq);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CLKDIV, clk_div);
-
- clk_disable(clk);
- priv->clk = clk;
- }
-
- priv->adap.dev.parent = &pdev->dev;
- priv->adap.dev.of_node = pdev->dev.of_node;
- priv->adap.owner = THIS_MODULE;
- priv->adap.algo_data = priv;
- priv->adap.algo = &xlr_i2c_algo;
- priv->adap.quirks = &xlr_i2c_quirks;
- priv->adap.nr = pdev->id;
- priv->adap.class = I2C_CLASS_HWMON;
- snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
-
- i2c_set_adapdata(&priv->adap, priv);
- ret = i2c_add_numbered_adapter(&priv->adap);
- if (ret < 0)
- goto err_unprepare_clk;
-
- platform_set_drvdata(pdev, priv);
- dev_info(&priv->adap.dev, "Added I2C Bus.\n");
- return 0;
-
-err_unprepare_clk:
- clk_unprepare(clk);
- return ret;
-}
-
-static int xlr_i2c_remove(struct platform_device *pdev)
-{
- struct xlr_i2c_private *priv;
-
- priv = platform_get_drvdata(pdev);
- i2c_del_adapter(&priv->adap);
- clk_unprepare(priv->clk);
-
- return 0;
-}
-
-static struct platform_driver xlr_i2c_driver = {
- .probe = xlr_i2c_probe,
- .remove = xlr_i2c_remove,
- .driver = {
- .name = "xlr-i2cbus",
- .of_match_table = xlr_i2c_dt_ids,
- },
-};
-
-module_platform_driver(xlr_i2c_driver);
-
-MODULE_AUTHOR("Ganesan Ramalingam <[email protected]>");
-MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:xlr-i2cbus");
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index bac415a52b78..73a23e117ebe 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -7,6 +7,7 @@
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
+#include <linux/overflow.h>
#include <linux/platform_data/i2c-mux-gpio.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -49,49 +50,11 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
return 0;
}
-#ifdef CONFIG_ACPI
-
-static int i2c_mux_gpio_get_acpi_adr(struct device *dev,
- struct fwnode_handle *fwdev,
- unsigned int *adr)
-
-{
- unsigned long long adr64;
- acpi_status status;
-
- status = acpi_evaluate_integer(ACPI_HANDLE_FWNODE(fwdev),
- METHOD_NAME__ADR,
- NULL, &adr64);
-
- if (!ACPI_SUCCESS(status)) {
- dev_err(dev, "Cannot get address\n");
- return -EINVAL;
- }
-
- *adr = adr64;
- if (*adr != adr64) {
- dev_err(dev, "Address out of range\n");
- return -ERANGE;
- }
-
- return 0;
-}
-
-#else
-
-static int i2c_mux_gpio_get_acpi_adr(struct device *dev,
- struct fwnode_handle *fwdev,
- unsigned int *adr)
-{
- return -EINVAL;
-}
-
-#endif
-
static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
struct device_node *np = dev->of_node;
struct device_node *adapter_np;
struct i2c_adapter *adapter = NULL;
@@ -99,7 +62,7 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
unsigned *values;
int rc, i = 0;
- if (is_of_node(dev->fwnode)) {
+ if (is_of_node(fwnode)) {
if (!np)
return -ENODEV;
@@ -111,7 +74,7 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
adapter = of_find_i2c_adapter_by_node(adapter_np);
of_node_put(adapter_np);
- } else if (is_acpi_node(dev->fwnode)) {
+ } else if (is_acpi_node(fwnode)) {
/*
* In ACPI land the mux should be a direct child of the i2c
* bus it muxes.
@@ -141,16 +104,16 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
fwnode_property_read_u32(child, "reg", values + i);
} else if (is_acpi_node(child)) {
- rc = i2c_mux_gpio_get_acpi_adr(dev, child, values + i);
+ rc = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), values + i);
if (rc)
- return rc;
+ return dev_err_probe(dev, rc, "Cannot get address\n");
}
i++;
}
mux->data.values = values;
- if (fwnode_property_read_u32(dev->fwnode, "idle-state", &mux->data.idle))
+ if (device_property_read_u32(dev, "idle-state", &mux->data.idle))
mux->data.idle = I2C_MUX_GPIO_NO_IDLE;
return 0;
@@ -190,7 +153,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values,
- ngpios * sizeof(*mux->gpios), 0,
+ array_size(ngpios, sizeof(*mux->gpios)), 0,
i2c_mux_gpio_select, NULL);
if (!muxc) {
ret = -ENOMEM;