diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 7 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-at91.c | 23 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-bcm283x.c | 36 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-cadence.c | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware.c | 9 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-gpio.c | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx-early.c | 57 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx-lpi2c.c | 555 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 42 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 15 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-rockchip.c | 25 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32.c | 455 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-versatile.c | 7 | ||||
-rw-r--r-- | drivers/i2c/i2c-mux.c | 10 | ||||
-rw-r--r-- | drivers/i2c/i2c.c | 115 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-pca954x.c | 8 |
20 files changed, 1107 insertions, 308 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 2d6010869d..9b7e5d96f0 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -245,7 +245,7 @@ static int i2c_inb(struct i2c_adapter *i2c_adap) static int test_bus(struct i2c_adapter *i2c_adap) { struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - struct device_d *dev = &i2c_adap->dev; + struct device *dev = &i2c_adap->dev; int scl, sda, ret; if (adap->pre_xfer) { diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 766aa5edfa..a274baf4b6 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -30,6 +30,13 @@ config I2C_IMX for many i.MX ARM based SoCs, for MPC85xx and MPC5200 PowerPC based SoCs. +config I2C_IMX_LPI2C + tristate "IMX Low Power I2C interface" + depends on ARCH_IMX || COMPILE_TEST + help + Say Y here if you want to use the Low Power IIC bus controller + on the Freescale i.MX processors. + config I2C_DESIGNWARE bool "Synopsys DesignWare I2C Master driver" help diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index a1ab46fb28..b4225995c0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_I2C_BCM283X) += i2c-bcm283x.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o lwl-$(CONFIG_I2C_IMX_EARLY) += i2c-imx-early.o +obj-pbl-$(CONFIG_I2C_IMX_LPI2C) += i2c-imx-lpi2c.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index b100dc6c17..5b1f456187 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -78,11 +78,10 @@ struct at91_twi_pdata { bool has_dig_filtr; bool has_adv_dig_filtr; bool has_ana_filtr; - bool has_clear_cmd; }; struct at91_twi_dev { - struct device_d *dev; + struct device *dev; void __iomem *base; struct clk *clk; u8 *buf; @@ -438,6 +437,13 @@ static struct at91_twi_pdata at91sam9x5_config = { .has_unre_flag = false, }; +static struct at91_twi_pdata sama5d4_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_hold_field = true, + .has_dig_filtr = true, +}; + static struct at91_twi_pdata sama5d2_config = { .clk_max_div = 7, .clk_offset = 3, @@ -493,14 +499,21 @@ static struct of_device_id at91_twi_dt_ids[] = { .compatible = "atmel,at91sam9x5-i2c", .data = &at91sam9x5_config, }, { + .compatible = "atmel,sama5d4-i2c", + .data = &sama5d4_config, + }, { .compatible = "atmel,sama5d2-i2c", .data = &sama5d2_config, }, { + .compatible = "microchip,sam9x60-i2c", + .data = &sama5d2_config, + }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, at91_twi_dt_ids); -static int at91_twi_probe(struct device_d *dev) +static int at91_twi_probe(struct device *dev) { struct resource *iores; struct at91_twi_dev *i2c_at91; @@ -546,7 +559,7 @@ static int at91_twi_probe(struct device_d *dev) i2c_at91->adapter.master_xfer = at91_twi_xfer; i2c_at91->adapter.dev.parent = dev; i2c_at91->adapter.nr = dev->id; - i2c_at91->adapter.dev.device_node = dev->device_node; + i2c_at91->adapter.dev.of_node = dev->of_node; rc = i2c_add_numbered_adapter(&i2c_at91->adapter); if (rc) { @@ -565,7 +578,7 @@ out_free: return rc; } -static struct driver_d at91_twi_driver = { +static struct driver at91_twi_driver = { .name = "at91-twi", .probe = at91_twi_probe, .id_table = at91_twi_devtypes, diff --git a/drivers/i2c/busses/i2c-bcm283x.c b/drivers/i2c/busses/i2c-bcm283x.c index 097f73d983..b40918932f 100644 --- a/drivers/i2c/busses/i2c-bcm283x.c +++ b/drivers/i2c/busses/i2c-bcm283x.c @@ -74,7 +74,7 @@ static inline struct bcm283x_i2c *to_bcm283x_i2c(struct i2c_adapter *adapter) static inline int bcm283x_i2c_init(struct bcm283x_i2c *bcm_i2c) { - struct device_d *dev = &bcm_i2c->adapter.dev; + struct device *dev = bcm_i2c->adapter.dev.parent; u32 mclk_rate, cdiv, redl, fedl; /* @@ -130,7 +130,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, { int ret; u32 reg_c, reg_s, reg_dlen, timeout; - struct device_d *dev = &bcm_i2c->adapter.dev; + struct device *dev = &bcm_i2c->adapter.dev; bool msg_read = (msg->flags & I2C_M_RD) > 0; bool msg_10bit = (msg->flags & I2C_M_TEN) > 0; u16 buf_pos = 0; @@ -147,7 +147,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: 10bit read initilization\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; @@ -178,7 +178,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: waiting for data in FIFO\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; @@ -197,7 +197,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: waiting for space in FIFO\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; @@ -216,16 +216,23 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: waiting for transfer to end\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; - writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s); - writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c); - return 0; + goto out; nack: dev_dbg(dev, "device with addr %x didn't ACK\n", msg->addr); - return -EREMOTEIO; + writel(BSC_S_ERR, &bcm_i2c->regs->s); + timeout = calc_byte_timeout_us(bcm_i2c->bitrate); + // Wait for end of transfer so BSC has time to send STOP condition + readl_poll_timeout(&bcm_i2c->regs->s, reg_s, ~reg_s & BSC_S_TA, timeout); + ret = -EREMOTEIO; +out: + // Return to default state for next xfer + writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s); + writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c); + return ret; } static int bcm283x_i2c_xfer(struct i2c_adapter *adapter, @@ -259,12 +266,12 @@ out: return ret; } -static int bcm283x_i2c_probe(struct device_d *dev) +static int bcm283x_i2c_probe(struct device *dev) { int ret; struct resource *iores; struct bcm283x_i2c *bcm_i2c; - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; bcm_i2c = xzalloc(sizeof(*bcm_i2c)); @@ -301,7 +308,7 @@ static int bcm283x_i2c_probe(struct device_d *dev) bcm_i2c->adapter.master_xfer = bcm283x_i2c_xfer; bcm_i2c->adapter.nr = dev->id; bcm_i2c->adapter.dev.parent = dev; - bcm_i2c->adapter.dev.device_node = np; + bcm_i2c->adapter.dev.of_node = np; ret = bcm283x_i2c_init(bcm_i2c); if (ret) @@ -318,8 +325,9 @@ static struct of_device_id bcm283x_i2c_dt_ids[] = { { .compatible = "brcm,bcm2711-i2c", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, bcm283x_i2c_dt_ids); -static struct driver_d bcm283x_i2c_driver = { +static struct driver bcm283x_i2c_driver = { .name = "i2c-bcm283x", .probe = bcm283x_i2c_probe, .of_compatible = DRV_OF_COMPAT(bcm283x_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 5537efff23..bf9ec30994 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -16,7 +16,7 @@ #include <driver.h> #include <io.h> #include <linux/clk.h> -#include <regmap.h> +#include <linux/regmap.h> struct __packed i2c_regs { u32 control; @@ -396,9 +396,9 @@ static int cdns_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, return nmsgs; } -static int cdns_i2c_probe(struct device_d *dev) +static int cdns_i2c_probe(struct device *dev) { - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; struct resource *iores; struct cdns_i2c *i2c; u32 bitrate; @@ -424,7 +424,7 @@ static int cdns_i2c_probe(struct device_d *dev) i2c->adapter.master_xfer = cdns_i2c_xfer; i2c->adapter.nr = dev->id; i2c->adapter.dev.parent = dev; - i2c->adapter.dev.device_node = np; + i2c->adapter.dev.of_node = np; cdns_i2c_reset_hardware(i2c); @@ -444,8 +444,9 @@ static const struct of_device_id cdns_i2c_match[] = { { .compatible = "cdns,i2c-r1p14" }, {}, }; +MODULE_DEVICE_TABLE(of, cdns_i2c_match); -static struct driver_d cdns_i2c_driver = { +static struct driver cdns_i2c_driver = { .name = "cdns-i2c", .of_compatible = cdns_i2c_match, .probe = cdns_i2c_probe, diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index 93b7af6623..152b795c37 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c @@ -245,7 +245,7 @@ static void i2c_dw_setup_timings(struct dw_i2c_dev *dw) u32 ht; int ret; - ret = of_property_read_u32(dw->adapter.dev.device_node, + ret = of_property_read_u32(dw->adapter.dev.of_node, "i2c-sda-hold-time-ns", &ht); if (ret) { /* Keep previous hold time setting if no one set it */ @@ -504,7 +504,7 @@ static int i2c_dw_xfer(struct i2c_adapter *adapter, } -static int i2c_dw_probe(struct device_d *pdev) +static int i2c_dw_probe(struct device *pdev) { struct resource *iores; struct dw_i2c_dev *dw; @@ -527,7 +527,7 @@ static int i2c_dw_probe(struct device_d *pdev) dw->adapter.master_xfer = i2c_dw_xfer; dw->adapter.nr = pdev->id; dw->adapter.dev.parent = pdev; - dw->adapter.dev.device_node = pdev->device_node; + dw->adapter.dev.of_node = pdev->of_node; iores = dev_request_mem_resource(pdev, 0); if (IS_ERR(iores)) { @@ -599,8 +599,9 @@ static __maybe_unused struct of_device_id i2c_dw_dt_ids[] = { { .compatible = "snps,designware-i2c", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, i2c_dw_dt_ids); -static struct driver_d i2c_dw_driver = { +static struct driver i2c_dw_driver = { .probe = i2c_dw_probe, .name = "i2c-designware", .of_compatible = DRV_OF_COMPAT(i2c_dw_dt_ids), diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index ad0c4c8f82..3649c8b189 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -126,7 +126,7 @@ static int of_i2c_gpio_probe(struct device_node *np, return 0; } -static int i2c_gpio_probe(struct device_d *dev) +static int i2c_gpio_probe(struct device *dev) { struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; @@ -140,8 +140,8 @@ static int i2c_gpio_probe(struct device_d *dev) bit_data = &priv->bit_data; pdata = &priv->pdata; - if (dev->device_node) { - ret = of_i2c_gpio_probe(dev->device_node, pdata); + if (dev->of_node) { + ret = of_i2c_gpio_probe(dev->of_node, pdata); if (ret) return ret; } else { @@ -193,7 +193,7 @@ static int i2c_gpio_probe(struct device_d *dev) adap->algo_data = bit_data; adap->dev.parent = dev; - adap->dev.device_node = dev->device_node; + adap->dev.of_node = dev->of_node; adap->bus_recovery_info = xzalloc(sizeof(*adap->bus_recovery_info)); adap->bus_recovery_info->scl_gpio = pdata->scl_pin; adap->bus_recovery_info->sda_gpio = pdata->sda_pin; @@ -228,8 +228,9 @@ static struct of_device_id i2c_gpio_dt_ids[] = { { .compatible = "i2c-gpio", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); -static struct driver_d i2c_gpio_driver = { +static struct driver i2c_gpio_driver = { .name = "i2c-gpio", .probe = i2c_gpio_probe, .of_compatible = DRV_OF_COMPAT(i2c_gpio_dt_ids), diff --git a/drivers/i2c/busses/i2c-imx-early.c b/drivers/i2c/busses/i2c-imx-early.c index a79d7bd88c..1db48a85e5 100644 --- a/drivers/i2c/busses/i2c-imx-early.c +++ b/drivers/i2c/busses/i2c-imx-early.c @@ -9,11 +9,12 @@ */ #include <common.h> #include <i2c/i2c.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> #include "i2c-imx.h" struct fsl_i2c { + struct pbl_i2c i2c; void __iomem *regs; unsigned int i2cr_ien_opcode; unsigned int i2sr_clr_opcode; @@ -89,6 +90,26 @@ static int i2c_fsl_acked(struct fsl_i2c *fsl_i2c) return i2c_fsl_poll_status(fsl_i2c, 0, I2SR_RXAK); } +static void i2c_fsl_settle(struct fsl_i2c *fsl_i2c) +{ +#ifdef CPU_ARCH_ARMv8 + udelay(100); +#else + /* + * We lack udelay on the 32bit i.MX SoCs, so delay manually: On an + * i.MX6 with a 66Mhz I2C peripheral clock one cycle of this loop + * takes 1.30us. Let's be generous and round up to 100 cycles. Other + * i.MX SoCs do not have a higher peripheral clock, so we should be + * safe here as well. + */ + + volatile int i = 0; + + for (i = 0; i < 100; i++) + fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2SR); +#endif +} + static int i2c_fsl_start(struct fsl_i2c *fsl_i2c) { unsigned int temp = 0; @@ -103,7 +124,7 @@ static int i2c_fsl_start(struct fsl_i2c *fsl_i2c) fsl_i2c, FSL_I2C_I2CR); /* Wait controller to be stable */ - udelay(100); + i2c_fsl_settle(fsl_i2c); /* Start I2C transaction */ temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2CR); @@ -170,7 +191,7 @@ static int i2c_fsl_write(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg) /* write data */ for (i = 0; i < msg->len; i++) { ret = i2c_fsl_send(fsl_i2c, msg->buf[i]); - if (ret) + if (ret) return ret; } @@ -229,9 +250,9 @@ static int i2c_fsl_read(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg) * If successful returns the number of messages transferred, otherwise a negative * error code is returned. */ -int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num) +static int i2c_fsl_xfer(struct pbl_i2c *i2c, struct i2c_msg *msgs, int num) { - struct fsl_i2c *fsl_i2c = ctx; + struct fsl_i2c *fsl_i2c = container_of(i2c, struct fsl_i2c, i2c); unsigned int i, temp; int ret; @@ -288,7 +309,7 @@ static struct fsl_i2c fsl_i2c; * This function returns a context pointer suitable to transfer I2C messages * using i2c_fsl_xfer. */ -void *ls1046_i2c_init(void __iomem *regs) +struct pbl_i2c *ls1046_i2c_init(void __iomem *regs) { fsl_i2c.regs = regs; fsl_i2c.regshift = 0; @@ -297,10 +318,26 @@ void *ls1046_i2c_init(void __iomem *regs) /* Divider for ~100kHz when coming from the ROM */ fsl_i2c.ifdr = 0x3e; - return &fsl_i2c; + fsl_i2c.i2c.xfer = i2c_fsl_xfer; + + return &fsl_i2c.i2c; } -void *imx8m_i2c_early_init(void __iomem *regs) +struct pbl_i2c *imx6_i2c_early_init(void __iomem *regs) +{ + fsl_i2c.regs = regs; + fsl_i2c.regshift = 2; + fsl_i2c.i2cr_ien_opcode = I2CR_IEN_OPCODE_1; + fsl_i2c.i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C; + /* Divider for ~100kHz when coming from the ROM */ + fsl_i2c.ifdr = 0x36; + + fsl_i2c.i2c.xfer = i2c_fsl_xfer; + + return &fsl_i2c.i2c; +} + +struct pbl_i2c *imx8m_i2c_early_init(void __iomem *regs) { fsl_i2c.regs = regs; fsl_i2c.regshift = 2; @@ -309,5 +346,7 @@ void *imx8m_i2c_early_init(void __iomem *regs) /* Divider for ~100kHz when coming from the ROM */ fsl_i2c.ifdr = 0x0f; - return &fsl_i2c; + fsl_i2c.i2c.xfer = i2c_fsl_xfer; + + return &fsl_i2c.i2c; } diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c new file mode 100644 index 0000000000..e32bc4fd18 --- /dev/null +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -0,0 +1,555 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * This is i.MX low power i2c controller driver. + * + * Copyright 2016 Freescale Semiconductor, Inc. + */ + +#include <clock.h> +#include <common.h> +#include <driver.h> +#include <init.h> +#include <of.h> +#include <gpio.h> +#include <malloc.h> +#include <types.h> +#include <xfuncs.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <pinctrl.h> +#include <of_gpio.h> +#include <of_device.h> +#include <pbl/i2c.h> + +#include <io.h> +#include <i2c/i2c.h> + +#define DRIVER_NAME "imx-lpi2c" + +#define LPI2C_PARAM 0x04 /* i2c RX/TX FIFO size */ +#define LPI2C_MCR 0x10 /* i2c contrl register */ +#define LPI2C_MSR 0x14 /* i2c status register */ +#define LPI2C_MIER 0x18 /* i2c interrupt enable */ +#define LPI2C_MCFGR0 0x20 /* i2c master configuration */ +#define LPI2C_MCFGR1 0x24 /* i2c master configuration */ +#define LPI2C_MCFGR2 0x28 /* i2c master configuration */ +#define LPI2C_MCFGR3 0x2C /* i2c master configuration */ +#define LPI2C_MCCR0 0x48 /* i2c master clk configuration */ +#define LPI2C_MCCR1 0x50 /* i2c master clk configuration */ +#define LPI2C_MFCR 0x58 /* i2c master FIFO control */ +#define LPI2C_MFSR 0x5C /* i2c master FIFO status */ +#define LPI2C_MTDR 0x60 /* i2c master TX data register */ +#define LPI2C_MRDR 0x70 /* i2c master RX data register */ + +/* i2c command */ +#define TRAN_DATA 0X00 +#define RECV_DATA 0X01 +#define GEN_STOP 0X02 +#define RECV_DISCARD 0X03 +#define GEN_START 0X04 +#define START_NACK 0X05 +#define START_HIGH 0X06 +#define START_HIGH_NACK 0X07 + +#define MCR_MEN BIT(0) +#define MCR_RST BIT(1) +#define MCR_DOZEN BIT(2) +#define MCR_DBGEN BIT(3) +#define MCR_RTF BIT(8) +#define MCR_RRF BIT(9) +#define MSR_TDF BIT(0) +#define MSR_RDF BIT(1) +#define MSR_SDF BIT(9) +#define MSR_NDF BIT(10) +#define MSR_ALF BIT(11) +#define MSR_MBF BIT(24) +#define MSR_BBF BIT(25) +#define MIER_TDIE BIT(0) +#define MIER_RDIE BIT(1) +#define MIER_SDIE BIT(9) +#define MIER_NDIE BIT(10) +#define MCFGR1_AUTOSTOP BIT(8) +#define MCFGR1_IGNACK BIT(9) +#define MRDR_RXEMPTY BIT(14) + +#define I2C_CLK_RATIO 2 +#define CHUNK_DATA 256 + +#define I2C_PM_TIMEOUT 10 /* ms */ + +enum lpi2c_imx_mode { + STANDARD, /* 100+Kbps */ + FAST, /* 400+Kbps */ + FAST_PLUS, /* 1.0+Mbps */ + HS, /* 3.4+Mbps */ + ULTRA_FAST, /* 5.0+Mbps */ +}; + +enum lpi2c_imx_pincfg { + TWO_PIN_OD, + TWO_PIN_OO, + TWO_PIN_PP, + FOUR_PIN_PP, +}; + +struct lpi2c_imx_struct { + struct i2c_adapter adapter; + struct pbl_i2c pbl_i2c; + int num_clks; + struct clk_bulk_data *clks; + void __iomem *base; + __u8 *rx_buf; + __u8 *tx_buf; + unsigned int msglen; + unsigned int delivered; + unsigned int bitrate; + unsigned int txfifosize; + unsigned int rxfifosize; + enum lpi2c_imx_mode mode; + unsigned long clk_rate; +}; + +static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, + unsigned int enable) +{ + writel(enable, lpi2c_imx->base + LPI2C_MIER); +} + +static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int temp; + unsigned int timeout = 500000; + + while (1) { + temp = readl(lpi2c_imx->base + LPI2C_MSR); + + /* check for arbitration lost, clear if set */ + if (temp & (MSR_ALF | MSR_NDF)) { + writel(temp, lpi2c_imx->base + LPI2C_MSR); + return -EAGAIN; + } + + if (temp & (MSR_BBF | MSR_MBF)) + break; + + udelay(1); + if (!timeout--) { + dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int bitrate = lpi2c_imx->bitrate; + enum lpi2c_imx_mode mode; + + if (bitrate < I2C_MAX_FAST_MODE_FREQ) + mode = STANDARD; + else if (bitrate < I2C_MAX_FAST_MODE_PLUS_FREQ) + mode = FAST; + else if (bitrate < I2C_MAX_HIGH_SPEED_MODE_FREQ) + mode = FAST_PLUS; + else if (bitrate < I2C_MAX_ULTRA_FAST_MODE_FREQ) + mode = HS; + else + mode = ULTRA_FAST; + + lpi2c_imx->mode = mode; +} + +static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msgs) +{ + unsigned int temp; + + temp = readl(lpi2c_imx->base + LPI2C_MCR); + temp |= MCR_RRF | MCR_RTF; + writel(temp, lpi2c_imx->base + LPI2C_MCR); + writel(0x7f00, lpi2c_imx->base + LPI2C_MSR); + + temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START << 8); + writel(temp, lpi2c_imx->base + LPI2C_MTDR); + + return lpi2c_imx_bus_busy(lpi2c_imx); +} + +static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int temp; + unsigned int timeout = 500000; + + writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR); + + do { + temp = readl(lpi2c_imx->base + LPI2C_MSR); + if (temp & MSR_SDF) + break; + + udelay(1); + if (!timeout--) { + dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n"); + break; + } + + } while (1); +} + +/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */ +static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) +{ + u8 prescale, filt, sethold, datavd; + unsigned int clk_cycle, clkhi, clklo; + enum lpi2c_imx_pincfg pincfg; + unsigned int temp; + + lpi2c_imx_set_mode(lpi2c_imx); + + if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST) + filt = 0; + else + filt = 2; + + for (prescale = 0; prescale <= 7; prescale++) { + clk_cycle = lpi2c_imx->clk_rate / ((1 << prescale) * lpi2c_imx->bitrate) + - 3 - (filt >> 1); + clkhi = DIV_ROUND_UP(clk_cycle, I2C_CLK_RATIO + 1); + clklo = clk_cycle - clkhi; + if (clklo < 64) + break; + } + + if (prescale > 7) + return -EINVAL; + + /* set MCFGR1: PINCFG, PRESCALE, IGNACK */ + if (lpi2c_imx->mode == ULTRA_FAST) + pincfg = TWO_PIN_OO; + else + pincfg = TWO_PIN_OD; + temp = prescale | pincfg << 24; + + if (lpi2c_imx->mode == ULTRA_FAST) + temp |= MCFGR1_IGNACK; + + writel(temp, lpi2c_imx->base + LPI2C_MCFGR1); + + /* set MCFGR2: FILTSDA, FILTSCL */ + temp = (filt << 16) | (filt << 24); + writel(temp, lpi2c_imx->base + LPI2C_MCFGR2); + + /* set MCCR: DATAVD, SETHOLD, CLKHI, CLKLO */ + sethold = clkhi; + datavd = clkhi >> 1; + temp = datavd << 24 | sethold << 16 | clkhi << 8 | clklo; + + if (lpi2c_imx->mode == HS) + writel(temp, lpi2c_imx->base + LPI2C_MCCR1); + else + writel(temp, lpi2c_imx->base + LPI2C_MCCR0); + + return 0; +} + +static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int temp; + int ret; + + temp = MCR_RST; + writel(temp, lpi2c_imx->base + LPI2C_MCR); + writel(0, lpi2c_imx->base + LPI2C_MCR); + + ret = lpi2c_imx_config(lpi2c_imx); + if (ret) + return ret; + + temp = readl(lpi2c_imx->base + LPI2C_MCR); + temp |= MCR_MEN; + writel(temp, lpi2c_imx->base + LPI2C_MCR); + + return 0; +} + +static int lpi2c_imx_master_disable(struct lpi2c_imx_struct *lpi2c_imx) +{ + u32 temp; + + temp = readl(lpi2c_imx->base + LPI2C_MCR); + temp &= ~MCR_MEN; + writel(temp, lpi2c_imx->base + LPI2C_MCR); + + return 0; +} + +static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx) +{ + u32 txcnt; + unsigned int timeout = 500000; + + do { + txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff; + + if (readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) { + dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n"); + return -EIO; + } + + udelay(1); + if (!timeout--) { + dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n"); + return -ETIMEDOUT; + } + + } while (txcnt); + + return 0; +} + +static void lpi2c_imx_set_tx_watermark(struct lpi2c_imx_struct *lpi2c_imx) +{ + writel(lpi2c_imx->txfifosize >> 1, lpi2c_imx->base + LPI2C_MFCR); +} + +static void lpi2c_imx_set_rx_watermark(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int temp, remaining; + + remaining = lpi2c_imx->msglen - lpi2c_imx->delivered; + + if (remaining > (lpi2c_imx->rxfifosize >> 1)) + temp = lpi2c_imx->rxfifosize >> 1; + else + temp = 0; + + writel(temp << 16, lpi2c_imx->base + LPI2C_MFCR); +} + +static int lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int data, remaining; + unsigned int timeout = 100000;; + + do { + u32 cnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff; + if (cnt == lpi2c_imx->txfifosize) { + udelay(1); + if (!timeout--) + return -EIO; + continue; + } + + data = lpi2c_imx->tx_buf[lpi2c_imx->delivered++]; + + writel(data, lpi2c_imx->base + LPI2C_MTDR); + remaining = lpi2c_imx->msglen - lpi2c_imx->delivered; + } while (remaining); + + return 0; +} + +static int lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx) +{ + unsigned int remaining; + unsigned int data; + unsigned int timeout = 100000;; + + do { + data = readl(lpi2c_imx->base + LPI2C_MRDR); + if (data & MRDR_RXEMPTY) { + udelay(1); + if (!timeout--) + return -EIO; + continue; + } + + lpi2c_imx->rx_buf[lpi2c_imx->delivered++] = data & 0xff; + + remaining = lpi2c_imx->msglen - lpi2c_imx->delivered; + } while (remaining); + + return 0; +} + +static int lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msgs) +{ + lpi2c_imx->tx_buf = msgs->buf; + lpi2c_imx_set_tx_watermark(lpi2c_imx); + + return lpi2c_imx_write_txfifo(lpi2c_imx); +} + +static int lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx, + struct i2c_msg *msgs) +{ + unsigned int temp; + + lpi2c_imx->rx_buf = msgs->buf; + + lpi2c_imx_set_rx_watermark(lpi2c_imx); + temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1; + temp |= (RECV_DATA << 8); + writel(temp, lpi2c_imx->base + LPI2C_MTDR); + + lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE); + + return lpi2c_imx_read_rxfifo(lpi2c_imx); +} + +static int lpi2c_imx_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + struct lpi2c_imx_struct *lpi2c_imx = container_of(adapter, struct lpi2c_imx_struct, adapter); + unsigned int temp; + int i, result; + + result = lpi2c_imx_master_enable(lpi2c_imx); + if (result) + return result; + + for (i = 0; i < num; i++) { + result = lpi2c_imx_start(lpi2c_imx, &msgs[i]); + if (result) + goto disable; + + /* quick smbus */ + if (num == 1 && msgs[0].len == 0) + goto stop; + + lpi2c_imx->rx_buf = NULL; + lpi2c_imx->tx_buf = NULL; + lpi2c_imx->delivered = 0; + lpi2c_imx->msglen = msgs[i].len; + + if (msgs[i].flags & I2C_M_RD) + result = lpi2c_imx_read(lpi2c_imx, &msgs[i]); + else + result = lpi2c_imx_write(lpi2c_imx, &msgs[i]); + + if (result) + goto stop; + + if (!(msgs[i].flags & I2C_M_RD)) { + result = lpi2c_imx_txfifo_empty(lpi2c_imx); + if (result) + goto stop; + } + } + +stop: + lpi2c_imx_stop(lpi2c_imx); + + temp = readl(lpi2c_imx->base + LPI2C_MSR); + if ((temp & MSR_NDF) && !result) + result = -EIO; + +disable: + lpi2c_imx_master_disable(lpi2c_imx); + + dev_dbg(&lpi2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, + (result < 0) ? "error" : "success msg", + (result < 0) ? result : num); + + return (result < 0) ? result : num; +} + +#ifdef __PBL__ + +static int lpi2c_pbl_imx_xfer(struct pbl_i2c *lpi2c, struct i2c_msg *msgs, int num) +{ + struct lpi2c_imx_struct *lpi2c_imx = container_of(lpi2c, struct lpi2c_imx_struct, pbl_i2c); + + return lpi2c_imx_xfer(&lpi2c_imx->adapter, msgs, num); +} + +struct pbl_i2c *imx93_i2c_early_init(void __iomem *regs) +{ + static struct lpi2c_imx_struct lpi2c; + u32 temp; + + lpi2c.base = regs; + + temp = readl(lpi2c.base + LPI2C_PARAM); + lpi2c.txfifosize = 1 << (temp & 0x0f); + lpi2c.rxfifosize = 1 << ((temp >> 8) & 0x0f); + lpi2c.bitrate = 100000; + lpi2c.clk_rate = 24000000; + + lpi2c.pbl_i2c.xfer = lpi2c_pbl_imx_xfer; + + return &lpi2c.pbl_i2c; +} + +#else + +static const struct of_device_id lpi2c_imx_of_match[] = { + { .compatible = "fsl,imx7ulp-lpi2c" }, + { }, +}; +MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match); + +static int lpi2c_imx_probe(struct device *dev) +{ + struct lpi2c_imx_struct *lpi2c_imx; + struct resource *iores; + unsigned int temp; + int ret; + + lpi2c_imx = xzalloc(sizeof(*lpi2c_imx)); + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + lpi2c_imx->base = IOMEM(iores->start); + + lpi2c_imx->adapter.nr = -1; + lpi2c_imx->adapter.master_xfer = lpi2c_imx_xfer; + lpi2c_imx->adapter.dev.parent = dev; + lpi2c_imx->adapter.dev.of_node = dev->of_node; + + ret = clk_bulk_get_all(dev, &lpi2c_imx->clks); + if (ret < 0) + return dev_err_probe(dev, ret, "can't get I2C peripheral clock\n"); + lpi2c_imx->num_clks = ret; + + ret = of_property_read_u32(dev->of_node, + "clock-frequency", &lpi2c_imx->bitrate); + if (ret) + lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ; + + ret = clk_bulk_enable(lpi2c_imx->num_clks, lpi2c_imx->clks); + if (ret) + return ret; + + lpi2c_imx->clk_rate = clk_get_rate(lpi2c_imx->clks[0].clk); + + temp = readl(lpi2c_imx->base + LPI2C_PARAM); + lpi2c_imx->txfifosize = 1 << (temp & 0x0f); + lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f); + + ret = i2c_add_numbered_adapter(&lpi2c_imx->adapter); + if (ret) + return ret; + + dev_dbg(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n"); + + return 0; +} + +static struct driver lpi2c_imx_driver = { + .probe = lpi2c_imx_probe, + .name = "i2c-fsl", + .of_compatible = DRV_OF_COMPAT(lpi2c_imx_of_match), +}; +coredevice_platform_driver(lpi2c_imx_driver); + +#endif + +MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>"); +MODULE_DESCRIPTION("I2C adapter driver for LPI2C bus"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a2abfa5b43..f6a67ec067 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -102,6 +102,7 @@ struct fsl_i2c_hwdata { struct fsl_i2c_struct { void __iomem *base; struct clk *clk; + struct device *dev; struct i2c_adapter adapter; unsigned int disable_delay; unsigned int ifdr; /* FSL_I2C_IFDR */ @@ -201,7 +202,7 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter) static int i2c_fsl_acked(struct i2c_adapter *adapter) { - return i2c_fsl_poll_status(adapter, 1, 0, I2SR_RXAK); + return i2c_fsl_poll_status(adapter, 5, 0, I2SR_RXAK); } static int i2c_fsl_start(struct i2c_adapter *adapter) @@ -295,7 +296,7 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl, * Translate to dfsr = 5 * Frequency / 100,000,000 */ dfsr = (5 * (i2c_clk / 1000)) / 100000; - dev_dbg(&i2c_fsl->adapter.dev, + dev_dbg(i2c_fsl->dev, "<%s> requested speed:%d, i2c_clk:%d\n", __func__, rate, i2c_clk); if (!dfsr) @@ -314,12 +315,12 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl, bin_ga = (ga & 0x3) | ((ga & 0x4) << 3); fdr = bin_gb | bin_ga; rate = i2c_clk / est_div; - dev_dbg(&i2c_fsl->adapter.dev, + dev_dbg(i2c_fsl->dev, "FDR:0x%.2x, div:%ld, ga:0x%x, gb:0x%x," " a:%d, b:%d, speed:%d\n", fdr, est_div, ga, gb, a, b, rate); /* Condition 2 not accounted for */ - dev_dbg(&i2c_fsl->adapter.dev, + dev_dbg(i2c_fsl->dev, "Tr <= %d ns\n", (b - 3 * dfsr) * 1000000 / (i2c_clk / 1000)); } @@ -329,9 +330,9 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl, if (a == 24) a += 4; } - dev_dbg(&i2c_fsl->adapter.dev, + dev_dbg(i2c_fsl->dev, "divider:%d, est_div:%ld, DFSR:%d\n", divider, est_div, dfsr); - dev_dbg(&i2c_fsl->adapter.dev, "FDR:0x%.2x, speed:%d\n", fdr, rate); + dev_dbg(i2c_fsl->dev, "FDR:0x%.2x, speed:%d\n", fdr, rate); i2c_fsl->ifdr = fdr; i2c_fsl->dfsrr = dfsr; } @@ -368,9 +369,9 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl, (500000U * i2c_clk_div[i].div + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); - dev_dbg(&i2c_fsl->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", + dev_dbg(i2c_fsl->dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", __func__, i2c_clk_rate, div); - dev_dbg(&i2c_fsl->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", + dev_dbg(i2c_fsl->dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); } #endif @@ -525,15 +526,18 @@ static void i2c_fsl_unprepare_recovery(struct i2c_adapter *adapter) dev_err(adapter->dev.parent, "pinctrl failed: %s\n", strerror(-ret)); } -static void i2c_fsl_init_recovery(struct fsl_i2c_struct *i2c_fsl, struct device_d *dev) +static void i2c_fsl_init_recovery(struct fsl_i2c_struct *i2c_fsl, + struct device *dev) { - if (!dev->device_node) + if (!dev->of_node) return; - i2c_fsl->rinfo.sda_gpio = of_get_named_gpio_flags(dev->device_node, - "sda-gpios", 0, NULL); - i2c_fsl->rinfo.scl_gpio = of_get_named_gpio_flags(dev->device_node, - "scl-gpios", 0, NULL); + i2c_fsl->rinfo.sda_gpio = of_get_named_gpio_flags(dev->of_node, + "sda-gpios", 0, + NULL); + i2c_fsl->rinfo.scl_gpio = of_get_named_gpio_flags(dev->of_node, + "scl-gpios", 0, + NULL); if (!gpio_is_valid(i2c_fsl->rinfo.sda_gpio) || !gpio_is_valid(i2c_fsl->rinfo.scl_gpio)) @@ -550,7 +554,7 @@ static void i2c_fsl_init_recovery(struct fsl_i2c_struct *i2c_fsl, struct device_ dev_dbg(dev, "initialized recovery info\n"); } -static int __init i2c_fsl_probe(struct device_d *pdev) +static int __init i2c_fsl_probe(struct device *pdev) { struct resource *iores; struct fsl_i2c_struct *i2c_fsl; @@ -561,6 +565,7 @@ static int __init i2c_fsl_probe(struct device_d *pdev) pdata = pdev->platform_data; i2c_fsl = xzalloc(sizeof(*i2c_fsl)); + i2c_fsl->dev = pdev; #ifdef CONFIG_COMMON_CLK i2c_fsl->clk = clk_get(pdev, NULL); @@ -585,7 +590,7 @@ static int __init i2c_fsl_probe(struct device_d *pdev) i2c_fsl->adapter.master_xfer = i2c_fsl_xfer; i2c_fsl->adapter.nr = pdev->id; i2c_fsl->adapter.dev.parent = pdev; - i2c_fsl->adapter.dev.device_node = pdev->device_node; + i2c_fsl->adapter.dev.of_node = pdev->of_node; iores = dev_request_mem_resource(pdev, 0); if (IS_ERR(iores)) { ret = PTR_ERR(iores); @@ -599,7 +604,7 @@ static int __init i2c_fsl_probe(struct device_d *pdev) /* Set up clock divider */ bitrate = 100000; - of_property_read_u32(pdev->device_node, "clock-frequency", &bitrate); + of_property_read_u32(pdev->of_node, "clock-frequency", &bitrate); if (pdata && pdata->bitrate) bitrate = pdata->bitrate; @@ -645,8 +650,9 @@ static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = { { .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_i2c_dt_ids); -static struct driver_d i2c_fsl_driver = { +static struct driver i2c_fsl_driver = { .probe = i2c_fsl_probe, .name = "i2c-fsl", .of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 765fc9926b..44f1fd4ce6 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -495,6 +495,7 @@ static struct of_device_id mv64xxx_i2c_of_match_table[] = { { .compatible = "marvell,mv78230-a0-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, {} }; +MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); static inline int mv64xxx_calc_freq(const int tclk, const int n, const int m) @@ -528,9 +529,9 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, static int mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, - struct device_d *pd) + struct device *pd) { - struct device_node *np = pd->device_node; + struct device_node *np = pd->of_node; u32 bus_freq, tclk; int rc = 0; u32 prop; @@ -596,13 +597,13 @@ out: } static int -mv64xxx_i2c_probe(struct device_d *pd) +mv64xxx_i2c_probe(struct device *pd) { struct resource *iores; struct mv64xxx_i2c_data *drv_data; int rc; - if (!pd->device_node) + if (!pd->of_node) return -ENODEV; drv_data = xzalloc(sizeof(*drv_data)); @@ -625,7 +626,7 @@ mv64xxx_i2c_probe(struct device_d *pd) drv_data->adapter.master_xfer = mv64xxx_i2c_xfer; drv_data->adapter.dev.parent = pd; drv_data->adapter.nr = pd->id; - drv_data->adapter.dev.device_node = pd->device_node; + drv_data->adapter.dev.of_node = pd->of_node; mv64xxx_i2c_hw_init(drv_data); @@ -643,7 +644,7 @@ exit_clk: return rc; } -static struct driver_d mv64xxx_i2c_driver = { +static struct driver mv64xxx_i2c_driver = { .probe = mv64xxx_i2c_probe, .name = "mv64xxx_i2c", .of_compatible = DRV_OF_COMPAT(mv64xxx_i2c_of_match_table), diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 29a618c8b2..023c9673ba 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -28,8 +28,8 @@ #include <io.h> #include <i2c/i2c.h> -#include <mach/generic.h> -#include <mach/omap3-clock.h> +#include <mach/omap/generic.h> +#include <mach/omap/omap3-clock.h> /* This will be the driver name */ #define DRIVER_NAME "i2c-omap" @@ -1059,7 +1059,7 @@ static struct i2c_bus_recovery_info omap_i2c_bus_recovery_info = { }; static int __init -i2c_omap_probe(struct device_d *pdev) +i2c_omap_probe(struct device *pdev) { struct resource *iores; struct omap_i2c_struct *i2c_omap; @@ -1091,8 +1091,8 @@ i2c_omap_probe(struct device_d *pdev) if (pdev->platform_data != NULL) { speed = *(u32 *)pdev->platform_data; } else { - of_property_read_u32(pdev->device_node, "clock-frequency", - &speed); + of_property_read_u32(pdev->of_node, "clock-frequency", + &speed); /* convert DT freq value in Hz into kHz for speed */ speed /= 1000; } @@ -1170,7 +1170,7 @@ i2c_omap_probe(struct device_d *pdev) i2c_omap->adapter.master_xfer = omap_i2c_xfer; i2c_omap->adapter.nr = pdev->id; i2c_omap->adapter.dev.parent = pdev; - i2c_omap->adapter.dev.device_node = pdev->device_node; + i2c_omap->adapter.dev.of_node = pdev->of_node; i2c_omap->adapter.bus_recovery_info = &omap_i2c_bus_recovery_info; /* i2c device drivers may be active on return from add_adapter() */ @@ -1219,8 +1219,9 @@ static __maybe_unused struct of_device_id omap_i2c_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, omap_i2c_dt_ids); -static struct driver_d omap_i2c_driver = { +static struct driver omap_i2c_driver = { .probe = i2c_omap_probe, .name = DRIVER_NAME, .id_table = omap_i2c_ids, diff --git a/drivers/i2c/busses/i2c-rockchip.c b/drivers/i2c/busses/i2c-rockchip.c index ca33905335..ce029d148f 100644 --- a/drivers/i2c/busses/i2c-rockchip.c +++ b/drivers/i2c/busses/i2c-rockchip.c @@ -15,7 +15,7 @@ #include <io.h> #include <linux/clk.h> #include <mfd/syscon.h> -#include <regmap.h> +#include <linux/regmap.h> #include <linux/sizes.h> struct i2c_regs { @@ -108,7 +108,7 @@ static inline void rk_i2c_get_div(int div, int *divh, int *divl) */ static void rk_i2c_set_clk(struct rk_i2c *i2c, uint32_t scl_rate) { - struct device_d *dev = i2c->adapter.dev.parent; + struct device *dev = i2c->adapter.dev.parent; uint32_t i2c_rate; int div, divl, divh; @@ -130,7 +130,7 @@ static void rk_i2c_set_clk(struct rk_i2c *i2c, uint32_t scl_rate) static void rk_i2c_show_regs(struct rk_i2c *i2c) { - struct device_d *dev = &i2c->adapter.dev; + struct device *dev = &i2c->adapter.dev; struct i2c_regs *regs = i2c->regs; int i; @@ -152,7 +152,7 @@ static void rk_i2c_show_regs(struct rk_i2c *i2c) static int rk_i2c_send_start_bit(struct rk_i2c *i2c) { - struct device_d *dev = &i2c->adapter.dev; + struct device *dev = &i2c->adapter.dev; struct i2c_regs *regs = i2c->regs; u32 val; int err; @@ -176,7 +176,7 @@ static int rk_i2c_send_start_bit(struct rk_i2c *i2c) static int rk_i2c_send_stop_bit(struct rk_i2c *i2c) { - struct device_d *dev = &i2c->adapter.dev; + struct device *dev = &i2c->adapter.dev; struct i2c_regs *regs = i2c->regs; u32 val; int err; @@ -206,7 +206,7 @@ static inline void rk_i2c_disable(struct rk_i2c *i2c) static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len) { - struct device_d *dev = &i2c->adapter.dev; + struct device *dev = &i2c->adapter.dev; struct i2c_regs *regs = i2c->regs; uchar *pbuf = buf; uint bytes_remain_len = b_len; @@ -302,7 +302,7 @@ i2c_exit: static int rk_i2c_write(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len) { - struct device_d *dev = &i2c->adapter.dev; + struct device *dev = &i2c->adapter.dev; struct i2c_regs *regs = i2c->regs; u32 val; int err; @@ -379,7 +379,7 @@ static int rockchip_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) { struct rk_i2c *i2c = to_rk_i2c(adapter); - struct device_d *dev = &adapter->dev; + struct device *dev = &adapter->dev; int i, ret = 0; dev_dbg(dev, "i2c_xfer: %d messages\n", nmsgs); @@ -408,9 +408,9 @@ static int rockchip_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, return ret < 0 ? ret : nmsgs; } -static int rk_i2c_probe(struct device_d *dev) +static int rk_i2c_probe(struct device *dev) { - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; struct resource *iores; struct rk_i2c *i2c; unsigned bitrate; @@ -434,7 +434,7 @@ static int rk_i2c_probe(struct device_d *dev) i2c->adapter.master_xfer = rockchip_i2c_xfer; i2c->adapter.nr = dev->id; i2c->adapter.dev.parent = dev; - i2c->adapter.dev.device_node = np; + i2c->adapter.dev.of_node = np; /* Set up clock divider */ bitrate = 100000; @@ -452,8 +452,9 @@ static const struct of_device_id rk_i2c_match[] = { { .compatible = "rockchip,rk3399-i2c" }, {}, }; +MODULE_DEVICE_TABLE(of, rk_i2c_match); -static struct driver_d rk_i2c_driver = { +static struct driver rk_i2c_driver = { .name = "rk3x-i2c", .of_compatible = rk_i2c_match, .probe = rk_i2c_probe, diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c index d412630365..1be52b3dd9 100644 --- a/drivers/i2c/busses/i2c-stm32.c +++ b/drivers/i2c/busses/i2c-stm32.c @@ -9,9 +9,11 @@ #include <common.h> #include <i2c/i2c.h> #include <init.h> +#include <linux/regmap.h> #include <linux/clk.h> #include <linux/iopoll.h> #include <linux/reset.h> +#include <mfd/syscon.h> /* STM32 I2C registers */ struct __packed stm32_i2c_regs { @@ -38,6 +40,8 @@ struct __packed stm32_i2c_regs { /* STM32 I2C control 1 */ #define STM32_I2C_CR1_ANFOFF BIT(12) +#define STM32_I2C_CR1_DNF_MASK GENMASK(11, 8) +#define STM32_I2C_CR1_DNF(n) (((n) & 0xf) << 8) #define STM32_I2C_CR1_ERRIE BIT(7) #define STM32_I2C_CR1_TCIE BIT(6) #define STM32_I2C_CR1_STOPIE BIT(5) @@ -48,7 +52,6 @@ struct __packed stm32_i2c_regs { #define STM32_I2C_CR1_PE BIT(0) /* STM32 I2C control 2 */ -#define STM32_I2C_CR2_AUTOEND BIT(25) #define STM32_I2C_CR2_RELOAD BIT(24) #define STM32_I2C_CR2_NBYTES_MASK GENMASK(23, 16) #define STM32_I2C_CR2_NBYTES(n) ((n & 0xff) << 16) @@ -98,10 +101,8 @@ struct __packed stm32_i2c_regs { #define STM32_I2C_MAX_LEN 0xff -#define STM32_I2C_DNF_DEFAULT 0 -#define STM32_I2C_DNF_MAX 16 +#define STM32_I2C_DNF_MAX 15 -#define STM32_I2C_ANALOG_FILTER_ENABLE 1 #define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ @@ -119,10 +120,9 @@ struct __packed stm32_i2c_regs { #define FAST_PLUS_RATE 1000000 enum stm32_i2c_speed { - STM32_I2C_SPEED_STANDARD, /* 100 kHz */ - STM32_I2C_SPEED_FAST, /* 400 kHz */ - STM32_I2C_SPEED_FAST_PLUS, /* 1 MHz */ - STM32_I2C_SPEED_END, + IC_SPEED_MODE_STANDARD, + IC_SPEED_MODE_FAST, + IC_SPEED_MODE_FAST_PLUS, }; /** @@ -154,20 +154,23 @@ struct stm32_i2c_spec { /** * struct stm32_i2c_setup - private I2C timing setup parameters - * @speed: I2C speed mode (standard, Fast Plus) - * @speed_freq: actual I2C speed frequency (Hz) * @clock_src: I2C clock source frequency (Hz) - * @dnf: Digital filter coefficient (0-16) + * @timings: I2C timing information * @analog_filter: Analog filter delay (On/Off) - * @timings: I2C timings parameters */ struct stm32_i2c_setup { - enum stm32_i2c_speed speed; - u32 speed_freq; u32 clock_src; + struct i2c_timings timings; u8 dnf; bool analog_filter; - struct i2c_timings timings; +}; + +/** + * struct stm32_i2c_data - driver data for I2C configuration by compatible + * @fmp_clr_offset: Fast Mode Plus clear register offset from set register + */ +struct stm32_i2c_data { + u32 fmp_clr_offset; }; /** @@ -187,8 +190,32 @@ struct stm32_i2c_timings { u8 scll; }; +/** + * struct stm32_i2c_priv - private data of the controller + * @regs: I2C registers address + * @clk: hw i2c clock + * @setup: I2C timing setup parameters + * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+ + * @regmap: holds SYSCFG phandle for Fast Mode Plus bit + * @regmap_sreg: register address for setting Fast Mode Plus bits + * @regmap_creg: register address for clearing Fast Mode Plus bits + * @regmap_mask: mask for Fast Mode Plus bits + */ +struct stm32_i2c_priv { + struct stm32_i2c_regs __iomem *regs; + struct clk *clk; + struct i2c_adapter adapter; + struct stm32_i2c_setup setup; + u32 speed; + struct regmap *regmap; + u32 regmap_sreg; + u32 regmap_creg; + u32 regmap_mask; +}; + static const struct stm32_i2c_spec i2c_specs[] = { - [STM32_I2C_SPEED_STANDARD] = { + /* Standard speed - 100 KHz */ + [IC_SPEED_MODE_STANDARD] = { .rate = STANDARD_RATE, .rate_min = 8000, .rate_max = 120000, @@ -200,7 +227,8 @@ static const struct stm32_i2c_spec i2c_specs[] = { .l_min = 4700, .h_min = 4000, }, - [STM32_I2C_SPEED_FAST] = { + /* Fast speed - 400 KHz */ + [IC_SPEED_MODE_FAST] = { .rate = FAST_RATE, .rate_min = 320000, .rate_max = 480000, @@ -212,7 +240,8 @@ static const struct stm32_i2c_spec i2c_specs[] = { .l_min = 1300, .h_min = 600, }, - [STM32_I2C_SPEED_FAST_PLUS] = { + /* Fast Plus Speed - 1 MHz */ + [IC_SPEED_MODE_FAST_PLUS] = { .rate = FAST_PLUS_RATE, .rate_min = 800000, .rate_max = 1200000, @@ -226,22 +255,30 @@ static const struct stm32_i2c_spec i2c_specs[] = { }, }; -struct stm32_i2c { - struct stm32_i2c_regs __iomem *regs; - struct clk *clk; - struct i2c_adapter adapter; - struct stm32_i2c_setup setup; +static const struct stm32_i2c_data stm32f7_data = { + .fmp_clr_offset = 0x00, }; -#define to_stm32_i2c(a) container_of(a, struct stm32_i2c, adapter) -static inline int stm32_i2c_check_device_busy(struct stm32_i2c *priv) +static const struct stm32_i2c_data stm32mp15_data = { + .fmp_clr_offset = 0x40, +}; + +static const struct stm32_i2c_data stm32mp13_data = { + .fmp_clr_offset = 0x4, +}; + +static inline int stm32_i2c_check_device_busy(struct stm32_i2c_priv *priv) { u32 status = readl(&priv->regs->isr); - return status & STM32_I2C_ISR_BUSY; + + if (status & STM32_I2C_ISR_BUSY) + return -EBUSY; + + return 0; } -static void stm32_i2c_message_start(struct stm32_i2c *i2c_priv, - struct i2c_msg *msg, bool stop) +static void stm32_i2c_message_start(struct stm32_i2c_priv *i2c_priv, + struct i2c_msg *msg) { struct stm32_i2c_regs *regs = i2c_priv->regs; u32 cr2 = readl(®s->cr2); @@ -262,9 +299,8 @@ static void stm32_i2c_message_start(struct stm32_i2c *i2c_priv, cr2 |= STM32_I2C_CR2_SADD7(msg->addr); } - /* Set nb bytes to transfer and reload or autoend bits */ - cr2 &= ~(STM32_I2C_CR2_NBYTES_MASK | STM32_I2C_CR2_RELOAD | - STM32_I2C_CR2_AUTOEND); + /* Set nb bytes to transfer and reload (if needed) */ + cr2 &= ~(STM32_I2C_CR2_NBYTES_MASK | STM32_I2C_CR2_RELOAD); if (msg->len > STM32_I2C_MAX_LEN) { cr2 |= STM32_I2C_CR2_NBYTES(STM32_I2C_MAX_LEN); cr2 |= STM32_I2C_CR2_RELOAD; @@ -284,8 +320,8 @@ static void stm32_i2c_message_start(struct stm32_i2c *i2c_priv, * sent is greater than MAX_LEN */ -static void stm32_i2c_handle_reload(struct stm32_i2c *i2c_priv, - struct i2c_msg *msg, bool stop) +static void stm32_i2c_handle_reload(struct stm32_i2c_priv *i2c_priv, + struct i2c_msg *msg) { struct stm32_i2c_regs *regs = i2c_priv->regs; u32 cr2 = readl(®s->cr2); @@ -302,7 +338,7 @@ static void stm32_i2c_handle_reload(struct stm32_i2c *i2c_priv, writel(cr2, ®s->cr2); } -static int stm32_i2c_wait_flags(struct stm32_i2c *i2c_priv, +static int stm32_i2c_wait_flags(struct stm32_i2c_priv *i2c_priv, u32 flags, u32 *status) { struct stm32_i2c_regs *regs = i2c_priv->regs; @@ -311,12 +347,12 @@ static int stm32_i2c_wait_flags(struct stm32_i2c *i2c_priv, *status & flags, USEC_PER_SEC); } -static int stm32_i2c_check_end_of_message(struct stm32_i2c *i2c_priv) +static int stm32_i2c_check_end_of_message(struct stm32_i2c_priv *i2c_priv) { struct stm32_i2c_regs *regs = i2c_priv->regs; u32 mask = STM32_I2C_ISR_ERRORS | STM32_I2C_ISR_NACKF | STM32_I2C_ISR_STOPF; - struct device_d *dev = &i2c_priv->adapter.dev; + struct device *dev = &i2c_priv->adapter.dev; u32 status; int ret; @@ -362,30 +398,29 @@ static int stm32_i2c_check_end_of_message(struct stm32_i2c *i2c_priv) setbits_le32(®s->icr, STM32_I2C_ICR_STOPCF); /* Clear control register 2 */ - setbits_le32(®s->cr2, STM32_I2C_CR2_RESET_MASK); + clrbits_le32(®s->cr2, STM32_I2C_CR2_RESET_MASK); } return ret; } -static int stm32_i2c_message_xfer(struct stm32_i2c *i2c_priv, +static int stm32_i2c_message_xfer(struct stm32_i2c_priv *i2c_priv, struct i2c_msg *msg, bool stop) { struct stm32_i2c_regs *regs = i2c_priv->regs; - int len = msg->len; - u8 *buf = msg->buf; u32 status; u32 mask = msg->flags & I2C_M_RD ? STM32_I2C_ISR_RXNE : STM32_I2C_ISR_TXIS | STM32_I2C_ISR_NACKF; - int bytes_to_rw = min(len, STM32_I2C_MAX_LEN); + int bytes_to_rw = msg->len > STM32_I2C_MAX_LEN ? + STM32_I2C_MAX_LEN : msg->len; int ret = 0; /* Add errors */ mask |= STM32_I2C_ISR_ERRORS; - stm32_i2c_message_start(i2c_priv, msg, stop); + stm32_i2c_message_start(i2c_priv, msg); - while (len) { + while (msg->len) { /* * Wait until TXIS/NACKF/BERR/ARLO flags or * RXNE/BERR/ARLO flags are set @@ -398,29 +433,30 @@ static int stm32_i2c_message_xfer(struct stm32_i2c *i2c_priv, break; if (status & STM32_I2C_ISR_RXNE) { - *buf++ = readb(®s->rxdr); - len--; + *msg->buf++ = readb(®s->rxdr); + msg->len--; bytes_to_rw--; } if (status & STM32_I2C_ISR_TXIS) { - writeb(*buf++, ®s->txdr); - len--; + writeb(*msg->buf++, ®s->txdr); + msg->len--; bytes_to_rw--; } - if (!bytes_to_rw && len) { + if (!bytes_to_rw && msg->len) { /* Wait until TCR flag is set */ mask = STM32_I2C_ISR_TCR; ret = stm32_i2c_wait_flags(i2c_priv, mask, &status); if (ret) break; - bytes_to_rw = min(len, STM32_I2C_MAX_LEN); + bytes_to_rw = msg->len > STM32_I2C_MAX_LEN ? + STM32_I2C_MAX_LEN : msg->len; mask = msg->flags & I2C_M_RD ? STM32_I2C_ISR_RXNE : STM32_I2C_ISR_TXIS | STM32_I2C_ISR_NACKF; - stm32_i2c_handle_reload(i2c_priv, msg, stop); + stm32_i2c_handle_reload(i2c_priv, msg); } else if (!bytes_to_rw) { /* Wait until TC flag is set */ mask = STM32_I2C_ISR_TC; @@ -434,9 +470,9 @@ static int stm32_i2c_message_xfer(struct stm32_i2c *i2c_priv, } } - /* End of transfer, send stop condition */ - mask = STM32_I2C_CR2_STOP; - setbits_le32(®s->cr2, mask); + /* End of transfer, send stop condition if appropriate */ + if (!ret && !(status & (STM32_I2C_ISR_NACKF | STM32_I2C_ISR_ERRORS))) + setbits_le32(®s->cr2, STM32_I2C_CR2_STOP); return stm32_i2c_check_end_of_message(i2c_priv); } @@ -444,16 +480,16 @@ static int stm32_i2c_message_xfer(struct stm32_i2c *i2c_priv, static int stm32_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg, int nmsgs) { - struct stm32_i2c *i2c_priv = to_stm32_i2c(adapter); - int ret; - int i; + struct stm32_i2c_priv *i2c_priv = + container_of(adapter, struct stm32_i2c_priv, adapter); + int i, ret; ret = stm32_i2c_check_device_busy(i2c_priv); if (ret) - return -EBUSY; + return ret; - for (i = 0; i < nmsgs; i++) { - ret = stm32_i2c_message_xfer(i2c_priv, &msg[i], i == nmsgs - 1); + for (i = nmsgs; i > 0; i--, msg++) { + ret = stm32_i2c_message_xfer(i2c_priv, msg, i == 1); if (ret) return ret; } @@ -461,30 +497,30 @@ static int stm32_i2c_xfer(struct i2c_adapter *adapter, return nmsgs; } - -static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, +static int stm32_i2c_compute_solutions(u32 i2cclk, + struct stm32_i2c_setup *setup, + const struct stm32_i2c_spec *specs, struct list_head *solutions) { struct stm32_i2c_timings *v; u32 p_prev = STM32_PRESC_MAX; - u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->clock_src); - u32 af_delay_min = 0, af_delay_max = 0; + u32 af_delay_min, af_delay_max; u16 p, l, a; int sdadel_min, sdadel_max, scldel_min; int ret = 0; - if (setup->analog_filter) { - af_delay_min = STM32_I2C_ANALOG_FILTER_DELAY_MIN; - af_delay_max = STM32_I2C_ANALOG_FILTER_DELAY_MAX; - } + af_delay_min = setup->analog_filter ? + STM32_I2C_ANALOG_FILTER_DELAY_MIN : 0; + af_delay_max = setup->analog_filter ? + STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0; - sdadel_min = i2c_specs[setup->speed].hddat_min + setup->timings.scl_fall_ns - + sdadel_min = specs->hddat_min + setup->timings.scl_fall_ns - af_delay_min - (setup->dnf + 3) * i2cclk; - sdadel_max = i2c_specs[setup->speed].vddat_max - setup->timings.scl_rise_ns - + sdadel_max = specs->vddat_max - setup->timings.scl_rise_ns - af_delay_max - (setup->dnf + 4) * i2cclk; - scldel_min = setup->timings.scl_rise_ns + i2c_specs[setup->speed].sudat_min; + scldel_min = setup->timings.scl_rise_ns + specs->sudat_min; if (sdadel_min < 0) sdadel_min = 0; @@ -497,13 +533,13 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, /* Compute possible values for PRESC, SCLDEL and SDADEL */ for (p = 0; p < STM32_PRESC_MAX; p++) { for (l = 0; l < STM32_SCLDEL_MAX; l++) { - u32 scldel = (l + 1) * (p + 1) * i2cclk; + int scldel = (l + 1) * (p + 1) * i2cclk; if (scldel < scldel_min) continue; for (a = 0; a < STM32_SDADEL_MAX; a++) { - u32 sdadel = (a * (p + 1) + 1) * i2cclk; + int sdadel = (a * (p + 1) + 1) * i2cclk; if (((sdadel >= sdadel_min) && (sdadel <= sdadel_max)) && @@ -527,36 +563,40 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, } } - if (list_empty(solutions)) + if (list_empty(solutions)) { + pr_err("no Prescaler solution\n"); ret = -EPERM; + } return ret; } -static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, +static int stm32_i2c_choose_solution(u32 i2cclk, + struct stm32_i2c_setup *setup, + const struct stm32_i2c_spec *specs, struct list_head *solutions, struct stm32_i2c_timings *s) { struct stm32_i2c_timings *v; - u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->speed_freq); + u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC, + setup->timings.bus_freq_hz); u32 clk_error_prev = i2cbus; - u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->clock_src); u32 clk_min, clk_max; - u32 af_delay_min = 0; + u32 af_delay_min; u32 dnf_delay; u32 tsync; u16 l, h; bool sol_found = false; int ret = 0; - if (setup->analog_filter) - af_delay_min = STM32_I2C_ANALOG_FILTER_DELAY_MIN; + af_delay_min = setup->analog_filter ? + STM32_I2C_ANALOG_FILTER_DELAY_MIN : 0; dnf_delay = setup->dnf * i2cclk; tsync = af_delay_min + dnf_delay + (2 * i2cclk); - clk_max = NSEC_PER_SEC / i2c_specs[setup->speed].rate_min; - clk_min = NSEC_PER_SEC / i2c_specs[setup->speed].rate_max; + clk_max = NSEC_PER_SEC / specs->rate_min; + clk_min = NSEC_PER_SEC / specs->rate_max; /* * Among Prescaler possibilities discovered above figures out SCL Low @@ -574,7 +614,7 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, for (l = 0; l < STM32_SCLL_MAX; l++) { u32 tscl_l = (l + 1) * prescaler + tsync; - if ((tscl_l < i2c_specs[setup->speed].l_min) || + if (tscl_l < specs->l_min || (i2cclk >= ((tscl_l - af_delay_min - dnf_delay) / 4))) { continue; @@ -583,16 +623,17 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, for (h = 0; h < STM32_SCLH_MAX; h++) { u32 tscl_h = (h + 1) * prescaler + tsync; u32 tscl = tscl_l + tscl_h + - setup->timings.scl_rise_ns + - setup->timings.scl_fall_ns; + setup->timings.scl_rise_ns + setup->timings.scl_fall_ns; if ((tscl >= clk_min) && (tscl <= clk_max) && - (tscl_h >= i2c_specs[setup->speed].h_min) && + (tscl_h >= specs->h_min) && (i2cclk < tscl_h)) { - int clk_error = tscl - i2cbus; + u32 clk_error; - if (clk_error < 0) - clk_error = -clk_error; + if (tscl > i2cbus) + clk_error = tscl - i2cbus; + else + clk_error = i2cbus - tscl; if (clk_error < clk_error_prev) { clk_error_prev = clk_error; @@ -606,61 +647,68 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, } } - if (!sol_found) + if (!sol_found) { + pr_err("no solution at all\n"); ret = -EPERM; + } return ret; } -static int stm32_i2c_compute_timing(struct stm32_i2c *i2c_priv, - struct stm32_i2c_setup *setup, +static const struct stm32_i2c_spec *get_specs(u32 rate) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) + if (rate <= i2c_specs[i].rate) + return &i2c_specs[i]; + + /* NOT REACHED */ + return ERR_PTR(-EINVAL); +} + +static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, struct stm32_i2c_timings *output) { - struct device_d *dev = &i2c_priv->adapter.dev; + struct device *dev = &i2c_priv->adapter.dev; + struct stm32_i2c_setup *setup = &i2c_priv->setup; + const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions; + u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->clock_src); int ret; - if (setup->speed >= STM32_I2C_SPEED_END) { - dev_err(dev, "speed out of bound {%d/%d}\n", - setup->speed, STM32_I2C_SPEED_END - 1); + specs = get_specs(setup->timings.bus_freq_hz); + if (specs == ERR_PTR(-EINVAL)) { + dev_err(dev, "speed out of bound {%d}\n", + setup->timings.bus_freq_hz); return -EINVAL; } - if ((setup->timings.scl_rise_ns > i2c_specs[setup->speed].rise_max) || - (setup->timings.scl_fall_ns > i2c_specs[setup->speed].fall_max)) { + if (setup->timings.scl_rise_ns > specs->rise_max || + setup->timings.scl_fall_ns > specs->fall_max) { dev_err(dev, "timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", - setup->timings.scl_rise_ns, i2c_specs[setup->speed].rise_max, - setup->timings.scl_fall_ns, i2c_specs[setup->speed].fall_max); + setup->timings.scl_rise_ns, specs->rise_max, + setup->timings.scl_fall_ns, specs->fall_max); return -EINVAL; } + /* Analog and Digital Filters */ + setup->dnf = DIV_ROUND_CLOSEST(i2c_priv->setup.timings.digital_filter_width_ns, i2cclk); if (setup->dnf > STM32_I2C_DNF_MAX) { dev_err(dev, "DNF out of bound %d/%d\n", - setup->dnf, STM32_I2C_DNF_MAX); - return -EINVAL; - } - - if (setup->speed_freq > i2c_specs[setup->speed].rate) { - dev_err(dev, "Freq {%d/%d}\n", - setup->speed_freq, i2c_specs[setup->speed].rate); + setup->dnf, STM32_I2C_DNF_MAX); return -EINVAL; } INIT_LIST_HEAD(&solutions); - ret = stm32_i2c_compute_solutions(setup, &solutions); - if (ret) { - if (ret == -EPERM) - dev_err(dev, "No prescaler solution\n"); + ret = stm32_i2c_compute_solutions(i2cclk, setup, specs, &solutions); + if (ret) goto exit; - } - ret = stm32_i2c_choose_solution(setup, &solutions, output); - if (ret) { - if (ret == -EPERM) - dev_err(dev, "no solution at all\n"); + ret = stm32_i2c_choose_solution(i2cclk, setup, specs, &solutions, output); + if (ret) goto exit; - } dev_dbg(dev, "Presc: %i, scldel: %i, sdadel: %i, scll: %i, sclh: %i\n", output->presc, @@ -677,16 +725,25 @@ exit: return ret; } -static int stm32_i2c_setup_timing(struct stm32_i2c *i2c_priv, - enum stm32_i2c_speed speed, +static u32 get_lower_rate(u32 rate) +{ + int i; + + for (i = ARRAY_SIZE(i2c_specs) - 1; i >= 0; i--) + if (rate > i2c_specs[i].rate) + return i2c_specs[i].rate; + + return i2c_specs[0].rate; +} + +static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, struct stm32_i2c_timings *timing) { - struct device_d *dev = &i2c_priv->adapter.dev; + struct device *dev = &i2c_priv->adapter.dev; struct stm32_i2c_setup *setup = &i2c_priv->setup; int ret = 0; - setup->speed = speed; - setup->speed_freq = i2c_specs[setup->speed].rate; + setup->timings.bus_freq_hz = i2c_priv->speed; setup->clock_src = clk_get_rate(i2c_priv->clk); if (!setup->clock_src) { @@ -695,15 +752,14 @@ static int stm32_i2c_setup_timing(struct stm32_i2c *i2c_priv, } do { - ret = stm32_i2c_compute_timing(i2c_priv, setup, timing); + ret = stm32_i2c_compute_timing(i2c_priv, timing); if (ret) { dev_dbg(dev, "failed to compute I2C timings.\n"); - if (speed > STM32_I2C_SPEED_STANDARD) { - speed--; - setup->speed = speed; - setup->speed_freq = i2c_specs[setup->speed].rate; + if (setup->timings.bus_freq_hz > STANDARD_RATE) { + setup->timings.bus_freq_hz = + get_lower_rate(setup->timings.bus_freq_hz); dev_dbg(dev, "downgrade I2C Speed Freq to (%i)\n", - i2c_specs[setup->speed].rate); + setup->timings.bus_freq_hz); } else { break; } @@ -715,31 +771,60 @@ static int stm32_i2c_setup_timing(struct stm32_i2c *i2c_priv, return ret; } - dev_dbg(dev, "I2C Speed(%i), Freq(%i), Clk Source(%i)\n", - setup->speed, setup->speed_freq, setup->clock_src); + dev_dbg(dev, "I2C Freq(%i), Clk Source(%i)\n", + setup->timings.bus_freq_hz, setup->clock_src); dev_dbg(dev, "I2C Rise(%i) and Fall(%i) Time\n", - setup->timings.scl_rise_ns, setup->timings.scl_fall_ns); + setup->timings.scl_rise_ns, setup->timings.scl_fall_ns); dev_dbg(dev, "I2C Analog Filter(%s), DNF(%i)\n", - setup->analog_filter ? "On" : "Off", setup->dnf); + setup->analog_filter ? "On" : "Off", setup->dnf); + + i2c_priv->speed = setup->timings.bus_freq_hz; return 0; } -static int stm32_i2c_hw_config(struct stm32_i2c *i2c_priv, - enum stm32_i2c_speed speed) +static int stm32_i2c_write_fm_plus_bits(struct stm32_i2c_priv *i2c_priv) +{ + int ret; + bool enable = i2c_priv->speed > FAST_RATE; + + /* Optional */ + if (IS_ERR_OR_NULL(i2c_priv->regmap)) + return 0; + + if (i2c_priv->regmap_sreg == i2c_priv->regmap_creg) + ret = regmap_update_bits(i2c_priv->regmap, + i2c_priv->regmap_sreg, + i2c_priv->regmap_mask, + enable ? i2c_priv->regmap_mask : 0); + else + ret = regmap_write(i2c_priv->regmap, + enable ? i2c_priv->regmap_sreg : + i2c_priv->regmap_creg, + i2c_priv->regmap_mask); + + return ret; +} + +static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) { struct stm32_i2c_regs *regs = i2c_priv->regs; struct stm32_i2c_timings t; int ret; u32 timing = 0; - ret = stm32_i2c_setup_timing(i2c_priv, speed, &t); + ret = stm32_i2c_setup_timing(i2c_priv, &t); if (ret) return ret; /* Disable I2C */ clrbits_le32(®s->cr1, STM32_I2C_CR1_PE); + /* Setup Fast mode plus if necessary */ + ret = stm32_i2c_write_fm_plus_bits(i2c_priv); + if (ret) + return ret; + /* Timing settings */ timing |= STM32_I2C_TIMINGR_PRESC(t.presc); timing |= STM32_I2C_TIMINGR_SCLDEL(t.scldel); @@ -753,44 +838,74 @@ static int stm32_i2c_hw_config(struct stm32_i2c *i2c_priv, clrbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); + + /* Program the Digital Filter */ + clrsetbits_le32(®s->cr1, STM32_I2C_CR1_DNF_MASK, + STM32_I2C_CR1_DNF(i2c_priv->setup.dnf)); + setbits_le32(®s->cr1, STM32_I2C_CR1_PE); return 0; } -static int stm32_i2c_set_bus_speed(struct stm32_i2c *i2c_priv, unsigned speed) +static int stm32_i2c_set_bus_speed(struct stm32_i2c_priv *i2c_priv, unsigned int speed) { - struct device_d *parent_dev = i2c_priv->adapter.dev.parent; - enum stm32_i2c_speed stm32_speed; - switch (speed) { - case STANDARD_RATE: - stm32_speed = STM32_I2C_SPEED_STANDARD; - break; - case FAST_RATE: - stm32_speed = STM32_I2C_SPEED_FAST; - break; - case FAST_PLUS_RATE: - stm32_speed = STM32_I2C_SPEED_FAST_PLUS; - break; - default: - dev_warn(parent_dev, "Speed %d not supported\n", speed); + struct device *dev = &i2c_priv->adapter.dev; + + if (speed > FAST_PLUS_RATE) { + dev_dbg(dev, "Speed %d not supported\n", speed); return -EINVAL; } - return stm32_i2c_hw_config(i2c_priv, stm32_speed); + i2c_priv->speed = speed; + + return stm32_i2c_hw_config(i2c_priv); +} + +static int stm32_of_to_plat(struct device *dev, struct stm32_i2c_priv *i2c_priv) +{ + const struct stm32_i2c_data *data; + int ret; + + ret = dev_get_drvdata(dev, (const void **)&data); + if (ret) + return ret; + + if (of_property_read_u32(dev->of_node, "i2c-digital-filter-width-ns", + &i2c_priv->setup.timings.digital_filter_width_ns)) + i2c_priv->setup.timings.digital_filter_width_ns = 0; + if (!of_property_read_bool(dev->of_node, "i2c-digital-filter")) + i2c_priv->setup.timings.digital_filter_width_ns = 0; + + i2c_priv->setup.analog_filter = + of_property_read_bool(dev->of_node, "i2c-analog-filter"); + + /* Optional */ + i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "st,syscfg-fmp"); + if (!IS_ERR(i2c_priv->regmap)) { + u32 fmp[3]; + + ret = of_property_read_u32_array(dev->of_node, "st,syscfg-fmp", fmp, 3); + if (ret) + return ret; + + i2c_priv->regmap_sreg = fmp[1]; + i2c_priv->regmap_creg = fmp[1] + data->fmp_clr_offset; + i2c_priv->regmap_mask = fmp[2]; + } + + return 0; } -static int __init stm32_i2c_probe(struct device_d *dev) +static int __init stm32_i2c_probe(struct device *dev) { struct resource *iores; - struct stm32_i2c *stm32_i2c; + struct stm32_i2c_priv *stm32_i2c; struct i2c_platform_data *pdata; - const struct stm32_i2c_setup *setup; struct i2c_timings *timings; int ret; - pdata = dev->platform_data; - stm32_i2c = xzalloc(sizeof(*stm32_i2c)); stm32_i2c->clk = clk_get(dev, NULL); @@ -798,15 +913,20 @@ static int __init stm32_i2c_probe(struct device_d *dev) return PTR_ERR(stm32_i2c->clk); clk_enable(stm32_i2c->clk); + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + stm32_i2c->regs = IOMEM(iores->start); + ret = device_reset_us(dev, 2); if (ret) return ret; - ret = dev_get_drvdata(dev, (const void **)&setup); + ret = stm32_of_to_plat(dev, stm32_i2c); if (ret) return ret; - stm32_i2c->setup = *setup; timings = &stm32_i2c->setup.timings; /* We've our own defaults, so don't use the i2c_parse_fw_timings ones */ @@ -823,13 +943,9 @@ static int __init stm32_i2c_probe(struct device_d *dev) stm32_i2c->adapter.master_xfer = stm32_i2c_xfer; stm32_i2c->adapter.nr = dev->id; stm32_i2c->adapter.dev.parent = dev; - stm32_i2c->adapter.dev.device_node = dev->device_node; - iores = dev_request_mem_resource(dev, 0); - if (IS_ERR(iores)) - return PTR_ERR(iores); - - stm32_i2c->regs = IOMEM(iores->start); + stm32_i2c->adapter.dev.of_node = dev->of_node; + pdata = dev->platform_data; if (pdata && pdata->bitrate) timings->bus_freq_hz = pdata->bitrate; @@ -840,18 +956,15 @@ static int __init stm32_i2c_probe(struct device_d *dev) return i2c_add_numbered_adapter(&stm32_i2c->adapter); } -static const struct stm32_i2c_setup stm32f7_setup = { - .dnf = STM32_I2C_DNF_DEFAULT, - .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE, -}; - static __maybe_unused struct of_device_id stm32_i2c_dt_ids[] = { - { .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup, }, - { .compatible = "st,stm32mp15-i2c", .data = &stm32f7_setup}, + { .compatible = "st,stm32f7-i2c", .data = &stm32f7_data }, + { .compatible = "st,stm32mp15-i2c", .data = &stm32mp15_data }, + { .compatible = "st,stm32mp13-i2c", .data = &stm32mp13_data }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, stm32_i2c_dt_ids); -static struct driver_d stm32_i2c_driver = { +static struct driver stm32_i2c_driver = { .probe = stm32_i2c_probe, .name = "stm32f7-i2c", .of_compatible = DRV_OF_COMPAT(stm32_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 077b55e175..f86f64f573 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -137,7 +137,7 @@ struct tegra_i2c_hw_feature { * @bus_clk_rate: current i2c bus clock rate */ struct tegra_i2c_dev { - struct device_d *dev; + struct device *dev; const struct tegra_i2c_hw_feature *hw; struct i2c_adapter adapter; struct clk *div_clk; @@ -594,7 +594,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { .clk_divisor_std_fast_mode = 0x19, }; -static int tegra_i2c_probe(struct device_d *dev) +static int tegra_i2c_probe(struct device *dev) { struct resource *iores; struct tegra_i2c_dev *i2c_dev; @@ -627,14 +627,14 @@ static int tegra_i2c_probe(struct device_d *dev) return PTR_ERR(i2c_dev->rst); } - ret = of_property_read_u32(dev->device_node, "clock-frequency", + ret = of_property_read_u32(dev->of_node, "clock-frequency", &i2c_dev->bus_clk_rate); if (ret) i2c_dev->bus_clk_rate = 100000; /* default clock rate */ i2c_dev->hw = &tegra20_i2c_hw; dev_get_drvdata(dev, (const void **)&i2c_dev->hw); - i2c_dev->is_dvc = of_device_is_compatible(dev->device_node, + i2c_dev->is_dvc = of_device_is_compatible(dev->of_node, "nvidia,tegra20-i2c-dvc"); if (!i2c_dev->hw->has_single_clk_source) { @@ -655,7 +655,7 @@ static int tegra_i2c_probe(struct device_d *dev) i2c_dev->adapter.master_xfer = tegra_i2c_xfer; i2c_dev->adapter.dev.parent = dev; i2c_dev->adapter.nr = dev->id; - i2c_dev->adapter.dev.device_node = dev->device_node; + i2c_dev->adapter.dev.of_node = dev->of_node; ret = i2c_add_numbered_adapter(&i2c_dev->adapter); if (ret) { @@ -683,8 +683,9 @@ static __maybe_unused struct of_device_id tegra_i2c_compatible[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, tegra_i2c_compatible); -static struct driver_d tegra_i2c_driver = { +static struct driver tegra_i2c_driver = { .name = "tegra-i2c", .probe = tegra_i2c_probe, .of_compatible = DRV_OF_COMPAT(tegra_i2c_compatible), diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index ece483f6f5..f508cf1506 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -63,7 +63,7 @@ static struct i2c_algo_bit_data i2c_versatile_algo = { .timeout_ms = 100, }; -static int i2c_versatile_probe(struct device_d *dev) +static int i2c_versatile_probe(struct device *dev) { struct resource *iores; struct i2c_versatile *i2c; @@ -86,7 +86,7 @@ static int i2c_versatile_probe(struct device_d *dev) i2c->adap.algo_data = &i2c->algo; i2c->adap.dev.parent = dev; - i2c->adap.dev.device_node = dev->device_node; + i2c->adap.dev.of_node = dev->of_node; i2c->algo = i2c_versatile_algo; i2c->algo.data = i2c; @@ -106,8 +106,9 @@ static struct of_device_id i2c_versatile_match[] = { { .compatible = "arm,versatile-i2c", }, {}, }; +MODULE_DEVICE_TABLE(of, i2c_versatile_match); -static struct driver_d i2c_versatile_driver = { +static struct driver i2c_versatile_driver = { .name = "versatile-i2c", .probe = i2c_versatile_probe, .of_compatible = DRV_OF_COMPAT(i2c_versatile_match), diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 233d231525..6695ec0411 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -31,7 +31,7 @@ struct i2c_mux_priv { struct i2c_adapter adap; struct i2c_adapter *parent; - struct device_d *mux_dev; + struct device *mux_dev; void *mux_priv; u32 chan_id; @@ -58,7 +58,7 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap, } struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, - struct device_d *mux_dev, + struct device *mux_dev, void *mux_priv, u32 force_nr, u32 chan_id, int (*select) (struct i2c_adapter *, void *, u32), @@ -95,16 +95,16 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, * Try to populate the mux adapter's device_node, expands to * nothing if !CONFIG_OFDEVICE. */ - if (mux_dev->device_node) { + if (mux_dev->of_node) { struct device_node *child; u32 reg; - for_each_child_of_node(mux_dev->device_node, child) { + for_each_child_of_node(mux_dev->of_node, child) { ret = of_property_read_u32(child, "reg", ®); if (ret) continue; if (chan_id == reg) { - priv->adap.dev.device_node = child; + priv->adap.dev.of_node = child; break; } } diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c index b24fd88f5b..5471519045 100644 --- a/drivers/i2c/i2c.c +++ b/drivers/i2c/i2c.c @@ -23,6 +23,7 @@ #include <init.h> #include <of.h> #include <gpio.h> +#include <slice.h> #include <i2c/i2c.h> @@ -62,6 +63,8 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) uint64_t start; int ret, try; + slice_acquire(&adap->slice); + /* * REVISIT the fault reporting model here is weak: * @@ -96,6 +99,8 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) break; } + slice_release(&adap->slice); + return ret; } EXPORT_SYMBOL(i2c_transfer); @@ -253,7 +258,7 @@ int i2c_get_sda_gpio_value(struct i2c_adapter *adap) static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - struct device_d *dev = &adap->dev; + struct device *dev = &adap->dev; int ret = 0; ret = gpio_request_one(bri->scl_gpio, GPIOF_IN, "i2c-scl"); @@ -353,13 +358,13 @@ int i2c_generic_gpio_recovery(struct i2c_adapter *adap) int i2c_recover_bus(struct i2c_adapter *adap) { if (!adap->bus_recovery_info) - return -EOPNOTSUPP; + return -EBUSY; dev_dbg(&adap->dev, "Trying i2c bus recovery\n"); return adap->bus_recovery_info->recover_bus(adap); } -static void i2c_info(struct device_d *dev) +static void i2c_info(struct device *dev) { const struct i2c_client *client = to_i2c_client(dev); @@ -394,7 +399,7 @@ static struct i2c_client *i2c_new_device(struct i2c_adapter *adapter, client->dev.platform_data = chip->platform_data; client->dev.id = DEVICE_ID_DYNAMIC; client->dev.bus = &i2c_bus; - client->dev.device_node = chip->of_node; + client->dev.of_node = chip->of_node; client->adapter = adapter; client->addr = chip->addr; @@ -410,6 +415,9 @@ static struct i2c_client *i2c_new_device(struct i2c_adapter *adapter, if (chip->of_node) chip->of_node->dev = &client->dev; + dev_dbg(&client->dev, "registered on bus %d, chip->addr 0x%02x\n", + adapter->nr, client->addr); + return client; } @@ -418,37 +426,68 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) struct device_node *n; /* Only register child devices if the adapter has a node pointer set */ - if (!IS_ENABLED(CONFIG_OFDEVICE) || !adap->dev.device_node) + if (!IS_ENABLED(CONFIG_OFDEVICE) || !adap->dev.of_node) return; - for_each_available_child_of_node(adap->dev.device_node, n) { + for_each_available_child_of_node(adap->dev.of_node, n) { struct i2c_board_info info = {}; struct i2c_client *result; const __be32 *addr; int len; + if (n->dev) { + dev_dbg(&adap->dev, "of_i2c: skipping already registered %s\n", + dev_name(n->dev)); + continue; + } + of_modalias_node(n, info.type, I2C_NAME_SIZE); info.of_node = n; addr = of_get_property(n, "reg", &len); if (!addr || (len < sizeof(int))) { - dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", - n->full_name); + dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", n); continue; } info.addr = be32_to_cpup(addr); if (info.addr > (1 << 10) - 1) { - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", - info.addr, n->full_name); + dev_err(&adap->dev, "of_i2c: invalid addr=%x on %pOF\n", + info.addr, n); continue; } result = i2c_new_device(adap, &info); if (!result) - dev_err(&adap->dev, "of_i2c: Failure registering %s\n", - n->full_name); + dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", + n); + } +} + +int of_i2c_register_devices_by_node(struct device_node *node) +{ + struct i2c_adapter *adap; + + adap = of_find_i2c_adapter_by_node(node); + if (!adap) + return -ENODEV; + if (IS_ERR(adap)) + return PTR_ERR(adap); + + of_i2c_register_devices(adap); + return 0; +} + +static void i2c_hw_rescan(struct device *dev) +{ + struct i2c_adapter *adap; + + list_for_each_entry(adap, &i2c_adapter_list, list) { + if (dev != adap->dev.parent) + continue; + of_i2c_register_devices(adap); + break; } } @@ -521,7 +560,6 @@ static void scan_boardinfo(struct i2c_adapter *adapter) continue; for (n = bi->n_board_info; n > 0; n--, chip++) { - debug("%s: bus_num: %d, chip->addr 0x%02x\n", __func__, bi->bus_num, chip->addr); /* * NOTE: this relies on i2c_new_device to * issue diagnostics when given bogus inputs @@ -555,10 +593,10 @@ struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) ret = of_device_ensure_probed(node); if (ret) - return ERR_PTR(ret); + return NULL; for_each_i2c_adapter(adap) - if (adap->dev.device_node == node) + if (adap->dev.of_node == node) return adap; return NULL; @@ -566,7 +604,7 @@ struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) { - struct device_d *dev = of_find_device_by_node(node); + struct device *dev = of_find_device_by_node(node); if (!dev) return NULL; @@ -577,12 +615,26 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) return to_i2c_client(dev); } -static void i2c_parse_timing(struct device_d *dev, char *prop_name, u32 *cur_val_p, - u32 def_val, bool use_def) +int of_i2c_device_enable_and_register_by_alias(const char *alias) +{ + struct device_node *np; + + np = of_find_node_by_alias(NULL, alias); + if (!np) + return -ENODEV; + + of_device_enable(np); + return of_i2c_register_devices_by_node(np->parent); +} + + +static void i2c_parse_timing(struct device *dev, char *prop_name, + u32 *cur_val_p, + u32 def_val, bool use_def) { int ret; - ret = of_property_read_u32(dev->device_node, prop_name, cur_val_p); + ret = of_property_read_u32(dev->of_node, prop_name, cur_val_p); if (ret && use_def) *cur_val_p = def_val; @@ -605,7 +657,8 @@ static void i2c_parse_timing(struct device_d *dev, char *prop_name, u32 *cur_val * to switch to this function. New drivers almost always should use the defaults. */ -void i2c_parse_fw_timings(struct device_d *dev, struct i2c_timings *t, bool use_defaults) +void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, + bool use_defaults) { bool u = use_defaults; u32 d; @@ -649,6 +702,7 @@ EXPORT_SYMBOL_GPL(i2c_parse_fw_timings); */ int i2c_add_numbered_adapter(struct i2c_adapter *adapter) { + struct device *hw_dev; int ret; if (adapter->nr < 0) { @@ -672,31 +726,26 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter) list_add_tail(&adapter->list, &i2c_adapter_list); + slice_init(&adapter->slice, dev_name(&adapter->dev)); + /* populate children from any i2c device tables */ scan_boardinfo(adapter); of_i2c_register_devices(adapter); + hw_dev = adapter->dev.parent; + if (hw_dev && dev_of_node(hw_dev)) { + if (!hw_dev->rescan) + hw_dev->rescan = i2c_hw_rescan; + } + return 0; } EXPORT_SYMBOL(i2c_add_numbered_adapter); -static int i2c_probe(struct device_d *dev) -{ - return dev->driver->probe(dev); -} - -static void i2c_remove(struct device_d *dev) -{ - if (dev->driver->remove) - dev->driver->remove(dev); -} - struct bus_type i2c_bus = { .name = "i2c", .match = device_match_of_modalias, - .probe = i2c_probe, - .remove = i2c_remove, }; static int i2c_bus_init(void) diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index f547527fed..6c21b92860 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -180,7 +180,7 @@ static int pca954x_deselect_chan(struct i2c_adapter *adap, /* * I2C init/probing/exit functions */ -static int pca954x_probe(struct device_d *dev) +static int pca954x_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); @@ -199,7 +199,7 @@ static int pca954x_probe(struct device_d *dev) i2c_set_clientdata(client, data); - gpio = of_get_named_gpio(dev->device_node, "reset-gpios", 0); + gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); if (gpio_is_valid(gpio)) gpio_direction_output(gpio, 1); @@ -215,7 +215,7 @@ static int pca954x_probe(struct device_d *dev) if (ret) goto exit_free; - idle_disconnect = of_property_read_bool(dev->device_node, + idle_disconnect = of_property_read_bool(dev->of_node, "i2c-mux-idle-disconnect"); data->last_chan = 0; /* force the first selection */ @@ -255,7 +255,7 @@ err: return ret; } -static struct driver_d pca954x_driver = { +static struct driver pca954x_driver = { .name = "pca954x", .probe = pca954x_probe, .id_table = pca954x_id, |