
Signed-off-by: Sergey Kubushyn ksi@koi8.net --- diff -purN u-boot-i2c.orig/common/cmd_date.c u-boot-i2c/common/cmd_date.c --- u-boot-i2c.orig/common/cmd_date.c 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/common/cmd_date.c 2009-02-12 10:46:00.000000000 -0800 @@ -46,8 +46,13 @@ int do_date (cmd_tbl_t *cmdtp, int flag, int old_bus;
/* switch to correct I2C bus */ +#ifdef CONFIG_NEW_I2C + old_bus = i2c_get_bus_num(); + i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM); +#else old_bus = I2C_GET_BUS(); I2C_SET_BUS(CONFIG_SYS_RTC_BUS_NUM); +#endif
switch (argc) { case 2: /* set date & time */ @@ -94,7 +99,11 @@ int do_date (cmd_tbl_t *cmdtp, int flag, }
/* switch back to original I2C bus */ +#ifdef CONFIG_NEW_I2C + i2c_set_bus_num(old_bus); +#else I2C_SET_BUS(old_bus); +#endif
return rcode; } diff -purN u-boot-i2c.orig/common/cmd_dtt.c u-boot-i2c/common/cmd_dtt.c --- u-boot-i2c.orig/common/cmd_dtt.c 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/common/cmd_dtt.c 2009-02-12 10:46:00.000000000 -0800 @@ -35,8 +35,13 @@ int do_dtt (cmd_tbl_t * cmdtp, int flag, int old_bus;
/* switch to correct I2C bus */ +#ifdef CONFIG_NEW_I2C + old_bus = i2c_get_bus_num(); + i2c_set_bus_num(CONFIG_SYS_DTT_BUS_NUM); +#else old_bus = I2C_GET_BUS(); I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); +#endif
/* * Loop through sensors, read @@ -46,7 +51,11 @@ int do_dtt (cmd_tbl_t * cmdtp, int flag, printf ("DTT%d: %i C\n", i + 1, dtt_get_temp (sensors[i]));
/* switch back to original I2C bus */ +#ifdef CONFIG_NEW_I2C + i2c_set_bus_num(old_bus); +#else I2C_SET_BUS(old_bus); +#endif
return 0; } /* do_dtt() */ diff -purN u-boot-i2c.orig/common/cmd_i2c.c u-boot-i2c/common/cmd_i2c.c --- u-boot-i2c.orig/common/cmd_i2c.c 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/common/cmd_i2c.c 2009-02-12 10:46:00.000000000 -0800 @@ -1,4 +1,9 @@ /* + * (C) Copyright 2009 + * Sergey Kubushyn, himself, ksi@koi8.net + * + * Changes for unified multibus/multiadapter I2C support. + * * (C) Copyright 2001 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. * @@ -106,7 +111,7 @@ static uint i2c_mm_last_alen; * pairs. The following macros take care of this */
#if defined(CONFIG_SYS_I2C_NOPROBES) -#if defined(CONFIG_I2C_MULTI_BUS) +#if CONFIG_SYS_NUM_I2C_BUSSES > 1 static struct { uchar bus; @@ -122,19 +127,11 @@ static uchar i2c_no_probes[] = CONFIG_SY #define COMPARE_BUS(b,i) ((b) == 0) /* Make compiler happy */ #define COMPARE_ADDR(a,i) (i2c_no_probes[(i)] == (a)) #define NO_PROBE_ADDR(i) i2c_no_probes[(i)] -#endif /* CONFIG_MULTI_BUS */ +#endif /* CONFIG_SYS_NUM_I2C_BUSSES > 1 */
#define NUM_ELEMENTS_NOPROBE (sizeof(i2c_no_probes)/sizeof(i2c_no_probes[0])) #endif
-#if defined(CONFIG_I2C_MUX) -static I2C_MUX_DEVICE *i2c_mux_devices = NULL; -static int i2c_mux_busid = CONFIG_SYS_MAX_I2C_BUS; - -DECLARE_GLOBAL_DATA_PTR; - -#endif - static int mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]);
@@ -548,10 +545,10 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrfl */ int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - int j; + int j; #if defined(CONFIG_SYS_I2C_NOPROBES) - int k, skip; - uchar bus = GET_BUS_NUM; + int k, skip; + unsigned int bus = GET_BUS_NUM; #endif /* NOPROBES */
puts ("Valid chip addresses:"); @@ -1189,59 +1186,79 @@ int do_sdram (cmd_tbl_t * cmdtp, int fla #if defined(CONFIG_I2C_CMD_TREE) int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + i2c_init (ADAP(i2c_get_bus_num())->speed, ADAP(i2c_get_bus_num())->slaveaddr); return 0; }
-#if defined(CONFIG_I2C_MUX) -int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +int do_i2c_show_bus(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int ret=0; + int i; +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + int j; +#endif
if (argc == 1) { /* show all busses */ - I2C_MUX *mux; - I2C_MUX_DEVICE *device = i2c_mux_devices; - - printf ("Busses reached over muxes:\n"); - while (device != NULL) { - printf ("Bus ID: %x\n", device->busid); - printf (" reached over Mux(es):\n"); - mux = device->mux; - while (mux != NULL) { - printf (" %s@%x ch: %x\n", mux->name, mux->chip, mux->channel); - mux = mux->next; + for (i = 0; i < CONFIG_SYS_NUM_I2C_BUSSES; i++) { + printf("Bus %d:\t%s", i, ADAP(i)->name); +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) { + if (i2c_bus[i].next_hop[j].chip == 0) break; + printf("->%s@0x%2x:%d", + i2c_bus[i].next_hop[j].mux.name, + i2c_bus[i].next_hop[j].chip, + i2c_bus[i].next_hop[j].channel); } - device = device->next; +#endif + printf("\n"); } - } else { - I2C_MUX_DEVICE *dev;
- dev = i2c_mux_ident_muxstring ((uchar *)argv[1]); - ret = 0; + } else { + /* show specific bus */ + i = simple_strtoul(argv[1], NULL, 10); + if (i >= CONFIG_SYS_NUM_I2C_BUSSES) { + printf("Invalid bus %d\n", i); + return(-1); + } + printf("Bus %d:\t%s", i, ADAP(i)->name); +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) { + if (i2c_bus[i].next_hop[j].chip == 0) break; + printf("->%s@0x%2x:%d", + i2c_bus[i].next_hop[j].mux.name, + i2c_bus[i].next_hop[j].chip, + i2c_bus[i].next_hop[j].channel); + } +#endif + printf("\n"); } - return ret; + + return(0); } -#endif /* CONFIG_I2C_MUX */
-#if defined(CONFIG_I2C_MULTI_BUS) +#if CONFIG_SYS_NUM_I2C_BUSSES > 1 int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int bus_idx, ret=0; + int ret=0; + unsigned int bus_no;
if (argc == 1) /* querying current setting */ printf("Current bus is %d\n", i2c_get_bus_num()); else { - bus_idx = simple_strtoul(argv[1], NULL, 10); - printf("Setting bus to %d\n", bus_idx); - ret = i2c_set_bus_num(bus_idx); + bus_no = simple_strtoul(argv[1], NULL, 10); + if (bus_no >= CONFIG_SYS_NUM_I2C_BUSSES) { + printf("Invalid bus %d\n", bus_no); + return(-1); + } + printf("Setting bus to %d\n", bus_no); + ret = i2c_set_bus_num(bus_no); if (ret) printf("Failure changing bus number (%d)\n", ret); } return ret; } -#endif /* CONFIG_I2C_MULTI_BUS */ +#endif /* CONFIG_SYS_NUM_I2C_BUSSES > 1 */
int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { @@ -1262,16 +1279,16 @@ int do_i2c_bus_speed(cmd_tbl_t * cmdtp,
int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { -#if defined(CONFIG_I2C_MUX) +#if CONFIG_SYS_NUM_I2C_BUSSES > 1 if (!strncmp(argv[1], "bu", 2)) - return do_i2c_add_bus(cmdtp, flag, --argc, ++argv); -#endif /* CONFIG_I2C_MUX */ + return do_i2c_show_bus(cmdtp, flag, --argc, ++argv); +#endif /* CONFIG_SYS_NUM_I2C_BUSSES > 1 */ if (!strncmp(argv[1], "sp", 2)) return do_i2c_bus_speed(cmdtp, flag, --argc, ++argv); -#if defined(CONFIG_I2C_MULTI_BUS) +#if CONFIG_SYS_NUM_I2C_BUSSES > 1 if (!strncmp(argv[1], "de", 2)) return do_i2c_bus_num(cmdtp, flag, --argc, ++argv); -#endif /* CONFIG_I2C_MULTI_BUS */ +#endif /* CONFIG_SYS_NUM_I2C_BUSSES > 1 */ if (!strncmp(argv[1], "md", 2)) return do_i2c_md(cmdtp, flag, --argc, ++argv); if (!strncmp(argv[1], "mm", 2)) @@ -1304,13 +1321,11 @@ int do_i2c(cmd_tbl_t * cmdtp, int flag, U_BOOT_CMD( i2c, 6, 1, do_i2c, "I2C sub-system", -#if defined(CONFIG_I2C_MUX) - "bus [muxtype:muxaddr:muxchannel] - add a new bus reached over muxes.\n" -#endif /* CONFIG_I2C_MUX */ - "speed [speed] - show or set I2C bus speed\n" -#if defined(CONFIG_I2C_MULTI_BUS) +#if CONFIG_SYS_NUM_I2C_BUSSES > 1 + "bus [bus_no] - show I2C bus info.\n" "i2c dev [dev] - show or set current I2C bus\n" -#endif /* CONFIG_I2C_MULTI_BUS */ +#endif /* CONFIG_SYS_NUM_I2C_BUSSES > 1 */ + "i2c speed [speed] - show or set I2C bus speed\n" "i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n" "i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n" "i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)\n" @@ -1323,7 +1338,7 @@ U_BOOT_CMD( "i2c sdram chip - print SDRAM configuration information\n" #endif ); -#endif /* CONFIG_I2C_CMD_TREE */ +#else /* CONFIG_I2C_CMD_TREE */ U_BOOT_CMD( imd, 4, 1, do_i2c_md, \ "i2c memory display", \ @@ -1378,221 +1393,4 @@ U_BOOT_CMD( " (valid chip values 50..57)\n" ); #endif - -#if defined(CONFIG_I2C_MUX) - -int i2c_mux_add_device(I2C_MUX_DEVICE *dev) -{ - I2C_MUX_DEVICE *devtmp = i2c_mux_devices; - - if (i2c_mux_devices == NULL) { - i2c_mux_devices = dev; - return 0; - } - while (devtmp->next != NULL) - devtmp = devtmp->next; - - devtmp->next = dev; - return 0; -} - -I2C_MUX_DEVICE *i2c_mux_search_device(int id) -{ - I2C_MUX_DEVICE *device = i2c_mux_devices; - - while (device != NULL) { - if (device->busid == id) - return device; - device = device->next; - } - return NULL; -} - -/* searches in the buf from *pos the next ':'. - * returns: - * 0 if found (with *pos = where) - * < 0 if an error occured - * > 0 if the end of buf is reached - */ -static int i2c_mux_search_next (int *pos, uchar *buf, int len) -{ - while ((buf[*pos] != ':') && (*pos < len)) { - *pos += 1; - } - if (*pos >= len) - return 1; - if (buf[*pos] != ':') - return -1; - return 0; -} - -static int i2c_mux_get_busid (void) -{ - int tmp = i2c_mux_busid; - - i2c_mux_busid ++; - return tmp; -} - -/* Analyses a Muxstring and sends immediately the - Commands to the Muxes. Runs from Flash. - */ -int i2c_mux_ident_muxstring_f (uchar *buf) -{ - int pos = 0; - int oldpos; - int ret = 0; - int len = strlen((char *)buf); - int chip; - uchar channel; - int was = 0; - - while (ret == 0) { - oldpos = pos; - /* search name */ - ret = i2c_mux_search_next(&pos, buf, len); - if (ret != 0) - printf ("ERROR\n"); - /* search address */ - pos ++; - oldpos = pos; - ret = i2c_mux_search_next(&pos, buf, len); - if (ret != 0) - printf ("ERROR\n"); - buf[pos] = 0; - chip = simple_strtoul((char *)&buf[oldpos], NULL, 16); - buf[pos] = ':'; - /* search channel */ - pos ++; - oldpos = pos; - ret = i2c_mux_search_next(&pos, buf, len); - if (ret < 0) - printf ("ERROR\n"); - was = 0; - if (buf[pos] != 0) { - buf[pos] = 0; - was = 1; - } - channel = simple_strtoul((char *)&buf[oldpos], NULL, 16); - if (was) - buf[pos] = ':'; - if (i2c_write(chip, 0, 0, &channel, 1) != 0) { - printf ("Error setting Mux: chip:%x channel: \ - %x\n", chip, channel); - return -1; - } - pos ++; - oldpos = pos; - - } - - return 0; -} - -/* Analyses a Muxstring and if this String is correct - * adds a new I2C Bus. - */ -I2C_MUX_DEVICE *i2c_mux_ident_muxstring (uchar *buf) -{ - I2C_MUX_DEVICE *device; - I2C_MUX *mux; - int pos = 0; - int oldpos; - int ret = 0; - int len = strlen((char *)buf); - int was = 0; - - device = (I2C_MUX_DEVICE *)malloc (sizeof(I2C_MUX_DEVICE)); - device->mux = NULL; - device->busid = i2c_mux_get_busid (); - device->next = NULL; - while (ret == 0) { - mux = (I2C_MUX *)malloc (sizeof(I2C_MUX)); - mux->next = NULL; - /* search name of mux */ - oldpos = pos; - ret = i2c_mux_search_next(&pos, buf, len); - if (ret != 0) - printf ("%s no name.\n", __FUNCTION__); - mux->name = (char *)malloc (pos - oldpos + 1); - memcpy (mux->name, &buf[oldpos], pos - oldpos); - mux->name[pos - oldpos] = 0; - /* search address */ - pos ++; - oldpos = pos; - ret = i2c_mux_search_next(&pos, buf, len); - if (ret != 0) - printf ("%s no mux address.\n", __FUNCTION__); - buf[pos] = 0; - mux->chip = simple_strtoul((char *)&buf[oldpos], NULL, 16); - buf[pos] = ':'; - /* search channel */ - pos ++; - oldpos = pos; - ret = i2c_mux_search_next(&pos, buf, len); - if (ret < 0) - printf ("%s no mux channel.\n", __FUNCTION__); - was = 0; - if (buf[pos] != 0) { - buf[pos] = 0; - was = 1; - } - mux->channel = simple_strtoul((char *)&buf[oldpos], NULL, 16); - if (was) - buf[pos] = ':'; - if (device->mux == NULL) - device->mux = mux; - else { - I2C_MUX *muxtmp = device->mux; - while (muxtmp->next != NULL) { - muxtmp = muxtmp->next; - } - muxtmp->next = mux; - } - pos ++; - oldpos = pos; - } - if (ret > 0) { - /* Add Device */ - i2c_mux_add_device (device); - return device; - } - - return NULL; -} - -int i2x_mux_select_mux(int bus) -{ - I2C_MUX_DEVICE *dev; - I2C_MUX *mux; - - if ((gd->flags & GD_FLG_RELOC) != GD_FLG_RELOC) { - /* select Default Mux Bus */ -#if defined(CONFIG_SYS_I2C_IVM_BUS) - i2c_mux_ident_muxstring_f ((uchar *)CONFIG_SYS_I2C_IVM_BUS); -#else - { - unsigned char *buf; - buf = (unsigned char *) getenv("EEprom_ivm"); - if (buf != NULL) - i2c_mux_ident_muxstring_f (buf); - } -#endif - return 0; - } - dev = i2c_mux_search_device(bus); - if (dev == NULL) - return -1; - - mux = dev->mux; - while (mux != NULL) { - if (i2c_write(mux->chip, 0, 0, &mux->channel, 1) != 0) { - printf ("Error setting Mux: chip:%x channel: \ - %x\n", mux->chip, mux->channel); - return -1; - } - mux = mux->next; - } - return 0; -} -#endif /* CONFIG_I2C_MUX */ +#endif /* CONFIG_I2C_CMD_TREE */ diff -purN u-boot-i2c.orig/common/devices.c u-boot-i2c/common/devices.c --- u-boot-i2c.orig/common/devices.c 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/common/devices.c 2009-02-12 10:46:00.000000000 -0800 @@ -1,4 +1,8 @@ /* + * Copyright (C) 2009 Sergey Kubushyn ksi@koi8.net + * + * Changes for multibus/multiadapter I2C support. + * * (C) Copyright 2000 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it * @@ -30,7 +34,7 @@ #ifdef CONFIG_LOGBUFFER #include <logbuff.h> #endif -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) || defined(CONFIG_SYS_I2C_ADAPTERS) #include <i2c.h> #endif
@@ -215,9 +219,15 @@ int devices_init (void) /* Initialize the list */ INIT_LIST_HEAD(&(devs.list));
+#ifdef CONFIG_NEW_I2C +#ifdef CONFIG_SYS_I2C_ADAPTERS + i2c_init_all(); +#endif +#else #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); #endif +#endif #ifdef CONFIG_LCD drv_lcd_init (); #endif diff -purN u-boot-i2c.orig/drivers/hwmon/adm1021.c u-boot-i2c/drivers/hwmon/adm1021.c --- u-boot-i2c.orig/drivers/hwmon/adm1021.c 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/drivers/hwmon/adm1021.c 2009-02-12 10:46:00.000000000 -0800 @@ -174,7 +174,11 @@ dtt_init (void) const char *const header = "DTT: ";
/* switch to correct I2C bus */ +#ifdef CONFIG_NEW_I2C + i2c_set_bus_num(CONFIG_SYS_DTT_BUS_NUM); +#else I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); +#endif
for (i = 0; i < sizeof(sensors); i++) { if (_dtt_init(sensors[i]) != 0) diff -purN u-boot-i2c.orig/drivers/hwmon/lm75.c u-boot-i2c/drivers/hwmon/lm75.c --- u-boot-i2c.orig/drivers/hwmon/lm75.c 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/drivers/hwmon/lm75.c 2009-02-12 10:46:00.000000000 -0800 @@ -156,8 +156,13 @@ int dtt_init (void) int old_bus;
/* switch to correct I2C bus */ +#ifdef CONFIG_NEW_I2C + old_bus = i2c_get_bus_num(); + i2c_set_bus_num(CONFIG_SYS_DTT_BUS_NUM); +#else old_bus = I2C_GET_BUS(); I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); +#endif
for (i = 0; i < sizeof(sensors); i++) { if (_dtt_init(sensors[i]) != 0) @@ -167,7 +172,11 @@ int dtt_init (void) dtt_get_temp(sensors[i])); } /* switch back to original I2C bus */ +#ifdef CONFIG_NEW_I2C + i2c_set_bus_num(old_bus); +#else I2C_SET_BUS(old_bus); +#endif
return (0); } /* dtt_init() */ diff -purN u-boot-i2c.orig/drivers/i2c/i2c_core.c u-boot-i2c/drivers/i2c/i2c_core.c --- u-boot-i2c.orig/drivers/i2c/i2c_core.c 1969-12-31 16:00:00.000000000 -0800 +++ u-boot-i2c/drivers/i2c/i2c_core.c 2009-02-12 11:06:54.000000000 -0800 @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2009 Sergey Kubushyn ksi@koi8.net + * + * Multibus/multiadapter I2C core functions (wrappers) + */ +#include <common.h> +#include <i2c.h> + +#ifdef CONFIG_BFIN_TWI_I2C +extern i2c_adap_t bfin_twi_i2c_adap; +#endif + +#ifdef CONFIG_FSL_I2C +extern i2c_adap_t fsl_i2c_adap[]; +#endif + +#ifdef CONFIG_MXC_I2C +extern i2c_adap_t mxc_i2c_adap[]; +#endif + +#ifdef CONFIG_OMAP1510_I2C +extern i2c_adap_t omap1510_i2c_adap; +#endif + +#ifdef CONFIG_OMAP24XX_I2C +extern i2c_adap_t omap24xx_i2c_adap[]; +#endif + +#ifdef CONFIG_SM502_I2C +extern i2c_adap_t sm501_i2c_adap; +#endif + +#ifdef CONFIG_SOFT_I2C +extern i2c_adap_t soft_i2c_adap[]; +#endif + +#ifdef CONFIG_TSI108_I2C +extern i2c_adap_t tsi108_i2c_adap; +#endif + +i2c_adap_t *i2c_adap[CONFIG_SYS_NUM_I2C_ADAPTERS] = CONFIG_SYS_I2C_ADAPTERS; +#ifndef CONFIG_SYS_I2C_DIRECT_BUS +i2c_bus_t i2c_bus[CONFIG_SYS_NUM_I2C_BUSSES] = CONFIG_SYS_I2C_BUSSES; +#endif + +static unsigned int i2c_cur_bus __attribute__ ((section (".data"))) = CONFIG_SYS_SPD_BUS_NUM; + +DECLARE_GLOBAL_DATA_PTR; + +void i2c_reloc_fixup(void) +{ + int i; + unsigned long addr; + + for (i = 0; i < CONFIG_SYS_NUM_I2C_ADAPTERS; i++) { + /* Adapter itself */ + addr = (unsigned long)i2c_adap[i]; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i] = (i2c_adap_t *)addr; + /* i2c_init() */ + addr = (unsigned long)i2c_adap[i]->init; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->init = (void (*)(int, int))addr; + /* i2c_probe() */ + addr = (unsigned long)i2c_adap[i]->probe; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->probe = (int (*)(u_int8_t))addr; + /* i2c_read() */ + addr = (unsigned long)i2c_adap[i]->read; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->read = (int (*)(u_int8_t, uint, int, u_int8_t *, int))addr; + /* i2c_write() */ + addr = (unsigned long)i2c_adap[i]->write; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->write = (int (*)(u_int8_t, uint, int, u_int8_t *, int))addr; + /* i2c_set_bus_speed() */ + addr = (unsigned long)i2c_adap[i]->set_bus_speed; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->set_bus_speed = (uint (*)(uint))addr; + /* i2c_get_bus_speed() */ + addr = (unsigned long)i2c_adap[i]->get_bus_speed; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->get_bus_speed = (uint (*)(void))addr; + /* name */ + addr = (unsigned long)i2c_adap[i]->name; + if (addr != 0) addr += gd->reloc_off; + i2c_adap[i]->name = (char *)addr; + } +} + +#ifndef CONFIG_SYS_I2C_DIRECT_BUS +/* + * i2c_mux_set() + * ------------- + * + * This turns on the given channel on I2C multiplexer chip connected to + * a given I2C adapter directly or via other multiplexers. In the latter + * case the entire multiplexer chain must be initialized first starting + * with the one connected directly to the adapter. When disabling a chain + * muxes must be programmed in reverse order, starting with the one + * farthest from the adapter. + * + * mux_id is the multiplexer chip type from defined in i2c.h. So far only + * NXP (Philips) PCA954x multiplexers are supported. Switches are NOT + * supported (anybody uses them?) + */ + +static int i2c_mux_set(int adapter, int mux_id, int chip, int channel) +{ + u_int8_t buf; + + /* channel < 0 - turn off the mux */ + if (channel < 0) { + buf = 0; + return(i2c_adap[adapter]->write(chip, 0, 0, &buf, 1)); + } + + switch (mux_id) { + case I2C_MUX_PCA9540_ID: + case I2C_MUX_PCA9542_ID: + if (channel > 1) return(-1); + buf = (u_int8_t)((channel & 0x01) | (1 << 2)); + break; + case I2C_MUX_PCA9544_ID: + if (channel > 3) return(-1); + buf = (u_int8_t)((channel & 0x03) | (1 << 2)); + break; + case I2C_MUX_PCA9547_ID: + if (channel > 7) return(-1); + buf = (u_int8_t)((channel & 0x07) | (1 << 3)); + break; + default: + return(-1); + } + + return(i2c_adap[adapter]->write(chip, 0, 0, &buf, 1)); +} +#endif + +/* + * i2c_get_bus_num(): + * ------------------ + * + * Returns index of currently active I2C bus. Zero-based. + */ +unsigned int i2c_get_bus_num(void) +{ + return(i2c_cur_bus); +} + +/* + * i2c_set_bus_num(): + * ------------------ + * + * Change the active I2C bus. Subsequent read/write calls will + * go to this one. Sets all of the muxes in a proper condition + * if that bus is behind muxes. Fails if called before relocation. + * If previously selected bus is behind the muxes turns off all the + * muxes along the path to that bus. + * + * bus - bus index, zero based + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_set_bus_num(unsigned int bus) +{ +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + int i; + u_int8_t buf; +#endif + + if ((bus >= CONFIG_SYS_NUM_I2C_BUSSES) || !(gd->flags & GD_FLG_RELOC)) + return(-1); + +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + /* Disconnect current bus (turn off muxes if any) */ + if ((i2c_bus[i2c_cur_bus].next_hop[0].chip != 0) && + (ADAP(i2c_cur_bus)->init_done != 0)) { + + i = CONFIG_SYS_I2C_MAX_HOPS; + + do { + u_int8_t chip; + + if ((chip = i2c_bus[i2c_cur_bus].next_hop[--i].chip) == 0) + continue; + + ADAP(i2c_cur_bus)->write(chip, 0, 0, &buf, 1); + + } while (i > 0); + } + + /* Connect requested bus if behind muxes */ + if ((i2c_bus[bus].next_hop[0].chip != 0) && + (ADAP(bus)->init_done != 0)) { + + /* Set all muxes along the path to that bus */ + for (i = 0; i < CONFIG_SYS_I2C_MAX_HOPS; i++) { + + if (i2c_bus[bus].next_hop[i].chip == 0) break; + + i2c_mux_set(i2c_bus[bus].adapter, + i2c_bus[bus].next_hop[i].mux.id, + i2c_bus[bus].next_hop[i].chip, + i2c_bus[bus].next_hop[i].channel); + } + } +#endif + + i2c_cur_bus = bus; + return(0); +} + +/* + * i2c_init_bus(): + * --------------- + * + * Initializes one bus. Will initialize the parent adapter. No current bus + * changes, no mux (if any) setup. + */ +static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr) +{ + if (bus_no >= CONFIG_SYS_NUM_I2C_BUSSES) + return; + + ADAP(bus_no)->init(speed, slaveaddr); + + if (gd->flags & GD_FLG_RELOC) { + ADAP(bus_no)->init_done = 1; + ADAP(bus_no)->speed = speed; + ADAP(bus_no)->slaveaddr = slaveaddr; + } +} + +/* + * i2c_init_all(): + * + * Initializes all I2C adapters in the system. All i2c_adap_t structures in + * i2c_adap[] must be initialized beforehead with function pointers and + * data, including speed and slaveaddr. + */ +void i2c_init_all(void) +{ + int i; + + for (i = 0; i < CONFIG_SYS_NUM_I2C_ADAPTERS; i++) { + if ((i2c_adap[i]->speed != 0) && (i2c_adap[i]->init != NULL)) { + i2c_adap[i]->init(i2c_adap[i]->speed, i2c_adap[i]->slaveaddr); + if (gd->flags & GD_FLG_RELOC) + i2c_adap[i]->init_done = 1; + } + } +} + +/* + * Probe the given I2C chip address. Returns 0 if a chip responded, + * not 0 on failure. + */ +int i2c_probe(u_int8_t chip) +{ + return(ADAP(i2c_cur_bus)->probe(chip)); +} + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_read(u_int8_t chip, unsigned int addr, int alen, + u_int8_t *buffer, int len) +{ + return(ADAP(i2c_cur_bus)->read(chip, addr, alen, buffer, len)); +} + +int i2c_write(u_int8_t chip, unsigned int addr, int alen, + u_int8_t *buffer, int len) +{ + return(ADAP(i2c_cur_bus)->write(chip, addr, alen, buffer, len)); +} + +unsigned int i2c_set_bus_speed(unsigned int speed) +{ + return(ADAP(i2c_cur_bus)->set_bus_speed(speed)); +} + +unsigned int i2c_get_bus_speed(void) +{ + return(ADAP(i2c_cur_bus)->get_bus_speed()); +} + +u_int8_t i2c_reg_read(u_int8_t addr, u_int8_t reg) +{ + u_int8_t buf; + +#ifdef CONFIG_8xx + /* MPC8xx needs this. Maybe one day we can get rid of it. */ + i2c_init_bus(i2c_cur_bus, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif + i2c_read(addr, reg, 1, &buf, 1); + +#ifdef DEBUG + printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", + __func__, i2c_cur_bus, addr, reg, buf); +#endif + + return buf; +} + +void i2c_reg_write(u_int8_t addr, u_int8_t reg, u_int8_t val) +{ +#ifdef CONFIG_8xx + /* MPC8xx needs this. Maybe one day we can get rid of it. */ + i2c_init_bus(i2c_cur_bus, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif + +#ifdef DEBUG + printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", + __func__, i2c_cur_bus, addr, reg, val); +#endif + + i2c_write(addr, reg, 1, &val, 1); +} + +void inline __i2c_init(unsigned int speed, int slaveaddr) +{ + i2c_init_bus(i2c_cur_bus, speed, slaveaddr); +} + +void inline i2c_init(unsigned int speed, int slaveaddr) + __attribute__((weak, alias("__i2c_init"))); diff -purN u-boot-i2c.orig/drivers/i2c/Makefile u-boot-i2c/drivers/i2c/Makefile --- u-boot-i2c.orig/drivers/i2c/Makefile 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/drivers/i2c/Makefile 2009-02-12 10:46:00.000000000 -0800 @@ -27,12 +27,13 @@ LIB := $(obj)libi2c.a
COBJS-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o -COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o -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_MXC_I2C) += mxc_i2c.o +COBJS-$(CONFIG_OMAP1510_I2C) += omap1510_i2c.o +COBJS-$(CONFIG_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o +COBJS-$(CONFIG_SM502_I2C) += sm502_i2c.o +COBJS-$(CONFIG_NEW_I2C) += i2c_core.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff -purN u-boot-i2c.orig/include/i2c.h u-boot-i2c/include/i2c.h --- u-boot-i2c.orig/include/i2c.h 2009-02-12 10:43:41.000000000 -0800 +++ u-boot-i2c/include/i2c.h 2009-02-12 11:00:50.000000000 -0800 @@ -1,4 +1,7 @@ /* + * Copyright (C) 2009 Sergey Kubushyn ksi@koi8.net + * Changes for multibus/multiadapter I2C support. + * * (C) Copyright 2001 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. * @@ -46,14 +49,20 @@ */ #define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */
-#if defined(CONFIG_I2C_MULTI_BUS) -#define CONFIG_SYS_MAX_I2C_BUS 2 -#define I2C_GET_BUS() i2c_get_bus_num() -#define I2C_SET_BUS(a) i2c_set_bus_num(a) +#ifndef CONFIG_SYS_NUM_I2C_ADAPTERS +#define CONFIG_SYS_NUM_I2C_ADAPTERS 1 +#endif + +#if !defined(CONFIG_SYS_I2C_MAX_HOPS) || (CONFIG_SYS_I2C_MAX_HOPS == 0) +#define CONFIG_SYS_I2C_DIRECT_BUS 1 +#if !defined(CONFIG_SYS_NUM_I2C_BUSSES) || (CONFIG_SYS_NUM_I2C_BUSSES != CONFIG_SYS_NUM_I2C_ADAPTERS) +#define CONFIG_SYS_NUM_I2C_BUSSES CONFIG_SYS_NUM_I2C_ADAPTERS +#endif #else -#define CONFIG_SYS_MAX_I2C_BUS 1 -#define I2C_GET_BUS() 0 -#define I2C_SET_BUS(a) +#undef CONFIG_SYS_I2C_DIRECT_BUS +#ifndef CONFIG_SYS_NUM_I2C_BUSSES +#define CONFIG_SYS_NUM_I2C_BUSSES 1 +#endif #endif
/* define the I2C bus number for RTC and DTT if not already done */ @@ -67,66 +76,95 @@ #define CONFIG_SYS_SPD_BUS_NUM 0 #endif
-#ifndef I2C_SOFT_DECLARATIONS -# if defined(CONFIG_MPC8260) -# define I2C_SOFT_DECLARATIONS volatile ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, I2C_PORT); -# elif defined(CONFIG_8xx) -# define I2C_SOFT_DECLARATIONS volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; -# else -# define I2C_SOFT_DECLARATIONS -# endif +#ifndef CONFIG_SYS_I2C_DIRECT_BUS +#define ADAP(bus) i2c_adap[i2c_bus[(bus)].adapter] +#else +#define ADAP(bus) i2c_adap[(bus)] #endif
-#ifdef CONFIG_8xx -/* Set default values for the I2C bus speed and slave address on 8xx. In the - * future, we'll define these in all 8xx board config files. - */ -#ifndef CONFIG_SYS_I2C_SPEED -#define CONFIG_SYS_I2C_SPEED 50000 -#endif +typedef struct i2c_adapter { + void (*init)(int speed, int slaveaddr); + int (*probe)(u_int8_t chip); + int (*read)(u_int8_t chip, uint addr, int alen, + u_int8_t *buffer, int len); + int (*write)(u_int8_t chip, uint addr, int alen, + u_int8_t *buffer, int len); + uint (*set_bus_speed)(uint speed); + uint (*get_bus_speed)(void); + + int speed; + int slaveaddr; + int init_done; + char *name; +} i2c_adap_t; + +#ifndef CONFIG_SYS_I2C_DIRECT_BUS +#define I2C_MUX_PCA9540_ID 1 +#define I2C_MUX_PCA9540 {I2C_MUX_PCA9540_ID, "PCA9540B"} +#define I2C_MUX_PCA9542_ID 2 +#define I2C_MUX_PCA9542 {I2C_MUX_PCA9542_ID, "PCA9542A"} +#define I2C_MUX_PCA9544_ID 3 +#define I2C_MUX_PCA9544 {I2C_MUX_PCA9544_ID, "PCA9544A"} +#define I2C_MUX_PCA9547_ID 4 +#define I2C_MUX_PCA9547 {I2C_MUX_PCA9547_ID, "PCA9547A"} + +typedef struct i2c_mux { + int id; + char name[16]; +} i2c_mux_t; + +typedef struct i2c_next_hop { + i2c_mux_t mux; + u_int8_t chip; + u_int8_t channel; +} i2c_next_hop_t; + +typedef struct i2c_bus_hose { + int adapter; + i2c_next_hop_t next_hop[CONFIG_SYS_I2C_MAX_HOPS]; +} i2c_bus_t;
-#ifndef CONFIG_SYS_I2C_SLAVE -#define CONFIG_SYS_I2C_SLAVE 0xFE -#endif +#define I2C_NULL_HOP {{-1, ""}, 0, 0} + +extern i2c_bus_t i2c_bus[]; #endif
+extern i2c_adap_t *i2c_adap[]; + /* - * Initialization, must be called once on start up, may be called - * repeatedly to change the speed and slave addresses. + * i2c_get_bus_num: + * + * Returns index of currently active I2C bus. Zero-based. */ -void i2c_init(int speed, int slaveaddr); -#ifdef CONFIG_SYS_I2C_INIT_BOARD -void i2c_init_board(void); -#endif +unsigned int i2c_get_bus_num(void);
-#if defined(CONFIG_I2C_MUX) +/* + * i2c_set_bus_num: + * + * Change the active I2C bus. Subsequent read/write calls will + * go to this one. + * + * bus - bus index, zero based + * + * Returns: 0 on success, not 0 on failure + * + */ +int i2c_set_bus_num(unsigned int bus);
-typedef struct _mux { - uchar chip; - uchar channel; - char *name; - struct _mux *next; -} I2C_MUX; - -typedef struct _mux_device { - int busid; - I2C_MUX *mux; /* List of muxes, to reach the device */ - struct _mux_device *next; -} I2C_MUX_DEVICE; - -int i2c_mux_add_device(I2C_MUX_DEVICE *dev); - -I2C_MUX_DEVICE *i2c_mux_search_device(int id); -I2C_MUX_DEVICE *i2c_mux_ident_muxstring (uchar *buf); -int i2x_mux_select_mux(int bus); -int i2c_mux_ident_muxstring_f (uchar *buf); -#endif +/* + * i2c_init_all(): + * + * Initializes all I2C adapters in the system. All i2c_adap structures must + * be initialized beforehead with function pointers and data, including + * speed and slaveaddr. Returns 0 on success, non-0 on failure. + */ +void i2c_init_all(void);
/* * Probe the given I2C chip address. Returns 0 if a chip responded, * not 0 on failure. */ -int i2c_probe(uchar chip); +int i2c_probe(u_int8_t chip);
/* * Read/Write interface: @@ -140,88 +178,62 @@ int i2c_probe(uchar chip); * * Returns: 0 on success, not 0 on failure */ -int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len); -int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len); +int i2c_read(u_int8_t chip, unsigned int addr, int alen, + u_int8_t *buffer, int len); + +int i2c_write(u_int8_t chip, unsigned int addr, int alen, + u_int8_t *buffer, int len);
/* * Utility routines to read/write registers. */ -static inline u8 i2c_reg_read(u8 addr, u8 reg) -{ - u8 buf; - -#ifdef CONFIG_8xx - /* MPC8xx needs this. Maybe one day we can get rid of it. */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -#endif - -#ifdef DEBUG - printf("%s: addr=0x%02x, reg=0x%02x\n", __func__, addr, reg); -#endif - - i2c_read(addr, reg, 1, &buf, 1); +u_int8_t i2c_reg_read(u_int8_t addr, u_int8_t reg);
- return buf; -} - -static inline void i2c_reg_write(u8 addr, u8 reg, u8 val) -{ -#ifdef CONFIG_8xx - /* MPC8xx needs this. Maybe one day we can get rid of it. */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -#endif - -#ifdef DEBUG - printf("%s: addr=0x%02x, reg=0x%02x, val=0x%02x\n", - __func__, addr, reg, val); -#endif - - i2c_write(addr, reg, 1, &val, 1); -} - -/* - * Functions for setting the current I2C bus and its speed - */ +void i2c_reg_write(u_int8_t addr, u_int8_t reg, u_int8_t val);
/* - * i2c_set_bus_num: + * i2c_set_bus_speed: * - * Change the active I2C bus. Subsequent read/write calls will - * go to this one. + * Change the speed of the active I2C bus * - * bus - bus index, zero based + * speed - bus speed in Hz * - * Returns: 0 on success, not 0 on failure + * Returns: new bus speed * */ -int i2c_set_bus_num(unsigned int bus); +unsigned int i2c_set_bus_speed(unsigned int speed);
/* - * i2c_get_bus_num: + * i2c_get_bus_speed: * - * Returns index of currently active I2C bus. Zero-based. + * Returns speed of currently active I2C bus in Hz */
-unsigned int i2c_get_bus_num(void); +unsigned int i2c_get_bus_speed(void);
/* - * i2c_set_bus_speed: - * - * Change the speed of the active I2C bus - * - * speed - bus speed in Hz - * - * Returns: 0 on success, not 0 on failure + * i2c_reloc_fixup: * + * Adjusts I2C pointers after U-Boot is relocated to DRAM */ -int i2c_set_bus_speed(unsigned int); +void i2c_reloc_fixup(void); + +#ifndef I2C_SOFT_DEFS +# if defined(CONFIG_MPC8260) +# define I2C_SOFT_DEFS volatile ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, I2C_PORT); +# elif defined(CONFIG_8xx) +# define I2C_SOFT_DEFS volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; +# else +# define I2C_SOFT_DEFS +# endif
/* - * i2c_get_bus_speed: - * - * Returns speed of currently active I2C bus in Hz + * Initialization, must be called once on start up, may be called + * repeatedly to change the speed and slave addresses. */ - -unsigned int i2c_get_bus_speed(void); +void i2c_init(unsigned int speed, int slaveaddr); +#ifdef CONFIG_SYS_I2C_INIT_BOARD +void i2c_init_board(void); +#endif
#endif /* _I2C_H_ */