diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/Kconfig | 169 | ||||
-rw-r--r-- | drivers/i2c/designware_i2c.c | 10 | ||||
-rw-r--r-- | drivers/i2c/fsl_i2c.c | 13 | ||||
-rw-r--r-- | drivers/i2c/i2c-uclass.c | 118 | ||||
-rw-r--r-- | drivers/i2c/ihs_i2c.c | 45 | ||||
-rw-r--r-- | drivers/i2c/mxc_i2c.c | 56 |
6 files changed, 373 insertions, 38 deletions
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 3299ef0fea..7fb201d8e6 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -149,13 +149,176 @@ config SYS_I2C_MESON both 7-bit and 10-bit addresses. config SYS_I2C_MXC - bool "NXP i.MX I2C driver" - depends on MX6 + bool "NXP MXC I2C driver" help - Add support for the NXP i.MX I2C driver. This supports upto for bus + Add support for the NXP I2C driver. This supports upto for bus channels and operating on standard mode upto 100 kbits/s and fast mode upto 400 kbits/s. +if SYS_I2C_MXC +config SYS_I2C_MXC_I2C1 + bool "NXP MXC I2C1" + help + Add support for NXP MXC I2C Controller 1. + Required for SoCs which have I2C MXC controller 1 eg LS1088A, LS2080A + +config SYS_I2C_MXC_I2C2 + bool "NXP MXC I2C2" + help + Add support for NXP MXC I2C Controller 2. + Required for SoCs which have I2C MXC controller 2 eg LS1088A, LS2080A + +config SYS_I2C_MXC_I2C3 + bool "NXP MXC I2C3" + help + Add support for NXP MXC I2C Controller 3. + Required for SoCs which have I2C MXC controller 3 eg LS1088A, LS2080A + +config SYS_I2C_MXC_I2C4 + bool "NXP MXC I2C4" + help + Add support for NXP MXC I2C Controller 4. + Required for SoCs which have I2C MXC controller 4 eg LS1088A, LS2080A + +config SYS_I2C_MXC_I2C5 + bool "NXP MXC I2C5" + help + Add support for NXP MXC I2C Controller 5. + Required for SoCs which have I2C MXC controller 5 eg LX2160A + +config SYS_I2C_MXC_I2C6 + bool "NXP MXC I2C6" + help + Add support for NXP MXC I2C Controller 6. + Required for SoCs which have I2C MXC controller 6 eg LX2160A + +config SYS_I2C_MXC_I2C7 + bool "NXP MXC I2C7" + help + Add support for NXP MXC I2C Controller 7. + Required for SoCs which have I2C MXC controller 7 eg LX2160A + +config SYS_I2C_MXC_I2C8 + bool "NXP MXC I2C8" + help + Add support for NXP MXC I2C Controller 8. + Required for SoCs which have I2C MXC controller 8 eg LX2160A +endif + +if SYS_I2C_MXC_I2C1 +config SYS_MXC_I2C1_SPEED + int "I2C Channel 1 speed" + default 40000000 if TARGET_LS2080A_SIMU || TARGET_LS2080A_EMU + default 100000 + help + MXC I2C Channel 1 speed + +config SYS_MXC_I2C1_SLAVE + int "I2C1 Slave" + default 0 + help + MXC I2C1 Slave +endif + +if SYS_I2C_MXC_I2C2 +config SYS_MXC_I2C2_SPEED + int "I2C Channel 2 speed" + default 40000000 if TARGET_LS2080A_SIMU || TARGET_LS2080A_EMU + default 100000 + help + MXC I2C Channel 2 speed + +config SYS_MXC_I2C2_SLAVE + int "I2C2 Slave" + default 0 + help + MXC I2C2 Slave +endif + +if SYS_I2C_MXC_I2C3 +config SYS_MXC_I2C3_SPEED + int "I2C Channel 3 speed" + default 100000 + help + MXC I2C Channel 3 speed + +config SYS_MXC_I2C3_SLAVE + int "I2C3 Slave" + default 0 + help + MXC I2C3 Slave +endif + +if SYS_I2C_MXC_I2C4 +config SYS_MXC_I2C4_SPEED + int "I2C Channel 4 speed" + default 100000 + help + MXC I2C Channel 4 speed + +config SYS_MXC_I2C4_SLAVE + int "I2C4 Slave" + default 0 + help + MXC I2C4 Slave +endif + +if SYS_I2C_MXC_I2C5 +config SYS_MXC_I2C5_SPEED + int "I2C Channel 5 speed" + default 100000 + help + MXC I2C Channel 5 speed + +config SYS_MXC_I2C5_SLAVE + int "I2C5 Slave" + default 0 + help + MXC I2C5 Slave +endif + +if SYS_I2C_MXC_I2C6 +config SYS_MXC_I2C6_SPEED + int "I2C Channel 6 speed" + default 100000 + help + MXC I2C Channel 6 speed + +config SYS_MXC_I2C6_SLAVE + int "I2C6 Slave" + default 0 + help + MXC I2C6 Slave +endif + +if SYS_I2C_MXC_I2C7 +config SYS_MXC_I2C7_SPEED + int "I2C Channel 7 speed" + default 100000 + help + MXC I2C Channel 7 speed + +config SYS_MXC_I2C7_SLAVE + int "I2C7 Slave" + default 0 + help + MXC I2C7 Slave +endif + +if SYS_I2C_MXC_I2C8 +config SYS_MXC_I2C8_SPEED + int "I2C Channel 8 speed" + default 100000 + help + MXC I2C Channel 8 speed + +config SYS_MXC_I2C8_SLAVE + int "I2C8 Slave" + default 0 + help + MXC I2C8 Slave +endif + config SYS_I2C_OMAP24XX bool "TI OMAP2+ I2C driver" depends on ARCH_OMAP2PLUS diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index 8cfed2194c..419d021a31 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -9,6 +9,7 @@ #include <dm.h> #include <i2c.h> #include <pci.h> +#include <reset.h> #include <asm/io.h> #include "designware_i2c.h" @@ -34,6 +35,7 @@ static struct dw_scl_sda_cfg byt_config = { struct dw_i2c { struct i2c_regs *regs; struct dw_scl_sda_cfg *scl_sda_cfg; + struct reset_ctl reset_ctl; }; #ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED @@ -534,6 +536,7 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr, static int designware_i2c_probe(struct udevice *bus) { struct dw_i2c *priv = dev_get_priv(bus); + int ret; if (device_is_on_pci_bus(bus)) { #ifdef CONFIG_DM_PCI @@ -549,6 +552,13 @@ static int designware_i2c_probe(struct udevice *bus) priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus); } + ret = reset_get_by_name(bus, "i2c", &priv->reset_ctl); + if (ret) + pr_info("reset_get_by_name() failed: %d\n", ret); + + if (&priv->reset_ctl) + reset_deassert(&priv->reset_ctl); + __dw_i2c_init(priv->regs, 0, 0); return 0; diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index cb0f5ea233..450a91ded6 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -12,6 +12,7 @@ #include <i2c.h> /* Functional interface */ #include <asm/io.h> #include <asm/fsl_i2c.h> /* HW definitions */ +#include <clk.h> #include <dm.h> #include <mapmem.h> @@ -573,11 +574,9 @@ static int fsl_i2c_set_bus_speed(struct udevice *bus, uint speed) static int fsl_i2c_ofdata_to_platdata(struct udevice *bus) { struct fsl_i2c_dev *dev = dev_get_priv(bus); - fdt_addr_t addr; + struct clk clock; - addr = dev_read_u32_default(bus, "reg", -1); - - dev->base = map_sysmem(CONFIG_SYS_IMMR + addr, sizeof(struct fsl_i2c_base)); + dev->base = map_sysmem(dev_read_addr(bus), sizeof(struct fsl_i2c_base)); if (!dev->base) return -ENOMEM; @@ -587,7 +586,11 @@ static int fsl_i2c_ofdata_to_platdata(struct udevice *bus) 0x7f); dev->speed = dev_read_u32_default(bus, "clock-frequency", 400000); - dev->i2c_clk = dev->index ? gd->arch.i2c2_clk : gd->arch.i2c1_clk; + if (!clk_get_by_index(bus, 0, &clock)) + dev->i2c_clk = clk_get_rate(&clock); + else + dev->i2c_clk = dev->index ? gd->arch.i2c2_clk : + gd->arch.i2c1_clk; return 0; } diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 920811a075..4ac6ef84f5 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -11,9 +11,19 @@ #include <malloc.h> #include <dm/device-internal.h> #include <dm/lists.h> +#include <dm/pinctrl.h> +#ifdef CONFIG_DM_GPIO +#include <asm/gpio.h> +#endif #define I2C_MAX_OFFSET_LEN 4 +enum { + PIN_SDA = 0, + PIN_SCL, + PIN_COUNT, +}; + /* Useful debugging function */ void i2c_dump_msgs(struct i2c_msg *msg, int nmsgs) { @@ -445,20 +455,110 @@ int i2c_get_chip_offset_len(struct udevice *dev) return chip->offset_len; } +#ifdef CONFIG_DM_GPIO +static void i2c_gpio_set_pin(struct gpio_desc *pin, int bit) +{ + if (bit) + dm_gpio_set_dir_flags(pin, GPIOD_IS_IN); + else + dm_gpio_set_dir_flags(pin, GPIOD_IS_OUT | + GPIOD_ACTIVE_LOW | + GPIOD_IS_OUT_ACTIVE); +} + +static int i2c_gpio_get_pin(struct gpio_desc *pin) +{ + return dm_gpio_get_value(pin); +} + +static int i2c_deblock_gpio_loop(struct gpio_desc *sda_pin, + struct gpio_desc *scl_pin) +{ + int counter = 9; + int ret = 0; + + i2c_gpio_set_pin(sda_pin, 1); + i2c_gpio_set_pin(scl_pin, 1); + udelay(5); + + /* Toggle SCL until slave release SDA */ + while (counter-- >= 0) { + i2c_gpio_set_pin(scl_pin, 1); + udelay(5); + i2c_gpio_set_pin(scl_pin, 0); + udelay(5); + if (i2c_gpio_get_pin(sda_pin)) + break; + } + + /* Then, send I2C stop */ + i2c_gpio_set_pin(sda_pin, 0); + udelay(5); + + i2c_gpio_set_pin(scl_pin, 1); + udelay(5); + + i2c_gpio_set_pin(sda_pin, 1); + udelay(5); + + if (!i2c_gpio_get_pin(sda_pin) || !i2c_gpio_get_pin(scl_pin)) + ret = -EREMOTEIO; + + return ret; +} + +static int i2c_deblock_gpio(struct udevice *bus) +{ + struct gpio_desc gpios[PIN_COUNT]; + int ret, ret0; + + ret = gpio_request_list_by_name(bus, "gpios", gpios, + ARRAY_SIZE(gpios), GPIOD_IS_IN); + if (ret != ARRAY_SIZE(gpios)) { + debug("%s: I2C Node '%s' has no 'gpios' property %s\n", + __func__, dev_read_name(bus), bus->name); + if (ret >= 0) { + gpio_free_list(bus, gpios, ret); + ret = -ENOENT; + } + goto out; + } + + ret = pinctrl_select_state(bus, "gpio"); + if (ret) { + debug("%s: I2C Node '%s' has no 'gpio' pinctrl state. %s\n", + __func__, dev_read_name(bus), bus->name); + goto out_no_pinctrl; + } + + ret0 = i2c_deblock_gpio_loop(&gpios[PIN_SDA], &gpios[PIN_SCL]); + + ret = pinctrl_select_state(bus, "default"); + if (ret) { + debug("%s: I2C Node '%s' has no 'default' pinctrl state. %s\n", + __func__, dev_read_name(bus), bus->name); + } + + ret = !ret ? ret0 : ret; + +out_no_pinctrl: + gpio_free_list(bus, gpios, ARRAY_SIZE(gpios)); +out: + return ret; +} +#else +static int i2c_deblock_gpio(struct udevice *bus) +{ + return -ENOSYS; +} +#endif // CONFIG_DM_GPIO + int i2c_deblock(struct udevice *bus) { struct dm_i2c_ops *ops = i2c_get_ops(bus); - /* - * We could implement a software deblocking here if we could get - * access to the GPIOs used by I2C, and switch them to GPIO mode - * and then back to I2C. This is somewhat beyond our powers in - * driver model at present, so for now just fail. - * - * See https://patchwork.ozlabs.org/patch/399040/ - */ if (!ops->deblock) - return -ENOSYS; + return i2c_deblock_gpio(bus); return ops->deblock(bus); } diff --git a/drivers/i2c/ihs_i2c.c b/drivers/i2c/ihs_i2c.c index 9298521220..82abb439f0 100644 --- a/drivers/i2c/ihs_i2c.c +++ b/drivers/i2c/ihs_i2c.c @@ -99,7 +99,8 @@ static int wait_for_int(bool read) #endif #ifdef CONFIG_DM_I2C - fpgamap_read16(fpga, priv->addr + REG_INTERRUPT_STATUS, &val); + fpgamap_read(fpga, priv->addr + REG_INTERRUPT_STATUS, &val, + FPGAMAP_SIZE_16); #else I2C_GET_REG(interrupt_status, &val); #endif @@ -110,7 +111,8 @@ static int wait_for_int(bool read) if (ctr++ > 5000) return 1; #ifdef CONFIG_DM_I2C - fpgamap_read16(fpga, priv->addr + REG_INTERRUPT_STATUS, &val); + fpgamap_read(fpga, priv->addr + REG_INTERRUPT_STATUS, &val, + FPGAMAP_SIZE_16); #else I2C_GET_REG(interrupt_status, &val); #endif @@ -128,6 +130,7 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read, #endif { u16 val; + u16 data; #ifdef CONFIG_DM_I2C struct ihs_i2c_priv *priv = dev_get_priv(dev); struct udevice *fpga; @@ -136,13 +139,14 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read, #endif /* Clear interrupt status */ + data = I2CINT_ERROR_EV | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV; #ifdef CONFIG_DM_I2C - fpgamap_write16(fpga, priv->addr + REG_INTERRUPT_STATUS, - I2CINT_ERROR_EV | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV); - fpgamap_read16(fpga, priv->addr + REG_INTERRUPT_STATUS, &val); + fpgamap_write(fpga, priv->addr + REG_INTERRUPT_STATUS, &data, + FPGAMAP_SIZE_16); + fpgamap_read(fpga, priv->addr + REG_INTERRUPT_STATUS, &val, + FPGAMAP_SIZE_16); #else - I2C_SET_REG(interrupt_status, I2CINT_ERROR_EV - | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV); + I2C_SET_REG(interrupt_status, data); I2C_GET_REG(interrupt_status, &val); #endif @@ -153,26 +157,24 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read, if (len > 1) val |= buffer[1] << 8; #ifdef CONFIG_DM_I2C - fpgamap_write16(fpga, priv->addr + REG_WRITE_MAILBOX_EXT, val); + fpgamap_write(fpga, priv->addr + REG_WRITE_MAILBOX_EXT, &val, + FPGAMAP_SIZE_16); #else I2C_SET_REG(write_mailbox_ext, val); #endif } + data = I2CMB_NATIVE + | (read ? 0 : I2CMB_WRITE) + | (chip << 1) + | ((len > 1) ? I2CMB_2BYTE : 0) + | (is_last ? 0 : I2CMB_HOLD_BUS); + #ifdef CONFIG_DM_I2C - fpgamap_write16(fpga, priv->addr + REG_WRITE_MAILBOX, - I2CMB_NATIVE - | (read ? I2CMB_READ : I2CMB_WRITE) - | (chip << 1) - | ((len > 1) ? I2CMB_2BYTE : I2CMB_1BYTE) - | (!is_last ? I2CMB_HOLD_BUS : I2CMB_DONT_HOLD_BUS)); + fpgamap_write(fpga, priv->addr + REG_WRITE_MAILBOX, &data, + FPGAMAP_SIZE_16); #else - I2C_SET_REG(write_mailbox, - I2CMB_NATIVE - | (read ? 0 : I2CMB_WRITE) - | (chip << 1) - | ((len > 1) ? I2CMB_2BYTE : 0) - | (is_last ? 0 : I2CMB_HOLD_BUS)); + I2C_SET_REG(write_mailbox, data); #endif #ifdef CONFIG_DM_I2C @@ -185,7 +187,8 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read, /* If we want to read, get the bytes from the mailbox */ if (read) { #ifdef CONFIG_DM_I2C - fpgamap_read16(fpga, priv->addr + REG_READ_MAILBOX_EXT, &val); + fpgamap_read(fpga, priv->addr + REG_READ_MAILBOX_EXT, &val, + FPGAMAP_SIZE_16); #else I2C_GET_REG(read_mailbox_ext, &val); #endif diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 79228c2757..a17c1eceae 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -589,6 +589,22 @@ static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr, #define I2C4_BASE_ADDR 0 #endif +#if !defined(I2C5_BASE_ADDR) +#define I2C5_BASE_ADDR 0 +#endif + +#if !defined(I2C6_BASE_ADDR) +#define I2C6_BASE_ADDR 0 +#endif + +#if !defined(I2C7_BASE_ADDR) +#define I2C7_BASE_ADDR 0 +#endif + +#if !defined(I2C8_BASE_ADDR) +#define I2C8_BASE_ADDR 0 +#endif + static struct mxc_i2c_bus mxc_i2c_buses[] = { #if defined(CONFIG_ARCH_LS1021A) || defined(CONFIG_VF610) || \ defined(CONFIG_FSL_LAYERSCAPE) @@ -596,11 +612,19 @@ static struct mxc_i2c_bus mxc_i2c_buses[] = { { 1, I2C2_BASE_ADDR, I2C_QUIRK_FLAG }, { 2, I2C3_BASE_ADDR, I2C_QUIRK_FLAG }, { 3, I2C4_BASE_ADDR, I2C_QUIRK_FLAG }, + { 4, I2C5_BASE_ADDR, I2C_QUIRK_FLAG }, + { 5, I2C6_BASE_ADDR, I2C_QUIRK_FLAG }, + { 6, I2C7_BASE_ADDR, I2C_QUIRK_FLAG }, + { 7, I2C8_BASE_ADDR, I2C_QUIRK_FLAG }, #else { 0, I2C1_BASE_ADDR, 0 }, { 1, I2C2_BASE_ADDR, 0 }, { 2, I2C3_BASE_ADDR, 0 }, { 3, I2C4_BASE_ADDR, 0 }, + { 4, I2C5_BASE_ADDR, 0 }, + { 5, I2C6_BASE_ADDR, 0 }, + { 6, I2C7_BASE_ADDR, 0 }, + { 7, I2C8_BASE_ADDR, 0 }, #endif }; @@ -738,6 +762,38 @@ U_BOOT_I2C_ADAP_COMPLETE(mxc3, mxc_i2c_init, mxc_i2c_probe, CONFIG_SYS_MXC_I2C4_SLAVE, 3) #endif +#ifdef CONFIG_SYS_I2C_MXC_I2C5 +U_BOOT_I2C_ADAP_COMPLETE(mxc4, mxc_i2c_init, mxc_i2c_probe, + mxc_i2c_read, mxc_i2c_write, + mxc_i2c_set_bus_speed, + CONFIG_SYS_MXC_I2C5_SPEED, + CONFIG_SYS_MXC_I2C5_SLAVE, 4) +#endif + +#ifdef CONFIG_SYS_I2C_MXC_I2C6 +U_BOOT_I2C_ADAP_COMPLETE(mxc5, mxc_i2c_init, mxc_i2c_probe, + mxc_i2c_read, mxc_i2c_write, + mxc_i2c_set_bus_speed, + CONFIG_SYS_MXC_I2C6_SPEED, + CONFIG_SYS_MXC_I2C6_SLAVE, 5) +#endif + +#ifdef CONFIG_SYS_I2C_MXC_I2C7 +U_BOOT_I2C_ADAP_COMPLETE(mxc6, mxc_i2c_init, mxc_i2c_probe, + mxc_i2c_read, mxc_i2c_write, + mxc_i2c_set_bus_speed, + CONFIG_SYS_MXC_I2C7_SPEED, + CONFIG_SYS_MXC_I2C7_SLAVE, 6) +#endif + +#ifdef CONFIG_SYS_I2C_MXC_I2C8 +U_BOOT_I2C_ADAP_COMPLETE(mxc7, mxc_i2c_init, mxc_i2c_probe, + mxc_i2c_read, mxc_i2c_write, + mxc_i2c_set_bus_speed, + CONFIG_SYS_MXC_I2C8_SPEED, + CONFIG_SYS_MXC_I2C8_SLAVE, 7) +#endif + #else static int mxc_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) |