[U-Boot] [POWERPC] mgcoge, mgsuvd: add I2C support.

Heiko Schocher hs at denx.de
Mon Sep 29 09:53:22 CEST 2008


Also support CONFIG_I2C_MULTI_BUS for the
soft_i2c and the cpu/mpc8260/i2c.c driver.

Signed-off-by: Heiko Schocher <hs at denx.de>
---
 board/keymile/mgcoge/mgcoge.c |   93 ++++++++++++++++++++++-------------------
 board/keymile/mgsuvd/mgsuvd.c |   13 ++++++
 cpu/mpc8260/i2c.c             |   36 ++++++++++++++++
 drivers/i2c/soft_i2c.c        |   36 ++++++++++++++++
 include/configs/mgcoge.h      |   25 +++++++++++
 include/configs/mgsuvd.h      |   42 ++++++++++++++++++
 6 files changed, 202 insertions(+), 43 deletions(-)

diff --git a/board/keymile/mgcoge/mgcoge.c b/board/keymile/mgcoge/mgcoge.c
index 51b6dc6..9b37959 100644
--- a/board/keymile/mgcoge/mgcoge.c
+++ b/board/keymile/mgcoge/mgcoge.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007
+ * (C) Copyright 2007 - 2008
  * Heiko Schocher, DENX Software Engineering, hs at denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -24,11 +24,16 @@
 #include <common.h>
 #include <mpc8260.h>
 #include <ioports.h>
+#include <malloc.h>

 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
 #include <libfdt.h>
 #endif

+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+#include <i2c.h>
+#endif
+
 /*
  * I/O Port configuration table
  *
@@ -163,8 +168,13 @@ const iop_conf_t iop_conf_tab[4][32] = {
 	/* PD18 */ { 0,          0,   0,   0,   0,   0 }, /* PD18            */
 	/* PD17 */ { 0,          0,   0,   0,   0,   0 }, /* PD17            */
 	/* PD16 */ { 0,          0,   0,   0,   0,   0 }, /* PD16            */
-	/* PD15 */ { 0,          0,   0,   0,   0,   0 }, /* PD15            */
-	/* PD14 */ { 0,          0,   0,   0,   0,   0 }, /* PD14            */
+#if defined(CONFIG_HARD_I2C)
+	/* PD15 */ { 1,          1,   1,   0,   1,   0 }, /* I2C SDA         */
+	/* PD14 */ { 1,          1,   1,   0,   1,   0 }, /* I2C SCL         */
+#else
+	/* PD15 */ { 1,          0,   0,   0,   1,   1 }, /* PD15            */
+	/* PD14 */ { 1,          0,   0,   1,   1,   1 }, /* PD14            */
+#endif
 	/* PD13 */ { 0,          0,   0,   0,   0,   0 }, /* PD13            */
 	/* PD12 */ { 0,          0,   0,   0,   0,   0 }, /* PD12            */
 	/* PD11 */ { 0,          0,   0,   0,   0,   0 }, /* PD11            */
@@ -243,13 +253,13 @@ static long int try_init (volatile memctl8260_t * memctl, ulong sdmr,
 	*sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN;
 	*base = c;

-	size = get_ram_size((long *)base, maxsize);
+	size = get_ram_size ((long *)base, maxsize);
 	*orx_ptr = orx | ~(size - 1);

 	return (size);
 }

-phys_size_t initdram(int board_type)
+phys_size_t initdram (int board_type)
 {
 	volatile immap_t *immap = (immap_t *) CFG_IMMR;
 	volatile memctl8260_t *memctl = &immap->im_memctl;
@@ -273,7 +283,7 @@ phys_size_t initdram(int board_type)

 int checkboard(void)
 {
-	puts("Board: mgcoge\n");
+	puts ("Board: mgcoge\n");

 	return 0;
 }
@@ -281,7 +291,7 @@ int checkboard(void)
 /*
  * Early board initalization.
  */
-int board_early_init_r(void)
+int board_early_init_r (void)
 {
 	/* setup the UPIOx */
 	*(char *)(CFG_PIGGY_BASE + 0x02) = 0xc0;
@@ -293,68 +303,65 @@ int board_early_init_r(void)
 /*
  * update "memory" property in the blob
  */
-void ft_blob_update(void *blob, bd_t *bd)
+void ft_blob_update (void *blob, bd_t *bd)
 {
 	int ret, nodeoffset = 0;
 	ulong memory_data[2] = {0};
 	ulong flash_data[8] = {0};

-	memory_data[0] = cpu_to_be32(bd->bi_memstart);
-	memory_data[1] = cpu_to_be32(bd->bi_memsize);
+	memory_data[0] = cpu_to_be32 (bd->bi_memstart);
+	memory_data[1] = cpu_to_be32 (bd->bi_memsize);

 	nodeoffset = fdt_path_offset (blob, "/memory");
 	if (nodeoffset >= 0) {
-		ret = fdt_setprop(blob, nodeoffset, "reg", memory_data,
-					sizeof(memory_data));
+		ret = fdt_setprop (blob, nodeoffset, "reg", memory_data,
+					sizeof (memory_data));
 	if (ret < 0)
-		printf("ft_blob_update(): cannot set /memory/reg "
-			"property err:%s\n", fdt_strerror(ret));
-	}
-	else {
+		printf ("ft_blob_update(): cannot set /memory/reg "
+			"property err:%s\n", fdt_strerror (ret));
+	} else {
 		/* memory node is required in dts */
-		printf("ft_blob_update(): cannot find /memory node "
-		"err:%s\n", fdt_strerror(nodeoffset));
+		printf ("ft_blob_update(): cannot find /memory node "
+		"err:%s\n", fdt_strerror (nodeoffset));
 	}
 	/* update Flash addr, size */
-	flash_data[2] = cpu_to_be32(CFG_FLASH_BASE);
-	flash_data[3] = cpu_to_be32(CFG_FLASH_SIZE);
-	flash_data[4] = cpu_to_be32(1);
-	flash_data[5] = cpu_to_be32(0);
-	flash_data[6] = cpu_to_be32(CFG_FLASH_BASE_1);
-	flash_data[7] = cpu_to_be32(CFG_FLASH_SIZE_1);
+	flash_data[2] = cpu_to_be32 (CFG_FLASH_BASE);
+	flash_data[3] = cpu_to_be32 (CFG_FLASH_SIZE);
+	flash_data[4] = cpu_to_be32 (1);
+	flash_data[5] = cpu_to_be32 (0);
+	flash_data[6] = cpu_to_be32 (CFG_FLASH_BASE_1);
+	flash_data[7] = cpu_to_be32 (CFG_FLASH_SIZE_1);
 	nodeoffset = fdt_path_offset (blob, "/localbus");
 	if (nodeoffset >= 0) {
-		ret = fdt_setprop(blob, nodeoffset, "ranges", flash_data,
-					sizeof(flash_data));
+		ret = fdt_setprop (blob, nodeoffset, "ranges", flash_data,
+					sizeof (flash_data));
 	if (ret < 0)
-		printf("ft_blob_update(): cannot set /localbus/ranges "
-			"property err:%s\n", fdt_strerror(ret));
-	}
-	else {
+		printf ("ft_blob_update(): cannot set /localbus/ranges "
+			"property err:%s\n", fdt_strerror (ret));
+	} else {
 		/* memory node is required in dts */
-		printf("ft_blob_update(): cannot find /localbus node "
-		"err:%s\n", fdt_strerror(nodeoffset));
+		printf ("ft_blob_update(): cannot find /localbus node "
+		"err:%s\n", fdt_strerror (nodeoffset));
 	}
 	/* MAC Adresse */
 	nodeoffset = fdt_path_offset (blob, "/soc/cpm/ethernet");
 	if (nodeoffset >= 0) {
-		ret = fdt_setprop(blob, nodeoffset, "mac-address", bd->bi_enetaddr,
-					sizeof(uchar) * 6);
+		ret = fdt_setprop (blob, nodeoffset, "mac-address", bd->bi_enetaddr,
+					sizeof (uchar) * 6);
 	if (ret < 0)
-		printf("ft_blob_update(): cannot set /soc/cpm/ethernet/mac-address "
-			"property err:%s\n", fdt_strerror(ret));
-	}
-	else {
+		printf ("ft_blob_update(): cannot set /soc/cpm/ethernet/mac-address "
+			"property err:%s\n", fdt_strerror (ret));
+	} else {
 		/* memory node is required in dts */
-		printf("ft_blob_update(): cannot find /soc/cpm/ethernet node "
-		"err:%s\n", fdt_strerror(nodeoffset));
+		printf ("ft_blob_update(): cannot find /soc/cpm/ethernet node "
+		"err:%s\n", fdt_strerror (nodeoffset));
 	}

 }

-void ft_board_setup(void *blob, bd_t *bd)
+void ft_board_setup (void *blob, bd_t *bd)
 {
-	ft_cpu_setup( blob, bd);
-	ft_blob_update(blob, bd);
+	ft_cpu_setup (blob, bd);
+	ft_blob_update (blob, bd);
 }
 #endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
diff --git a/board/keymile/mgsuvd/mgsuvd.c b/board/keymile/mgsuvd/mgsuvd.c
index c51ea7e..49b43ee 100644
--- a/board/keymile/mgsuvd/mgsuvd.c
+++ b/board/keymile/mgsuvd/mgsuvd.c
@@ -225,3 +225,16 @@ void ft_board_setup(void *blob, bd_t *bd)
 	ft_blob_update(blob, bd);
 }
 #endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
+
+#if defined(CONFIG_SOFT_I2C)
+int i2c_mgsuvd_read (void)
+{
+	int val;
+
+	*(unsigned short *)(I2C_BASE_DIR) &=  ~SDA_CONF;	
+	udelay(1);
+	val = *(unsigned char *)(I2C_BASE_PORT);
+	
+	return ((val & SDA_BIT) == SDA_BIT);
+}
+#endif
diff --git a/cpu/mpc8260/i2c.c b/cpu/mpc8260/i2c.c
index c3af7b6..335177f 100644
--- a/cpu/mpc8260/i2c.c
+++ b/cpu/mpc8260/i2c.c
@@ -36,6 +36,10 @@

 DECLARE_GLOBAL_DATA_PTR;

+#if defined(CONFIG_I2C_MULTI_BUS)
+static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0;
+#endif /* CONFIG_I2C_MULTI_BUS */
+
 /* uSec to wait between polls of the i2c */
 #define DELAY_US	100
 /* uSec to wait for the CPM to start processing the buffer */
@@ -765,4 +769,36 @@ i2c_reg_write(uchar chip, uchar reg, uchar val)
 	i2c_write(chip, reg, 1, &val, 1);
 }

+#if defined(CONFIG_I2C_MULTI_BUS)
+/*
+ * Functions for multiple I2C bus handling
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	return i2c_bus_num;
+}
+
+int i2c_set_bus_num(unsigned int bus)
+{
+	if (bus >= CFG_MAX_I2C_BUS)
+		return -1;
+	i2c_bus_num = bus;
+
+	return 0;
+}
+/* TODO: add 100/400k switching */
+unsigned int i2c_get_bus_speed(void)
+{
+	return CFG_I2C_SPEED;
+}
+
+int i2c_set_bus_speed(unsigned int speed)
+{
+	if (speed != CFG_I2C_SPEED)
+		return -1;
+
+	return 0;
+}
+
+#endif	/* CONFIG_I2C_MULTI_BUS */
 #endif	/* CONFIG_HARD_I2C */
diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c
index 23db2ee..57736da 100644
--- a/drivers/i2c/soft_i2c.c
+++ b/drivers/i2c/soft_i2c.c
@@ -68,6 +68,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #define PRINTD(fmt,args...)
 #endif

+#if defined(CONFIG_I2C_MULTI_BUS)
+static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0;
+#endif /* CONFIG_I2C_MULTI_BUS */
+
 /*-----------------------------------------------------------------------
  * Local functions
  */
@@ -230,6 +234,38 @@ static int write_byte(uchar data)
 	return(nack);	/* not a nack is an ack */
 }

+#if defined(CONFIG_I2C_MULTI_BUS)
+/*
+ * Functions for multiple I2C bus handling
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	return i2c_bus_num;
+}
+
+int i2c_set_bus_num(unsigned int bus)
+{
+	if (bus >= CFG_MAX_I2C_BUS)
+		return -1;
+	i2c_bus_num = bus;
+
+	return 0;
+}
+
+/* TODO: add 100/400k switching */
+unsigned int i2c_get_bus_speed(void)
+{
+	return CFG_I2C_SPEED;
+}
+
+int i2c_set_bus_speed(unsigned int speed)
+{
+	if (speed != CFG_I2C_SPEED)
+		return -1;
+
+	return 0;
+}
+#endif

 /*-----------------------------------------------------------------------
  * if ack == I2C_ACK, ACK the byte so can continue reading, else
diff --git a/include/configs/mgcoge.h b/include/configs/mgcoge.h
index 23af3ec..159eeae 100644
--- a/include/configs/mgcoge.h
+++ b/include/configs/mgcoge.h
@@ -82,6 +82,7 @@
 #include <config_cmd_default.h>

 #define CONFIG_CMD_ECHO
+#define CONFIG_CMD_I2C
 #define CONFIG_CMD_IMMAP
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_PING
@@ -176,6 +177,30 @@
 #define CONFIG_ENV_ADDR		(CFG_MONITOR_BASE + CFG_MONITOR_LEN)
 #endif /* CONFIG_ENV_IS_IN_FLASH */

+/* enable I2C and select the hardware/software driver */
+#undef	CONFIG_HARD_I2C			/* I2C with hardware support	*/
+#define	CONFIG_SOFT_I2C		1	/* I2C bit-banged		*/
+#define CFG_I2C_SPEED		50000	/* I2C speed and slave address	*/
+#define CFG_I2C_SLAVE		0x7F
+
+/*
+ * Software (bit-bang) I2C driver configuration
+ */
+
+#define I2C_PORT	3		/* Port A=0, B=1, C=2, D=3 */
+#define I2C_ACTIVE	(iop->pdir |=  0x00010000)
+#define I2C_TRISTATE	(iop->pdir &= ~0x00010000)
+#define I2C_READ	((iop->pdat & 0x00010000) != 0)
+#define I2C_SDA(bit)	if(bit) iop->pdat |=  0x00010000; \
+			else    iop->pdat &= ~0x00010000
+#define I2C_SCL(bit)	if(bit) iop->pdat |=  0x00020000; \
+			else    iop->pdat &= ~0x00020000
+#define I2C_DELAY	udelay(5)	/* 1/4 I2C clock duration */
+
+#define CONFIG_I2C_MULTI_BUS	1
+#define CONFIG_I2C_CMD_TREE	1
+#define CFG_MAX_I2C_BUS		2
+
 #define CFG_IMMR		0xF0000000

 #define CFG_INIT_RAM_ADDR	CFG_IMMR
diff --git a/include/configs/mgsuvd.h b/include/configs/mgsuvd.h
index 740767e..2c30fab 100644
--- a/include/configs/mgsuvd.h
+++ b/include/configs/mgsuvd.h
@@ -113,6 +113,7 @@

 #define CONFIG_CMD_ASKENV
 #define CONFIG_CMD_DHCP
+#define CONFIG_CMD_I2C
 #define CONFIG_CMD_NFS
 #define CONFIG_CMD_PING

@@ -330,4 +331,45 @@
 #define OF_TBCLK		(bd->bi_busfreq / 4)
 #define OF_STDOUT_PATH		"/soc/cpm/serial at a80"

+/* enable I2C and select the hardware/software driver */
+#undef	CONFIG_HARD_I2C			/* I2C with hardware support	*/
+#define	CONFIG_SOFT_I2C		1	/* I2C bit-banged		*/
+#define CFG_I2C_SPEED		50000	/* I2C speed and slave address	*/
+#define CFG_I2C_SLAVE		0x7F
+
+/*
+ * Software (bit-bang) I2C driver configuration
+ */
+#define I2C_BASE_DIR	(CFG_PIGGY_BASE + 0x04)
+#define I2C_BASE_PORT	(CFG_PIGGY_BASE + 0x09)
+
+#define SDA_BIT		0x40
+#define SCL_BIT		0x80
+#define SDA_CONF	0x1000
+#define SCL_CONF	0x2000
+
+#define I2C_ACTIVE	do {} while (0)
+#define I2C_TRISTATE	do {} while (0)
+#define I2C_READ	i2c_mgsuvd_read ()
+#define I2C_SDA(bit)	if(bit) { \
+				*(unsigned short *)(I2C_BASE_DIR) &=  ~SDA_CONF; \
+				} \
+			else    { \
+				*(unsigned char *)(I2C_BASE_PORT) &= ~SDA_BIT; \
+				*(unsigned short *)(I2C_BASE_DIR) |= SDA_CONF; \
+				}
+#define I2C_SCL(bit)	if(bit) { \
+				*(unsigned short *)(I2C_BASE_DIR) &=  ~SCL_CONF; \
+				} \
+			else    { \
+				*(unsigned char *)(I2C_BASE_PORT) &= ~SCL_BIT; \
+				*(unsigned short *)(I2C_BASE_DIR) |= SCL_CONF; \
+				}
+#define I2C_DELAY	udelay(50)	/* 1/4 I2C clock duration */
+
+#define CONFIG_I2C_MULTI_BUS	1
+#define CONFIG_I2C_CMD_TREE	1
+#define CFG_MAX_I2C_BUS		2
+
+
 #endif	/* __CONFIG_H */
-- 
1.5.6.1

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


More information about the U-Boot mailing list