[U-Boot] [PATCH/RFC, 1/2] I2C rework -- what do you think

ksi at koi8.net ksi at koi8.net
Sat Jan 24 02:10:18 CET 2009


diff -purN u-boot.orig/common/cmd_i2c.c u-boot/common/cmd_i2c.c
--- u-boot.orig/common/cmd_i2c.c	2008-11-25 16:41:07.000000000 -0800
+++ u-boot/common/cmd_i2c.c	2009-01-23 16:01:48.000000000 -0800
@@ -1,4 +1,9 @@
  /*
+ * (C) Copyright 2009
+ * Sergey Kubushyn, himself, ksi at koi8.net
+ *
+ * Changes for unified multibus/multiadapter I2C support.
+ *
   * (C) Copyright 2001
   * Gerald Van Baren, Custom IDEAS, vanbaren at 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 at 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 at 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     - I2C sub-system\n",
-#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,		\
  	"imd     - i2c memory display\n",				\
@@ -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.orig/common/devices.c u-boot/common/devices.c
--- u-boot.orig/common/devices.c	2008-10-20 13:59:38.000000000 -0700
+++ u-boot/common/devices.c	2009-01-23 16:01:48.000000000 -0800
@@ -1,4 +1,8 @@
  /*
+ * Copyright (C) 2009 Sergey Kubushyn <ksi at koi8.net>
+ *
+ * Changes for multibus/multiadapter I2C support.
+ *
   * (C) Copyright 2000
   * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio at 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.orig/drivers/i2c/i2c_core.c u-boot/drivers/i2c/i2c_core.c
--- u-boot.orig/drivers/i2c/i2c_core.c	1969-12-31 16:00:00.000000000 -0800
+++ u-boot/drivers/i2c/i2c_core.c	2009-01-23 16:01:48.000000000 -0800
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2009 Sergey Kubushyn <ksi at koi8.net>
+ *
+ * Multibus/multiadapter I2C core functions (wrappers)
+ */
+#include <common.h>
+#include <i2c.h>
+
+#ifdef CONFIG_FSL_UNI_I2C
+extern i2c_adap_t	fsl_i2c_adap[];
+#endif
+
+#ifdef CONFIG_SM502_I2C
+extern i2c_adap_t	sm501_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;
+
+	/* Adapters */
+	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
+
+#ifdef CONFIG_BLACKFIN
+	/* This ifdef will become unneccessary in a future version of the
+	 * blackfin I2C driver.
+	 */
+	i2c_read(addr, reg, 0, &buf, 1);
+#else
+	i2c_read(addr, reg, 1, &buf, 1);
+#endif
+
+#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
+
+#ifdef CONFIG_BLACKFIN
+	/* This ifdef will become unneccessary in a future version of the
+	 * blackfin I2C driver.
+	 */
+	i2c_write(addr, reg, 0, &val, 1);
+#else
+	i2c_write(addr, reg, 1, &val, 1);
+#endif
+}
+
+
+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.orig/drivers/i2c/Makefile u-boot/drivers/i2c/Makefile
--- u-boot.orig/drivers/i2c/Makefile	2008-09-12 10:10:35.000000000 -0700
+++ u-boot/drivers/i2c/Makefile	2009-01-23 16:01:48.000000000 -0800
@@ -26,13 +26,15 @@ include $(TOPDIR)/config.mk
  LIB	:= $(obj)libi2c.a

  COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
+COBJS-$(CONFIG_FSL_UNI_I2C) += fsl_uni_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_SOFT_I2C) += soft_i2c.o
  COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
+COBJS-$(CONFIG_SM502_I2C) += sm502_i2c.o

-COBJS	:= $(COBJS-y)
+COBJS	:= i2c_core.o $(COBJS-y)
  SRCS	:= $(COBJS:.o=.c)
  OBJS	:= $(addprefix $(obj),$(COBJS))

diff -purN u-boot.orig/include/i2c.h u-boot/include/i2c.h
--- u-boot.orig/include/i2c.h	2008-12-16 15:32:13.000000000 -0800
+++ u-boot/include/i2c.h	2009-01-23 16:01:48.000000000 -0800
@@ -1,4 +1,7 @@
  /*
+ * Copyright (C) 2009 Sergey Kubushyn <ksi at koi8.net>
+ * Changes for multibus/multiadapter I2C support.
+ *
   * (C) Copyright 2001
   * Gerald Van Baren, Custom IDEAS, vanbaren at 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,111 @@
  #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[];
+
+/*
+ * i2c_get_bus_num:
+ *
+ *  Returns index of currently active I2C bus.  Zero-based.
+ */
+unsigned int i2c_get_bus_num(void);
+
+
  /*
+ * 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);
+
+
+/*
+ * i2c_init_bus()
+ *
   * Initialization, must be called once on start up, may be called
- * repeatedly to change the speed and slave addresses.
+ * repeatedly to change the speed and slave addresses. This initializes
+ * a single current i2c bus.
   */
-void i2c_init(int speed, int slaveaddr);
-#ifdef CONFIG_SYS_I2C_INIT_BOARD
-void i2c_init_board(void);
-#endif
+/* void i2c_init_bus(int speed, int slaveaddr); */

-#if defined(CONFIG_I2C_MUX)

-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,83 +194,25 @@ 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
+u_int8_t i2c_reg_read(u_int8_t addr, u_int8_t reg);

-#ifdef DEBUG
-	printf("%s: addr=0x%02x, reg=0x%02x\n", __func__, addr, reg);
-#endif
+void i2c_reg_write(u_int8_t addr, u_int8_t reg, u_int8_t val);

-#ifdef CONFIG_BLACKFIN
-	/* This ifdef will become unneccessary in a future version of the
-	 * blackfin I2C driver.
-	 */
-	i2c_read(addr, reg, 0, &buf, 1);
-#else
-	i2c_read(addr, reg, 1, &buf, 1);
-#endif
-
-	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
-
-#ifdef CONFIG_BLACKFIN
-	/* This ifdef will become unneccessary in a future version of the
-	 * blackfin I2C driver.
-	 */
-	i2c_write(addr, reg, 0, &val, 1);
-#else
-	i2c_write(addr, reg, 1, &val, 1);
-#endif
-}

  /*
   * Functions for setting the current I2C bus and its speed
   */

-/*
- * 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);
-
-/*
- * i2c_get_bus_num:
- *
- *  Returns index of currently active I2C bus.  Zero-based.
- */
-
-unsigned int i2c_get_bus_num(void);

  /*
   * i2c_set_bus_speed:
@@ -225,10 +221,10 @@ unsigned int i2c_get_bus_num(void);
   *
   *	speed - bus speed in Hz
   *
- *	Returns: 0 on success, not 0 on failure
+ *	Returns: new bus speed
   *
   */
-int i2c_set_bus_speed(unsigned int);
+unsigned int i2c_set_bus_speed(unsigned int speed);

  /*
   * i2c_get_bus_speed:
@@ -238,4 +234,44 @@ int i2c_set_bus_speed(unsigned int);

  unsigned int i2c_get_bus_speed(void);

+/*
+ * i2c_reloc_fixup:
+ *
+ * Adjusts I2C pointers after U-Boot is relocated to DRAM
+ */
+void i2c_reloc_fixup(void);
+
+
+#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
+#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
+
+#ifndef	CONFIG_SYS_I2C_SLAVE
+#define	CONFIG_SYS_I2C_SLAVE	0xFE
+#endif
+#endif
+
+/*
+ * Initialization, must be called once on start up, may be called
+ * repeatedly to change the speed and slave addresses.
+ */
+void i2c_init(unsigned int speed, int slaveaddr);
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+void i2c_init_board(void);
+#endif
+
  #endif	/* _I2C_H_ */
diff -purN u-boot.orig/lib_ppc/board.c u-boot/lib_ppc/board.c
--- u-boot.orig/lib_ppc/board.c	2009-01-23 10:39:27.000000000 -0800
+++ u-boot/lib_ppc/board.c	2009-01-23 16:01:48.000000000 -0800
@@ -91,7 +91,8 @@ extern void sc3_read_eeprom(void);
  void doc_init (void);
  #endif
  #if defined(CONFIG_HARD_I2C) || \
-    defined(CONFIG_SOFT_I2C)
+    defined(CONFIG_SOFT_I2C) || \
+    defined(CONFIG_SYS_I2C_ADAPTERS)
  #include <i2c.h>
  #endif
  #include <spi.h>
@@ -234,11 +235,15 @@ static int init_func_ram (void)

  /***********************************************************************/

-#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) || defined(CONFIG_SYS_I2C_ADAPTERS)
  static int init_func_i2c (void)
  {
  	puts ("I2C:   ");
+#ifdef CONFIG_NEW_I2C
+	i2c_init_all();
+#else
  	i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
  	puts ("ready\n");
  	return (0);
  }
@@ -333,7 +338,7 @@ init_fnc_t *init_sequence[] = {
  	misc_init_f,
  #endif
  	INIT_FUNC_WATCHDOG_RESET
-#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) || defined(CONFIG_SYS_I2C_ADAPTERS)
  	init_func_i2c,
  #endif
  #if defined(CONFIG_HARD_SPI)
@@ -863,6 +868,11 @@ void board_init_r (gd_t *id, ulong dest_
  	 * the environment is in EEPROM.
  	 */

+#if defined(CONFIG_NEW_I2C) && defined(CONFIG_SYS_I2C_ADAPTERS)
+	/* Adjust I2C subsystem pointers after relocation */
+	i2c_reloc_fixup();
+#endif
+
  #if defined(CONFIG_SYS_EXTBDINFO)
  #if defined(CONFIG_405GP) || defined(CONFIG_405EP)
  #if defined(CONFIG_I2CFAST)
diff -purN u-boot.orig/include/configs/MPC8548CDS.h u-boot/include/configs/MPC8548CDS.h
--- u-boot.orig/include/configs/MPC8548CDS.h	2008-12-16 15:32:13.000000000 -0800
+++ u-boot/include/configs/MPC8548CDS.h	2009-01-23 16:01:48.000000000 -0800
@@ -52,6 +52,8 @@

  #define CONFIG_FSL_VIA

+#define CONFIG_NEW_I2C
+
  /*
   * When initializing flash, if we cannot find the manufacturer ID,
   * assume this is the AMD flash associated with the CDS board.
@@ -343,6 +345,8 @@ extern unsigned long get_clock_freq(void
  #define CONFIG_SYS_64BIT_VSPRINTF	1
  #define CONFIG_SYS_64BIT_STRTOUL	1

+
+#ifndef CONFIG_NEW_I2C
  /*
   * I2C
   */
@@ -353,6 +357,57 @@ extern unsigned long get_clock_freq(void
  #define CONFIG_SYS_I2C_SLAVE		0x7F
  #define CONFIG_SYS_I2C_NOPROBES	{0x69}	/* Don't probe these addrs */
  #define CONFIG_SYS_I2C_OFFSET		0x3000
+#else /* CONFIG_NEW_I2C */
+#if 0
+/*
+ * Illustrative example with 3 I2C adapters and 5 I2C busses.
+ *
+ * Adapters: 2x FSL_I2C (0 and 1) and SM502 adapter (3)
+ *
+ * Busses:
+ *
+ *	0:	Direct off of FSL_I2C[0]
+ *	1:	FSL_I2C[1]->PCA9542(0)->PCA9542(0)
+ *	2:	FSL_I2C[1]->PCA9542(0)->PCA9542(1)
+ *	3:	FSL_I2C[1]->PCA9542(1)
+ *	4:	SM502_I2C
+ *
+ * This might not have sense (it is much more logical to use a single
+ * PCA9544 for 3 busses off of FSL_I2C[1]) but it is just an illustrative
+ * example.
+ */
+#define CONFIG_SYS_NUM_I2C_ADAPTERS	3
+#define CONFIG_SYS_NUM_I2C_BUSSES	5
+#define CONFIG_SYS_I2C_MAX_HOPS		2
+#define CONFIG_SM502_I2C			/* Use SM502 I2C driver */
+#define CONFIG_SYS_SM501_I2C_SPEED	400000	/* I2C speed and slave address */
+#define CONFIG_SYS_SM501_I2C_SLAVE	0x7F	/* Adapter #1 */
+#define CONFIG_SYS_SM501_BASEADDR	0x80000000	/* Bogus */
+#define CONFIG_FSL_UNI_I2C			/* Use FSL common I2C driver */
+#define CONFIG_SYS_FSL_I2C_SPEED	400000	/* I2C speed and slave address */
+#define CONFIG_SYS_FSL_I2C_SLAVE	0x7F	/* Adapter #1 */
+#define CONFIG_SYS_FSL_I2C_OFFSET	0x3000
+#define CONFIG_SYS_FSL_I2C2_SPEED	400000	/* I2C speed and slave address */
+#define CONFIG_SYS_FSL_I2C2_SLAVE	0x7F	/* Adapter #2 */
+#define CONFIG_SYS_FSL_I2C2_OFFSET	0x3100
+#define CONFIG_SYS_I2C_ADAPTERS		{&fsl_i2c_adap[0], &fsl_i2c_adap[1], &sm501_i2c_adap}
+#define CONFIG_SYS_I2C_BUSSES	{	{0, {I2C_NULL_HOP, I2C_NULL_HOP}}, \
+		{1, {{I2C_MUX_PCA9542, 0x70, 0}, {I2C_MUX_PCA9542, 0x71, 0}}}, \
+		{1, {{I2C_MUX_PCA9542, 0x70, 0}, {I2C_MUX_PCA9542, 0x71, 1}}}, \
+		{1, {{I2C_MUX_PCA9542, 0x70, 1}, I2C_NULL_HOP}}, \
+		{2, {I2C_NULL_HOP, I2C_NULL_HOP}}}
+#define CONFIG_SYS_I2C_NOPROBES		{{0,0x69},{1,0x69}}	/* Don't probe these addrs */
+#else
+#define CONFIG_SYS_NUM_I2C_ADAPTERS	1
+#define CONFIG_SYS_NUM_I2C_BUSSES	1
+#define CONFIG_FSL_UNI_I2C				/* Use FSL common I2C driver */
+#define CONFIG_SYS_FSL_I2C_SPEED	400000	/* I2C speed and slave address */
+#define CONFIG_SYS_FSL_I2C_SLAVE	0x7F	/* Adapter #1 */
+#define CONFIG_SYS_FSL_I2C_OFFSET	0x3000
+#define CONFIG_SYS_I2C_NOPROBES		{0x69}	/* Don't probe these addrs */
+#define CONFIG_SYS_I2C_ADAPTERS		{&fsl_i2c_adap[0]}
+#endif
+#endif /* CONFIG_NEW_I2C */

  /* EEPROM */
  #define CONFIG_ID_EEPROM
@@ -482,8 +537,11 @@ extern unsigned long get_clock_freq(void
   */
  #include <config_cmd_default.h>

+#define CONFIG_I2C_CMD_TREE
+
  #define CONFIG_CMD_PING
  #define CONFIG_CMD_I2C
+#define CONFIG_CMD_SDRAM
  #define CONFIG_CMD_MII
  #define CONFIG_CMD_ELF
  #define CONFIG_CMD_IRQ


---
******************************************************************
*  KSI at home    KOI8 Net  < >  The impossible we do immediately.  *
*  Las Vegas   NV, USA   < >  Miracles require 24-hour notice.   *
******************************************************************


More information about the U-Boot mailing list