summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2006-11-01 03:23:16 (GMT)
committerKim Phillips <kim.phillips@freescale.com>2006-11-04 01:42:22 (GMT)
commit9ca880a250870a7d55754291b5591d2b5fe89b54 (patch)
treebfef7c3013d3423222e2af4522b3341f42398f8e
parentac4b5622ce050b5ee1e154b98df630d778661632 (diff)
downloadu-boot-9ca880a250870a7d55754291b5591d2b5fe89b54.tar.xz
mpc83xx: Fix dual I2C support for the MPC8349ITX, MPC8349EMDS, TQM834x, and MPC8360EMDS
This patch also adds an improved I2C set_speed(), which handles all clock frequencies. Signed-off-by: Timur Tabi <timur@freescale.com>
-rw-r--r--board/mpc8349emds/pci.c8
-rw-r--r--board/mpc8349itx/mpc8349itx.c6
-rw-r--r--board/mpc8349itx/pci.c2
-rw-r--r--board/mpc8360emds/pci.c11
-rw-r--r--cpu/mpc83xx/i2c.c214
-rw-r--r--include/asm-ppc/i2c.h10
-rw-r--r--include/configs/MPC8349ITX.h2
-rw-r--r--include/configs/TQM834x.h2
-rw-r--r--include/i2c.h8
9 files changed, 154 insertions, 109 deletions
diff --git a/board/mpc8349emds/pci.c b/board/mpc8349emds/pci.c
index a916245..93827f1 100644
--- a/board/mpc8349emds/pci.c
+++ b/board/mpc8349emds/pci.c
@@ -75,10 +75,8 @@ pib_init(void)
/* Switch temporarily to I2C bus #2 */
orig_i2c_bus = i2c_get_bus_num();
- if(orig_i2c_bus != I2C_BUS_2)
- i2c_set_bus_num(I2C_BUS_2);
-
- i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);
+ if(orig_i2c_bus != 2)
+ i2c_set_bus_num(2);
val8 = 0;
i2c_write(0x23, 0x6, 1, &val8, 1);
@@ -124,7 +122,7 @@ pib_init(void)
printf("PCI2: 32-bit on PMC3\n");
#endif
/* Reset to original I2C bus */
- if(orig_i2c_bus != I2C_BUS_2)
+ if(orig_i2c_bus != 2)
i2c_set_bus_num(orig_i2c_bus);
}
diff --git a/board/mpc8349itx/mpc8349itx.c b/board/mpc8349itx/mpc8349itx.c
index 9a5cbec..4662645 100644
--- a/board/mpc8349itx/mpc8349itx.c
+++ b/board/mpc8349itx/mpc8349itx.c
@@ -259,7 +259,7 @@ int checkboard(void)
puts("Board: Freescale MPC8349E-mITX");
#ifdef CONFIG_HARD_I2C
- i2c_set_bus_num(I2C_BUS_2);
+ i2c_set_bus_num(2);
if (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) ==
0)
printf(" %u.%u (PCF8475A)", (i2c_data & 0x02) >> 1,
@@ -379,7 +379,7 @@ int misc_init_r(void)
u8 data[sizeof(eeprom_data)];
- i2c_set_bus_num(I2C_BUS_1);
+ i2c_set_bus_num(1);
if (i2c_read(CFG_I2C_EEPROM_ADDR, 0, 2, data, sizeof(data)) == 0) {
if (memcmp(data, eeprom_data, sizeof(data)) != 0) {
@@ -397,7 +397,7 @@ int misc_init_r(void)
#endif
#ifdef CFG_I2C_RTC_ADDR
- i2c_set_bus_num(I2C_BUS_2);
+ i2c_set_bus_num(2);
if (i2c_read(CFG_I2C_RTC_ADDR, 0, 1, ds1339_data, sizeof(ds1339_data))
== 0) {
diff --git a/board/mpc8349itx/pci.c b/board/mpc8349itx/pci.c
index acac185..cf07020 100644
--- a/board/mpc8349itx/pci.c
+++ b/board/mpc8349itx/pci.c
@@ -105,7 +105,7 @@ void pci_init_board(void)
udelay(2000);
#ifdef CONFIG_HARD_I2C
- i2c_set_bus_num(I2C_BUS_2);
+ i2c_set_bus_num(2);
/* Read the PCI_M66EN jumper setting */
if ((i2c_read(CFG_I2C_8574_ADDR2, 0, 0, &reg8, sizeof(reg8)) == 0) ||
(i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, &reg8, sizeof(reg8)) == 0)) {
diff --git a/board/mpc8360emds/pci.c b/board/mpc8360emds/pci.c
index 880b2ec..64ea509 100644
--- a/board/mpc8360emds/pci.c
+++ b/board/mpc8360emds/pci.c
@@ -198,8 +198,11 @@ void pci_init_board(void)
* Assign PIB PMC slot to desired PCI bus
*/
- mpc83xx_i2c = (i2c_t *) (CFG_IMMRBAR + CFG_I2C2_OFFSET);
- i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);
+ /* Switch temporarily to I2C bus #2 */
+ orig_i2c_bus = i2c_get_bus_num();
+
+ if(orig_i2c_bus != 2)
+ i2c_set_bus_num(2);
val8 = 0;
i2c_write(0x23, 0x6, 1, &val8, 1);
@@ -227,6 +230,10 @@ void pci_init_board(void)
i2c_write(0x27, 0x3, 1, &val8, 1);
asm("eieio");
+ /* Reset to original I2C bus */
+ if(orig_i2c_bus != 2)
+ i2c_set_bus_num(orig_i2c_bus);
+
/*
* Release PCI RST Output signal
*/
diff --git a/cpu/mpc83xx/i2c.c b/cpu/mpc83xx/i2c.c
index fc89fb1..ce78491 100644
--- a/cpu/mpc83xx/i2c.c
+++ b/cpu/mpc83xx/i2c.c
@@ -47,75 +47,121 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Three I2C bus speeds are supported here (50kHz, 100kHz
- * and 400kHz). It should be easy to add more. Note that
- * the maximum bus speed for I2C bus 1 is CSB/3, while I2C
- * bus 2 can go as high as CSB.
- * Typical values for CSB are 266MHz and 200MHz. */
-
- /* 50kH 100kHz 400kHz */
-static const uchar speed_map_266[][3] =
- {{0x2e, 0x2a, 0x20}, /* base 88MHz */
- {0x34, 0x30, 0x28}}; /* base 266 MHz */
-
-static const uchar speed_map_200[][3] =
- {{0x2c, 0x28, 0x20}, /* base 66 MHz */
- {0x33, 0x2f, 0x26}}; /* base 200 MHz */
-
/* Initialize the bus pointer to whatever one the SPD EEPROM is on.
* Default is bus 1. This is necessary because the DDR initialization
* runs from ROM, and we can't switch buses because we can't modify
* the i2c_dev variable. Everything gets straightened out once i2c_init
* is called from RAM. */
-#if defined CFG_SPD_BUS_NUM
-static i2c_t *i2c_dev = CFG_SPD_BUS_NUM;
+#ifndef CFG_SPD_BUS_NUM
+#define CFG_SPD_BUS_NUM 1
+#endif
+
+static unsigned int i2c_bus_num = CFG_SPD_BUS_NUM;
+
+#if CFG_SPD_BUS_NUM == 1
+static volatile i2c_t *i2c_dev = I2C_1;
#else
-static i2c_t *i2c_dev = I2C_1;
+static volatile i2c_t *i2c_dev = I2C_2;
#endif
-static uchar busNum = I2C_BUS_1 ;
-static int bus_speed[2] = {0, 0};
+static int i2c_bus_speed[2] = {0, 0};
-static int set_speed(int speed)
+/*
+ * Map the frequency divider to the FDR. This data is taken from table 17-5
+ * of the MPC8349EA reference manual, with duplicates removed.
+ */
+static struct {
+ unsigned int divider;
+ u8 fdr;
+} i2c_speed_map[] =
{
- uchar value;
- const uchar *spdPtr;
-
- /* Global data contains maximum I2C bus 1 speed, which is CSB/3 */
- if(gd->i2c_clk == 88000000)
- {
- spdPtr = speed_map_266[busNum];
- }
- else if(gd->i2c_clk == 66000000)
- {
- spdPtr = speed_map_200[busNum];
- }
- else
- {
- printf("Max I2C bus speed %d not supported\n", gd->i2c_clk);
- return -1;
- }
-
- switch(speed)
- {
- case 50000:
- value = *(spdPtr + 0);
- break;
- case 100000:
- value = *(spdPtr + 1);
- break;
- case 400000:
- value = *(spdPtr + 2);
- break;
- default:
- printf("I2C bus speed %d not supported\n", speed);
- return -2;
- }
- /* set clock */
- writeb(value, &i2c_dev->fdr);
- bus_speed[busNum] = speed;
- return 0;
+ {0, 0x20},
+ {256, 0x20},
+ {288, 0x21},
+ {320, 0x22},
+ {352, 0x23},
+ {384, 0x24},
+ {416, 0x01},
+ {448, 0x25},
+ {480, 0x02},
+ {512, 0x26},
+ {576, 0x27},
+ {640, 0x28},
+ {704, 0x05},
+ {768, 0x29},
+ {832, 0x06},
+ {896, 0x2A},
+ {1024, 0x2B},
+ {1152, 0x08},
+ {1280, 0x2C},
+ {1536, 0x2D},
+ {1792, 0x2E},
+ {1920, 0x0B},
+ {2048, 0x2F},
+ {2304, 0x0C},
+ {2560, 0x30},
+ {3072, 0x31},
+ {3584, 0x32},
+ {3840, 0x0F},
+ {4096, 0x33},
+ {4608, 0x10},
+ {5120, 0x34},
+ {6144, 0x35},
+ {7168, 0x36},
+ {7680, 0x13},
+ {8192, 0x37},
+ {9216, 0x14},
+ {10240, 0x38},
+ {12288, 0x39},
+ {14336, 0x3A},
+ {15360, 0x17},
+ {16384, 0x3B},
+ {18432, 0x18},
+ {20480, 0x3C},
+ {24576, 0x3D},
+ {28672, 0x3E},
+ {30720, 0x1B},
+ {32768, 0x3F},
+ {36864, 0x1C},
+ {40960, 0x1D},
+ {49152, 0x1E},
+ {61440, 0x1F},
+ {-1, 0x1F}
+};
+
+#define NUM_I2C_SPEEDS (sizeof(i2c_speed_map) / sizeof(i2c_speed_map[0]))
+
+static int set_speed(unsigned int speed)
+{
+ unsigned long i2c_clk;
+ unsigned int divider, i;
+ u8 fdr = 0x3F;
+
+ i2c_clk = (i2c_bus_num == 2) ? gd->i2c2_clk : gd->i2c1_clk;
+
+ divider = i2c_clk / speed;
+
+ /* Scan i2c_speed_map[] for the closest matching divider.*/
+
+ for (i = 0; i < NUM_I2C_SPEEDS-1; i++) {
+ /* Locate our divider in between two entries in i2c_speed_map[] */
+ if ((divider >= i2c_speed_map[i].divider) &&
+ (divider <= i2c_speed_map[i+1].divider)) {
+ /* Which one is closer? */
+ if ((divider - i2c_speed_map[i].divider) < (i2c_speed_map[i+1].divider - divider)) {
+ fdr = i2c_speed_map[i].fdr;
+ } else {
+ fdr = i2c_speed_map[i+1].fdr;
+ }
+ break;
+ }
+ }
+
+ writeb(fdr, &i2c_dev->fdr);
+ i2c_bus_speed[i2c_bus_num - 1] = speed;
+
+ return 0;
}
@@ -125,16 +171,16 @@ static void _i2c_init(int speed, int slaveadd)
writeb(0x00 , &i2c_dev->cr);
/* set clock */
- writeb(speed, &i2c_dev->fdr);
+ set_speed(speed);
/* set default filter */
- writeb(0x10,&i2c_dev->dfsrr);
+ writeb(IC2_FDR,&i2c_dev->dfsrr);
/* write slave address */
writeb(slaveadd, &i2c_dev->adr);
/* clear status register */
- writeb(0x00, &i2c_dev->sr);
+ writeb(I2C_CR_MTX, &i2c_dev->sr);
/* start I2C controller */
writeb(I2C_CR_MEN, &i2c_dev->cr);
@@ -142,19 +188,19 @@ static void _i2c_init(int speed, int slaveadd)
void i2c_init(int speed, int slaveadd)
{
- /* Set both interfaces to the same speed and slave address */
- /* Note: This function gets called twice - before and after
- * relocation to RAM. The first time it's called, we are unable
- * to change buses, so whichever one 'i2c_dev' was initialized to
- * gets set twice. When run from RAM both buses get set properly */
-
- i2c_set_bus_num(I2C_BUS_1);
- _i2c_init(speed, slaveadd);
-#ifdef CFG_I2C2_OFFSET
- i2c_set_bus_num(I2C_BUS_2);
- _i2c_init(speed, slaveadd);
- i2c_set_bus_num(I2C_BUS_1);
-#endif /* CFG_I2C2_OFFSET */
+ /* Set both interfaces to the same speed and slave address */
+ /* Note: This function gets called twice - before and after
+ * relocation to RAM. The first time it's called, we are unable
+ * to change buses, so whichever one 'i2c_dev' was initialized to
+ * gets set twice. When run from RAM both buses get set properly */
+
+ i2c_set_bus_num(1);
+ _i2c_init(speed, slaveadd);
+#ifdef CFG_I2C2_OFFSET
+ i2c_set_bus_num(2);
+ _i2c_init(speed, slaveadd);
+ i2c_set_bus_num(1);
+#endif /* CFG_I2C2_OFFSET */
}
static __inline__ int
@@ -340,38 +386,38 @@ void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
i2c_write (i2c_addr, reg, 1, &val, 1);
}
-int i2c_set_bus_num(uchar bus)
+int i2c_set_bus_num(unsigned int bus)
{
- if(bus == I2C_BUS_1)
+ if(bus == 1)
{
i2c_dev = I2C_1;
}
#ifdef CFG_I2C2_OFFSET
- else if(bus == I2C_BUS_2)
+ else if(bus == 2)
{
i2c_dev = I2C_2;
}
-#endif /* CFG_I2C2_OFFSET */
+#endif
else
{
return -1;
}
- busNum = bus;
+ i2c_bus_num = bus;
return 0;
}
-int i2c_set_bus_speed(int speed)
+int i2c_set_bus_speed(unsigned int speed)
{
return set_speed(speed);
}
-uchar i2c_get_bus_num(void)
+unsigned int i2c_get_bus_num(void)
{
- return busNum;
+ return i2c_bus_num;
}
-int i2c_get_bus_speed(void)
+unsigned int i2c_get_bus_speed(void)
{
- return bus_speed[busNum];
+ return i2c_bus_speed[i2c_bus_num - 1];
}
#endif /* CONFIG_HARD_I2C */
diff --git a/include/asm-ppc/i2c.h b/include/asm-ppc/i2c.h
index baf9d9a..8afdda2 100644
--- a/include/asm-ppc/i2c.h
+++ b/include/asm-ppc/i2c.h
@@ -79,12 +79,6 @@ typedef struct i2c
#endif
#define I2C_TIMEOUT (CFG_HZ/4)
-enum I2C_BUS_NUM
-{
- I2C_BUS_1 = 0,
- I2C_BUS_2,
-};
-
#ifndef CFG_IMMRBAR
#error CFG_IMMRBAR is not defined in /include/configs/${BOARD}.h
#endif
@@ -96,9 +90,9 @@ enum I2C_BUS_NUM
#define I2C_1 ((i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET))
/* Optional support for second I2C bus */
-#ifdef CFG_I2C2_OFFSET
+#ifdef CFG_I2C2_OFFSET
#define I2C_2 ((i2c_t*)(CFG_IMMRBAR + CFG_I2C2_OFFSET))
-#endif /* CFG_I2C2_OFFSET */
+#endif /* CFG_I2C2_OFFSET */
#define I2C_READ 1
#define I2C_WRITE 0
diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h
index 20f3c6d..2fbc736 100644
--- a/include/configs/MPC8349ITX.h
+++ b/include/configs/MPC8349ITX.h
@@ -81,7 +81,7 @@
#define CONFIG_I2C_CMD_TREE
#define CFG_I2C_OFFSET 0x3000
#define CFG_I2C2_OFFSET 0x3100
-#define CFG_SPD_BUS_NUM I2C_2
+#define CFG_SPD_BUS_NUM 2
#define CFG_I2C_8574_ADDR1 0x20 /* I2C2, PCF8574 */
#define CFG_I2C_8574_ADDR2 0x21 /* I2C2, PCF8574 */
diff --git a/include/configs/TQM834x.h b/include/configs/TQM834x.h
index f0e4900..727094b 100644
--- a/include/configs/TQM834x.h
+++ b/include/configs/TQM834x.h
@@ -36,8 +36,8 @@
*/
#define CONFIG_E300 1 /* E300 Family */
#define CONFIG_MPC83XX 1 /* MPC83XX family */
-#define CONFIG_MPC8349 1 /* MPC8349 specific */
#define CONFIG_MPC834X 1 /* MPC834X specific */
+#define CONFIG_MPC8349 1 /* MPC8349 specific */
#define CONFIG_TQM834X 1 /* TQM834X board specific */
/* IMMR Base Addres Register, use Freescale default: 0xff400000 */
diff --git a/include/i2c.h b/include/i2c.h
index 97e0061..a8f729a 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -97,7 +97,7 @@ void i2c_reg_write(uchar chip, uchar reg, uchar val);
* Returns: 0 on success, not 0 on failure
*
*/
-int i2c_set_bus_num(uchar bus);
+int i2c_set_bus_num(unsigned int bus);
/*
* i2c_get_bus_num:
@@ -105,7 +105,7 @@ int i2c_set_bus_num(uchar bus);
* Returns index of currently active I2C bus. Zero-based.
*/
-uchar i2c_get_bus_num(void);
+unsigned int i2c_get_bus_num(void);
/*
* i2c_set_bus_speed:
@@ -117,7 +117,7 @@ uchar i2c_get_bus_num(void);
* Returns: 0 on success, not 0 on failure
*
*/
-int i2c_set_bus_speed(int);
+int i2c_set_bus_speed(unsigned int);
/*
* i2c_get_bus_speed:
@@ -125,6 +125,6 @@ int i2c_set_bus_speed(int);
* Returns speed of currently active I2C bus in Hz
*/
-int i2c_get_bus_speed(void);
+unsigned int i2c_get_bus_speed(void);
#endif /* _I2C_H_ */