diff options
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 12 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-bcm-iproc.c | 117 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-bcm2835.c | 135 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-fsi.c | 32 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 163 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.c | 32 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.h | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-meson.c | 5 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mt7621.c | 357 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-nvidia-gpu.c | 64 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ocores.c | 33 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qcom-geni.c | 17 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 47 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32f7.c | 26 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 136 |
17 files changed, 955 insertions, 235 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ee5dfb5aee2a..68b677be1fa4 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -143,6 +143,7 @@ config I2C_I801 Cedar Fork (PCH) Ice Lake (PCH) Comet Lake (PCH) + Elkhart Lake (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -436,7 +437,7 @@ config I2C_AXXIA config I2C_BCM2835 tristate "Broadcom BCM2835 I2C controller" - depends on ARCH_BCM2835 + depends on ARCH_BCM2835 || ARCH_BRCMSTB help If you say yes to this option, support will be included for the BCM2835 I2C controller. @@ -692,7 +693,7 @@ config I2C_IOP3XX config I2C_JZ4780 tristate "JZ4780 I2C controller interface support" - depends on MACH_JZ4780 || COMPILE_TEST + depends on MIPS || COMPILE_TEST help If you say yes to this option, support will be included for the Ingenic JZ4780 I2C controller. @@ -746,6 +747,13 @@ config I2C_MT65XX If you want to use MediaTek(R) I2C interface, say Y or M here. If unsure, say N. +config I2C_MT7621 + tristate "MT7621/MT7628 I2C Controller" + depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || COMPILE_TEST + help + Say Y here to include support for I2C controller in the + MediaTek MT7621/MT7628 SoCs. + config I2C_MV64XXX tristate "Marvell mv64xxx I2C Controller" depends on MV64X60 || PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index a3245231b0b7..80c23895eaaf 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_I2C_LPC2K) += i2c-lpc2k.o obj-$(CONFIG_I2C_MESON) += i2c-meson.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MT65XX) += i2c-mt65xx.o +obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_MXS) += i2c-mxs.o obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index a845b8decac8..2c7f145a036e 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -165,12 +165,6 @@ enum i2c_slave_read_status { I2C_SLAVE_RX_END, }; -enum i2c_slave_xfer_dir { - I2C_SLAVE_DIR_READ = 0, - I2C_SLAVE_DIR_WRITE, - I2C_SLAVE_DIR_NONE, -}; - enum bus_speed_index { I2C_SPD_100K = 0, I2C_SPD_400K, @@ -203,7 +197,6 @@ struct bcm_iproc_i2c_dev { struct i2c_msg *msg; struct i2c_client *slave; - enum i2c_slave_xfer_dir xfer_dir; /* bytes that have been transferred */ unsigned int tx_bytes; @@ -219,7 +212,8 @@ struct bcm_iproc_i2c_dev { | BIT(IS_M_RX_THLD_SHIFT)) #define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\ - | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)) + | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)\ + | BIT(IS_S_TX_UNDERRUN_SHIFT)) static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave); static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave); @@ -297,15 +291,11 @@ static void bcm_iproc_i2c_slave_init( /* clear all pending slave interrupts */ iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, ISR_MASK_SLAVE); - /* Enable interrupt register for any READ event */ - val = BIT(IE_S_RD_EVENT_SHIFT); /* Enable interrupt register to indicate a valid byte in receive fifo */ - val |= BIT(IE_S_RX_EVENT_SHIFT); + val = BIT(IE_S_RX_EVENT_SHIFT); /* Enable interrupt register for the Slave BUSY command */ val |= BIT(IE_S_START_BUSY_SHIFT); iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); - - iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; } static void bcm_iproc_i2c_check_slave_status( @@ -314,8 +304,11 @@ static void bcm_iproc_i2c_check_slave_status( u32 val; val = iproc_i2c_rd_reg(iproc_i2c, S_CMD_OFFSET); - val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; + /* status is valid only when START_BUSY is cleared after it was set */ + if (val & BIT(S_CMD_START_BUSY_SHIFT)) + return; + val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; if (val == S_CMD_STATUS_TIMEOUT) { dev_err(iproc_i2c->device, "slave random stretch time timeout\n"); @@ -327,70 +320,66 @@ static void bcm_iproc_i2c_check_slave_status( } static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, - u32 status) + u32 status) { - u8 value; u32 val; - u32 rd_status; - u32 tmp; + u8 value, rx_status; - /* Start of transaction. check address and populate the direction */ - if (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_NONE) { - tmp = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); - rd_status = (tmp >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; - /* This condition checks whether the request is a new request */ - if (((rd_status == I2C_SLAVE_RX_START) && - (status & BIT(IS_S_RX_EVENT_SHIFT))) || - ((rd_status == I2C_SLAVE_RX_END) && - (status & BIT(IS_S_RD_EVENT_SHIFT)))) { - - /* Last bit is W/R bit. - * If 1 then its a read request(by master). - */ - iproc_i2c->xfer_dir = tmp & SLAVE_READ_WRITE_BIT_MASK; - if (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_WRITE) - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_READ_REQUESTED, &value); - else - i2c_slave_event(iproc_i2c->slave, + /* Slave RX byte receive */ + if (status & BIT(IS_S_RX_EVENT_SHIFT)) { + val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); + rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; + if (rx_status == I2C_SLAVE_RX_START) { + /* Start of SMBUS for Master write */ + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_WRITE_REQUESTED, &value); - } - } - /* read request from master */ - if ((status & BIT(IS_S_RD_EVENT_SHIFT)) && - (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_WRITE)) { - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_READ_PROCESSED, &value); - iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); + val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); + value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_WRITE_RECEIVED, &value); + } else if (status & BIT(IS_S_RD_EVENT_SHIFT)) { + /* Start of SMBUS for Master Read */ + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_READ_REQUESTED, &value); + iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); - val = BIT(S_CMD_START_BUSY_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); - } + val = BIT(S_CMD_START_BUSY_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); - /* write request from master */ - if ((status & BIT(IS_S_RX_EVENT_SHIFT)) && - (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_READ)) { - val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); - /* Its a write request by Master to Slave. - * We read data present in receive FIFO - */ - value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + /* + * Enable interrupt for TX FIFO becomes empty and + * less than PKT_LENGTH bytes were output on the SMBUS + */ + val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); + val |= BIT(IE_S_TX_UNDERRUN_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); + } else { + /* Master write other than start */ + value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_WRITE_RECEIVED, &value); + } + } else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { + /* Master read other than start */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_RECEIVED, &value); - - /* check the status for the last byte of the transaction */ - rd_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; - if (rd_status == I2C_SLAVE_RX_END) - iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; + I2C_SLAVE_READ_PROCESSED, &value); - dev_dbg(iproc_i2c->device, "\nread value = 0x%x\n", value); + iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); + val = BIT(S_CMD_START_BUSY_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); } /* Stop */ if (status & BIT(IS_S_START_BUSY_SHIFT)) { i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); - iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; + /* + * Enable interrupt for TX FIFO becomes empty and + * less than PKT_LENGTH bytes were output on the SMBUS + */ + val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); + val &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); } /* clear interrupt status */ diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index d2fbb4bb4a43..67752f7b0371 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -4,6 +4,8 @@ */ #include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> #include <linux/completion.h> #include <linux/err.h> #include <linux/i2c.h> @@ -51,9 +53,7 @@ struct bcm2835_i2c_dev { struct device *dev; void __iomem *regs; - struct clk *clk; int irq; - u32 bus_clk_rate; struct i2c_adapter adapter; struct completion completion; struct i2c_msg *curr_msg; @@ -74,12 +74,17 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) return readl(i2c_dev->regs + reg); } -static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) +#define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw) +struct clk_bcm2835_i2c { + struct clk_hw hw; + struct bcm2835_i2c_dev *i2c_dev; +}; + +static int clk_bcm2835_i2c_calc_divider(unsigned long rate, + unsigned long parent_rate) { - u32 divider, redl, fedl; + u32 divider = DIV_ROUND_UP(parent_rate, rate); - divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), - i2c_dev->bus_clk_rate); /* * Per the datasheet, the register is always interpreted as an even * number, by rounding down. In other words, the LSB is ignored. So, @@ -88,12 +93,23 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) if (divider & 1) divider++; if ((divider < BCM2835_I2C_CDIV_MIN) || - (divider > BCM2835_I2C_CDIV_MAX)) { - dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n"); + (divider > BCM2835_I2C_CDIV_MAX)) return -EINVAL; - } - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); + return divider; +} + +static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw); + u32 redl, fedl; + u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate); + + if (divider == -EINVAL) + return -EINVAL; + + bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider); /* * Number of core clocks to wait after falling edge before @@ -108,12 +124,65 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) */ redl = max(divider / 4, 1u); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL, + bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL, (fedl << BCM2835_I2C_FEDL_SHIFT) | (redl << BCM2835_I2C_REDL_SHIFT)); return 0; } +static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate); + + return DIV_ROUND_UP(*parent_rate, divider); +} + +static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw); + u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV); + + return DIV_ROUND_UP(parent_rate, divider); +} + +static const struct clk_ops clk_bcm2835_i2c_ops = { + .set_rate = clk_bcm2835_i2c_set_rate, + .round_rate = clk_bcm2835_i2c_round_rate, + .recalc_rate = clk_bcm2835_i2c_recalc_rate, +}; + +static struct clk *bcm2835_i2c_register_div(struct device *dev, + struct clk *mclk, + struct bcm2835_i2c_dev *i2c_dev) +{ + struct clk_init_data init; + struct clk_bcm2835_i2c *priv; + char name[32]; + const char *mclk_name; + + snprintf(name, sizeof(name), "%s_div", dev_name(dev)); + + mclk_name = __clk_get_name(mclk); + + init.ops = &clk_bcm2835_i2c_ops; + init.name = name; + init.parent_names = (const char* []) { mclk_name }; + init.num_parents = 1; + init.flags = 0; + + priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL); + if (priv == NULL) + return ERR_PTR(-ENOMEM); + + priv->hw.init = &init; + priv->i2c_dev = i2c_dev; + + clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev)); + return devm_clk_register(dev, &priv->hw); +} + static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) { u32 val; @@ -271,7 +340,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], { struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); unsigned long time_left; - int i, ret; + int i; for (i = 0; i < (num - 1); i++) if (msgs[i].flags & I2C_M_RD) { @@ -280,10 +349,6 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], return -EOPNOTSUPP; } - ret = bcm2835_i2c_set_divider(i2c_dev); - if (ret) - return ret; - i2c_dev->curr_msg = msgs; i2c_dev->num_msgs = num; reinit_completion(&i2c_dev->completion); @@ -338,6 +403,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) struct resource *mem, *irq; int ret; struct i2c_adapter *adap; + struct clk *bus_clk; + struct clk *mclk; + u32 bus_clk_rate; i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) @@ -351,19 +419,38 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c_dev->regs)) return PTR_ERR(i2c_dev->regs); - i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c_dev->clk)) { - if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER) + mclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(mclk)) { + if (PTR_ERR(mclk) != -EPROBE_DEFER) dev_err(&pdev->dev, "Could not get clock\n"); - return PTR_ERR(i2c_dev->clk); + return PTR_ERR(mclk); + } + + bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev); + + if (IS_ERR(bus_clk)) { + dev_err(&pdev->dev, "Could not register clock\n"); + return PTR_ERR(bus_clk); } ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &i2c_dev->bus_clk_rate); + &bus_clk_rate); if (ret < 0) { dev_warn(&pdev->dev, "Could not read clock-frequency property\n"); - i2c_dev->bus_clk_rate = 100000; + bus_clk_rate = 100000; + } + + ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate); + if (ret < 0) { + dev_err(&pdev->dev, "Could not set clock frequency\n"); + return ret; + } + + ret = clk_prepare_enable(bus_clk); + if (ret) { + dev_err(&pdev->dev, "Couldn't prepare clock"); + return ret; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -402,6 +489,10 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) static int bcm2835_i2c_remove(struct platform_device *pdev) { struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div"); + + clk_rate_exclusive_put(bus_clk); + clk_disable_unprepare(bus_clk); free_irq(i2c_dev->irq, i2c_dev); i2c_del_adapter(&i2c_dev->adapter); diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c index 1e2be2219a60..da5eb3960def 100644 --- a/drivers/i2c/busses/i2c-fsi.c +++ b/drivers/i2c/busses/i2c-fsi.c @@ -658,13 +658,29 @@ static const struct i2c_algorithm fsi_i2c_algorithm = { .functionality = fsi_i2c_functionality, }; +static struct device_node *fsi_i2c_find_port_of_node(struct device_node *fsi, + int port) +{ + struct device_node *np; + u32 port_no; + int rc; + + for_each_child_of_node(fsi, np) { + rc = of_property_read_u32(np, "reg", &port_no); + if (!rc && port_no == port) + return np; + } + + return NULL; +} + static int fsi_i2c_probe(struct device *dev) { struct fsi_i2c_master *i2c; struct fsi_i2c_port *port; struct device_node *np; + u32 port_no, ports, stat; int rc; - u32 port_no; i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) @@ -678,10 +694,16 @@ static int fsi_i2c_probe(struct device *dev) if (rc) return rc; - /* Add adapter for each i2c port of the master. */ - for_each_available_child_of_node(dev->of_node, np) { - rc = of_property_read_u32(np, "reg", &port_no); - if (rc || port_no > USHRT_MAX) + rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); + if (rc) + return rc; + + ports = FIELD_GET(I2C_STAT_MAX_PORT, stat) + 1; + dev_dbg(dev, "I2C master has %d ports\n", ports); + + for (port_no = 0; port_no < ports; port_no++) { + np = fsi_i2c_find_port_of_node(dev->of_node, port_no); + if (np && !of_device_is_available(np)) continue; port = kzalloc(sizeof(*port), GFP_KERNEL); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index bf484cd775ec..763a8d6cc336 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -72,12 +72,13 @@ * Cedar Fork (PCH) 0x18df 32 hard yes yes yes * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes * Comet Lake (PCH) 0x02a3 32 hard yes yes yes + * Elkhart Lake (PCH) 0x4b23 32 hard yes yes yes * * Features supported by this driver: * Software PEC no * Hardware PEC yes * Block buffer yes - * Block process call transaction no + * Block process call transaction yes * I2C block read transaction yes (doesn't use the block buffer) * Slave mode no * SMBus Host Notify yes @@ -100,6 +101,7 @@ #include <linux/io.h> #include <linux/dmi.h> #include <linux/slab.h> +#include <linux/string.h> #include <linux/wait.h> #include <linux/err.h> #include <linux/platform_device.h> @@ -177,6 +179,7 @@ #define I801_PROC_CALL 0x10 /* unimplemented */ #define I801_BLOCK_DATA 0x14 #define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ +#define I801_BLOCK_PROC_CALL 0x1C /* I801 Host Control register bits */ #define SMBHSTCNT_INTREN BIT(0) @@ -242,6 +245,7 @@ #define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3 #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323 #define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3 +#define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 struct i801_mux_config { char *gpio_chip; @@ -518,10 +522,23 @@ static int i801_transaction(struct i801_priv *priv, int xact) static int i801_block_transaction_by_block(struct i801_priv *priv, union i2c_smbus_data *data, - char read_write, int hwpec) + char read_write, int command, + int hwpec) { int i, len; int status; + int xact = hwpec ? SMBHSTCNT_PEC_EN : 0; + + switch (command) { + case I2C_SMBUS_BLOCK_PROC_CALL: + xact |= I801_BLOCK_PROC_CALL; + break; + case I2C_SMBUS_BLOCK_DATA: + xact |= I801_BLOCK_DATA; + break; + default: + return -EOPNOTSUPP; + } inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ @@ -533,12 +550,12 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, outb_p(data->block[i+1], SMBBLKDAT(priv)); } - status = i801_transaction(priv, I801_BLOCK_DATA | - (hwpec ? SMBHSTCNT_PEC_EN : 0)); + status = i801_transaction(priv, xact); if (status) return status; - if (read_write == I2C_SMBUS_READ) { + if (read_write == I2C_SMBUS_READ || + command == I2C_SMBUS_BLOCK_PROC_CALL) { len = inb_p(SMBHSTDAT0(priv)); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) return -EPROTO; @@ -676,6 +693,9 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, int result; const struct i2c_adapter *adap = &priv->adapter; + if (command == I2C_SMBUS_BLOCK_PROC_CALL) + return -EOPNOTSUPP; + result = i801_check_pre(priv); if (result < 0) return result; @@ -807,7 +827,8 @@ static int i801_block_transaction(struct i801_priv *priv, && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode(priv) == 0) result = i801_block_transaction_by_block(priv, data, - read_write, hwpec); + read_write, + command, hwpec); else result = i801_block_transaction_byte_by_byte(priv, data, read_write, @@ -899,6 +920,15 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, outb_p(command, SMBHSTCMD(priv)); block = 1; break; + case I2C_SMBUS_BLOCK_PROC_CALL: + /* + * Bit 0 of the slave address register always indicate a write + * command. + */ + outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); + outb_p(command, SMBHSTCMD(priv)); + block = 1; + break; default: dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", size); @@ -959,6 +989,8 @@ static u32 i801_func(struct i2c_adapter *adapter) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | + ((priv->features & FEATURE_BLOCK_PROC) ? + I2C_FUNC_SMBUS_BLOCK_PROC_CALL : 0) | ((priv->features & FEATURE_I2C_BLOCK_READ) ? I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) | ((priv->features & FEATURE_HOST_NOTIFY) ? @@ -1042,6 +1074,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) }, { 0, } }; @@ -1143,6 +1176,118 @@ static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) } } +/* NOTE: Keep this list in sync with drivers/platform/x86/dell-smo8800.c */ +static const char *const acpi_smo8800_ids[] = { + "SMO8800", + "SMO8801", + "SMO8810", + "SMO8811", + "SMO8820", + "SMO8821", + "SMO8830", + "SMO8831", +}; + +static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + struct acpi_device_info *info; + acpi_status status; + char *hid; + int i; + + status = acpi_get_object_info(obj_handle, &info); + if (!ACPI_SUCCESS(status) || !(info->valid & ACPI_VALID_HID)) + return AE_OK; + + hid = info->hardware_id.string; + if (!hid) + return AE_OK; + + i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid); + if (i < 0) + return AE_OK; + + *((bool *)return_value) = true; + return AE_CTRL_TERMINATE; +} + +static bool is_dell_system_with_lis3lv02d(void) +{ + bool found; + const char *vendor; + + vendor = dmi_get_system_info(DMI_SYS_VENDOR); + if (!vendor || strcmp(vendor, "Dell Inc.")) + return false; + + /* + * Check that ACPI device SMO88xx is present and is functioning. + * Function acpi_get_devices() already filters all ACPI devices + * which are not present or are not functioning. + * ACPI device SMO88xx represents our ST microelectronics lis3lv02d + * accelerometer but unfortunately ACPI does not provide any other + * information (like I2C address). + */ + found = false; + acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL, + (void **)&found); + + return found; +} + +/* + * Accelerometer's I2C address is not specified in DMI nor ACPI, + * so it is needed to define mapping table based on DMI product names. + */ +static const struct { + const char *dmi_product_name; + unsigned short i2c_addr; +} dell_lis3lv02d_devices[] = { + /* + * Dell platform team told us that these Latitude devices have + * ST microelectronics accelerometer at I2C address 0x29. + */ + { "Latitude E5250", 0x29 }, + { "Latitude E5450", 0x29 }, + { "Latitude E5550", 0x29 }, + { "Latitude E6440", 0x29 }, + { "Latitude E6440 ATG", 0x29 }, + { "Latitude E6540", 0x29 }, + /* + * Additional individual entries were added after verification. + */ + { "Vostro V131", 0x1d }, +}; + +static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) +{ + struct i2c_board_info info; + const char *dmi_product_name; + int i; + + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { + if (strcmp(dmi_product_name, + dell_lis3lv02d_devices[i].dmi_product_name) == 0) + break; + } + + if (i == ARRAY_SIZE(dell_lis3lv02d_devices)) { + dev_warn(&priv->pci_dev->dev, + "Accelerometer lis3lv02d is present on SMBus but its" + " address is unknown, skipping registration\n"); + return; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = dell_lis3lv02d_devices[i].i2c_addr; + strlcpy(info.type, "lis3lv02d", I2C_NAME_SIZE); + i2c_new_device(&priv->adapter, &info); +} + /* Register optional slaves */ static void i801_probe_optional_slaves(struct i801_priv *priv) { @@ -1161,6 +1306,9 @@ static void i801_probe_optional_slaves(struct i801_priv *priv) if (dmi_name_in_vendors("FUJITSU")) dmi_walk(dmi_check_onboard_devices, &priv->adapter); + + if (is_dell_system_with_lis3lv02d()) + register_dell_lis3lv02d_i2c_device(priv); } #else static void __init input_apanel_init(void) {} @@ -1561,6 +1709,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS: case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: + case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS: + priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_IRQ; priv->features |= FEATURE_SMBUS_PEC; @@ -1580,6 +1730,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) priv->features |= FEATURE_IDF; /* fall through */ default: + priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_IRQ; /* fall through */ diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index fd70b110e8f4..b1b8b938d7f4 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1220,8 +1220,7 @@ static int i2c_imx_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int i2c_imx_runtime_suspend(struct device *dev) +static int __maybe_unused i2c_imx_runtime_suspend(struct device *dev) { struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); @@ -1230,7 +1229,7 @@ static int i2c_imx_runtime_suspend(struct device *dev) return 0; } -static int i2c_imx_runtime_resume(struct device *dev) +static int __maybe_unused i2c_imx_runtime_resume(struct device *dev) { struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); int ret; @@ -1246,17 +1245,13 @@ static const struct dev_pm_ops i2c_imx_pm_ops = { SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL) }; -#define I2C_IMX_PM_OPS (&i2c_imx_pm_ops) -#else -#define I2C_IMX_PM_OPS NULL -#endif /* CONFIG_PM */ static struct platform_driver i2c_imx_driver = { .probe = i2c_imx_probe, .remove = i2c_imx_remove, .driver = { .name = DRIVER_NAME, - .pm = I2C_IMX_PM_OPS, + .pm = &i2c_imx_pm_ops, .of_match_table = i2c_imx_dt_ids, }, .id_table = imx_i2c_devtype, diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index a34cb3848280..eafc1a4d8656 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -38,7 +38,7 @@ #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/io.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include "i2c-iop3xx.h" @@ -71,17 +71,16 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) /* * Every time unit enable is asserted, GPOD needs to be cleared - * on IOP3XX to avoid data corruption on the bus. + * on IOP3XX to avoid data corruption on the bus. We use the + * gpiod_set_raw_value() to make sure the 0 hits the hardware + * GPOD register. These descriptors are only passed along to + * the device if this is necessary. */ -#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X) - if (iop3xx_adap->id == 0) { - gpio_set_value(7, 0); - gpio_set_value(6, 0); - } else { - gpio_set_value(5, 0); - gpio_set_value(4, 0); - } -#endif + if (iop3xx_adap->gpio_scl) + gpiod_set_raw_value(iop3xx_adap->gpio_scl, 0); + if (iop3xx_adap->gpio_sda) + gpiod_set_raw_value(iop3xx_adap->gpio_sda, 0); + /* NB SR bits not same position as CR IE bits :-( */ iop3xx_adap->SR_enabled = IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD | @@ -434,6 +433,17 @@ iop3xx_i2c_probe(struct platform_device *pdev) goto free_adapter; } + adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev, + "scl", + GPIOD_ASIS); + if (IS_ERR(adapter_data->gpio_scl)) + return PTR_ERR(adapter_data->gpio_scl); + adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev, + "sda", + GPIOD_ASIS); + if (IS_ERR(adapter_data->gpio_sda)) + return PTR_ERR(adapter_data->gpio_sda); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENODEV; diff --git a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h index 2d6929c2bd92..231897838386 100644 --- a/drivers/i2c/busses/i2c-iop3xx.h +++ b/drivers/i2c/busses/i2c-iop3xx.h @@ -98,6 +98,8 @@ struct i2c_algo_iop3xx_data { spinlock_t lock; u32 SR_enabled, SR_received; int id; + struct gpio_desc *gpio_scl; + struct gpio_desc *gpio_sda; }; #endif /* I2C_IOP3XX_H */ diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 90f5d0407d73..f530d9a0450b 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * I2C bus driver for Amlogic Meson SoCs * * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/clk.h> diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c new file mode 100644 index 000000000000..2a1cb414766d --- /dev/null +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * drivers/i2c/busses/i2c-mt7621.c + * + * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com> + * Copyright (C) 2016 Michael Lee <igvtee@gmail.com> + * Copyright (C) 2018 Jan Breuer <jan.breuer@jaybee.cz> + * + * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. + * (C) 2014 Sittisak <sittisaks@hotmail.com> + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/reset.h> + +#define REG_SM0CFG2_REG 0x28 +#define REG_SM0CTL0_REG 0x40 +#define REG_SM0CTL1_REG 0x44 +#define REG_SM0D0_REG 0x50 +#define REG_SM0D1_REG 0x54 +#define REG_PINTEN_REG 0x5c +#define REG_PINTST_REG 0x60 +#define REG_PINTCL_REG 0x64 + +/* REG_SM0CFG2_REG */ +#define SM0CFG2_IS_AUTOMODE BIT(0) + +/* REG_SM0CTL0_REG */ +#define SM0CTL0_ODRAIN BIT(31) +#define SM0CTL0_CLK_DIV_MASK (0x7ff << 16) +#define SM0CTL0_CLK_DIV_MAX 0x7ff +#define SM0CTL0_CS_STATUS BIT(4) +#define SM0CTL0_SCL_STATE BIT(3) +#define SM0CTL0_SDA_STATE BIT(2) +#define SM0CTL0_EN BIT(1) +#define SM0CTL0_SCL_STRETCH BIT(0) + +/* REG_SM0CTL1_REG */ +#define SM0CTL1_ACK_MASK (0xff << 16) +#define SM0CTL1_PGLEN_MASK (0x7 << 8) +#define SM0CTL1_PGLEN(x) ((((x) - 1) << 8) & SM0CTL1_PGLEN_MASK) +#define SM0CTL1_READ (5 << 4) +#define SM0CTL1_READ_LAST (4 << 4) +#define SM0CTL1_STOP (3 << 4) +#define SM0CTL1_WRITE (2 << 4) +#define SM0CTL1_START (1 << 4) +#define SM0CTL1_MODE_MASK (0x7 << 4) +#define SM0CTL1_TRI BIT(0) + +/* timeout waiting for I2C devices to respond */ +#define TIMEOUT_MS 1000 + +struct mtk_i2c { + void __iomem *base; + struct device *dev; + struct i2c_adapter adap; + u32 bus_freq; + u32 clk_div; + u32 flags; + struct clk *clk; +}; + +static int mtk_i2c_wait_idle(struct mtk_i2c *i2c) +{ + int ret; + u32 val; + + ret = readl_relaxed_poll_timeout(i2c->base + REG_SM0CTL1_REG, + val, !(val & SM0CTL1_TRI), + 10, TIMEOUT_MS * 1000); + if (ret) + dev_dbg(i2c->dev, "idle err(%d)\n", ret); + + return ret; +} + +static void mtk_i2c_reset(struct mtk_i2c *i2c) +{ + int ret; + + ret = device_reset(i2c->adap.dev.parent); + if (ret) + dev_err(i2c->dev, "I2C reset failed!\n"); + + /* + * Don't set SM0CTL0_ODRAIN as its bit meaning is inverted. To + * configure open-drain mode, this bit needs to be cleared. + */ + iowrite32(((i2c->clk_div << 16) & SM0CTL0_CLK_DIV_MASK) | SM0CTL0_EN | + SM0CTL0_SCL_STRETCH, i2c->base + REG_SM0CTL0_REG); + iowrite32(0, i2c->base + REG_SM0CFG2_REG); +} + +static void mtk_i2c_dump_reg(struct mtk_i2c *i2c) +{ + dev_dbg(i2c->dev, + "SM0CFG2 %08x, SM0CTL0 %08x, SM0CTL1 %08x, SM0D0 %08x, SM0D1 %08x\n", + ioread32(i2c->base + REG_SM0CFG2_REG), + ioread32(i2c->base + REG_SM0CTL0_REG), + ioread32(i2c->base + REG_SM0CTL1_REG), + ioread32(i2c->base + REG_SM0D0_REG), + ioread32(i2c->base + REG_SM0D1_REG)); +} + +static int mtk_i2c_check_ack(struct mtk_i2c *i2c, u32 expected) +{ + u32 ack = readl_relaxed(i2c->base + REG_SM0CTL1_REG); + u32 ack_expected = (expected << 16) & SM0CTL1_ACK_MASK; + + return ((ack & ack_expected) == ack_expected) ? 0 : -ENXIO; +} + +static int mtk_i2c_master_start(struct mtk_i2c *i2c) +{ + iowrite32(SM0CTL1_START | SM0CTL1_TRI, i2c->base + REG_SM0CTL1_REG); + return mtk_i2c_wait_idle(i2c); +} + +static int mtk_i2c_master_stop(struct mtk_i2c *i2c) +{ + iowrite32(SM0CTL1_STOP | SM0CTL1_TRI, i2c->base + REG_SM0CTL1_REG); + return mtk_i2c_wait_idle(i2c); +} + +static int mtk_i2c_master_cmd(struct mtk_i2c *i2c, u32 cmd, int page_len) +{ + iowrite32(cmd | SM0CTL1_TRI | SM0CTL1_PGLEN(page_len), + i2c->base + REG_SM0CTL1_REG); + return mtk_i2c_wait_idle(i2c); +} + +static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + struct mtk_i2c *i2c; + struct i2c_msg *pmsg; + u16 addr; + int i, j, ret, len, page_len; + u32 cmd; + u32 data[2]; + + i2c = i2c_get_adapdata(adap); + + for (i = 0; i < num; i++) { + pmsg = &msgs[i]; + + /* wait hardware idle */ + ret = mtk_i2c_wait_idle(i2c); + if (ret) + goto err_timeout; + + /* start sequence */ + ret = mtk_i2c_master_start(i2c); + if (ret) + goto err_timeout; + + /* write address */ + if (pmsg->flags & I2C_M_TEN) { + /* 10 bits address */ + addr = 0xf0 | ((pmsg->addr >> 7) & 0x06); + addr |= (pmsg->addr & 0xff) << 8; + if (pmsg->flags & I2C_M_RD) + addr |= 1; + iowrite32(addr, i2c->base + REG_SM0D0_REG); + ret = mtk_i2c_master_cmd(i2c, SM0CTL1_WRITE, 2); + if (ret) + goto err_timeout; + } else { + /* 7 bits address */ + addr = i2c_8bit_addr_from_msg(pmsg); + iowrite32(addr, i2c->base + REG_SM0D0_REG); + ret = mtk_i2c_master_cmd(i2c, SM0CTL1_WRITE, 1); + if (ret) + goto err_timeout; + } + + /* check address ACK */ + if (!(pmsg->flags & I2C_M_IGNORE_NAK)) { + ret = mtk_i2c_check_ack(i2c, BIT(0)); + if (ret) + goto err_ack; + } + + /* transfer data */ + for (len = pmsg->len, j = 0; len > 0; len -= 8, j += 8) { + page_len = (len >= 8) ? 8 : len; + + if (pmsg->flags & I2C_M_RD) { + cmd = (len > 8) ? + SM0CTL1_READ : SM0CTL1_READ_LAST; + } else { + memcpy(data, &pmsg->buf[j], page_len); + iowrite32(data[0], i2c->base + REG_SM0D0_REG); + iowrite32(data[1], i2c->base + REG_SM0D1_REG); + cmd = SM0CTL1_WRITE; + } + + ret = mtk_i2c_master_cmd(i2c, cmd, page_len); + if (ret) + goto err_timeout; + + if (pmsg->flags & I2C_M_RD) { + data[0] = ioread32(i2c->base + REG_SM0D0_REG); + data[1] = ioread32(i2c->base + REG_SM0D1_REG); + memcpy(&pmsg->buf[j], data, page_len); + } else { + if (!(pmsg->flags & I2C_M_IGNORE_NAK)) { + ret = mtk_i2c_check_ack(i2c, + (1 << page_len) + - 1); + if (ret) + goto err_ack; + } + } + } + } + + ret = mtk_i2c_master_stop(i2c); + if (ret) + goto err_timeout; + + /* the return value is number of executed messages */ + return i; + +err_ack: + ret = mtk_i2c_master_stop(i2c); + if (ret) + goto err_timeout; + return -ENXIO; + +err_timeout: + mtk_i2c_dump_reg(i2c); + mtk_i2c_reset(i2c); + return ret; +} + +static u32 mtk_i2c_func(struct i2c_adapter *a) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; +} + +static const struct i2c_algorithm mtk_i2c_algo = { + .master_xfer = mtk_i2c_master_xfer, + .functionality = mtk_i2c_func, +}; + +static const struct of_device_id i2c_mtk_dt_ids[] = { + { .compatible = "mediatek,mt7621-i2c" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids); + +static void mtk_i2c_init(struct mtk_i2c *i2c) +{ + i2c->clk_div = clk_get_rate(i2c->clk) / i2c->bus_freq - 1; + if (i2c->clk_div < 99) + i2c->clk_div = 99; + if (i2c->clk_div > SM0CTL0_CLK_DIV_MAX) + i2c->clk_div = SM0CTL0_CLK_DIV_MAX; + + mtk_i2c_reset(i2c); +} + +static int mtk_i2c_probe(struct platform_device *pdev) +{ + struct resource *res; + struct mtk_i2c *i2c; + struct i2c_adapter *adap; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + i2c->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + + i2c->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "no clock defined\n"); + return PTR_ERR(i2c->clk); + } + ret = clk_prepare_enable(i2c->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock\n"); + return ret; + } + + i2c->dev = &pdev->dev; + + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &i2c->bus_freq)) + i2c->bus_freq = 100000; + + if (i2c->bus_freq == 0) { + dev_warn(i2c->dev, "clock-frequency 0 not supported\n"); + return -EINVAL; + } + + adap = &i2c->adap; + adap->owner = THIS_MODULE; + adap->algo = &mtk_i2c_algo; + adap->retries = 3; + adap->dev.parent = &pdev->dev; + i2c_set_adapdata(adap, i2c); + adap->dev.of_node = pdev->dev.of_node; + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); + + platform_set_drvdata(pdev, i2c); + + mtk_i2c_init(i2c); + + ret = i2c_add_adapter(adap); + if (ret < 0) + return ret; + + dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000); + + return ret; +} + +static int mtk_i2c_remove(struct platform_device *pdev) +{ + struct mtk_i2c *i2c = platform_get_drvdata(pdev); + + clk_disable_unprepare(i2c->clk); + i2c_del_adapter(&i2c->adap); + + return 0; +} + +static struct platform_driver mtk_i2c_driver = { + .probe = mtk_i2c_probe, + .remove = mtk_i2c_remove, + .driver = { + .owner = THIS_MODULE, + .name = "i2c-mt7621", + .of_match_table = i2c_mtk_dt_ids, + }, +}; + +module_platform_driver(mtk_i2c_driver); + +MODULE_AUTHOR("Steven Liu"); +MODULE_DESCRIPTION("MT7621 I2C host driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:MT7621-I2C"); diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index 1c8f708f212b..cfc76b5de726 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -51,6 +51,7 @@ struct gpu_i2c_dev { void __iomem *regs; struct i2c_adapter adapter; struct i2c_board_info *gpu_ccgx_ucsi; + struct i2c_client *ccgx_client; }; static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd) @@ -169,12 +170,14 @@ static int gpu_i2c_master_xfer(struct i2c_adapter *adap, { struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap); int status, status2; + bool send_stop = true; int i, j; /* * The controller supports maximum 4 byte read due to known * limitation of sending STOP after every read. */ + pm_runtime_get_sync(i2cd->dev); for (i = 0; i < num; i++) { if (msgs[i].flags & I2C_M_RD) { /* program client address before starting read */ @@ -182,37 +185,42 @@ static int gpu_i2c_master_xfer(struct i2c_adapter *adap, /* gpu_i2c_read has implicit start */ status = gpu_i2c_read(i2cd, msgs[i].buf, msgs[i].len); if (status < 0) - goto stop; + goto exit; } else { u8 addr = i2c_8bit_addr_from_msg(msgs + i); status = gpu_i2c_start(i2cd); if (status < 0) { if (i == 0) - return status; - goto stop; + send_stop = false; + goto exit; } status = gpu_i2c_write(i2cd, addr); if (status < 0) - goto stop; + goto exit; for (j = 0; j < msgs[i].len; j++) { status = gpu_i2c_write(i2cd, msgs[i].buf[j]); if (status < 0) - goto stop; + goto exit; } } } + send_stop = false; status = gpu_i2c_stop(i2cd); if (status < 0) - return status; - - return i; -stop: - status2 = gpu_i2c_stop(i2cd); - if (status2 < 0) - dev_err(i2cd->dev, "i2c stop failed %d\n", status2); + goto exit; + + status = i; +exit: + if (send_stop) { + status2 = gpu_i2c_stop(i2cd); + if (status2 < 0) + dev_err(i2cd->dev, "i2c stop failed %d\n", status2); + } + pm_runtime_mark_last_busy(i2cd->dev); + pm_runtime_put_autosuspend(i2cd->dev); return status; } @@ -261,8 +269,6 @@ static const struct property_entry ccgx_props[] = { static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq) { - struct i2c_client *ccgx_client; - i2cd->gpu_ccgx_ucsi = devm_kzalloc(i2cd->dev, sizeof(*i2cd->gpu_ccgx_ucsi), GFP_KERNEL); @@ -274,8 +280,8 @@ static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq) i2cd->gpu_ccgx_ucsi->addr = 0x8; i2cd->gpu_ccgx_ucsi->irq = irq; i2cd->gpu_ccgx_ucsi->properties = ccgx_props; - ccgx_client = i2c_new_device(&i2cd->adapter, i2cd->gpu_ccgx_ucsi); - if (!ccgx_client) + i2cd->ccgx_client = i2c_new_device(&i2cd->adapter, i2cd->gpu_ccgx_ucsi); + if (!i2cd->ccgx_client) return -ENODEV; return 0; @@ -332,6 +338,11 @@ static int gpu_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto del_adapter; } + pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); + return 0; del_adapter: @@ -345,19 +356,38 @@ static void gpu_i2c_remove(struct pci_dev *pdev) { struct gpu_i2c_dev *i2cd = dev_get_drvdata(&pdev->dev); + pm_runtime_get_noresume(i2cd->dev); i2c_del_adapter(&i2cd->adapter); pci_free_irq_vectors(pdev); } +/* + * We need gpu_i2c_suspend() even if it is stub, for runtime pm to work + * correctly. Without it, lspci shows runtime pm status as "D0" for the card. + * Documentation/power/pci.txt also insists for driver to provide this. + */ +static __maybe_unused int gpu_i2c_suspend(struct device *dev) +{ + return 0; +} + static __maybe_unused int gpu_i2c_resume(struct device *dev) { struct gpu_i2c_dev *i2cd = dev_get_drvdata(dev); gpu_enable_i2c_bus(i2cd); + /* + * Runtime resume ccgx client so that it can see for any + * connector change event. Old ccg firmware has known + * issue of not triggering interrupt when a device is + * connected to runtime resume the controller. + */ + pm_request_resume(&i2cd->ccgx_client->dev); return 0; } -static UNIVERSAL_DEV_PM_OPS(gpu_i2c_driver_pm, NULL, gpu_i2c_resume, NULL); +static UNIVERSAL_DEV_PM_OPS(gpu_i2c_driver_pm, gpu_i2c_suspend, gpu_i2c_resume, + NULL); static struct pci_driver gpu_i2c_driver = { .name = "nvidia-gpu", diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index c3dabee0aa35..4117f1abc7c6 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -35,6 +35,7 @@ struct ocores_i2c { int iobase; u32 reg_shift; u32 reg_io_width; + unsigned long flags; wait_queue_head_t wait; struct i2c_adapter adap; struct i2c_msg *msg; @@ -82,6 +83,9 @@ struct ocores_i2c { #define TYPE_OCORES 0 #define TYPE_GRLIB 1 +#define TYPE_SIFIVE_REV0 2 + +#define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */ static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) { @@ -235,9 +239,12 @@ static irqreturn_t ocores_isr(int irq, void *dev_id) struct ocores_i2c *i2c = dev_id; u8 stat = oc_getreg(i2c, OCI2C_STATUS); - if (!(stat & OCI2C_STAT_IF)) + if (i2c->flags & OCORES_FLAG_BROKEN_IRQ) { + if ((stat & OCI2C_STAT_IF) && !(stat & OCI2C_STAT_BUSY)) + return IRQ_NONE; + } else if (!(stat & OCI2C_STAT_IF)) { return IRQ_NONE; - + } ocores_process(i2c, stat); return IRQ_HANDLED; @@ -352,6 +359,11 @@ static void ocores_process_polling(struct ocores_i2c *i2c) ret = ocores_isr(-1, i2c); if (ret == IRQ_NONE) break; /* all messages have been transferred */ + else { + if (i2c->flags & OCORES_FLAG_BROKEN_IRQ) + if (i2c->state == STATE_DONE) + break; + } } } @@ -462,6 +474,14 @@ static const struct of_device_id ocores_i2c_match[] = { .compatible = "aeroflexgaisler,i2cmst", .data = (void *)TYPE_GRLIB, }, + { + .compatible = "sifive,fu540-c000-i2c", + .data = (void *)TYPE_SIFIVE_REV0, + }, + { + .compatible = "sifive,i2c0", + .data = (void *)TYPE_SIFIVE_REV0, + }, {}, }; MODULE_DEVICE_TABLE(of, ocores_i2c_match); @@ -586,6 +606,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) { struct ocores_i2c *i2c; struct ocores_i2c_platform_data *pdata; + const struct of_device_id *match; struct resource *res; int irq; int ret; @@ -668,6 +689,14 @@ static int ocores_i2c_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq == -ENXIO) { ocores_algorithm.master_xfer = ocores_xfer_polling; + + /* + * Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for + * FU540-C000 SoC in polling mode. + */ + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); + if (match && (long)match->data == TYPE_SIFIVE_REV0) + i2c->flags |= OCORES_FLAG_BROKEN_IRQ; } else { if (irq < 0) return irq; diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index db075bc0d952..a89bfce5388e 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +#include <linux/acpi.h> #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/err.h> @@ -483,6 +484,14 @@ static const struct i2c_algorithm geni_i2c_algo = { .functionality = geni_i2c_func, }; +#ifdef CONFIG_ACPI +static const struct acpi_device_id geni_i2c_acpi_match[] = { + { "QCOM0220"}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, geni_i2c_acpi_match); +#endif + static int geni_i2c_probe(struct platform_device *pdev) { struct geni_i2c_dev *gi2c; @@ -502,7 +511,7 @@ static int geni_i2c_probe(struct platform_device *pdev) return PTR_ERR(gi2c->se.base); gi2c->se.clk = devm_clk_get(&pdev->dev, "se"); - if (IS_ERR(gi2c->se.clk)) { + if (IS_ERR(gi2c->se.clk) && !has_acpi_companion(&pdev->dev)) { ret = PTR_ERR(gi2c->se.clk); dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret); return ret; @@ -516,6 +525,9 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->clk_freq_out = KHZ(100); } + if (has_acpi_companion(&pdev->dev)) + ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(&pdev->dev)); + gi2c->irq = platform_get_irq(pdev, 0); if (gi2c->irq < 0) { dev_err(&pdev->dev, "IRQ error for i2c-geni\n"); @@ -584,6 +596,8 @@ static int geni_i2c_probe(struct platform_device *pdev) return ret; } + dev_dbg(&pdev->dev, "Geni-I2C adaptor successfully added\n"); + return 0; } @@ -660,6 +674,7 @@ static struct platform_driver geni_i2c_driver = { .name = "geni_i2c", .pm = &geni_i2c_pm_ops, .of_match_table = geni_i2c_dt_match, + .acpi_match_table = ACPI_PTR(geni_i2c_acpi_match), }, }; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 53bc021f4a5a..ed06a8535d63 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -33,7 +33,7 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/pinctrl/consumer.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> @@ -122,7 +122,7 @@ struct s3c24xx_i2c { struct i2c_adapter adap; struct s3c2410_platform_i2c *pdata; - int gpios[2]; + struct gpio_desc *gpios[2]; struct pinctrl *pctrl; #if defined(CONFIG_ARM_S3C24XX_CPUFREQ) struct notifier_block freq_transition; @@ -956,53 +956,27 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) #ifdef CONFIG_OF static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) { - int idx, gpio, ret; + int i; if (i2c->quirks & QUIRK_NO_GPIO) return 0; - for (idx = 0; idx < 2; idx++) { - gpio = of_get_gpio(i2c->dev->of_node, idx); - if (!gpio_is_valid(gpio)) { - dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); - goto free_gpio; - } - i2c->gpios[idx] = gpio; - - ret = gpio_request(gpio, "i2c-bus"); - if (ret) { - dev_err(i2c->dev, "gpio [%d] request failed (%d)\n", - gpio, ret); - goto free_gpio; + for (i = 0; i < 2; i++) { + i2c->gpios[i] = devm_gpiod_get_index(i2c->dev, NULL, + i, GPIOD_ASIS); + if (IS_ERR(i2c->gpios[i])) { + dev_err(i2c->dev, "i2c gpio invalid at index %d\n", i); + return -EINVAL; } } return 0; - -free_gpio: - while (--idx >= 0) - gpio_free(i2c->gpios[idx]); - return -EINVAL; } -static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) -{ - unsigned int idx; - - if (i2c->quirks & QUIRK_NO_GPIO) - return; - - for (idx = 0; idx < 2; idx++) - gpio_free(i2c->gpios[idx]); -} #else static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) { return 0; } - -static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) -{ -} #endif /* @@ -1231,9 +1205,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); - if (pdev->dev.of_node && IS_ERR(i2c->pctrl)) - s3c24xx_i2c_dt_gpio_free(i2c); - return 0; } diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 48337bef5b87..3d90c0bb049e 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -25,7 +25,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> @@ -1816,15 +1815,14 @@ static struct i2c_algorithm stm32f7_i2c_algo = { static int stm32f7_i2c_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; struct stm32f7_i2c_dev *i2c_dev; const struct stm32f7_i2c_setup *setup; struct resource *res; - u32 irq_error, irq_event, clk_rate, rise_time, fall_time; + u32 clk_rate, rise_time, fall_time; struct i2c_adapter *adap; struct reset_control *rst; dma_addr_t phy_addr; - int ret; + int irq_error, irq_event, ret; i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) @@ -1836,16 +1834,20 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) return PTR_ERR(i2c_dev->base); phy_addr = (dma_addr_t)res->start; - irq_event = irq_of_parse_and_map(np, 0); - if (!irq_event) { - dev_err(&pdev->dev, "IRQ event missing or invalid\n"); - return -EINVAL; + irq_event = platform_get_irq(pdev, 0); + if (irq_event <= 0) { + if (irq_event != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get IRQ event: %d\n", + irq_event); + return irq_event ? : -ENOENT; } - irq_error = irq_of_parse_and_map(np, 1); - if (!irq_error) { - dev_err(&pdev->dev, "IRQ error missing or invalid\n"); - return -EINVAL; + irq_error = platform_get_irq(pdev, 1); + if (irq_error <= 0) { + if (irq_error != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get IRQ error: %d\n", + irq_error); + return irq_error ? : -ENOENT; } i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index ebaa78d17d6e..9fcb13beeb8f 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -54,20 +54,15 @@ #define I2C_INT_STATUS 0x068 #define I2C_INT_BUS_CLR_DONE BIT(11) #define I2C_INT_PACKET_XFER_COMPLETE BIT(7) -#define I2C_INT_ALL_PACKETS_XFER_COMPLETE BIT(6) -#define I2C_INT_TX_FIFO_OVERFLOW BIT(5) -#define I2C_INT_RX_FIFO_UNDERFLOW BIT(4) #define I2C_INT_NO_ACK BIT(3) #define I2C_INT_ARBITRATION_LOST BIT(2) #define I2C_INT_TX_FIFO_DATA_REQ BIT(1) #define I2C_INT_RX_FIFO_DATA_REQ BIT(0) #define I2C_CLK_DIVISOR 0x06c #define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16 -#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8 #define DVC_CTRL_REG1 0x000 #define DVC_CTRL_REG1_INTR_EN BIT(10) -#define DVC_CTRL_REG2 0x004 #define DVC_CTRL_REG3 0x008 #define DVC_CTRL_REG3_SW_PROG BIT(26) #define DVC_CTRL_REG3_I2C_DONE_INTR_EN BIT(30) @@ -75,24 +70,22 @@ #define DVC_STATUS_I2C_DONE_INTR BIT(30) #define I2C_ERR_NONE 0x00 -#define I2C_ERR_NO_ACK 0x01 -#define I2C_ERR_ARBITRATION_LOST 0x02 -#define I2C_ERR_UNKNOWN_INTERRUPT 0x04 +#define I2C_ERR_NO_ACK BIT(0) +#define I2C_ERR_ARBITRATION_LOST BIT(1) +#define I2C_ERR_UNKNOWN_INTERRUPT BIT(2) +#define I2C_ERR_RX_BUFFER_OVERFLOW BIT(3) #define PACKET_HEADER0_HEADER_SIZE_SHIFT 28 #define PACKET_HEADER0_PACKET_ID_SHIFT 16 #define PACKET_HEADER0_CONT_ID_SHIFT 12 #define PACKET_HEADER0_PROTOCOL_I2C BIT(4) -#define I2C_HEADER_HIGHSPEED_MODE BIT(22) #define I2C_HEADER_CONT_ON_NAK BIT(21) -#define I2C_HEADER_SEND_START_BYTE BIT(20) #define I2C_HEADER_READ BIT(19) #define I2C_HEADER_10BIT_ADDR BIT(18) #define I2C_HEADER_IE_ENABLE BIT(17) #define I2C_HEADER_REPEAT_START BIT(16) #define I2C_HEADER_CONTINUE_XFER BIT(15) -#define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT 1 #define I2C_BUS_CLEAR_CNFG 0x084 @@ -106,8 +99,6 @@ #define I2C_CONFIG_LOAD 0x08C #define I2C_MSTR_CONFIG_LOAD BIT(0) -#define I2C_SLV_CONFIG_LOAD BIT(1) -#define I2C_TIMEOUT_CONFIG_LOAD BIT(2) #define I2C_CLKEN_OVERRIDE 0x090 #define I2C_MST_CORE_CLKEN_OVR BIT(0) @@ -133,7 +124,6 @@ #define I2C_STANDARD_MODE 100000 #define I2C_FAST_MODE 400000 #define I2C_FAST_PLUS_MODE 1000000 -#define I2C_HS_MODE 3500000 /* Packet header size in bytes */ #define I2C_PACKET_HEADER_SIZE 12 @@ -280,6 +270,7 @@ struct tegra_i2c_dev { u32 bus_clk_rate; u16 clk_divisor_non_hs_mode; bool is_multimaster_mode; + /* xfer_lock: lock to serialize transfer submission and processing */ spinlock_t xfer_lock; struct dma_chan *tx_dma_chan; struct dma_chan *rx_dma_chan; @@ -306,7 +297,7 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) * to the I2C block inside the DVC block */ static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, - unsigned long reg) + unsigned long reg) { if (i2c_dev->is_dvc) reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; @@ -314,7 +305,7 @@ static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, } static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, - unsigned long reg) + unsigned long reg) { writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); @@ -329,13 +320,13 @@ static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) } static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data, - unsigned long reg, int len) + unsigned long reg, int len) { writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); } static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, - unsigned long reg, int len) + unsigned long reg, int len) { readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); } @@ -486,7 +477,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n"); return -ETIMEDOUT; } - msleep(1); + usleep_range(1000, 2000); } return 0; } @@ -499,6 +490,13 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) size_t buf_remaining = i2c_dev->msg_buf_remaining; int words_to_transfer; + /* + * Catch overflow due to message fully sent + * before the check for RX FIFO availability. + */ + if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining))) + return -EINVAL; + if (i2c_dev->hw->has_mst_fifo) { val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS); rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >> @@ -525,7 +523,11 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) * prevent overwriting past the end of buf */ if (rx_fifo_avail > 0 && buf_remaining > 0) { - BUG_ON(buf_remaining > 3); + /* + * buf_remaining > 3 check not needed as rx_fifo_avail == 0 + * when (words_to_transfer was > rx_fifo_avail) earlier + * in this function. + */ val = i2c_readl(i2c_dev, I2C_RX_FIFO); val = cpu_to_le32(val); memcpy(buf, &val, buf_remaining); @@ -533,7 +535,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) rx_fifo_avail--; } - BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0); + /* RX FIFO must be drained, otherwise it's an Overflow case. */ + if (WARN_ON_ONCE(rx_fifo_avail)) + return -EINVAL; + i2c_dev->msg_buf_remaining = buf_remaining; i2c_dev->msg_buf = buf; @@ -591,7 +596,11 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) * boundary and fault. */ if (tx_fifo_avail > 0 && buf_remaining > 0) { - BUG_ON(buf_remaining > 3); + /* + * buf_remaining > 3 check not needed as tx_fifo_avail == 0 + * when (words_to_transfer was > tx_fifo_avail) earlier + * in this function for non-zero words_to_transfer. + */ memcpy(&val, buf, buf_remaining); val = le32_to_cpu(val); @@ -680,10 +689,11 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); if (in_interrupt()) err = readl_poll_timeout_atomic(addr, val, val == 0, - 1000, I2C_CONFIG_LOAD_TIMEOUT); + 1000, + I2C_CONFIG_LOAD_TIMEOUT); else - err = readl_poll_timeout(addr, val, val == 0, - 1000, I2C_CONFIG_LOAD_TIMEOUT); + err = readl_poll_timeout(addr, val, val == 0, 1000, + I2C_CONFIG_LOAD_TIMEOUT); if (err) { dev_warn(i2c_dev->dev, @@ -700,7 +710,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) u32 val; int err; u32 clk_divisor, clk_multiplier; - u32 tsu_thd = 0; + u32 tsu_thd; u8 tlow, thigh; err = pm_runtime_get_sync(i2c_dev->dev); @@ -856,10 +866,15 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) if (!i2c_dev->is_curr_dma_xfer) { if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { - if (i2c_dev->msg_buf_remaining) - tegra_i2c_empty_rx_fifo(i2c_dev); - else - BUG(); + if (tegra_i2c_empty_rx_fifo(i2c_dev)) { + /* + * Overflow error condition: message fully sent, + * with no XFER_COMPLETE interrupt but hardware + * asks to transfer more. + */ + i2c_dev->msg_err |= I2C_ERR_RX_BUFFER_OVERFLOW; + goto err; + } } if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { @@ -885,7 +900,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) if (status & I2C_INT_PACKET_XFER_COMPLETE) { if (i2c_dev->is_curr_dma_xfer) i2c_dev->msg_buf_remaining = 0; - BUG_ON(i2c_dev->msg_buf_remaining); + /* + * Underflow error condition: XFER_COMPLETE before message + * fully sent. + */ + if (WARN_ON_ONCE(i2c_dev->msg_buf_remaining)) { + i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT; + goto err; + } complete(&i2c_dev->msg_complete); } goto done; @@ -1024,7 +1046,8 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) } static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, enum msg_end_type end_state) + struct i2c_msg *msg, + enum msg_end_type end_state) { u32 packet_header; u32 int_mask; @@ -1161,9 +1184,8 @@ unlock: if (err) return err; - time_left = wait_for_completion_timeout( - &i2c_dev->dma_complete, - msecs_to_jiffies(xfer_time)); + time_left = wait_for_completion_timeout(&i2c_dev->dma_complete, + msecs_to_jiffies(xfer_time)); if (time_left == 0) { dev_err(i2c_dev->dev, "DMA transfer timeout\n"); dmaengine_terminate_sync(i2c_dev->msg_read ? @@ -1225,11 +1247,11 @@ unlock: } static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - int num) + int num) { struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); int i; - int ret = 0; + int ret; ret = pm_runtime_get_sync(i2c_dev->dev); if (ret < 0) { @@ -1271,14 +1293,15 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) { struct device_node *np = i2c_dev->dev->of_node; int ret; + bool multi_mode; ret = of_property_read_u32(np, "clock-frequency", - &i2c_dev->bus_clk_rate); + &i2c_dev->bus_clk_rate); if (ret) i2c_dev->bus_clk_rate = 100000; /* default clock rate */ - i2c_dev->is_multimaster_mode = of_property_read_bool(np, - "multi-master"); + multi_mode = of_property_read_bool(np, "multi-master"); + i2c_dev->is_multimaster_mode = multi_mode; } static const struct i2c_algorithm tegra_i2c_algo = { @@ -1500,7 +1523,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) void __iomem *base; phys_addr_t base_phys; int irq; - int ret = 0; + int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base_phys = res->start; @@ -1517,7 +1540,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) div_clk = devm_clk_get(&pdev->dev, "div-clk"); if (IS_ERR(div_clk)) { - dev_err(&pdev->dev, "missing controller clock\n"); + if (PTR_ERR(div_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "missing controller clock\n"); + return PTR_ERR(div_clk); } @@ -1622,7 +1647,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(&pdev->dev, i2c_dev->irq, - tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); + tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); goto release_dma; @@ -1687,10 +1712,35 @@ static int tegra_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP +static int tegra_i2c_suspend(struct device *dev) +{ + struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); + + i2c_mark_adapter_suspended(&i2c_dev->adapter); + + return 0; +} + +static int tegra_i2c_resume(struct device *dev) +{ + struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); + int err; + + err = tegra_i2c_init(i2c_dev, false); + if (err) + return err; + + i2c_mark_adapter_resumed(&i2c_dev->adapter); + + return 0; +} + static const struct dev_pm_ops tegra_i2c_pm = { + SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume) SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume, NULL) }; + #define TEGRA_I2C_PM (&tegra_i2c_pm) #else #define TEGRA_I2C_PM NULL |