aboutsummaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/Kconfig169
-rw-r--r--drivers/i2c/designware_i2c.c10
-rw-r--r--drivers/i2c/fsl_i2c.c13
-rw-r--r--drivers/i2c/i2c-uclass.c118
-rw-r--r--drivers/i2c/ihs_i2c.c45
-rw-r--r--drivers/i2c/mxc_i2c.c56
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)