[U-Boot] [PATCH 0/6 V4] EXYNOS5: FDT Support for I2C

This patch set adds FDT support for I2C driver and API's to acess the bus number using the fdt node and also reset the port.
Changes in V2: - Baord i2c init moved to I2C driver in case of FDT. - Added Periph id to device node. - Modified i2c_get_bus_num_fdt api to compare using node. Changes in V3: - Peripheral id removed from dtsi file and decoded based on interrupts. - API for fdtdec_lookup removed as it is already present as fd_dec_lookup. Changes in V4: - renamed decode_peripheral_id to pinmux_decode_peripheral_id. - added comments in periph.h as suggested by Simon Glass.
Rajeshwari Shinde (6): EXYNOS5: FDT: Add I2C device node data EXYNOS5 : FDT: Add Aliases for I2C device EXYNOS5: FDT: Add compatible string for I2C EXYNOS5: FDT : Decode peripheral id I2C: Driver changes for FDT support SMDK5250: Initialise I2C using FDT
arch/arm/cpu/armv7/exynos/pinmux.c | 28 ++++++++++ arch/arm/dts/exynos5250.dtsi | 64 ++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/periph.h | 31 ++++++----- arch/arm/include/asm/arch-exynos/pinmux.h | 8 +++ board/samsung/dts/exynos5250-smdk5250.dts | 11 ++++ board/samsung/smdk5250/smdk5250.c | 20 +------- drivers/i2c/s3c24x0_i2c.c | 83 ++++++++++++++++++++++++++++- drivers/i2c/s3c24x0_i2c.h | 8 +++ include/fdtdec.h | 1 + include/i2c.h | 26 +++++++++ lib/fdtdec.c | 1 + 11 files changed, 248 insertions(+), 33 deletions(-)

Add I2C device node data for exynos
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com Acked-by: Simon Glass sjg@chromium.org --- Changes in V2: - Added Periph id to the I2C device node Changes in V3: - Removed Periph id as decoding done based on interrupts. Changes in V4: - None arch/arm/dts/exynos5250.dtsi | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi index db22db6..e877e6c 100644 --- a/arch/arm/dts/exynos5250.dtsi +++ b/arch/arm/dts/exynos5250.dtsi @@ -33,4 +33,68 @@ compatible = "samsung,exynos-tmu"; reg = <0x10060000 0xffff>; }; + + i2c@12c60000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C60000 0x100>; + interrupts = <0 56 0>; + }; + + i2c@12c70000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C70000 0x100>; + interrupts = <0 57 0>; + }; + + i2c@12c80000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C80000 0x100>; + interrupts = <0 58 0>; + }; + + i2c@12c90000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12C90000 0x100>; + interrupts = <0 59 0>; + }; + + i2c@12ca0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CA0000 0x100>; + interrupts = <0 60 0>; + }; + + i2c@12cb0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CB0000 0x100>; + interrupts = <0 61 0>; + }; + + i2c@12cc0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CC0000 0x100>; + interrupts = <0 62 0>; + }; + + i2c@12cd0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,s3c2440-i2c"; + reg = <0x12CD0000 0x100>; + interrupts = <0 63 0>; + }; };

This patch adds aliases for I2C.
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com Acked-by: Simon Glass sjg@chromium.org Acked-by: Heiko Schocher hs@denx.de --- Changes in V2: - None. Changes in V3: - None. Changes in V4: - None. board/samsung/dts/exynos5250-smdk5250.dts | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/board/samsung/dts/exynos5250-smdk5250.dts b/board/samsung/dts/exynos5250-smdk5250.dts index 2d3ecca..8722b36 100644 --- a/board/samsung/dts/exynos5250-smdk5250.dts +++ b/board/samsung/dts/exynos5250-smdk5250.dts @@ -16,6 +16,17 @@ model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; compatible = "samsung,smdk5250", "samsung,exynos5250";
+ aliases { + i2c0 = "/i2c@12c60000"; + i2c1 = "/i2c@12c70000"; + i2c2 = "/i2c@12c80000"; + i2c3 = "/i2c@12c90000"; + i2c4 = "/i2c@12ca0000"; + i2c5 = "/i2c@12cb0000"; + i2c6 = "/i2c@12cc0000"; + i2c7 = "/i2c@12cd0000"; + }; + sromc@12250000 { bank = <1>; srom-timing = <1 9 12 1 6 1 1>;

Add required compatible information for I2C driver.
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com Acked-by: Simon Glass sjg@chromium.org Acked-by: Heiko Schocher hs@denx.de --- Changes in V2: - None. Chnages in V3: - None. Chnages in V4: - None. include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/fdtdec.h b/include/fdtdec.h index 8b2218c..883961f 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -69,6 +69,7 @@ enum fdt_compat_id { COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */ COMPAT_SAMSUNG_EXYNOS5_SROMC, /* Exynos5 SROMC */ COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */ + COMPAT_SAMSUNG_S3C2440_I2C, /* Exynos I2C Controller */
COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index b9519f9..ff25db6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -46,6 +46,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SMSC_LAN9215, "smsc,lan9215"), COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"), COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"), + COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"), };
const char *fdtdec_get_compatible(enum fdt_compat_id id)

Api is added to decode peripheral id based on the interrupt number of the peripheral.
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com --- Chnages in V3: - New patch added. Chnages in V4: - Renamed decode_periph_id to pinmux_decode_periph_id. - Added comments in periph.h as suggested by Simon Glass. arch/arm/cpu/armv7/exynos/pinmux.c | 28 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/periph.h | 31 ++++++++++++++++------------ arch/arm/include/asm/arch-exynos/pinmux.h | 8 +++++++ 3 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index f02f441..f9f6911 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -22,6 +22,7 @@ */
#include <common.h> +#include <fdtdec.h> #include <asm/arch/gpio.h> #include <asm/arch/pinmux.h> #include <asm/arch/sromc.h> @@ -396,3 +397,30 @@ int exynos_pinmux_config(int peripheral, int flags) return -1; } } + +#ifdef CONFIG_OF_CONTROL +static int exynos5_pinmux_decode_periph_id(const void *blob, int node) +{ + int err; + u32 cell[3]; + + err = fdtdec_get_int_array(blob, node, "interrupts", cell, + ARRAY_SIZE(cell)); + if (err) + return PERIPH_ID_NONE; + + if ((130 > cell[1]) || (cell[1] < 31)) + return cell[1]; + + debug(" invalid peripheral id\n"); + return PERIPH_ID_NONE; +} + +int pinmux_decode_periph_id(const void *blob, int node) +{ + if (cpu_is_exynos5()) + return exynos5_pinmux_decode_periph_id(blob, node); + else + return PERIPH_ID_NONE; +} +#endif diff --git a/arch/arm/include/asm/arch-exynos/periph.h b/arch/arm/include/asm/arch-exynos/periph.h index 13abd2d..783b77c 100644 --- a/arch/arm/include/asm/arch-exynos/periph.h +++ b/arch/arm/include/asm/arch-exynos/periph.h @@ -25,12 +25,17 @@ #define __ASM_ARM_ARCH_PERIPH_H
/* - * Peripherals requiring clock/pinmux configuration. List will + * Peripherals requiring pinmux configuration0. List will * grow with support for more devices getting added. + * Numbering based on interrupt table. * */ enum periph_id { - PERIPH_ID_I2C0, + PERIPH_ID_UART0 = 51, + PERIPH_ID_UART1, + PERIPH_ID_UART2, + PERIPH_ID_UART3, + PERIPH_ID_I2C0 = 56, PERIPH_ID_I2C1, PERIPH_ID_I2C2, PERIPH_ID_I2C3, @@ -38,22 +43,22 @@ enum periph_id { PERIPH_ID_I2C5, PERIPH_ID_I2C6, PERIPH_ID_I2C7, - PERIPH_ID_I2S1, - PERIPH_ID_SDMMC0, + PERIPH_ID_SPI0 = 68, + PERIPH_ID_SPI1, + PERIPH_ID_SPI2, + PERIPH_ID_SDMMC0 = 75, PERIPH_ID_SDMMC1, PERIPH_ID_SDMMC2, PERIPH_ID_SDMMC3, - PERIPH_ID_SDMMC4, - PERIPH_ID_SROMC, - PERIPH_ID_SPI0, - PERIPH_ID_SPI1, - PERIPH_ID_SPI2, + PERIPH_ID_I2S1 = 99, + +/* Since following peripherals do not have shared peripheral interrupts (SPIs) + * they are numbered arbitiraly after the maximum SPIs Exynos has (128) + */ + PERIPH_ID_SROMC = 128, PERIPH_ID_SPI3, PERIPH_ID_SPI4, - PERIPH_ID_UART0, - PERIPH_ID_UART1, - PERIPH_ID_UART2, - PERIPH_ID_UART3, + PERIPH_ID_SDMMC4,
PERIPH_ID_COUNT, PERIPH_ID_NONE = -1, diff --git a/arch/arm/include/asm/arch-exynos/pinmux.h b/arch/arm/include/asm/arch-exynos/pinmux.h index 10ea736..00cbb0d 100644 --- a/arch/arm/include/asm/arch-exynos/pinmux.h +++ b/arch/arm/include/asm/arch-exynos/pinmux.h @@ -55,4 +55,12 @@ enum { */ int exynos_pinmux_config(int peripheral, int flags);
+/** + * Decode the peripheral id using the interrpt numbers. + * + * @param blob Device tree blbo + * @param node FDT I2C node to find + * @return peripheral id if ok, PERIPH_ID_NONE on error + */ +int pinmux_decode_periph_id(const void *blob, int node); #endif

On Wed, Nov 28, 2012 at 11:09 PM, Rajeshwari Shinde rajeshwari.s@samsung.com wrote:
Api is added to decode peripheral id based on the interrupt number of the peripheral.
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com
Acked-by; Simon Glass sjg@chromium.org
Chnages in V3: - New patch added. Chnages in V4: - Renamed decode_periph_id to pinmux_decode_periph_id. - Added comments in periph.h as suggested by Simon Glass. arch/arm/cpu/armv7/exynos/pinmux.c | 28 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/periph.h | 31 ++++++++++++++++------------ arch/arm/include/asm/arch-exynos/pinmux.h | 8 +++++++ 3 files changed, 54 insertions(+), 13 deletions(-)

Functions added to get the I2C bus number and reset I2C bus using FDT node.
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com Acked-by: Simon Glass sjg@chromium.org --- Changes in V2: - Added periph id to I2C bus structure. - Modified i2c_get_bus_num_fdt function to compare with node. - Board i2c init moved to driver in case of FDT. Chnages in V3: - peripheral id decoded based on interrupts. - removed compat id check in i2c_get_bus_num_fdt. Changes in V4: - Renamed decode_periph_id to pinmux_decode_periph_id. drivers/i2c/s3c24x0_i2c.c | 83 ++++++++++++++++++++++++++++++++++++++++++++- drivers/i2c/s3c24x0_i2c.h | 8 ++++ include/i2c.h | 26 ++++++++++++++ 3 files changed, 116 insertions(+), 1 deletions(-)
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 9bc4c7f..94a093e 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -27,9 +27,11 @@ */
#include <common.h> +#include <fdtdec.h> #ifdef CONFIG_EXYNOS5 #include <asm/arch/clk.h> #include <asm/arch/cpu.h> +#include <asm/arch/pinmux.h> #else #include <asm/arch/s3c24x0_cpu.h> #endif @@ -60,7 +62,14 @@ #define I2C_TIMEOUT 1 /* 1 second */
-static unsigned int g_current_bus; /* Stores Current I2C Bus */ +/* + * 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] + __attribute__((section(".data"))); +static int i2c_busses __attribute__((section(".data")));
#ifndef CONFIG_EXYNOS5 static int GetI2CSDA(void) @@ -507,4 +516,76 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, len) != 0); } + +#ifdef CONFIG_OF_CONTROL +void board_i2c_init(const void *blob) +{ + + int node_list[CONFIG_MAX_I2C_NUM]; + int count, i; + + count = fdtdec_find_aliases_for_id(blob, "i2c", + COMPAT_SAMSUNG_S3C2440_I2C, node_list, + CONFIG_MAX_I2C_NUM); + for (i = 0; i < count; i++) { + struct s3c24x0_i2c_bus *bus; + int node = node_list[i]; + + if (node < 0) + continue; + bus = &i2c_bus[i]; + bus->regs = (struct s3c24x0_i2c *) + fdtdec_get_addr(blob, node, "reg"); + bus->id = pinmux_decode_periph_id(blob, node); + bus->node = node; + bus->bus_num = i2c_busses++; + exynos_pinmux_config(bus->id, 0); + } + +} + +static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx) +{ + if (bus_idx < i2c_busses) + return &i2c_bus[bus_idx]; + debug("Undefined bus: %d\n", bus_idx); + return NULL; +} + +int i2c_get_bus_num_fdt(int node) +{ + int i; + + for (i = 0; i < i2c_busses; i++) { + if (node == i2c_bus[i].node) + return i; + } + + debug("%s: Can't find any matched I2C bus\n", __func__); + return -1; +} + +int i2c_reset_port_fdt(const void *blob, int node) +{ + struct s3c24x0_i2c_bus *i2c; + + int bus; + + bus = i2c_get_bus_num_fdt(node); + if (bus < 0) { + debug("could not get bus for node %d\n", node); + return -1; + } + i2c = get_bus(bus); + if (!i2c) { + debug("get_bus() failed for node node %d\n", node); + return -1; + } + + i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + return 0; +} +#endif + #endif /* CONFIG_HARD_I2C */ diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h index 2dd4b06..1243bf1 100644 --- a/drivers/i2c/s3c24x0_i2c.h +++ b/drivers/i2c/s3c24x0_i2c.h @@ -30,4 +30,12 @@ struct s3c24x0_i2c { u32 iicds; u32 iiclc; }; + +struct s3c24x0_i2c_bus { + int node; /* device tree node */ + int bus_num; /* i2c bus number */ + struct s3c24x0_i2c *regs; + enum periph_id id; +}; + #endif /* _S3C24X0_I2C_H */ diff --git a/include/i2c.h b/include/i2c.h index 16f099d..c60d075 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -262,4 +262,30 @@ extern int get_multi_scl_pin(void); extern int get_multi_sda_pin(void); extern int multi_i2c_init(void); #endif + +/** + * Get FDT values for i2c bus. + * + * @param blob Device tree blbo + * @return the number of I2C bus + */ +void board_i2c_init(const void *blob); + +/** + * Find the I2C bus number by given a FDT I2C node. + * + * @param blob Device tree blbo + * @param node FDT I2C node to find + * @return the number of I2C bus (zero based), or -1 on error + */ +int i2c_get_bus_num_fdt(int node); + +/** + * Reset the I2C bus represented by the given a FDT I2C node. + * + * @param blob Device tree blbo + * @param node FDT I2C node to find + * @return 0 if port was reset, -1 if not found + */ +int i2c_reset_port_fdt(const void *blob, int node); #endif /* _I2C_H_ */

Hello Rajeshwari,
On 29.11.2012 08:09, Rajeshwari Shinde wrote:
Functions added to get the I2C bus number and reset I2C bus using FDT node.
Signed-off-by: Rajeshwari Shinderajeshwari.s@samsung.com Acked-by: Simon Glasssjg@chromium.org
Nitpick: missing my Acked by ... so here it comes again:
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko

Hi Heiko,
Thank you for acking the patch. Had made a few changes in the Driver hence had removed the same.
Regards, Rajeshwari Shinde.
On Thu, Nov 29, 2012 at 2:03 PM, Heiko Schocher hs@denx.de wrote:
Hello Rajeshwari,
On 29.11.2012 08:09, Rajeshwari Shinde wrote:
Functions added to get the I2C bus number and reset I2C bus using FDT node.
Signed-off-by: Rajeshwari Shinderajeshwari.s@samsung.com Acked-by: Simon Glasssjg@chromium.org
Nitpick: missing my Acked by ... so here it comes again:
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

This patch initialises I2C using FDT.
Signed-off-by: Rajeshwari Shinde rajeshwari.s@samsung.com Acked-by: Simon Glass sjg@chromium.org Acked-by: Heiko Schocher hs@denx.de --- Changes in V2: - board_i2c_init moved to driver in case of FDT. Chnges in V3: - None. Chnages in V4: - None. board/samsung/smdk5250/smdk5250.c | 20 +------------------- 1 files changed, 1 insertions(+), 19 deletions(-)
diff --git a/board/samsung/smdk5250/smdk5250.c b/board/samsung/smdk5250/smdk5250.c index db2457b..5ebc665 100644 --- a/board/samsung/smdk5250/smdk5250.c +++ b/board/samsung/smdk5250/smdk5250.c @@ -272,24 +272,6 @@ static int board_uart_init(void) return 0; }
-#ifdef CONFIG_SYS_I2C_INIT_BOARD -static int board_i2c_init(void) -{ - int i, err; - - for (i = 0; i < CONFIG_MAX_I2C_NUM; i++) { - err = exynos_pinmux_config((PERIPH_ID_I2C0 + i), - PINMUX_FLAG_NONE); - if (err) { - debug("I2C%d not configured\n", (PERIPH_ID_I2C0 + i)); - return err; - } - } - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - return 0; -} -#endif - #ifdef CONFIG_BOARD_EARLY_INIT_F int board_early_init_f(void) { @@ -300,7 +282,7 @@ int board_early_init_f(void) return err; } #ifdef CONFIG_SYS_I2C_INIT_BOARD - err = board_i2c_init(); + board_i2c_init(gd->fdt_blob); #endif return err; }

Hi All,
This patch set is based on following patch sets "Add DT based ethernet driver for SMDK5250" "Add TMU support for Exynos5250 based SMDK5250"
Regards, Rajeshwari Shinde
On Thu, Nov 29, 2012 at 12:39 PM, Rajeshwari Shinde rajeshwari.s@samsung.com wrote:
This patch set adds FDT support for I2C driver and API's to acess the bus number using the fdt node and also reset the port.
Changes in V2: - Baord i2c init moved to I2C driver in case of FDT. - Added Periph id to device node. - Modified i2c_get_bus_num_fdt api to compare using node. Changes in V3: - Peripheral id removed from dtsi file and decoded based on interrupts. - API for fdtdec_lookup removed as it is already present as fd_dec_lookup. Changes in V4: - renamed decode_peripheral_id to pinmux_decode_peripheral_id. - added comments in periph.h as suggested by Simon Glass.
Rajeshwari Shinde (6): EXYNOS5: FDT: Add I2C device node data EXYNOS5 : FDT: Add Aliases for I2C device EXYNOS5: FDT: Add compatible string for I2C EXYNOS5: FDT : Decode peripheral id I2C: Driver changes for FDT support SMDK5250: Initialise I2C using FDT
arch/arm/cpu/armv7/exynos/pinmux.c | 28 ++++++++++ arch/arm/dts/exynos5250.dtsi | 64 ++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/periph.h | 31 ++++++----- arch/arm/include/asm/arch-exynos/pinmux.h | 8 +++ board/samsung/dts/exynos5250-smdk5250.dts | 11 ++++ board/samsung/smdk5250/smdk5250.c | 20 +------- drivers/i2c/s3c24x0_i2c.c | 83 ++++++++++++++++++++++++++++- drivers/i2c/s3c24x0_i2c.h | 8 +++ include/fdtdec.h | 1 + include/i2c.h | 26 +++++++++ lib/fdtdec.c | 1 + 11 files changed, 248 insertions(+), 33 deletions(-)
-- 1.7.4.4
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (4)
-
Heiko Schocher
-
Rajeshwari Birje
-
Rajeshwari Shinde
-
Simon Glass