Commit 9ca880a250870a7d55754291b5591d2b5fe89b54
Committed by
Kim Phillips
1 parent
ac4b5622ce
Exists in
master
and in
54 other branches
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>
Showing 9 changed files with 154 additions and 109 deletions Side-by-side Diff
board/mpc8349emds/pci.c
... | ... | @@ -75,11 +75,9 @@ |
75 | 75 | /* Switch temporarily to I2C bus #2 */ |
76 | 76 | orig_i2c_bus = i2c_get_bus_num(); |
77 | 77 | |
78 | - if(orig_i2c_bus != I2C_BUS_2) | |
79 | - i2c_set_bus_num(I2C_BUS_2); | |
78 | + if(orig_i2c_bus != 2) | |
79 | + i2c_set_bus_num(2); | |
80 | 80 | |
81 | - i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); | |
82 | - | |
83 | 81 | val8 = 0; |
84 | 82 | i2c_write(0x23, 0x6, 1, &val8, 1); |
85 | 83 | i2c_write(0x23, 0x7, 1, &val8, 1); |
... | ... | @@ -124,7 +122,7 @@ |
124 | 122 | printf("PCI2: 32-bit on PMC3\n"); |
125 | 123 | #endif |
126 | 124 | /* Reset to original I2C bus */ |
127 | - if(orig_i2c_bus != I2C_BUS_2) | |
125 | + if(orig_i2c_bus != 2) | |
128 | 126 | i2c_set_bus_num(orig_i2c_bus); |
129 | 127 | } |
130 | 128 |
board/mpc8349itx/mpc8349itx.c
... | ... | @@ -259,7 +259,7 @@ |
259 | 259 | puts("Board: Freescale MPC8349E-mITX"); |
260 | 260 | |
261 | 261 | #ifdef CONFIG_HARD_I2C |
262 | - i2c_set_bus_num(I2C_BUS_2); | |
262 | + i2c_set_bus_num(2); | |
263 | 263 | if (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, &i2c_data, sizeof(i2c_data)) == |
264 | 264 | 0) |
265 | 265 | printf(" %u.%u (PCF8475A)", (i2c_data & 0x02) >> 1, |
... | ... | @@ -379,7 +379,7 @@ |
379 | 379 | |
380 | 380 | u8 data[sizeof(eeprom_data)]; |
381 | 381 | |
382 | - i2c_set_bus_num(I2C_BUS_1); | |
382 | + i2c_set_bus_num(1); | |
383 | 383 | |
384 | 384 | if (i2c_read(CFG_I2C_EEPROM_ADDR, 0, 2, data, sizeof(data)) == 0) { |
385 | 385 | if (memcmp(data, eeprom_data, sizeof(data)) != 0) { |
... | ... | @@ -397,7 +397,7 @@ |
397 | 397 | #endif |
398 | 398 | |
399 | 399 | #ifdef CFG_I2C_RTC_ADDR |
400 | - i2c_set_bus_num(I2C_BUS_2); | |
400 | + i2c_set_bus_num(2); | |
401 | 401 | |
402 | 402 | if (i2c_read(CFG_I2C_RTC_ADDR, 0, 1, ds1339_data, sizeof(ds1339_data)) |
403 | 403 | == 0) { |
board/mpc8349itx/pci.c
... | ... | @@ -105,7 +105,7 @@ |
105 | 105 | udelay(2000); |
106 | 106 | |
107 | 107 | #ifdef CONFIG_HARD_I2C |
108 | - i2c_set_bus_num(I2C_BUS_2); | |
108 | + i2c_set_bus_num(2); | |
109 | 109 | /* Read the PCI_M66EN jumper setting */ |
110 | 110 | if ((i2c_read(CFG_I2C_8574_ADDR2, 0, 0, ®8, sizeof(reg8)) == 0) || |
111 | 111 | (i2c_read(CFG_I2C_8574A_ADDR2, 0, 0, ®8, sizeof(reg8)) == 0)) { |
board/mpc8360emds/pci.c
... | ... | @@ -198,9 +198,12 @@ |
198 | 198 | * Assign PIB PMC slot to desired PCI bus |
199 | 199 | */ |
200 | 200 | |
201 | - mpc83xx_i2c = (i2c_t *) (CFG_IMMRBAR + CFG_I2C2_OFFSET); | |
202 | - i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); | |
201 | + /* Switch temporarily to I2C bus #2 */ | |
202 | + orig_i2c_bus = i2c_get_bus_num(); | |
203 | 203 | |
204 | + if(orig_i2c_bus != 2) | |
205 | + i2c_set_bus_num(2); | |
206 | + | |
204 | 207 | val8 = 0; |
205 | 208 | i2c_write(0x23, 0x6, 1, &val8, 1); |
206 | 209 | i2c_write(0x23, 0x7, 1, &val8, 1); |
... | ... | @@ -226,6 +229,10 @@ |
226 | 229 | val8 = 0xef; |
227 | 230 | i2c_write(0x27, 0x3, 1, &val8, 1); |
228 | 231 | asm("eieio"); |
232 | + | |
233 | + /* Reset to original I2C bus */ | |
234 | + if(orig_i2c_bus != 2) | |
235 | + i2c_set_bus_num(orig_i2c_bus); | |
229 | 236 | |
230 | 237 | /* |
231 | 238 | * Release PCI RST Output signal |
cpu/mpc83xx/i2c.c
... | ... | @@ -47,75 +47,121 @@ |
47 | 47 | |
48 | 48 | DECLARE_GLOBAL_DATA_PTR; |
49 | 49 | |
50 | -/* Three I2C bus speeds are supported here (50kHz, 100kHz | |
51 | - * and 400kHz). It should be easy to add more. Note that | |
52 | - * the maximum bus speed for I2C bus 1 is CSB/3, while I2C | |
53 | - * bus 2 can go as high as CSB. | |
54 | - * Typical values for CSB are 266MHz and 200MHz. */ | |
55 | - | |
56 | - /* 50kH 100kHz 400kHz */ | |
57 | -static const uchar speed_map_266[][3] = | |
58 | - {{0x2e, 0x2a, 0x20}, /* base 88MHz */ | |
59 | - {0x34, 0x30, 0x28}}; /* base 266 MHz */ | |
60 | - | |
61 | -static const uchar speed_map_200[][3] = | |
62 | - {{0x2c, 0x28, 0x20}, /* base 66 MHz */ | |
63 | - {0x33, 0x2f, 0x26}}; /* base 200 MHz */ | |
64 | - | |
65 | 50 | /* Initialize the bus pointer to whatever one the SPD EEPROM is on. |
66 | 51 | * Default is bus 1. This is necessary because the DDR initialization |
67 | 52 | * runs from ROM, and we can't switch buses because we can't modify |
68 | 53 | * the i2c_dev variable. Everything gets straightened out once i2c_init |
69 | 54 | * is called from RAM. */ |
70 | 55 | |
71 | -#if defined CFG_SPD_BUS_NUM | |
72 | -static i2c_t *i2c_dev = CFG_SPD_BUS_NUM; | |
56 | +#ifndef CFG_SPD_BUS_NUM | |
57 | +#define CFG_SPD_BUS_NUM 1 | |
58 | +#endif | |
59 | + | |
60 | +static unsigned int i2c_bus_num = CFG_SPD_BUS_NUM; | |
61 | + | |
62 | +#if CFG_SPD_BUS_NUM == 1 | |
63 | +static volatile i2c_t *i2c_dev = I2C_1; | |
73 | 64 | #else |
74 | -static i2c_t *i2c_dev = I2C_1; | |
65 | +static volatile i2c_t *i2c_dev = I2C_2; | |
75 | 66 | #endif |
76 | 67 | |
77 | -static uchar busNum = I2C_BUS_1 ; | |
78 | -static int bus_speed[2] = {0, 0}; | |
68 | +static int i2c_bus_speed[2] = {0, 0}; | |
79 | 69 | |
80 | -static int set_speed(int speed) | |
70 | +/* | |
71 | + * Map the frequency divider to the FDR. This data is taken from table 17-5 | |
72 | + * of the MPC8349EA reference manual, with duplicates removed. | |
73 | + */ | |
74 | +static struct { | |
75 | + unsigned int divider; | |
76 | + u8 fdr; | |
77 | +} i2c_speed_map[] = | |
81 | 78 | { |
82 | - uchar value; | |
83 | - const uchar *spdPtr; | |
79 | + {0, 0x20}, | |
80 | + {256, 0x20}, | |
81 | + {288, 0x21}, | |
82 | + {320, 0x22}, | |
83 | + {352, 0x23}, | |
84 | + {384, 0x24}, | |
85 | + {416, 0x01}, | |
86 | + {448, 0x25}, | |
87 | + {480, 0x02}, | |
88 | + {512, 0x26}, | |
89 | + {576, 0x27}, | |
90 | + {640, 0x28}, | |
91 | + {704, 0x05}, | |
92 | + {768, 0x29}, | |
93 | + {832, 0x06}, | |
94 | + {896, 0x2A}, | |
95 | + {1024, 0x2B}, | |
96 | + {1152, 0x08}, | |
97 | + {1280, 0x2C}, | |
98 | + {1536, 0x2D}, | |
99 | + {1792, 0x2E}, | |
100 | + {1920, 0x0B}, | |
101 | + {2048, 0x2F}, | |
102 | + {2304, 0x0C}, | |
103 | + {2560, 0x30}, | |
104 | + {3072, 0x31}, | |
105 | + {3584, 0x32}, | |
106 | + {3840, 0x0F}, | |
107 | + {4096, 0x33}, | |
108 | + {4608, 0x10}, | |
109 | + {5120, 0x34}, | |
110 | + {6144, 0x35}, | |
111 | + {7168, 0x36}, | |
112 | + {7680, 0x13}, | |
113 | + {8192, 0x37}, | |
114 | + {9216, 0x14}, | |
115 | + {10240, 0x38}, | |
116 | + {12288, 0x39}, | |
117 | + {14336, 0x3A}, | |
118 | + {15360, 0x17}, | |
119 | + {16384, 0x3B}, | |
120 | + {18432, 0x18}, | |
121 | + {20480, 0x3C}, | |
122 | + {24576, 0x3D}, | |
123 | + {28672, 0x3E}, | |
124 | + {30720, 0x1B}, | |
125 | + {32768, 0x3F}, | |
126 | + {36864, 0x1C}, | |
127 | + {40960, 0x1D}, | |
128 | + {49152, 0x1E}, | |
129 | + {61440, 0x1F}, | |
130 | + {-1, 0x1F} | |
131 | +}; | |
84 | 132 | |
85 | - /* Global data contains maximum I2C bus 1 speed, which is CSB/3 */ | |
86 | - if(gd->i2c_clk == 88000000) | |
87 | - { | |
88 | - spdPtr = speed_map_266[busNum]; | |
89 | - } | |
90 | - else if(gd->i2c_clk == 66000000) | |
91 | - { | |
92 | - spdPtr = speed_map_200[busNum]; | |
93 | - } | |
94 | - else | |
95 | - { | |
96 | - printf("Max I2C bus speed %d not supported\n", gd->i2c_clk); | |
97 | - return -1; | |
98 | - } | |
133 | +#define NUM_I2C_SPEEDS (sizeof(i2c_speed_map) / sizeof(i2c_speed_map[0])) | |
99 | 134 | |
100 | - switch(speed) | |
101 | - { | |
102 | - case 50000: | |
103 | - value = *(spdPtr + 0); | |
104 | - break; | |
105 | - case 100000: | |
106 | - value = *(spdPtr + 1); | |
107 | - break; | |
108 | - case 400000: | |
109 | - value = *(spdPtr + 2); | |
110 | - break; | |
111 | - default: | |
112 | - printf("I2C bus speed %d not supported\n", speed); | |
113 | - return -2; | |
114 | - } | |
115 | - /* set clock */ | |
116 | - writeb(value, &i2c_dev->fdr); | |
117 | - bus_speed[busNum] = speed; | |
118 | - return 0; | |
135 | +static int set_speed(unsigned int speed) | |
136 | +{ | |
137 | + unsigned long i2c_clk; | |
138 | + unsigned int divider, i; | |
139 | + u8 fdr = 0x3F; | |
140 | + | |
141 | + i2c_clk = (i2c_bus_num == 2) ? gd->i2c2_clk : gd->i2c1_clk; | |
142 | + | |
143 | + divider = i2c_clk / speed; | |
144 | + | |
145 | + /* Scan i2c_speed_map[] for the closest matching divider.*/ | |
146 | + | |
147 | + for (i = 0; i < NUM_I2C_SPEEDS-1; i++) { | |
148 | + /* Locate our divider in between two entries in i2c_speed_map[] */ | |
149 | + if ((divider >= i2c_speed_map[i].divider) && | |
150 | + (divider <= i2c_speed_map[i+1].divider)) { | |
151 | + /* Which one is closer? */ | |
152 | + if ((divider - i2c_speed_map[i].divider) < (i2c_speed_map[i+1].divider - divider)) { | |
153 | + fdr = i2c_speed_map[i].fdr; | |
154 | + } else { | |
155 | + fdr = i2c_speed_map[i+1].fdr; | |
156 | + } | |
157 | + break; | |
158 | + } | |
159 | + } | |
160 | + | |
161 | + writeb(fdr, &i2c_dev->fdr); | |
162 | + i2c_bus_speed[i2c_bus_num - 1] = speed; | |
163 | + | |
164 | + return 0; | |
119 | 165 | } |
120 | 166 | |
121 | 167 | |
122 | 168 | |
123 | 169 | |
... | ... | @@ -125,16 +171,16 @@ |
125 | 171 | writeb(0x00 , &i2c_dev->cr); |
126 | 172 | |
127 | 173 | /* set clock */ |
128 | - writeb(speed, &i2c_dev->fdr); | |
174 | + set_speed(speed); | |
129 | 175 | |
130 | 176 | /* set default filter */ |
131 | - writeb(0x10,&i2c_dev->dfsrr); | |
177 | + writeb(IC2_FDR,&i2c_dev->dfsrr); | |
132 | 178 | |
133 | 179 | /* write slave address */ |
134 | 180 | writeb(slaveadd, &i2c_dev->adr); |
135 | 181 | |
136 | 182 | /* clear status register */ |
137 | - writeb(0x00, &i2c_dev->sr); | |
183 | + writeb(I2C_CR_MTX, &i2c_dev->sr); | |
138 | 184 | |
139 | 185 | /* start I2C controller */ |
140 | 186 | writeb(I2C_CR_MEN, &i2c_dev->cr); |
141 | 187 | |
... | ... | @@ -142,19 +188,19 @@ |
142 | 188 | |
143 | 189 | void i2c_init(int speed, int slaveadd) |
144 | 190 | { |
145 | - /* Set both interfaces to the same speed and slave address */ | |
146 | - /* Note: This function gets called twice - before and after | |
147 | - * relocation to RAM. The first time it's called, we are unable | |
148 | - * to change buses, so whichever one 'i2c_dev' was initialized to | |
149 | - * gets set twice. When run from RAM both buses get set properly */ | |
191 | + /* Set both interfaces to the same speed and slave address */ | |
192 | + /* Note: This function gets called twice - before and after | |
193 | + * relocation to RAM. The first time it's called, we are unable | |
194 | + * to change buses, so whichever one 'i2c_dev' was initialized to | |
195 | + * gets set twice. When run from RAM both buses get set properly */ | |
150 | 196 | |
151 | - i2c_set_bus_num(I2C_BUS_1); | |
152 | - _i2c_init(speed, slaveadd); | |
153 | -#ifdef CFG_I2C2_OFFSET | |
154 | - i2c_set_bus_num(I2C_BUS_2); | |
155 | - _i2c_init(speed, slaveadd); | |
156 | - i2c_set_bus_num(I2C_BUS_1); | |
157 | -#endif /* CFG_I2C2_OFFSET */ | |
197 | + i2c_set_bus_num(1); | |
198 | + _i2c_init(speed, slaveadd); | |
199 | +#ifdef CFG_I2C2_OFFSET | |
200 | + i2c_set_bus_num(2); | |
201 | + _i2c_init(speed, slaveadd); | |
202 | + i2c_set_bus_num(1); | |
203 | +#endif /* CFG_I2C2_OFFSET */ | |
158 | 204 | } |
159 | 205 | |
160 | 206 | static __inline__ int |
161 | 207 | |
162 | 208 | |
163 | 209 | |
164 | 210 | |
165 | 211 | |
166 | 212 | |
167 | 213 | |
168 | 214 | |
169 | 215 | |
... | ... | @@ -340,39 +386,39 @@ |
340 | 386 | i2c_write (i2c_addr, reg, 1, &val, 1); |
341 | 387 | } |
342 | 388 | |
343 | -int i2c_set_bus_num(uchar bus) | |
389 | +int i2c_set_bus_num(unsigned int bus) | |
344 | 390 | { |
345 | - if(bus == I2C_BUS_1) | |
391 | + if(bus == 1) | |
346 | 392 | { |
347 | 393 | i2c_dev = I2C_1; |
348 | 394 | } |
349 | 395 | #ifdef CFG_I2C2_OFFSET |
350 | - else if(bus == I2C_BUS_2) | |
396 | + else if(bus == 2) | |
351 | 397 | { |
352 | 398 | i2c_dev = I2C_2; |
353 | 399 | } |
354 | -#endif /* CFG_I2C2_OFFSET */ | |
400 | +#endif | |
355 | 401 | else |
356 | 402 | { |
357 | 403 | return -1; |
358 | 404 | } |
359 | - busNum = bus; | |
405 | + i2c_bus_num = bus; | |
360 | 406 | return 0; |
361 | 407 | } |
362 | 408 | |
363 | -int i2c_set_bus_speed(int speed) | |
409 | +int i2c_set_bus_speed(unsigned int speed) | |
364 | 410 | { |
365 | 411 | return set_speed(speed); |
366 | 412 | } |
367 | 413 | |
368 | -uchar i2c_get_bus_num(void) | |
414 | +unsigned int i2c_get_bus_num(void) | |
369 | 415 | { |
370 | - return busNum; | |
416 | + return i2c_bus_num; | |
371 | 417 | } |
372 | 418 | |
373 | -int i2c_get_bus_speed(void) | |
419 | +unsigned int i2c_get_bus_speed(void) | |
374 | 420 | { |
375 | - return bus_speed[busNum]; | |
421 | + return i2c_bus_speed[i2c_bus_num - 1]; | |
376 | 422 | } |
377 | 423 | #endif /* CONFIG_HARD_I2C */ |
include/asm-ppc/i2c.h
... | ... | @@ -79,12 +79,6 @@ |
79 | 79 | #endif |
80 | 80 | #define I2C_TIMEOUT (CFG_HZ/4) |
81 | 81 | |
82 | -enum I2C_BUS_NUM | |
83 | -{ | |
84 | - I2C_BUS_1 = 0, | |
85 | - I2C_BUS_2, | |
86 | -}; | |
87 | - | |
88 | 82 | #ifndef CFG_IMMRBAR |
89 | 83 | #error CFG_IMMRBAR is not defined in /include/configs/${BOARD}.h |
90 | 84 | #endif |
91 | 85 | |
... | ... | @@ -96,9 +90,9 @@ |
96 | 90 | #define I2C_1 ((i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET)) |
97 | 91 | |
98 | 92 | /* Optional support for second I2C bus */ |
99 | -#ifdef CFG_I2C2_OFFSET | |
93 | +#ifdef CFG_I2C2_OFFSET | |
100 | 94 | #define I2C_2 ((i2c_t*)(CFG_IMMRBAR + CFG_I2C2_OFFSET)) |
101 | -#endif /* CFG_I2C2_OFFSET */ | |
95 | +#endif /* CFG_I2C2_OFFSET */ | |
102 | 96 | |
103 | 97 | #define I2C_READ 1 |
104 | 98 | #define I2C_WRITE 0 |
include/configs/MPC8349ITX.h
... | ... | @@ -81,7 +81,7 @@ |
81 | 81 | #define CONFIG_I2C_CMD_TREE |
82 | 82 | #define CFG_I2C_OFFSET 0x3000 |
83 | 83 | #define CFG_I2C2_OFFSET 0x3100 |
84 | -#define CFG_SPD_BUS_NUM I2C_2 | |
84 | +#define CFG_SPD_BUS_NUM 2 | |
85 | 85 | |
86 | 86 | #define CFG_I2C_8574_ADDR1 0x20 /* I2C2, PCF8574 */ |
87 | 87 | #define CFG_I2C_8574_ADDR2 0x21 /* I2C2, PCF8574 */ |
include/configs/TQM834x.h
... | ... | @@ -36,8 +36,8 @@ |
36 | 36 | */ |
37 | 37 | #define CONFIG_E300 1 /* E300 Family */ |
38 | 38 | #define CONFIG_MPC83XX 1 /* MPC83XX family */ |
39 | -#define CONFIG_MPC8349 1 /* MPC8349 specific */ | |
40 | 39 | #define CONFIG_MPC834X 1 /* MPC834X specific */ |
40 | +#define CONFIG_MPC8349 1 /* MPC8349 specific */ | |
41 | 41 | #define CONFIG_TQM834X 1 /* TQM834X board specific */ |
42 | 42 | |
43 | 43 | /* IMMR Base Addres Register, use Freescale default: 0xff400000 */ |
include/i2c.h
... | ... | @@ -97,7 +97,7 @@ |
97 | 97 | * Returns: 0 on success, not 0 on failure |
98 | 98 | * |
99 | 99 | */ |
100 | -int i2c_set_bus_num(uchar bus); | |
100 | +int i2c_set_bus_num(unsigned int bus); | |
101 | 101 | |
102 | 102 | /* |
103 | 103 | * i2c_get_bus_num: |
... | ... | @@ -105,7 +105,7 @@ |
105 | 105 | * Returns index of currently active I2C bus. Zero-based. |
106 | 106 | */ |
107 | 107 | |
108 | -uchar i2c_get_bus_num(void); | |
108 | +unsigned int i2c_get_bus_num(void); | |
109 | 109 | |
110 | 110 | /* |
111 | 111 | * i2c_set_bus_speed: |
... | ... | @@ -117,7 +117,7 @@ |
117 | 117 | * Returns: 0 on success, not 0 on failure |
118 | 118 | * |
119 | 119 | */ |
120 | -int i2c_set_bus_speed(int); | |
120 | +int i2c_set_bus_speed(unsigned int); | |
121 | 121 | |
122 | 122 | /* |
123 | 123 | * i2c_get_bus_speed: |
... | ... | @@ -125,7 +125,7 @@ |
125 | 125 | * Returns speed of currently active I2C bus in Hz |
126 | 126 | */ |
127 | 127 | |
128 | -int i2c_get_bus_speed(void); | |
128 | +unsigned int i2c_get_bus_speed(void); | |
129 | 129 | |
130 | 130 | #endif /* _I2C_H_ */ |