]>
Commit | Line | Data |
---|---|---|
81a8824f WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | /* | |
25 | * I2C Functions similar to the standard memory functions. | |
26 | * | |
27 | * There are several parameters in many of the commands that bear further | |
28 | * explanations: | |
29 | * | |
30 | * Two of the commands (imm and imw) take a byte/word/long modifier | |
31 | * (e.g. imm.w specifies the word-length modifier). This was done to | |
32 | * allow manipulating word-length registers. It was not done on any other | |
33 | * commands because it was not deemed useful. | |
34 | * | |
35 | * {i2c_chip} is the I2C chip address (the first byte sent on the bus). | |
36 | * Each I2C chip on the bus has a unique address. On the I2C data bus, | |
37 | * the address is the upper seven bits and the LSB is the "read/write" | |
38 | * bit. Note that the {i2c_chip} address specified on the command | |
39 | * line is not shifted up: e.g. a typical EEPROM memory chip may have | |
40 | * an I2C address of 0x50, but the data put on the bus will be 0xA0 | |
41 | * for write and 0xA1 for read. This "non shifted" address notation | |
42 | * matches at least half of the data sheets :-/. | |
43 | * | |
44 | * {addr} is the address (or offset) within the chip. Small memory | |
45 | * chips have 8 bit addresses. Large memory chips have 16 bit | |
46 | * addresses. Other memory chips have 9, 10, or 11 bit addresses. | |
47 | * Many non-memory chips have multiple registers and {addr} is used | |
48 | * as the register index. Some non-memory chips have only one register | |
49 | * and therefore don't need any {addr} parameter. | |
50 | * | |
51 | * The default {addr} parameter is one byte (.1) which works well for | |
52 | * memories and registers with 8 bits of address space. | |
53 | * | |
54 | * You can specify the length of the {addr} field with the optional .0, | |
55 | * .1, or .2 modifier (similar to the .b, .w, .l modifier). If you are | |
56 | * manipulating a single register device which doesn't use an address | |
57 | * field, use "0.0" for the address and the ".0" length field will | |
58 | * suppress the address in the I2C data stream. This also works for | |
59 | * successive reads using the I2C auto-incrementing memory pointer. | |
60 | * | |
61 | * If you are manipulating a large memory with 2-byte addresses, use | |
62 | * the .2 address modifier, e.g. 210.2 addresses location 528 (decimal). | |
63 | * | |
64 | * Then there are the unfortunate memory chips that spill the most | |
65 | * significant 1, 2, or 3 bits of address into the chip address byte. | |
66 | * This effectively makes one chip (logically) look like 2, 4, or | |
67 | * 8 chips. This is handled (awkwardly) by #defining | |
68 | * CFG_I2C_EEPROM_ADDR_OVERFLOW and using the .1 modifier on the | |
69 | * {addr} field (since .1 is the default, it doesn't actually have to | |
70 | * be specified). Examples: given a memory chip at I2C chip address | |
71 | * 0x50, the following would happen... | |
72 | * imd 50 0 10 display 16 bytes starting at 0x000 | |
73 | * On the bus: <S> A0 00 <E> <S> A1 <rd> ... <rd> | |
74 | * imd 50 100 10 display 16 bytes starting at 0x100 | |
75 | * On the bus: <S> A2 00 <E> <S> A3 <rd> ... <rd> | |
76 | * imd 50 210 10 display 16 bytes starting at 0x210 | |
77 | * On the bus: <S> A4 10 <E> <S> A5 <rd> ... <rd> | |
78 | * This is awfully ugly. It would be nice if someone would think up | |
79 | * a better way of handling this. | |
80 | * | |
81 | * Adapted from cmd_mem.c which is copyright Wolfgang Denk (wd@denx.de). | |
82 | */ | |
83 | ||
84 | #include <common.h> | |
85 | #include <command.h> | |
81a8824f WD |
86 | #include <i2c.h> |
87 | #include <asm/byteorder.h> | |
88 | ||
89 | #if (CONFIG_COMMANDS & CFG_CMD_I2C) | |
90 | ||
91 | ||
92 | /* Display values from last command. | |
93 | * Memory modify remembered values are different from display memory. | |
94 | */ | |
95 | static uchar i2c_dp_last_chip; | |
96 | static uint i2c_dp_last_addr; | |
97 | static uint i2c_dp_last_alen; | |
98 | static uint i2c_dp_last_length = 0x10; | |
99 | ||
100 | static uchar i2c_mm_last_chip; | |
101 | static uint i2c_mm_last_addr; | |
102 | static uint i2c_mm_last_alen; | |
103 | ||
104 | #if defined(CFG_I2C_NOPROBES) | |
105 | static uchar i2c_no_probes[] = CFG_I2C_NOPROBES; | |
106 | #endif | |
107 | ||
108 | static int | |
109 | mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]); | |
110 | extern int cmd_get_data_size(char* arg, int default_size); | |
111 | ||
112 | /* | |
113 | * Syntax: | |
114 | * imd {i2c_chip} {addr}{.0, .1, .2} {len} | |
115 | */ | |
116 | #define DISP_LINE_LEN 16 | |
117 | ||
118 | int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
119 | { | |
120 | u_char chip; | |
121 | uint addr, alen, length; | |
122 | int j, nbytes, linebytes; | |
123 | ||
124 | /* We use the last specified parameters, unless new ones are | |
125 | * entered. | |
126 | */ | |
127 | chip = i2c_dp_last_chip; | |
128 | addr = i2c_dp_last_addr; | |
129 | alen = i2c_dp_last_alen; | |
130 | length = i2c_dp_last_length; | |
131 | ||
132 | if (argc < 3) { | |
133 | printf ("Usage:\n%s\n", cmdtp->usage); | |
134 | return 1; | |
135 | } | |
136 | ||
137 | if ((flag & CMD_FLAG_REPEAT) == 0) { | |
138 | /* | |
139 | * New command specified. | |
140 | */ | |
141 | alen = 1; | |
142 | ||
143 | /* | |
144 | * I2C chip address | |
145 | */ | |
146 | chip = simple_strtoul(argv[1], NULL, 16); | |
147 | ||
148 | /* | |
149 | * I2C data address within the chip. This can be 1 or | |
150 | * 2 bytes long. Some day it might be 3 bytes long :-). | |
151 | */ | |
152 | addr = simple_strtoul(argv[2], NULL, 16); | |
153 | alen = 1; | |
154 | for(j = 0; j < 8; j++) { | |
155 | if (argv[2][j] == '.') { | |
156 | alen = argv[2][j+1] - '0'; | |
157 | if (alen > 4) { | |
158 | printf ("Usage:\n%s\n", cmdtp->usage); | |
159 | return 1; | |
160 | } | |
161 | break; | |
162 | } else if (argv[2][j] == '\0') { | |
163 | break; | |
164 | } | |
165 | } | |
166 | ||
167 | /* | |
168 | * If another parameter, it is the length to display. | |
169 | * Length is the number of objects, not number of bytes. | |
170 | */ | |
171 | if (argc > 3) | |
172 | length = simple_strtoul(argv[3], NULL, 16); | |
173 | } | |
174 | ||
175 | /* | |
176 | * Print the lines. | |
177 | * | |
178 | * We buffer all read data, so we can make sure data is read only | |
179 | * once. | |
180 | */ | |
181 | nbytes = length; | |
182 | do { | |
183 | unsigned char linebuf[DISP_LINE_LEN]; | |
184 | unsigned char *cp; | |
185 | ||
186 | linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; | |
187 | ||
188 | if(i2c_read(chip, addr, alen, linebuf, linebytes) != 0) { | |
189 | printf("Error reading the chip.\n"); | |
190 | } else { | |
191 | printf("%04x:", addr); | |
192 | cp = linebuf; | |
193 | for (j=0; j<linebytes; j++) { | |
194 | printf(" %02x", *cp++); | |
195 | addr++; | |
196 | } | |
197 | printf(" "); | |
198 | cp = linebuf; | |
199 | for (j=0; j<linebytes; j++) { | |
200 | if ((*cp < 0x20) || (*cp > 0x7e)) | |
201 | printf("."); | |
202 | else | |
203 | printf("%c", *cp); | |
204 | cp++; | |
205 | } | |
206 | printf("\n"); | |
207 | } | |
208 | nbytes -= linebytes; | |
209 | } while (nbytes > 0); | |
210 | ||
211 | i2c_dp_last_chip = chip; | |
212 | i2c_dp_last_addr = addr; | |
213 | i2c_dp_last_alen = alen; | |
214 | i2c_dp_last_length = length; | |
215 | ||
216 | return 0; | |
217 | } | |
218 | ||
219 | int do_i2c_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
220 | { | |
221 | return mod_i2c_mem (cmdtp, 1, flag, argc, argv); | |
222 | } | |
223 | ||
224 | ||
225 | int do_i2c_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
226 | { | |
227 | return mod_i2c_mem (cmdtp, 0, flag, argc, argv); | |
228 | } | |
229 | ||
230 | /* Write (fill) memory | |
231 | * | |
232 | * Syntax: | |
233 | * imw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}] | |
234 | */ | |
235 | int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
236 | { | |
237 | uchar chip; | |
238 | ulong addr; | |
239 | uint alen; | |
240 | uchar byte; | |
241 | int count; | |
242 | int j; | |
243 | ||
244 | if ((argc < 4) || (argc > 5)) { | |
245 | printf ("Usage:\n%s\n", cmdtp->usage); | |
246 | return 1; | |
247 | } | |
248 | ||
249 | /* | |
250 | * Chip is always specified. | |
251 | */ | |
252 | chip = simple_strtoul(argv[1], NULL, 16); | |
253 | ||
254 | /* | |
255 | * Address is always specified. | |
256 | */ | |
257 | addr = simple_strtoul(argv[2], NULL, 16); | |
258 | alen = 1; | |
259 | for(j = 0; j < 8; j++) { | |
260 | if (argv[2][j] == '.') { | |
261 | alen = argv[2][j+1] - '0'; | |
262 | if(alen > 4) { | |
263 | printf ("Usage:\n%s\n", cmdtp->usage); | |
264 | return 1; | |
265 | } | |
266 | break; | |
267 | } else if (argv[2][j] == '\0') { | |
268 | break; | |
269 | } | |
270 | } | |
271 | ||
272 | /* | |
273 | * Value to write is always specified. | |
274 | */ | |
275 | byte = simple_strtoul(argv[3], NULL, 16); | |
276 | ||
277 | /* | |
278 | * Optional count | |
279 | */ | |
280 | if(argc == 5) { | |
281 | count = simple_strtoul(argv[4], NULL, 16); | |
282 | } else { | |
283 | count = 1; | |
284 | } | |
285 | ||
286 | while (count-- > 0) { | |
287 | if(i2c_write(chip, addr++, alen, &byte, 1) != 0) { | |
288 | printf("Error writing the chip.\n"); | |
289 | } | |
290 | /* | |
291 | * Wait for the write to complete. The write can take | |
292 | * up to 10mSec (we allow a little more time). | |
293 | * | |
294 | * On some chips, while the write is in progress, the | |
295 | * chip doesn't respond. This apparently isn't a | |
296 | * universal feature so we don't take advantage of it. | |
297 | */ | |
298 | udelay(11000); | |
299 | #if 0 | |
300 | for(timeout = 0; timeout < 10; timeout++) { | |
301 | udelay(2000); | |
302 | if(i2c_probe(chip) == 0) | |
303 | break; | |
304 | } | |
305 | #endif | |
306 | } | |
307 | ||
308 | return (0); | |
309 | } | |
310 | ||
311 | ||
312 | /* Calculate a CRC on memory | |
313 | * | |
314 | * Syntax: | |
315 | * icrc32 {i2c_chip} {addr}{.0, .1, .2} {count} | |
316 | */ | |
317 | int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
318 | { | |
319 | uchar chip; | |
320 | ulong addr; | |
321 | uint alen; | |
322 | int count; | |
323 | uchar byte; | |
324 | ulong crc; | |
325 | ulong err; | |
326 | int j; | |
327 | ||
328 | if (argc < 4) { | |
329 | printf ("Usage:\n%s\n", cmdtp->usage); | |
330 | return 1; | |
331 | } | |
332 | ||
333 | /* | |
334 | * Chip is always specified. | |
335 | */ | |
336 | chip = simple_strtoul(argv[1], NULL, 16); | |
337 | ||
338 | /* | |
339 | * Address is always specified. | |
340 | */ | |
341 | addr = simple_strtoul(argv[2], NULL, 16); | |
342 | alen = 1; | |
343 | for(j = 0; j < 8; j++) { | |
344 | if (argv[2][j] == '.') { | |
345 | alen = argv[2][j+1] - '0'; | |
346 | if(alen > 4) { | |
347 | printf ("Usage:\n%s\n", cmdtp->usage); | |
348 | return 1; | |
349 | } | |
350 | break; | |
351 | } else if (argv[2][j] == '\0') { | |
352 | break; | |
353 | } | |
354 | } | |
355 | ||
356 | /* | |
357 | * Count is always specified | |
358 | */ | |
359 | count = simple_strtoul(argv[3], NULL, 16); | |
360 | ||
361 | printf ("CRC32 for %08lx ... %08lx ==> ", addr, addr + count - 1); | |
362 | /* | |
363 | * CRC a byte at a time. This is going to be slooow, but hey, the | |
364 | * memories are small and slow too so hopefully nobody notices. | |
365 | */ | |
366 | crc = 0; | |
367 | err = 0; | |
368 | while(count-- > 0) { | |
369 | if(i2c_read(chip, addr, alen, &byte, 1) != 0) { | |
370 | err++; | |
371 | } | |
372 | crc = crc32 (crc, &byte, 1); | |
373 | addr++; | |
374 | } | |
375 | if(err > 0) | |
376 | { | |
377 | printf("Error reading the chip,\n"); | |
378 | } else { | |
379 | printf ("%08lx\n", crc); | |
380 | } | |
381 | ||
382 | return 0; | |
383 | } | |
384 | ||
385 | ||
386 | /* Modify memory. | |
387 | * | |
388 | * Syntax: | |
389 | * imm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2} | |
390 | * inm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2} | |
391 | */ | |
392 | ||
393 | static int | |
394 | mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]) | |
395 | { | |
396 | uchar chip; | |
397 | ulong addr; | |
398 | uint alen; | |
399 | ulong data; | |
400 | int size = 1; | |
401 | int nbytes; | |
402 | int j; | |
403 | extern char console_buffer[]; | |
404 | ||
405 | if (argc != 3) { | |
406 | printf ("Usage:\n%s\n", cmdtp->usage); | |
407 | return 1; | |
408 | } | |
409 | ||
410 | #ifdef CONFIG_BOOT_RETRY_TIME | |
411 | reset_cmd_timeout(); /* got a good command to get here */ | |
412 | #endif | |
413 | /* | |
414 | * We use the last specified parameters, unless new ones are | |
415 | * entered. | |
416 | */ | |
417 | chip = i2c_mm_last_chip; | |
418 | addr = i2c_mm_last_addr; | |
419 | alen = i2c_mm_last_alen; | |
420 | ||
421 | if ((flag & CMD_FLAG_REPEAT) == 0) { | |
422 | /* | |
423 | * New command specified. Check for a size specification. | |
424 | * Defaults to byte if no or incorrect specification. | |
425 | */ | |
426 | size = cmd_get_data_size(argv[0], 1); | |
427 | ||
428 | /* | |
429 | * Chip is always specified. | |
430 | */ | |
431 | chip = simple_strtoul(argv[1], NULL, 16); | |
432 | ||
433 | /* | |
434 | * Address is always specified. | |
435 | */ | |
436 | addr = simple_strtoul(argv[2], NULL, 16); | |
437 | alen = 1; | |
438 | for(j = 0; j < 8; j++) { | |
439 | if (argv[2][j] == '.') { | |
440 | alen = argv[2][j+1] - '0'; | |
441 | if(alen > 4) { | |
442 | printf ("Usage:\n%s\n", cmdtp->usage); | |
443 | return 1; | |
444 | } | |
445 | break; | |
446 | } else if (argv[2][j] == '\0') { | |
447 | break; | |
448 | } | |
449 | } | |
450 | } | |
451 | ||
452 | /* | |
453 | * Print the address, followed by value. Then accept input for | |
454 | * the next value. A non-converted value exits. | |
455 | */ | |
456 | do { | |
457 | printf("%08lx:", addr); | |
458 | if(i2c_read(chip, addr, alen, (char *)&data, size) != 0) { | |
459 | printf("\nError reading the chip,\n"); | |
460 | } else { | |
461 | data = cpu_to_be32(data); | |
462 | if(size == 1) { | |
463 | printf(" %02lx", (data >> 24) & 0x000000FF); | |
464 | } else if(size == 2) { | |
465 | printf(" %04lx", (data >> 16) & 0x0000FFFF); | |
466 | } else { | |
467 | printf(" %08lx", data); | |
468 | } | |
469 | } | |
470 | ||
471 | nbytes = readline (" ? "); | |
472 | if (nbytes == 0) { | |
473 | /* | |
474 | * <CR> pressed as only input, don't modify current | |
475 | * location and move to next. | |
476 | */ | |
477 | if (incrflag) | |
478 | addr += size; | |
479 | nbytes = size; | |
480 | #ifdef CONFIG_BOOT_RETRY_TIME | |
481 | reset_cmd_timeout(); /* good enough to not time out */ | |
482 | #endif | |
483 | } | |
484 | #ifdef CONFIG_BOOT_RETRY_TIME | |
485 | else if (nbytes == -2) { | |
486 | break; /* timed out, exit the command */ | |
487 | } | |
488 | #endif | |
489 | else { | |
490 | char *endp; | |
491 | ||
492 | data = simple_strtoul(console_buffer, &endp, 16); | |
493 | if(size == 1) { | |
494 | data = data << 24; | |
495 | } else if(size == 2) { | |
496 | data = data << 16; | |
497 | } | |
498 | data = be32_to_cpu(data); | |
499 | nbytes = endp - console_buffer; | |
500 | if (nbytes) { | |
501 | #ifdef CONFIG_BOOT_RETRY_TIME | |
502 | /* | |
503 | * good enough to not time out | |
504 | */ | |
505 | reset_cmd_timeout(); | |
506 | #endif | |
507 | if(i2c_write(chip, addr, alen, (char *)&data, size) != 0) { | |
508 | printf("Error writing the chip.\n"); | |
509 | } | |
510 | if (incrflag) | |
511 | addr += size; | |
512 | } | |
513 | } | |
514 | } while (nbytes); | |
515 | ||
516 | chip = i2c_mm_last_chip; | |
517 | addr = i2c_mm_last_addr; | |
518 | alen = i2c_mm_last_alen; | |
519 | ||
520 | return 0; | |
521 | } | |
522 | ||
523 | /* | |
524 | * Syntax: | |
525 | * iprobe {addr}{.0, .1, .2} | |
526 | */ | |
527 | int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
528 | { | |
529 | int j; | |
530 | #if defined(CFG_I2C_NOPROBES) | |
531 | int k, skip; | |
532 | #endif | |
533 | ||
534 | printf("Valid chip addresses:"); | |
535 | for(j = 0; j < 128; j++) { | |
536 | #if defined(CFG_I2C_NOPROBES) | |
537 | skip = 0; | |
538 | for (k = 0; k < sizeof(i2c_no_probes); k++){ | |
539 | if (j == i2c_no_probes[k]){ | |
540 | skip = 1; | |
541 | break; | |
542 | } | |
543 | } | |
544 | if (skip) | |
545 | continue; | |
546 | #endif | |
547 | if(i2c_probe(j) == 0) { | |
548 | printf(" %02X", j); | |
549 | } | |
550 | } | |
551 | printf("\n"); | |
552 | ||
553 | #if defined(CFG_I2C_NOPROBES) | |
554 | puts ("Excluded chip addresses:"); | |
555 | for( k = 0; k < sizeof(i2c_no_probes); k++ ) | |
556 | printf(" %02X", i2c_no_probes[k] ); | |
557 | puts ("\n"); | |
558 | #endif | |
559 | ||
560 | return 0; | |
561 | } | |
562 | ||
563 | ||
564 | /* | |
565 | * Syntax: | |
566 | * iloop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}] | |
567 | * {length} - Number of bytes to read | |
568 | * {delay} - A DECIMAL number and defaults to 1000 uSec | |
569 | */ | |
570 | int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
571 | { | |
572 | u_char chip; | |
573 | ulong alen; | |
574 | uint addr; | |
575 | uint length; | |
576 | u_char bytes[16]; | |
577 | int delay; | |
578 | int j; | |
579 | ||
580 | if (argc < 3) { | |
581 | printf ("Usage:\n%s\n", cmdtp->usage); | |
582 | return 1; | |
583 | } | |
584 | ||
585 | /* | |
586 | * Chip is always specified. | |
587 | */ | |
588 | chip = simple_strtoul(argv[1], NULL, 16); | |
589 | ||
590 | /* | |
591 | * Address is always specified. | |
592 | */ | |
593 | addr = simple_strtoul(argv[2], NULL, 16); | |
594 | alen = 1; | |
595 | for(j = 0; j < 8; j++) { | |
596 | if (argv[2][j] == '.') { | |
597 | alen = argv[2][j+1] - '0'; | |
598 | if (alen > 4) { | |
599 | printf ("Usage:\n%s\n", cmdtp->usage); | |
600 | return 1; | |
601 | } | |
602 | break; | |
603 | } else if (argv[2][j] == '\0') { | |
604 | break; | |
605 | } | |
606 | } | |
607 | ||
608 | /* | |
609 | * Length is the number of objects, not number of bytes. | |
610 | */ | |
611 | length = 1; | |
612 | length = simple_strtoul(argv[3], NULL, 16); | |
613 | if(length > sizeof(bytes)) { | |
614 | length = sizeof(bytes); | |
615 | } | |
616 | ||
617 | /* | |
618 | * The delay time (uSec) is optional. | |
619 | */ | |
620 | delay = 1000; | |
621 | if (argc > 3) { | |
622 | delay = simple_strtoul(argv[4], NULL, 10); | |
623 | } | |
624 | /* | |
625 | * Run the loop... | |
626 | */ | |
627 | while(1) { | |
628 | if(i2c_read(chip, addr, alen, bytes, length) != 0) { | |
629 | printf("Error reading the chip.\n"); | |
630 | } | |
631 | udelay(delay); | |
632 | } | |
633 | ||
634 | /* NOTREACHED */ | |
635 | return 0; | |
636 | } | |
637 | ||
638 | ||
639 | /* | |
640 | * The SDRAM command is separately configured because many | |
641 | * (most?) embedded boards don't use SDRAM DIMMs. | |
642 | */ | |
643 | #if (CONFIG_COMMANDS & CFG_CMD_SDRAM) | |
644 | ||
645 | /* | |
646 | * Syntax: | |
647 | * sdram {i2c_chip} | |
648 | */ | |
649 | int do_sdram ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
650 | { | |
651 | u_char chip; | |
652 | u_char data[128]; | |
653 | u_char cksum; | |
654 | int j; | |
655 | ||
656 | if (argc < 2) { | |
657 | printf ("Usage:\n%s\n", cmdtp->usage); | |
658 | return 1; | |
659 | } | |
660 | /* | |
661 | * Chip is always specified. | |
662 | */ | |
663 | chip = simple_strtoul(argv[1], NULL, 16); | |
664 | ||
665 | if(i2c_read(chip, 0, 1, data, sizeof(data)) != 0) { | |
666 | printf("No SDRAM Serial Presence Detect found.\n"); | |
667 | return 1; | |
668 | } | |
669 | ||
670 | cksum = 0; | |
671 | for (j = 0; j < 63; j++) { | |
672 | cksum += data[j]; | |
673 | } | |
674 | if(cksum != data[63]) { | |
675 | printf ("WARNING: Configuration data checksum failure:\n" | |
676 | " is 0x%02x, calculated 0x%02x\n", | |
677 | data[63], cksum); | |
678 | } | |
679 | printf("SPD data revision %d.%d\n", | |
680 | (data[62] >> 4) & 0x0F, data[62] & 0x0F); | |
681 | printf("Bytes used 0x%02X\n", data[0]); | |
682 | printf("Serial memory size 0x%02X\n", 1 << data[1]); | |
683 | printf("Memory type "); | |
684 | switch(data[2]) { | |
685 | case 2: printf("EDO\n"); break; | |
686 | case 4: printf("SDRAM\n"); break; | |
687 | default: printf("unknown\n"); break; | |
688 | } | |
689 | printf("Row address bits "); | |
690 | if((data[3] & 0x00F0) == 0) { | |
691 | printf("%d\n", data[3] & 0x0F); | |
692 | } else { | |
693 | printf("%d/%d\n", data[3] & 0x0F, (data[3] >> 4) & 0x0F); | |
694 | } | |
695 | printf("Column address bits "); | |
696 | if((data[4] & 0x00F0) == 0) { | |
697 | printf("%d\n", data[4] & 0x0F); | |
698 | } else { | |
699 | printf("%d/%d\n", data[4] & 0x0F, (data[4] >> 4) & 0x0F); | |
700 | } | |
701 | printf("Module rows %d\n", data[5]); | |
702 | printf("Module data width %d bits\n", (data[7] << 8) | data[6]); | |
703 | printf("Interface signal levels "); | |
704 | switch(data[8]) { | |
705 | case 0: printf("5.0v/TTL\n"); break; | |
706 | case 1: printf("LVTTL\n"); break; | |
707 | case 2: printf("HSTL 1.5\n"); break; | |
708 | case 3: printf("SSTL 3.3\n"); break; | |
709 | case 4: printf("SSTL 2.5\n"); break; | |
710 | default: printf("unknown\n"); break; | |
711 | } | |
712 | printf("SDRAM cycle time %d.%d nS\n", | |
713 | (data[9] >> 4) & 0x0F, data[9] & 0x0F); | |
714 | printf("SDRAM access time %d.%d nS\n", | |
715 | (data[10] >> 4) & 0x0F, data[10] & 0x0F); | |
716 | printf("EDC configuration "); | |
717 | switch(data[11]) { | |
718 | case 0: printf("None\n"); break; | |
719 | case 1: printf("Parity\n"); break; | |
720 | case 2: printf("ECC\n"); break; | |
721 | default: printf("unknown\n"); break; | |
722 | } | |
723 | if((data[12] & 0x80) == 0) { | |
724 | printf("No self refresh, rate "); | |
725 | } else { | |
726 | printf("Self refresh, rate "); | |
727 | } | |
728 | switch(data[12] & 0x7F) { | |
729 | case 0: printf("15.625uS\n"); break; | |
730 | case 1: printf("3.9uS\n"); break; | |
731 | case 2: printf("7.8uS\n"); break; | |
732 | case 3: printf("31.3uS\n"); break; | |
733 | case 4: printf("62.5uS\n"); break; | |
734 | case 5: printf("125uS\n"); break; | |
735 | default: printf("unknown\n"); break; | |
736 | } | |
737 | printf("SDRAM width (primary) %d\n", data[13] & 0x7F); | |
738 | if((data[13] & 0x80) != 0) { | |
739 | printf(" (second bank) %d\n", | |
740 | 2 * (data[13] & 0x7F)); | |
741 | } | |
742 | if(data[14] != 0) { | |
743 | printf("EDC width %d\n", | |
744 | data[14] & 0x7F); | |
745 | if((data[14] & 0x80) != 0) { | |
746 | printf(" (second bank) %d\n", | |
747 | 2 * (data[14] & 0x7F)); | |
748 | } | |
749 | } | |
750 | printf("Min clock delay, back-to-back random column addresses %d\n", | |
751 | data[15]); | |
752 | printf("Burst length(s) "); | |
753 | if(data[16] & 0x80) printf(" Page"); | |
754 | if(data[16] & 0x08) printf(" 8"); | |
755 | if(data[16] & 0x04) printf(" 4"); | |
756 | if(data[16] & 0x02) printf(" 2"); | |
757 | if(data[16] & 0x01) printf(" 1"); | |
758 | printf("\n"); | |
759 | printf("Number of banks %d\n", data[17]); | |
760 | printf("CAS latency(s) "); | |
761 | if(data[18] & 0x80) printf(" TBD"); | |
762 | if(data[18] & 0x40) printf(" 7"); | |
763 | if(data[18] & 0x20) printf(" 6"); | |
764 | if(data[18] & 0x10) printf(" 5"); | |
765 | if(data[18] & 0x08) printf(" 4"); | |
766 | if(data[18] & 0x04) printf(" 3"); | |
767 | if(data[18] & 0x02) printf(" 2"); | |
768 | if(data[18] & 0x01) printf(" 1"); | |
769 | printf("\n"); | |
770 | printf("CS latency(s) "); | |
771 | if(data[19] & 0x80) printf(" TBD"); | |
772 | if(data[19] & 0x40) printf(" 6"); | |
773 | if(data[19] & 0x20) printf(" 5"); | |
774 | if(data[19] & 0x10) printf(" 4"); | |
775 | if(data[19] & 0x08) printf(" 3"); | |
776 | if(data[19] & 0x04) printf(" 2"); | |
777 | if(data[19] & 0x02) printf(" 1"); | |
778 | if(data[19] & 0x01) printf(" 0"); | |
779 | printf("\n"); | |
780 | printf("WE latency(s) "); | |
781 | if(data[20] & 0x80) printf(" TBD"); | |
782 | if(data[20] & 0x40) printf(" 6"); | |
783 | if(data[20] & 0x20) printf(" 5"); | |
784 | if(data[20] & 0x10) printf(" 4"); | |
785 | if(data[20] & 0x08) printf(" 3"); | |
786 | if(data[20] & 0x04) printf(" 2"); | |
787 | if(data[20] & 0x02) printf(" 1"); | |
788 | if(data[20] & 0x01) printf(" 0"); | |
789 | printf("\n"); | |
790 | printf("Module attributes:\n"); | |
791 | if(!data[21]) printf(" (none)\n"); | |
792 | if(data[21] & 0x80) printf(" TBD (bit 7)\n"); | |
793 | if(data[21] & 0x40) printf(" Redundant row address\n"); | |
794 | if(data[21] & 0x20) printf(" Differential clock input\n"); | |
795 | if(data[21] & 0x10) printf(" Registerd DQMB inputs\n"); | |
796 | if(data[21] & 0x08) printf(" Buffered DQMB inputs\n"); | |
797 | if(data[21] & 0x04) printf(" On-card PLL\n"); | |
798 | if(data[21] & 0x02) printf(" Registered address/control lines\n"); | |
799 | if(data[21] & 0x01) printf(" Buffered address/control lines\n"); | |
800 | printf("Device attributes:\n"); | |
801 | if(data[22] & 0x80) printf(" TBD (bit 7)\n"); | |
802 | if(data[22] & 0x40) printf(" TBD (bit 6)\n"); | |
803 | if(data[22] & 0x20) printf(" Upper Vcc tolerance 5%%\n"); | |
804 | else printf(" Upper Vcc tolerance 10%%\n"); | |
805 | if(data[22] & 0x10) printf(" Lower Vcc tolerance 5%%\n"); | |
806 | else printf(" Lower Vcc tolerance 10%%\n"); | |
807 | if(data[22] & 0x08) printf(" Supports write1/read burst\n"); | |
808 | if(data[22] & 0x04) printf(" Supports precharge all\n"); | |
809 | if(data[22] & 0x02) printf(" Supports auto precharge\n"); | |
810 | if(data[22] & 0x01) printf(" Supports early RAS# precharge\n"); | |
811 | printf("SDRAM cycle time (2nd highest CAS latency) %d.%d nS\n", | |
812 | (data[23] >> 4) & 0x0F, data[23] & 0x0F); | |
813 | printf("SDRAM access from clock (2nd highest CAS latency) %d.%d nS\n", | |
814 | (data[24] >> 4) & 0x0F, data[24] & 0x0F); | |
815 | printf("SDRAM cycle time (3rd highest CAS latency) %d.%d nS\n", | |
816 | (data[25] >> 4) & 0x0F, data[25] & 0x0F); | |
817 | printf("SDRAM access from clock (3rd highest CAS latency) %d.%d nS\n", | |
818 | (data[26] >> 4) & 0x0F, data[26] & 0x0F); | |
819 | printf("Minimum row precharge %d nS\n", data[27]); | |
820 | printf("Row active to row active min %d nS\n", data[28]); | |
821 | printf("RAS to CAS delay min %d nS\n", data[29]); | |
822 | printf("Minimum RAS pulse width %d nS\n", data[30]); | |
823 | printf("Density of each row "); | |
824 | if(data[31] & 0x80) printf(" 512MByte"); | |
825 | if(data[31] & 0x40) printf(" 256MByte"); | |
826 | if(data[31] & 0x20) printf(" 128MByte"); | |
827 | if(data[31] & 0x10) printf(" 64MByte"); | |
828 | if(data[31] & 0x08) printf(" 32MByte"); | |
829 | if(data[31] & 0x04) printf(" 16MByte"); | |
830 | if(data[31] & 0x02) printf(" 8MByte"); | |
831 | if(data[31] & 0x01) printf(" 4MByte"); | |
832 | printf("\n"); | |
833 | printf("Command and Address setup %c%d.%d nS\n", | |
834 | (data[32] & 0x80) ? '-' : '+', | |
835 | (data[32] >> 4) & 0x07, data[32] & 0x0F); | |
836 | printf("Command and Address hold %c%d.%d nS\n", | |
837 | (data[33] & 0x80) ? '-' : '+', | |
838 | (data[33] >> 4) & 0x07, data[33] & 0x0F); | |
839 | printf("Data signal input setup %c%d.%d nS\n", | |
840 | (data[34] & 0x80) ? '-' : '+', | |
841 | (data[34] >> 4) & 0x07, data[34] & 0x0F); | |
842 | printf("Data signal input hold %c%d.%d nS\n", | |
843 | (data[35] & 0x80) ? '-' : '+', | |
844 | (data[35] >> 4) & 0x07, data[35] & 0x0F); | |
845 | printf("Manufacturer's JEDEC ID "); | |
846 | for(j = 64; j <= 71; j++) | |
847 | printf("%02X ", data[j]); | |
848 | printf("\n"); | |
849 | printf("Manufacturing Location %02X\n", data[72]); | |
850 | printf("Manufacturer's Part Number "); | |
851 | for(j = 73; j <= 90; j++) | |
852 | printf("%02X ", data[j]); | |
853 | printf("\n"); | |
854 | printf("Revision Code %02X %02X\n", data[91], data[92]); | |
855 | printf("Manufacturing Date %02X %02X\n", data[93], data[94]); | |
856 | printf("Assembly Serial Number "); | |
857 | for(j = 95; j <= 98; j++) | |
858 | printf("%02X ", data[j]); | |
859 | printf("\n"); | |
860 | printf("Speed rating PC%d\n", | |
861 | data[126] == 0x66 ? 66 : data[126]); | |
862 | ||
863 | return 0; | |
864 | } | |
865 | #endif /* CFG_CMD_SDRAM */ | |
866 | ||
8bde7f77 WD |
867 | |
868 | /***************************************************/ | |
869 | ||
0d498393 WD |
870 | U_BOOT_CMD( |
871 | imd, 4, 1, do_i2c_md, \ | |
8bde7f77 WD |
872 | "imd - i2c memory display\n", \ |
873 | "chip address[.0, .1, .2] [# of objects]\n - i2c memory display\n" \ | |
874 | ); | |
875 | ||
0d498393 WD |
876 | U_BOOT_CMD( |
877 | imm, 3, 1, do_i2c_mm, | |
8bde7f77 WD |
878 | "imm - i2c memory modify (auto-incrementing)\n", |
879 | "chip address[.0, .1, .2]\n" | |
880 | " - memory modify, auto increment address\n" | |
881 | ); | |
0d498393 WD |
882 | U_BOOT_CMD( |
883 | inm, 3, 1, do_i2c_nm, | |
8bde7f77 WD |
884 | "inm - memory modify (constant address)\n", |
885 | "chip address[.0, .1, .2]\n - memory modify, read and keep address\n" | |
886 | ); | |
887 | ||
0d498393 WD |
888 | U_BOOT_CMD( |
889 | imw, 5, 1, do_i2c_mw, | |
8bde7f77 WD |
890 | "imw - memory write (fill)\n", |
891 | "chip address[.0, .1, .2] value [count]\n - memory write (fill)\n" | |
892 | ); | |
893 | ||
0d498393 WD |
894 | U_BOOT_CMD( |
895 | icrc32, 5, 1, do_i2c_crc, | |
8bde7f77 WD |
896 | "icrc32 - checksum calculation\n", |
897 | "chip address[.0, .1, .2] count\n - compute CRC32 checksum\n" | |
898 | ); | |
899 | ||
0d498393 WD |
900 | U_BOOT_CMD( |
901 | iprobe, 1, 1, do_i2c_probe, | |
8bde7f77 WD |
902 | "iprobe - probe to discover valid I2C chip addresses\n", |
903 | "\n -discover valid I2C chip addresses\n" | |
904 | ); | |
905 | ||
906 | /* | |
907 | * Require full name for "iloop" because it is an infinite loop! | |
908 | */ | |
0d498393 WD |
909 | U_BOOT_CMD( |
910 | iloop, 5, 1, do_i2c_loop, | |
8bde7f77 WD |
911 | "iloop - infinite loop on address range\n", |
912 | "chip address[.0, .1, .2] [# of objects]\n" | |
913 | " - loop, reading a set of addresses\n" | |
914 | ); | |
915 | ||
916 | #if (CONFIG_COMMANDS & CFG_CMD_SDRAM) | |
0d498393 WD |
917 | U_BOOT_CMD( |
918 | isdram, 2, 1, do_sdram, | |
8bde7f77 WD |
919 | "isdram - print SDRAM configuration information\n", |
920 | "chip\n - print SDRAM configuration information\n" | |
921 | " (valid chip values 50..57)\n" | |
922 | ); | |
923 | #endif | |
81a8824f | 924 | #endif /* CFG_CMD_I2C */ |