[U-Boot] [PATCH 2/2 v2] samsung: i2c: Enable new CONFIG_SYS_I2C framework

Naveen Krishna Chatradhi ch.naveen at samsung.com
Wed Nov 20 11:50:12 CET 2013


This enables CONFIG_SYS_I2C on Samsung, updating existing s3c24x0
i2c driver to support this.

Signed-off-by: Naveen Krishna Chatradhi <ch.naveen at samsung.com>
---
These patches were tested on SMDK5420 

patches adding Exynos5420 support can be found at.
https://patches.linaro.org/21255/

Changes since v1:
1. Implemented double digit to get rid of indexing issue.
2. Use #ifdefs to define U_BOOT_I2C_ADAP_COMPLETE for various SoCs
As discussed at http://lists.denx.de/pipermail/u-boot/2013-October/163903.html

 drivers/i2c/Makefile      |    2 +-
 drivers/i2c/s3c24x0_i2c.c |  197 +++++++++++++++++++++++++++++++--------------
 2 files changed, 139 insertions(+), 60 deletions(-)

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index df3092e..3090533 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -20,7 +20,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
 COBJS-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
-COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o
+COBJS-$(CONFIG_SYS_I2C_S3C24X0_I2C) += s3c24x0_i2c.o
 COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o
 COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index 71f3637..b8dcc3a 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -23,8 +23,6 @@
 #include <i2c.h>
 #include "s3c24x0_i2c.h"
 
-#ifdef CONFIG_HARD_I2C
-
 #define	I2C_WRITE	0
 #define I2C_READ	1
 
@@ -123,34 +121,67 @@
 #define CONFIG_MAX_I2C_NUM 1
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * For SPL boot some boards need i2c before SDRAM is initialised so force
  * variables to live in SRAM
  */
 static unsigned int g_current_bus __attribute__((section(".data")));
-static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM]
+static struct s3c24x0_i2c_bus i2c_controllers[CONFIG_MAX_I2C_NUM]
 			__attribute__((section(".data")));
 
+static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd);
+static int hsi2c_get_clk_details(struct s3c24x0_i2c_bus *);
+static void hsi2c_ch_init(struct s3c24x0_i2c_bus *);
+
 /**
  * Get a pointer to the given bus index
  *
  * @bus_idx: Bus index to look up
  * @return pointer to bus, or NULL if invalid or not available
  */
-static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
+static struct s3c24x0_i2c_bus *s3c_i2c_get_bus(struct i2c_adapter *adap)
 {
-	if (bus_idx < ARRAY_SIZE(i2c_bus)) {
-		struct s3c24x0_i2c_bus *bus;
+	struct s3c24x0_i2c_bus *bus;
 
-		bus = &i2c_bus[bus_idx];
-		if (bus->active)
-			return bus;
-	}
+	bus = &i2c_controllers[adap->hwadapnr];
+	if (bus->active)
+		return bus;
 
-	debug("Undefined bus: %d\n", bus_idx);
+	debug("Undefined bus: %d\n", adap->hwadapnr);
 	return NULL;
 }
 
+static unsigned int s3c_i2c_set_bus_speed(struct i2c_adapter *adap,
+					  unsigned int speed)
+{
+	struct s3c24x0_i2c_bus *i2c_bus;
+
+	i2c_bus = s3c_i2c_get_bus(adap);
+	if (!i2c_bus)
+		return -1;
+	i2c_bus->clock_frequency = speed;
+
+	if (i2c_bus->is_highspeed) {
+		if (hsi2c_get_clk_details(i2c_bus))
+			return -1;
+		hsi2c_ch_init(i2c_bus);
+	} else {
+		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
+						CONFIG_SYS_I2C_SLAVE);
+	}
+
+	return 0;
+}
+
+static void exynos_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
+{
+	/* This will override the speed selected in the fdt for that port */
+	debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
+	i2c_set_bus_speed(speed);
+}
+
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 static int GetI2CSDA(void)
 {
@@ -399,41 +430,8 @@ static void exynos5_i2c_reset(struct s3c24x0_i2c_bus *i2c_bus)
 	hsi2c_ch_init(i2c_bus);
 }
 
-/*
- * MULTI BUS I2C support
- */
-
-#ifdef CONFIG_I2C_MULTI_BUS
-int i2c_set_bus_num(unsigned int bus)
-{
-	struct s3c24x0_i2c_bus *i2c_bus;
-
-	i2c_bus = get_bus(bus);
-	if (!i2c_bus)
-		return -1;
-	g_current_bus = bus;
-
-	if (i2c_bus->is_highspeed) {
-		if (hsi2c_get_clk_details(i2c_bus))
-			return -1;
-		hsi2c_ch_init(i2c_bus);
-	} else {
-		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
-						CONFIG_SYS_I2C_SLAVE);
-	}
-
-	return 0;
-}
-
-unsigned int i2c_get_bus_num(void)
-{
-	return g_current_bus;
-}
-#endif
-
-void i2c_init(int speed, int slaveadd)
+static void s3c_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
 {
-	int i;
 	struct s3c24x0_i2c *i2c;
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
@@ -457,6 +455,8 @@ void i2c_init(int speed, int slaveadd)
 	}
 
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
+	int i;
+
 	if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
 #ifdef CONFIG_S3C2410
 		ulong old_gpecon = readl(&gpio->gpecon);
@@ -501,7 +501,10 @@ void i2c_init(int speed, int slaveadd)
 #endif
 	}
 #endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
-	i2c_ch_init(i2c, speed, slaveadd);
+
+	/* This will override the speed selected in the fdt for that port */
+	debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
+	i2c_ch_init(i2c, speed, slaveaddr);
 }
 
 /*
@@ -837,13 +840,13 @@ bailout:
 	return result;
 }
 
-int i2c_probe(uchar chip)
+int s3c_i2c_probe(struct i2c_adapter *adap, uchar chip)
 {
 	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar buf[1];
 	int ret;
 
-	i2c_bus = get_bus(g_current_bus);
+	i2c_bus = s3c_i2c_get_bus(adap);
 	if (!i2c_bus)
 		return -1;
 	buf[0] = 0;
@@ -865,7 +868,8 @@ int i2c_probe(uchar chip)
 	return ret != I2C_OK;
 }
 
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+int s3c_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, int alen,
+	     uchar *buffer, int len)
 {
 	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar xaddr[4];
@@ -899,7 +903,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	i2c_bus = get_bus(g_current_bus);
+	i2c_bus = s3c_i2c_get_bus(adap);
 	if (!i2c_bus)
 		return -1;
 
@@ -919,7 +923,8 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 	return 0;
 }
 
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+int s3c_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, int alen,
+	      uchar *buffer, int len)
 {
 	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar xaddr[4];
@@ -952,7 +957,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	i2c_bus = get_bus(g_current_bus);
+	i2c_bus = s3c_i2c_get_bus(adap);
 	if (!i2c_bus)
 		return -1;
 
@@ -985,7 +990,7 @@ static void process_nodes(const void *blob, int node_list[], int count,
 		if (node <= 0)
 			continue;
 
-		bus = &i2c_bus[i];
+		bus = &i2c_controllers[i];
 		bus->active = true;
 		bus->is_highspeed = is_highspeed;
 
@@ -1025,15 +1030,14 @@ void board_i2c_init(const void *blob)
 		COMPAT_SAMSUNG_EXYNOS5_I2C, node_list,
 		CONFIG_MAX_I2C_NUM);
 	process_nodes(blob, node_list, count, 1);
-
 }
 
 int i2c_get_bus_num_fdt(int node)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) {
-		if (node == i2c_bus[i].node)
+	for (i = 0; i < ARRAY_SIZE(i2c_controllers); i++) {
+		if (node == i2c_controllers[i].node)
 			return i;
 	}
 
@@ -1052,8 +1056,8 @@ int i2c_reset_port_fdt(const void *blob, int node)
 		return -1;
 	}
 
-	i2c_bus = get_bus(bus);
-	if (!i2c_bus) {
+	i2c_bus = &i2c_controllers[bus];
+	if (!i2c_bus->active) {
 		debug("get_bus() failed for node node %d\n", node);
 		return -1;
 	}
@@ -1071,4 +1075,79 @@ int i2c_reset_port_fdt(const void *blob, int node)
 }
 #endif
 
-#endif /* CONFIG_HARD_I2C */
+/*
+ * Register soft i2c adapters
+ */
+#if defined(CONFIG_EXYNOS5420)
+U_BOOT_I2C_ADAP_COMPLETE(i2c00, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 0)
+U_BOOT_I2C_ADAP_COMPLETE(i2c01, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 1)
+U_BOOT_I2C_ADAP_COMPLETE(i2c02, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 2)
+U_BOOT_I2C_ADAP_COMPLETE(i2c03, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 3)
+U_BOOT_I2C_ADAP_COMPLETE(i2c04, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 4)
+U_BOOT_I2C_ADAP_COMPLETE(i2c05, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 5)
+U_BOOT_I2C_ADAP_COMPLETE(i2c06, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 6)
+U_BOOT_I2C_ADAP_COMPLETE(i2c07, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 7)
+U_BOOT_I2C_ADAP_COMPLETE(i2c08, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 8)
+U_BOOT_I2C_ADAP_COMPLETE(i2c09, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 9)
+U_BOOT_I2C_ADAP_COMPLETE(i2c10, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 10)
+#elif defined(CONFIG_EXYNOS5250)
+U_BOOT_I2C_ADAP_COMPLETE(i2c00, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 0)
+U_BOOT_I2C_ADAP_COMPLETE(i2c01, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 1)
+U_BOOT_I2C_ADAP_COMPLETE(i2c02, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 2)
+U_BOOT_I2C_ADAP_COMPLETE(i2c03, exynos_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 3)
+U_BOOT_I2C_ADAP_COMPLETE(i2c04, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 4)
+U_BOOT_I2C_ADAP_COMPLETE(i2c05, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 5)
+U_BOOT_I2C_ADAP_COMPLETE(i2c06, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 6)
+U_BOOT_I2C_ADAP_COMPLETE(i2c07, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 7)
+U_BOOT_I2C_ADAP_COMPLETE(i2c08, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 8)
+U_BOOT_I2C_ADAP_COMPLETE(i2c09, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 9)
+U_BOOT_I2C_ADAP_COMPLETE(s3c10, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 10)
+#else
+U_BOOT_I2C_ADAP_COMPLETE(s3c0, s3c_i2c_init, s3c_i2c_probe,
+			 s3c_i2c_read, s3c_i2c_write,
+			 s3c_i2c_set_bus_speed, 100000, 0, 0)
+#endif
-- 
1.7.10.4



More information about the U-Boot mailing list