From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heiko Schocher Date: Mon, 14 Oct 2013 08:06:28 +0200 Subject: [U-Boot] [PATCH] RFC: samsung: i2c: Enable new CONFIG_SYS_I2C framework In-Reply-To: <1380524290-9644-5-git-send-email-ch.naveen@samsung.com> References: <1363085897-19814-1-git-send-email-ch.naveen@samsung.com> <1380524290-9644-1-git-send-email-ch.naveen@samsung.com> <1380524290-9644-5-git-send-email-ch.naveen@samsung.com> Message-ID: <525B89E4.6080003@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello Naveen, Am 30.09.2013 08:58, schrieb Naveen Krishna Chatradhi: > This enables CONFIG_SYS_I2C on Samsung, updating existing s3c24x0 > i2c driver to support this. > > Note: Not for merge, Just for review and suggestions. > > Signed-off-by: Naveen Krishna Chatradhi > --- > drivers/i2c/Makefile | 2 +- > drivers/i2c/s3c24x0_i2c.c | 156 +++++++++++++++++++++++++++++++-------------- > 2 files changed, 108 insertions(+), 50 deletions(-) > > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile > index 37ccbd1..96448a6 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 Please keep lists sorted. > COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o > COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o > COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o > diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c > index 604d43d..89cb2d2 100644 > --- a/drivers/i2c/s3c24x0_i2c.c > +++ b/drivers/i2c/s3c24x0_i2c.c > @@ -117,6 +117,8 @@ > > #define HSI2C_TIMEOUT_US 100000 /* 100 ms, finer granularity */ > > +DECLARE_GLOBAL_DATA_PTR; > + > /* > * For SPL boot some boards need i2c before SDRAM is initialised so force > * variables to live in SRAM > @@ -126,6 +128,9 @@ static unsigned int g_current_bus __attribute__((section(".data"))); > static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM] > __attribute__((section(".data"))); > #endif > +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 > @@ -133,20 +138,40 @@ static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM] > * @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_bus[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; > +} > + > #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) > static int GetI2CSDA(void) > { > @@ -392,39 +417,7 @@ 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) > { > struct s3c24x0_i2c *i2c; > #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) > @@ -493,9 +486,15 @@ 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_bus->regs, speed, slaveaddr); > } > > +static void exynos_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) > +{ > + i2c_set_bus_speed(speed); > +} > /* > * Poll the appropriate bit of the fifo status register until the interface is > * ready to process the next byte or timeout expires. > @@ -829,13 +828,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; > @@ -857,7 +856,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]; > @@ -891,7 +891,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; > > @@ -911,7 +911,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]; > @@ -944,7 +945,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; > > @@ -1000,6 +1001,25 @@ static void process_nodes(const void *blob, int node_list[], int count, > node_list[i] = -1; > } > } > +void i2c_init_board() > +{ > + int node_list[CONFIG_MAX_I2C_NUM]; > + const void *blob = gd->fdt_blob; > + int count; > + > + /* First get the normal i2c ports */ > + count = fdtdec_find_aliases_for_id(blob, "i2c", > + COMPAT_SAMSUNG_S3C2440_I2C, node_list, > + CONFIG_MAX_I2C_NUM); > + process_nodes(blob, node_list, count, 0); > + > + /* Now look for high speed i2c ports */ > + count = fdtdec_find_aliases_for_id(blob, "i2c", > + COMPAT_SAMSUNG_EXYNOS5_I2C, node_list, > + CONFIG_MAX_I2C_NUM); > + process_nodes(blob, node_list, count, 1); > + > +} > > void board_i2c_init(const void *blob) > { > @@ -1017,9 +1037,10 @@ void board_i2c_init(const void *blob) > COMPAT_SAMSUNG_EXYNOS5_I2C, node_list, > CONFIG_MAX_I2C_NUM); > process_nodes(blob, node_list, count, 1); > - > } > > +#ifndef CONFIG_SYS_I2C > +/* TODO: fix this as per comments from upstream */ Why this? If we switch to the new i2c framework, please convert all boards, which using this driver ... > int i2c_get_bus_num_fdt(int node) > { > int i; > @@ -1062,5 +1083,42 @@ int i2c_reset_port_fdt(const void *blob, int node) > return 0; > } > #endif > +#endif > > +/* > + * Register soft i2c adapters > + */ > +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) > +U_BOOT_I2C_ADAP_COMPLETE(s3c1, 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(s3c2, 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(s3c3, 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(s3c4, 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(s3c5, 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(s3c6, 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(s3c7, 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(s3c8, 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(s3c9, 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(s3c10, exynos_i2c_init, s3c_i2c_probe, > + s3c_i2c_read, s3c_i2c_write, > + s3c_i2c_set_bus_speed, 100000, 0, 10) > #endif /* CONFIG_HARD_I2C */ Beside of that, it looks good to me. Thanks for your work! bye, Heiko -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany