1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <common.h>
29#include <asm/ppc4xx.h>
30#include <asm/ppc4xx-i2c.h>
31#include <i2c.h>
32#include <command.h>
33#include "ppc440gx_i2c.h"
34#include <asm/io.h>
35
36#ifdef CONFIG_I2C_BUS1
37
38#define IIC_OK 0
39#define IIC_NOK 1
40#define IIC_NOK_LA 2
41#define IIC_NOK_ICT 3
42#define IIC_NOK_XFRA 4
43#define IIC_NOK_DATA 5
44#define IIC_NOK_TOUT 6
45
46#define IIC_TIMEOUT 1
47#if defined(CONFIG_SYS_I2C_NOPROBES)
48static uchar i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES;
49#endif
50
51static struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_REGISTERS_BUS1_BASE_ADDRESS;
52
53static void _i2c_bus1_reset (void)
54{
55 int i, status;
56
57
58
59 out_8 (IIC_STS1, 0x0A);
60
61
62 out_8 (IIC_EXTSTS1, 0x8F);
63 __asm__ volatile ("eieio");
64
65
66
67
68
69 i = 10;
70 do {
71
72 status = in_8 (IIC_STS1);
73 udelay (500);
74 i--;
75 } while ((status & IIC_STS_PT) && (i > 0));
76
77 status = in_8 (IIC_XTCNTLSS1);
78 out_8 (IIC_XTCNTLSS1, (status | IIC_XTCNTLSS_SRST));
79 __asm__ volatile ("eieio");
80
81
82 out_8 (IIC_DIRECTCNTL1, 0xC);
83 for (i = 0; i < 10; i++) {
84 if ((in_8 (IIC_DIRECTCNTL1) & 0x3) != 0x3) {
85
86 out_8 (IIC_DIRECTCNTL1, 0x8);
87 udelay (100);
88 out_8 (IIC_DIRECTCNTL1, 0xC);
89 udelay (100);
90 } else {
91 break;
92 }
93 }
94
95 out_8 (IIC_DIRECTCNTL1, 0x4);
96 udelay (1000);
97
98 out_8 (IIC_DIRECTCNTL1, 0xC);
99 udelay (1000);
100
101 out_8 (IIC_XTCNTLSS1, (status & ~IIC_XTCNTLSS_SRST));
102 udelay (1000);
103}
104
105void i2c1_init (int speed, int slaveadd)
106{
107 sys_info_t sysInfo;
108 unsigned long freqOPB;
109 int val, divisor;
110
111#ifdef CONFIG_SYS_I2C_INIT_BOARD
112
113
114
115 i2c_init_board();
116#endif
117
118
119
120 _i2c_bus1_reset ();
121
122
123 out_8 (IIC_LMADR1, 0);
124
125
126 out_8 (IIC_HMADR1, 0);
127
128
129 out_8 (IIC_LSADR1, 0);
130
131
132 out_8 (IIC_HSADR1, 0);
133
134
135
136 get_sys_info (&sysInfo);
137 freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv;
138
139 divisor = (freqOPB - 1) / 10000000;
140 if (divisor == 0)
141 divisor = 1;
142 out_8 (IIC_CLKDIV1, divisor);
143
144
145 out_8 (IIC_INTRMSK1, 0);
146
147
148 out_8 (IIC_XFRCNT1, 0);
149
150
151
152 out_8 (IIC_XTCNTLSS1, 0xF0);
153
154
155
156 out_8 (IIC_MDCNTL1, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
157 __asm__ volatile ("eieio");
158
159
160 val = in_8(IIC_MDCNTL1);
161 __asm__ volatile ("eieio");
162
163
164
165
166
167
168
169 val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL;
170 if( speed >= 400000 ){
171 val |= IIC_MDCNTL_FSM;
172 }
173 out_8 (IIC_MDCNTL1, val);
174
175
176 out_8 (IIC_CNTL1, 0x00);
177 __asm__ volatile ("eieio");
178
179}
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206static
207int i2c_transfer1(unsigned char cmd_type,
208 unsigned char chip,
209 unsigned char addr[],
210 unsigned char addr_len,
211 unsigned char data[],
212 unsigned short data_len )
213{
214 unsigned char* ptr;
215 int reading;
216 int tran,cnt;
217 int result;
218 int status;
219 int i;
220 uchar creg;
221
222 if( data == 0 || data_len == 0 ){
223
224 printf( "i2c_transfer: bad call\n" );
225 return IIC_NOK;
226 }
227 if( addr && addr_len ){
228 ptr = addr;
229 cnt = addr_len;
230 reading = 0;
231 }else{
232 ptr = data;
233 cnt = data_len;
234 reading = cmd_type;
235 }
236
237
238 out_8(IIC_STS1,IIC_STS_SCMP);
239
240 i=10;
241 do {
242
243 status = in_8(IIC_STS1);
244 __asm__ volatile("eieio");
245 i--;
246 } while ((status & IIC_STS_PT) && (i>0));
247
248 if (status & IIC_STS_PT) {
249 result = IIC_NOK_TOUT;
250 return(result);
251 }
252
253 out_8(IIC_MDCNTL1, ((in_8(IIC_MDCNTL1))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
254
255
256
257 out_8(IIC_HMADR1,0);
258 out_8(IIC_LMADR1, chip);
259 __asm__ volatile("eieio");
260
261 tran = 0;
262 result = IIC_OK;
263 creg = 0;
264
265 while ( tran != cnt && (result == IIC_OK)) {
266 int bc,j;
267
268
269
270
271
272 creg |= IIC_CNTL_PT;
273
274 bc = (cnt - tran) > 4 ? 4 :
275 cnt - tran;
276 creg |= (bc-1)<<4;
277
278 if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) )
279 creg |= IIC_CNTL_CHT;
280
281 if (reading)
282 creg |= IIC_CNTL_READ;
283 else {
284 for(j=0; j<bc; j++) {
285
286 out_8(IIC_MDBUF1,ptr[tran+j]);
287 __asm__ volatile("eieio");
288 }
289 }
290 out_8(IIC_CNTL1, creg );
291 __asm__ volatile("eieio");
292
293
294
295
296
297
298
299
300 i=2*5*8;
301 do {
302
303 status = in_8(IIC_STS1);
304 __asm__ volatile("eieio");
305 udelay (10);
306 i--;
307 } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)
308 && (i>0));
309
310 if (status & IIC_STS_ERR) {
311 result = IIC_NOK;
312 status = in_8 (IIC_EXTSTS1);
313
314 if (status & IIC_EXTSTS_LA)
315 result = IIC_NOK_LA;
316
317 if (status & IIC_EXTSTS_ICT)
318 result = IIC_NOK_ICT;
319
320 if (status & IIC_EXTSTS_XFRA)
321 result = IIC_NOK_XFRA;
322 } else if ( status & IIC_STS_PT) {
323 result = IIC_NOK_TOUT;
324 }
325
326 if ((reading) && (result == IIC_OK)) {
327
328 if (status & IIC_STS_MDBS) {
329
330
331
332
333
334
335 udelay (1);
336 for(j=0;j<bc;j++) {
337 ptr[tran+j] = in_8(IIC_MDBUF1);
338 __asm__ volatile("eieio");
339 }
340 } else
341 result = IIC_NOK_DATA;
342 }
343 creg = 0;
344 tran+=bc;
345 if( ptr == addr && tran == cnt ) {
346 ptr = data;
347 cnt = data_len;
348 tran = 0;
349 reading = cmd_type;
350 if( reading )
351 creg = IIC_CNTL_RPST;
352 }
353 }
354 return (result);
355}
356
357int i2c_probe1 (uchar chip)
358{
359 uchar buf[1];
360
361 buf[0] = 0;
362
363
364
365
366
367
368 return(i2c_transfer1 (1, chip << 1, 0,0, buf, 1) != 0);
369}
370
371
372int i2c_read1 (uchar chip, uint addr, int alen, uchar * buffer, int len)
373{
374 uchar xaddr[4];
375 int ret;
376
377 if ( alen > 4 ) {
378 printf ("I2C read: addr len %d not supported\n", alen);
379 return 1;
380 }
381
382 if ( alen > 0 ) {
383 xaddr[0] = (addr >> 24) & 0xFF;
384 xaddr[1] = (addr >> 16) & 0xFF;
385 xaddr[2] = (addr >> 8) & 0xFF;
386 xaddr[3] = addr & 0xFF;
387 }
388
389
390#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
391
392
393
394
395
396
397
398
399
400
401
402 if( alen > 0 )
403 chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
404#endif
405 if( (ret = i2c_transfer1( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
406 printf( "I2c read: failed %d\n", ret);
407 return 1;
408 }
409 return 0;
410}
411
412int i2c_write1 (uchar chip, uint addr, int alen, uchar * buffer, int len)
413{
414 uchar xaddr[4];
415
416 if ( alen > 4 ) {
417 printf ("I2C write: addr len %d not supported\n", alen);
418 return 1;
419
420 }
421 if ( alen > 0 ) {
422 xaddr[0] = (addr >> 24) & 0xFF;
423 xaddr[1] = (addr >> 16) & 0xFF;
424 xaddr[2] = (addr >> 8) & 0xFF;
425 xaddr[3] = addr & 0xFF;
426 }
427
428#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
429
430
431
432
433
434
435
436
437
438
439
440 if( alen > 0 )
441 chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
442#endif
443
444 return (i2c_transfer1( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
445}
446
447
448
449
450uchar i2c_reg_read1(uchar i2c_addr, uchar reg)
451{
452 uchar buf;
453
454 i2c_read1(i2c_addr, reg, 1, &buf, (uchar)1);
455
456 return(buf);
457}
458
459
460
461
462void i2c_reg_write1(uchar i2c_addr, uchar reg, uchar val)
463{
464 i2c_write1(i2c_addr, reg, 1, &val, 1);
465}
466
467
468int do_i2c1_probe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
469{
470 int j;
471#if defined(CONFIG_SYS_I2C_NOPROBES)
472 int k, skip;
473#endif
474
475 puts ("Valid chip addresses:");
476 for(j = 0; j < 128; j++) {
477#if defined(CONFIG_SYS_I2C_NOPROBES)
478 skip = 0;
479 for (k = 0; k < sizeof(i2c_no_probes); k++){
480 if (j == i2c_no_probes[k]){
481 skip = 1;
482 break;
483 }
484 }
485 if (skip)
486 continue;
487#endif
488 if(i2c_probe1(j) == 0) {
489 printf(" %02X", j);
490 }
491 }
492 putc ('\n');
493
494#if defined(CONFIG_SYS_I2C_NOPROBES)
495 puts ("Excluded chip addresses:");
496 for( k = 0; k < sizeof(i2c_no_probes); k++ )
497 printf(" %02X", i2c_no_probes[k] );
498 putc ('\n');
499#endif
500
501 return 0;
502}
503
504U_BOOT_CMD(
505 iprobe1, 1, 1, do_i2c1_probe,
506 "probe to discover valid I2C chip addresses",
507 ""
508);
509
510#endif
511