Blame view

common/cmd_i2c.c 39.5 KB
81a8824f2   wdenk   Initial revision
1
  /*
3f4978c71   Heiko Schocher   i2c: common chang...
2
3
4
5
6
   * (C) Copyright 2009
   * Sergey Kubushyn, himself, ksi@koi8.net
   *
   * Changes for unified multibus/multiadapter I2C support.
   *
81a8824f2   wdenk   Initial revision
7
8
9
   * (C) Copyright 2001
   * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
10
   * SPDX-License-Identifier:	GPL-2.0+
81a8824f2   wdenk   Initial revision
11
12
13
14
15
16
17
18
   */
  
  /*
   * I2C Functions similar to the standard memory functions.
   *
   * There are several parameters in many of the commands that bear further
   * explanations:
   *
81a8824f2   wdenk   Initial revision
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
   * {i2c_chip} is the I2C chip address (the first byte sent on the bus).
   *   Each I2C chip on the bus has a unique address.  On the I2C data bus,
   *   the address is the upper seven bits and the LSB is the "read/write"
   *   bit.  Note that the {i2c_chip} address specified on the command
   *   line is not shifted up: e.g. a typical EEPROM memory chip may have
   *   an I2C address of 0x50, but the data put on the bus will be 0xA0
   *   for write and 0xA1 for read.  This "non shifted" address notation
   *   matches at least half of the data sheets :-/.
   *
   * {addr} is the address (or offset) within the chip.  Small memory
   *   chips have 8 bit addresses.  Large memory chips have 16 bit
   *   addresses.  Other memory chips have 9, 10, or 11 bit addresses.
   *   Many non-memory chips have multiple registers and {addr} is used
   *   as the register index.  Some non-memory chips have only one register
   *   and therefore don't need any {addr} parameter.
   *
   *   The default {addr} parameter is one byte (.1) which works well for
   *   memories and registers with 8 bits of address space.
   *
   *   You can specify the length of the {addr} field with the optional .0,
   *   .1, or .2 modifier (similar to the .b, .w, .l modifier).  If you are
   *   manipulating a single register device which doesn't use an address
   *   field, use "0.0" for the address and the ".0" length field will
   *   suppress the address in the I2C data stream.  This also works for
   *   successive reads using the I2C auto-incrementing memory pointer.
   *
   *   If you are manipulating a large memory with 2-byte addresses, use
   *   the .2 address modifier, e.g. 210.2 addresses location 528 (decimal).
   *
   *   Then there are the unfortunate memory chips that spill the most
   *   significant 1, 2, or 3 bits of address into the chip address byte.
   *   This effectively makes one chip (logically) look like 2, 4, or
   *   8 chips.  This is handled (awkwardly) by #defining
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
52
   *   CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW and using the .1 modifier on the
81a8824f2   wdenk   Initial revision
53
54
55
   *   {addr} field (since .1 is the default, it doesn't actually have to
   *   be specified).  Examples: given a memory chip at I2C chip address
   *   0x50, the following would happen...
0f89c54be   Peter Tyser   i2c: Update refer...
56
   *     i2c md 50 0 10   display 16 bytes starting at 0x000
81a8824f2   wdenk   Initial revision
57
   *                      On the bus: <S> A0 00 <E> <S> A1 <rd> ... <rd>
0f89c54be   Peter Tyser   i2c: Update refer...
58
   *     i2c md 50 100 10 display 16 bytes starting at 0x100
81a8824f2   wdenk   Initial revision
59
   *                      On the bus: <S> A2 00 <E> <S> A3 <rd> ... <rd>
0f89c54be   Peter Tyser   i2c: Update refer...
60
   *     i2c md 50 210 10 display 16 bytes starting at 0x210
81a8824f2   wdenk   Initial revision
61
62
63
64
65
66
67
68
69
   *                      On the bus: <S> A4 10 <E> <S> A5 <rd> ... <rd>
   *   This is awfully ugly.  It would be nice if someone would think up
   *   a better way of handling this.
   *
   * Adapted from cmd_mem.c which is copyright Wolfgang Denk (wd@denx.de).
   */
  
  #include <common.h>
  #include <command.h>
735987c5a   Tom Wai-Hong Tam   edid: Add I2C com...
70
  #include <edid.h>
67b23a322   Heiko Schocher   I2C: adding new "...
71
  #include <environment.h>
81a8824f2   wdenk   Initial revision
72
  #include <i2c.h>
67b23a322   Heiko Schocher   I2C: adding new "...
73
  #include <malloc.h>
81a8824f2   wdenk   Initial revision
74
  #include <asm/byteorder.h>
2515d8437   Marek Vasut   i2c: Use __weak i...
75
  #include <linux/compiler.h>
81a8824f2   wdenk   Initial revision
76

3f4978c71   Heiko Schocher   i2c: common chang...
77
  DECLARE_GLOBAL_DATA_PTR;
81a8824f2   wdenk   Initial revision
78
79
80
81
82
83
84
85
86
87
88
  /* Display values from last command.
   * Memory modify remembered values are different from display memory.
   */
  static uchar	i2c_dp_last_chip;
  static uint	i2c_dp_last_addr;
  static uint	i2c_dp_last_alen;
  static uint	i2c_dp_last_length = 0x10;
  
  static uchar	i2c_mm_last_chip;
  static uint	i2c_mm_last_addr;
  static uint	i2c_mm_last_alen;
bb99ad6d8   Ben Warren   Add support for m...
89
90
91
92
  /* If only one I2C bus is present, the list of devices to ignore when
   * the probe command is issued is represented by a 1D array of addresses.
   * When multiple buses are present, the list is an array of bus-address
   * pairs.  The following macros take care of this */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
93
  #if defined(CONFIG_SYS_I2C_NOPROBES)
9a2accb44   Heiko Schocher   i2c, multibus: ge...
94
  #if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS)
bb99ad6d8   Ben Warren   Add support for m...
95
96
97
98
  static struct
  {
  	uchar	bus;
  	uchar	addr;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
99
  } i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES;
bb99ad6d8   Ben Warren   Add support for m...
100
101
102
103
104
  #define GET_BUS_NUM	i2c_get_bus_num()
  #define COMPARE_BUS(b,i)	(i2c_no_probes[(i)].bus == (b))
  #define COMPARE_ADDR(a,i)	(i2c_no_probes[(i)].addr == (a))
  #define NO_PROBE_ADDR(i)	i2c_no_probes[(i)].addr
  #else		/* single bus */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
105
  static uchar i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES;
bb99ad6d8   Ben Warren   Add support for m...
106
107
108
109
  #define GET_BUS_NUM	0
  #define COMPARE_BUS(b,i)	((b) == 0)	/* Make compiler happy */
  #define COMPARE_ADDR(a,i)	(i2c_no_probes[(i)] == (a))
  #define NO_PROBE_ADDR(i)	i2c_no_probes[(i)]
3f4978c71   Heiko Schocher   i2c: common chang...
110
  #endif	/* defined(CONFIG_SYS_I2C) */
67b23a322   Heiko Schocher   I2C: adding new "...
111
  #endif
a266fe955   Frans Meulenbroeks   cmd_i2c: moved a ...
112
  #define DISP_LINE_LEN	16
06afa388b   Marek Vasut   i2c: kerneldoc: A...
113
114
115
116
117
118
119
  /**
   * i2c_init_board() - Board-specific I2C bus init
   *
   * This function is the default no-op implementation of I2C bus
   * initialization. This function can be overriden by board-specific
   * implementation if needed.
   */
2515d8437   Marek Vasut   i2c: Use __weak i...
120
121
  __weak
  void i2c_init_board(void)
c649dda53   Stefan Bigler   i2c: add i2c debl...
122
  {
c649dda53   Stefan Bigler   i2c: add i2c debl...
123
  }
c649dda53   Stefan Bigler   i2c: add i2c debl...
124

655b34a78   Peter Tyser   i2c: Create commo...
125
  /* TODO: Implement architecture-specific get/set functions */
06afa388b   Marek Vasut   i2c: kerneldoc: A...
126
127
128
129
130
131
132
133
134
135
136
137
138
  
  /**
   * i2c_get_bus_speed() - Return I2C bus speed
   *
   * This function is the default implementation of function for retrieveing
   * the current I2C bus speed in Hz.
   *
   * A driver implementing runtime switching of I2C bus speed must override
   * this function to report the speed correctly. Simple or legacy drivers
   * can use this fallback.
   *
   * Returns I2C bus speed in Hz.
   */
3f4978c71   Heiko Schocher   i2c: common chang...
139
140
141
142
143
  #if !defined(CONFIG_SYS_I2C)
  /*
   * TODO: Implement architecture-specific get/set functions
   * Should go away, if we switched completely to new multibus support
   */
2515d8437   Marek Vasut   i2c: Use __weak i...
144
145
  __weak
  unsigned int i2c_get_bus_speed(void)
655b34a78   Peter Tyser   i2c: Create commo...
146
147
148
  {
  	return CONFIG_SYS_I2C_SPEED;
  }
655b34a78   Peter Tyser   i2c: Create commo...
149

06afa388b   Marek Vasut   i2c: kerneldoc: A...
150
151
152
153
154
155
156
157
158
159
160
161
162
  /**
   * i2c_set_bus_speed() - Configure I2C bus speed
   * @speed:	Newly set speed of the I2C bus in Hz
   *
   * This function is the default implementation of function for setting
   * the I2C bus speed in Hz.
   *
   * A driver implementing runtime switching of I2C bus speed must override
   * this function to report the speed correctly. Simple or legacy drivers
   * can use this fallback.
   *
   * Returns zero on success, negative value on error.
   */
2515d8437   Marek Vasut   i2c: Use __weak i...
163
164
  __weak
  int i2c_set_bus_speed(unsigned int speed)
655b34a78   Peter Tyser   i2c: Create commo...
165
166
167
168
169
170
  {
  	if (speed != CONFIG_SYS_I2C_SPEED)
  		return -1;
  
  	return 0;
  }
3f4978c71   Heiko Schocher   i2c: common chang...
171
  #endif
655b34a78   Peter Tyser   i2c: Create commo...
172

06afa388b   Marek Vasut   i2c: kerneldoc: A...
173
174
175
176
  /**
   * get_alen() - Small parser helper function to get address length
   *
   * Returns the address length.
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
177
178
179
180
181
182
183
184
185
186
   */
  static uint get_alen(char *arg)
  {
  	int	j;
  	int	alen;
  
  	alen = 1;
  	for (j = 0; j < 8; j++) {
  		if (arg[j] == '.') {
  			alen = arg[j+1] - '0';
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
187
188
189
190
191
192
  			break;
  		} else if (arg[j] == '\0')
  			break;
  	}
  	return alen;
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
193
194
195
196
197
198
199
200
201
202
  /**
   * do_i2c_read() - Handle the "i2c read" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   *
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
203
204
205
   * Syntax:
   *	i2c read {i2c_chip} {devaddr}{.0, .1, .2} {len} {memaddr}
   */
54841ab50   Wolfgang Denk   Make sure that ar...
206
  static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
207
208
209
210
  {
  	u_char	chip;
  	uint	devaddr, alen, length;
  	u_char  *memaddr;
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
211

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
212
  	if (argc != 5)
4c12eeb8b   Simon Glass   Convert cmd_usage...
213
  		return CMD_RET_USAGE;
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
214
215
216
217
218
219
220
221
222
223
224
  
  	/*
  	 * I2C chip address
  	 */
  	chip = simple_strtoul(argv[1], NULL, 16);
  
  	/*
  	 * I2C data address within the chip.  This can be 1 or
  	 * 2 bytes long.  Some day it might be 3 bytes long :-).
  	 */
  	devaddr = simple_strtoul(argv[2], NULL, 16);
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
225
  	alen = get_alen(argv[2]);
7a92e53cd   Reinhard Meyer   CMD_I2C: make ale...
226
  	if (alen > 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
227
  		return CMD_RET_USAGE;
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  
  	/*
  	 * Length is the number of objects, not number of bytes.
  	 */
  	length = simple_strtoul(argv[3], NULL, 16);
  
  	/*
  	 * memaddr is the address where to store things in memory
  	 */
  	memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16);
  
  	if (i2c_read(chip, devaddr, alen, memaddr, length) != 0) {
  		puts ("Error reading the chip.
  ");
  		return 1;
  	}
  	return 0;
  }
ff5d2dce1   York Sun   common/i2c: Add i...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	u_char	chip;
  	uint	devaddr, alen, length;
  	u_char  *memaddr;
  
  	if (argc != 5)
  		return cmd_usage(cmdtp);
  
  	/*
  	 * memaddr is the address where to store things in memory
  	 */
  	memaddr = (u_char *)simple_strtoul(argv[1], NULL, 16);
  
  	/*
  	 * I2C chip address
  	 */
  	chip = simple_strtoul(argv[2], NULL, 16);
  
  	/*
  	 * I2C data address within the chip.  This can be 1 or
  	 * 2 bytes long.  Some day it might be 3 bytes long :-).
  	 */
  	devaddr = simple_strtoul(argv[3], NULL, 16);
  	alen = get_alen(argv[3]);
  	if (alen > 3)
  		return cmd_usage(cmdtp);
  
  	/*
  	 * Length is the number of objects, not number of bytes.
  	 */
  	length = simple_strtoul(argv[4], NULL, 16);
  
  	while (length-- > 0) {
  		if (i2c_write(chip, devaddr++, alen, memaddr++, 1) != 0) {
  			puts("Error writing to the chip.
  ");
  			return 1;
  		}
  /*
   * No write delay with FRAM devices.
   */
  #if !defined(CONFIG_SYS_I2C_FRAM)
  		udelay(11000);
  #endif
  	}
  	return 0;
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
294
295
296
297
298
299
300
301
302
303
  /**
   * do_i2c_md() - Handle the "i2c md" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   *
4a8cf3382   Frans Meulenbroeks   cmd_i2c: moved mi...
304
305
306
   * Syntax:
   *	i2c md {i2c_chip} {addr}{.0, .1, .2} {len}
   */
54841ab50   Wolfgang Denk   Make sure that ar...
307
  static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
308
309
310
311
312
313
314
315
316
317
318
319
  {
  	u_char	chip;
  	uint	addr, alen, length;
  	int	j, nbytes, linebytes;
  
  	/* We use the last specified parameters, unless new ones are
  	 * entered.
  	 */
  	chip   = i2c_dp_last_chip;
  	addr   = i2c_dp_last_addr;
  	alen   = i2c_dp_last_alen;
  	length = i2c_dp_last_length;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
320
  	if (argc < 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
321
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
322
323
324
325
326
  
  	if ((flag & CMD_FLAG_REPEAT) == 0) {
  		/*
  		 * New command specified.
  		 */
81a8824f2   wdenk   Initial revision
327
328
329
330
331
332
333
334
335
336
337
  
  		/*
  		 * I2C chip address
  		 */
  		chip = simple_strtoul(argv[1], NULL, 16);
  
  		/*
  		 * I2C data address within the chip.  This can be 1 or
  		 * 2 bytes long.  Some day it might be 3 bytes long :-).
  		 */
  		addr = simple_strtoul(argv[2], NULL, 16);
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
338
  		alen = get_alen(argv[2]);
7a92e53cd   Reinhard Meyer   CMD_I2C: make ale...
339
  		if (alen > 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
340
  			return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  
  		/*
  		 * If another parameter, it is the length to display.
  		 * Length is the number of objects, not number of bytes.
  		 */
  		if (argc > 3)
  			length = simple_strtoul(argv[3], NULL, 16);
  	}
  
  	/*
  	 * Print the lines.
  	 *
  	 * We buffer all read data, so we can make sure data is read only
  	 * once.
  	 */
  	nbytes = length;
  	do {
  		unsigned char	linebuf[DISP_LINE_LEN];
  		unsigned char	*cp;
  
  		linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
362
  		if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
4b9206ed5   wdenk   * Patches by Thom...
363
364
  			puts ("Error reading the chip.
  ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
365
  		else {
81a8824f2   wdenk   Initial revision
366
367
368
369
370
371
  			printf("%04x:", addr);
  			cp = linebuf;
  			for (j=0; j<linebytes; j++) {
  				printf(" %02x", *cp++);
  				addr++;
  			}
4b9206ed5   wdenk   * Patches by Thom...
372
  			puts ("    ");
81a8824f2   wdenk   Initial revision
373
374
375
  			cp = linebuf;
  			for (j=0; j<linebytes; j++) {
  				if ((*cp < 0x20) || (*cp > 0x7e))
4b9206ed5   wdenk   * Patches by Thom...
376
  					puts (".");
81a8824f2   wdenk   Initial revision
377
378
379
380
  				else
  					printf("%c", *cp);
  				cp++;
  			}
4b9206ed5   wdenk   * Patches by Thom...
381
382
  			putc ('
  ');
81a8824f2   wdenk   Initial revision
383
384
385
386
387
388
389
390
391
392
393
  		}
  		nbytes -= linebytes;
  	} while (nbytes > 0);
  
  	i2c_dp_last_chip   = chip;
  	i2c_dp_last_addr   = addr;
  	i2c_dp_last_alen   = alen;
  	i2c_dp_last_length = length;
  
  	return 0;
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
394
395
396
397
398
399
400
401
402
  /**
   * do_i2c_mw() - Handle the "i2c mw" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
81a8824f2   wdenk   Initial revision
403
404
   *
   * Syntax:
0f89c54be   Peter Tyser   i2c: Update refer...
405
   *	i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}]
81a8824f2   wdenk   Initial revision
406
   */
54841ab50   Wolfgang Denk   Make sure that ar...
407
  static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
408
409
410
411
412
413
  {
  	uchar	chip;
  	ulong	addr;
  	uint	alen;
  	uchar	byte;
  	int	count;
81a8824f2   wdenk   Initial revision
414

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
415
  	if ((argc < 4) || (argc > 5))
4c12eeb8b   Simon Glass   Convert cmd_usage...
416
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
417
418
  
  	/*
53677ef18   Wolfgang Denk   Big white-space c...
419
420
  	 * Chip is always specified.
  	 */
81a8824f2   wdenk   Initial revision
421
422
423
424
425
426
  	chip = simple_strtoul(argv[1], NULL, 16);
  
  	/*
  	 * Address is always specified.
  	 */
  	addr = simple_strtoul(argv[2], NULL, 16);
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
427
  	alen = get_alen(argv[2]);
7a92e53cd   Reinhard Meyer   CMD_I2C: make ale...
428
  	if (alen > 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
429
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
430
431
432
433
434
435
436
437
438
  
  	/*
  	 * Value to write is always specified.
  	 */
  	byte = simple_strtoul(argv[3], NULL, 16);
  
  	/*
  	 * Optional count
  	 */
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
439
  	if (argc == 5)
81a8824f2   wdenk   Initial revision
440
  		count = simple_strtoul(argv[4], NULL, 16);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
441
  	else
81a8824f2   wdenk   Initial revision
442
  		count = 1;
81a8824f2   wdenk   Initial revision
443
444
  
  	while (count-- > 0) {
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
445
  		if (i2c_write(chip, addr++, alen, &byte, 1) != 0)
4b9206ed5   wdenk   * Patches by Thom...
446
447
  			puts ("Error writing the chip.
  ");
81a8824f2   wdenk   Initial revision
448
449
450
  		/*
  		 * Wait for the write to complete.  The write can take
  		 * up to 10mSec (we allow a little more time).
81a8824f2   wdenk   Initial revision
451
  		 */
d4f5c7289     FRAM memory acces...
452
453
454
  /*
   * No write delay with FRAM devices.
   */
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
455
  #if !defined(CONFIG_SYS_I2C_FRAM)
81a8824f2   wdenk   Initial revision
456
  		udelay(11000);
d4f5c7289     FRAM memory acces...
457
  #endif
81a8824f2   wdenk   Initial revision
458
  	}
06afa388b   Marek Vasut   i2c: kerneldoc: A...
459
  	return 0;
81a8824f2   wdenk   Initial revision
460
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
461
462
463
464
465
466
467
468
469
470
471
  /**
   * do_i2c_crc() - Handle the "i2c crc32" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Calculate a CRC on memory
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
81a8824f2   wdenk   Initial revision
472
473
   *
   * Syntax:
0f89c54be   Peter Tyser   i2c: Update refer...
474
   *	i2c crc32 {i2c_chip} {addr}{.0, .1, .2} {count}
81a8824f2   wdenk   Initial revision
475
   */
54841ab50   Wolfgang Denk   Make sure that ar...
476
  static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
477
478
479
480
481
482
483
484
  {
  	uchar	chip;
  	ulong	addr;
  	uint	alen;
  	int	count;
  	uchar	byte;
  	ulong	crc;
  	ulong	err;
81a8824f2   wdenk   Initial revision
485

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
486
  	if (argc < 4)
4c12eeb8b   Simon Glass   Convert cmd_usage...
487
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
488
489
  
  	/*
53677ef18   Wolfgang Denk   Big white-space c...
490
491
  	 * Chip is always specified.
  	 */
81a8824f2   wdenk   Initial revision
492
493
494
495
496
497
  	chip = simple_strtoul(argv[1], NULL, 16);
  
  	/*
  	 * Address is always specified.
  	 */
  	addr = simple_strtoul(argv[2], NULL, 16);
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
498
  	alen = get_alen(argv[2]);
7a92e53cd   Reinhard Meyer   CMD_I2C: make ale...
499
  	if (alen > 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
500
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
501
502
503
504
505
506
507
508
509
510
511
512
513
  
  	/*
  	 * Count is always specified
  	 */
  	count = simple_strtoul(argv[3], NULL, 16);
  
  	printf ("CRC32 for %08lx ... %08lx ==> ", addr, addr + count - 1);
  	/*
  	 * CRC a byte at a time.  This is going to be slooow, but hey, the
  	 * memories are small and slow too so hopefully nobody notices.
  	 */
  	crc = 0;
  	err = 0;
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
514
515
  	while (count-- > 0) {
  		if (i2c_read(chip, addr, alen, &byte, 1) != 0)
81a8824f2   wdenk   Initial revision
516
  			err++;
81a8824f2   wdenk   Initial revision
517
518
519
  		crc = crc32 (crc, &byte, 1);
  		addr++;
  	}
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
520
  	if (err > 0)
4b9206ed5   wdenk   * Patches by Thom...
521
522
  		puts ("Error reading the chip,
  ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
523
  	else
81a8824f2   wdenk   Initial revision
524
525
  		printf ("%08lx
  ", crc);
81a8824f2   wdenk   Initial revision
526
527
528
  
  	return 0;
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
529
530
531
532
533
534
535
536
537
538
539
  /**
   * mod_i2c_mem() - Handle the "i2c mm" and "i2c nm" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Modify memory.
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
81a8824f2   wdenk   Initial revision
540
541
   *
   * Syntax:
0f89c54be   Peter Tyser   i2c: Update refer...
542
543
   *	i2c mm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
   *	i2c nm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
81a8824f2   wdenk   Initial revision
544
   */
81a8824f2   wdenk   Initial revision
545
  static int
54841ab50   Wolfgang Denk   Make sure that ar...
546
  mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
547
548
549
550
551
552
553
  {
  	uchar	chip;
  	ulong	addr;
  	uint	alen;
  	ulong	data;
  	int	size = 1;
  	int	nbytes;
81a8824f2   wdenk   Initial revision
554

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
555
  	if (argc != 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
556
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  
  #ifdef CONFIG_BOOT_RETRY_TIME
  	reset_cmd_timeout();	/* got a good command to get here */
  #endif
  	/*
  	 * We use the last specified parameters, unless new ones are
  	 * entered.
  	 */
  	chip = i2c_mm_last_chip;
  	addr = i2c_mm_last_addr;
  	alen = i2c_mm_last_alen;
  
  	if ((flag & CMD_FLAG_REPEAT) == 0) {
  		/*
  		 * New command specified.  Check for a size specification.
  		 * Defaults to byte if no or incorrect specification.
  		 */
  		size = cmd_get_data_size(argv[0], 1);
  
  		/*
53677ef18   Wolfgang Denk   Big white-space c...
577
578
  		 * Chip is always specified.
  		 */
81a8824f2   wdenk   Initial revision
579
580
581
582
583
584
  		chip = simple_strtoul(argv[1], NULL, 16);
  
  		/*
  		 * Address is always specified.
  		 */
  		addr = simple_strtoul(argv[2], NULL, 16);
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
585
  		alen = get_alen(argv[2]);
7a92e53cd   Reinhard Meyer   CMD_I2C: make ale...
586
  		if (alen > 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
587
  			return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
588
589
590
591
592
593
594
595
  	}
  
  	/*
  	 * Print the address, followed by value.  Then accept input for
  	 * the next value.  A non-converted value exits.
  	 */
  	do {
  		printf("%08lx:", addr);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
596
  		if (i2c_read(chip, addr, alen, (uchar *)&data, size) != 0)
4b9206ed5   wdenk   * Patches by Thom...
597
598
599
  			puts ("
  Error reading the chip,
  ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
600
  		else {
81a8824f2   wdenk   Initial revision
601
  			data = cpu_to_be32(data);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
602
  			if (size == 1)
81a8824f2   wdenk   Initial revision
603
  				printf(" %02lx", (data >> 24) & 0x000000FF);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
604
  			else if (size == 2)
81a8824f2   wdenk   Initial revision
605
  				printf(" %04lx", (data >> 16) & 0x0000FFFF);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
606
  			else
81a8824f2   wdenk   Initial revision
607
  				printf(" %08lx", data);
81a8824f2   wdenk   Initial revision
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  		}
  
  		nbytes = readline (" ? ");
  		if (nbytes == 0) {
  			/*
  			 * <CR> pressed as only input, don't modify current
  			 * location and move to next.
  			 */
  			if (incrflag)
  				addr += size;
  			nbytes = size;
  #ifdef CONFIG_BOOT_RETRY_TIME
  			reset_cmd_timeout(); /* good enough to not time out */
  #endif
  		}
  #ifdef CONFIG_BOOT_RETRY_TIME
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
624
  		else if (nbytes == -2)
81a8824f2   wdenk   Initial revision
625
  			break;	/* timed out, exit the command	*/
81a8824f2   wdenk   Initial revision
626
627
628
629
630
  #endif
  		else {
  			char *endp;
  
  			data = simple_strtoul(console_buffer, &endp, 16);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
631
  			if (size == 1)
81a8824f2   wdenk   Initial revision
632
  				data = data << 24;
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
633
  			else if (size == 2)
81a8824f2   wdenk   Initial revision
634
  				data = data << 16;
81a8824f2   wdenk   Initial revision
635
636
637
638
639
640
641
642
643
  			data = be32_to_cpu(data);
  			nbytes = endp - console_buffer;
  			if (nbytes) {
  #ifdef CONFIG_BOOT_RETRY_TIME
  				/*
  				 * good enough to not time out
  				 */
  				reset_cmd_timeout();
  #endif
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
644
  				if (i2c_write(chip, addr, alen, (uchar *)&data, size) != 0)
4b9206ed5   wdenk   * Patches by Thom...
645
646
  					puts ("Error writing the chip.
  ");
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
647
648
  #ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
  				udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
2535d6027   wdenk   * Patch by Martin...
649
  #endif
81a8824f2   wdenk   Initial revision
650
651
652
653
654
  				if (incrflag)
  					addr += size;
  			}
  		}
  	} while (nbytes);
0800707b6   Peter Tyser   mod_i2c_mem() bugfix
655
656
657
  	i2c_mm_last_chip = chip;
  	i2c_mm_last_addr = addr;
  	i2c_mm_last_alen = alen;
81a8824f2   wdenk   Initial revision
658
659
660
  
  	return 0;
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
661
662
663
664
665
666
667
668
669
670
  /**
   * do_i2c_probe() - Handle the "i2c probe" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   *
81a8824f2   wdenk   Initial revision
671
   * Syntax:
54b99e51a   Eric Nelson   i2c_probe: update...
672
673
674
   *	i2c probe {addr}
   *
   * Returns zero (success) if one or more I2C devices was found
81a8824f2   wdenk   Initial revision
675
   */
54841ab50   Wolfgang Denk   Make sure that ar...
676
  static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
677
678
  {
  	int j;
54b99e51a   Eric Nelson   i2c_probe: update...
679
680
  	int addr = -1;
  	int found = 0;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
681
  #if defined(CONFIG_SYS_I2C_NOPROBES)
81a8824f2   wdenk   Initial revision
682
  	int k, skip;
3f4978c71   Heiko Schocher   i2c: common chang...
683
  	unsigned int bus = GET_BUS_NUM;
bb99ad6d8   Ben Warren   Add support for m...
684
  #endif	/* NOPROBES */
81a8824f2   wdenk   Initial revision
685

54b99e51a   Eric Nelson   i2c_probe: update...
686
687
  	if (argc == 2)
  		addr = simple_strtol(argv[1], 0, 16);
4b9206ed5   wdenk   * Patches by Thom...
688
  	puts ("Valid chip addresses:");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
689
  	for (j = 0; j < 128; j++) {
54b99e51a   Eric Nelson   i2c_probe: update...
690
691
  		if ((0 <= addr) && (j != addr))
  			continue;
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
692
  #if defined(CONFIG_SYS_I2C_NOPROBES)
81a8824f2   wdenk   Initial revision
693
  		skip = 0;
cfb25cc40   Axel Lin   cmd_i2c: Use ARRA...
694
  		for (k = 0; k < ARRAY_SIZE(i2c_no_probes); k++) {
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
695
  			if (COMPARE_BUS(bus, k) && COMPARE_ADDR(j, k)) {
81a8824f2   wdenk   Initial revision
696
697
698
699
700
701
702
  				skip = 1;
  				break;
  			}
  		}
  		if (skip)
  			continue;
  #endif
54b99e51a   Eric Nelson   i2c_probe: update...
703
  		if (i2c_probe(j) == 0) {
81a8824f2   wdenk   Initial revision
704
  			printf(" %02X", j);
54b99e51a   Eric Nelson   i2c_probe: update...
705
706
  			found++;
  		}
81a8824f2   wdenk   Initial revision
707
  	}
4b9206ed5   wdenk   * Patches by Thom...
708
709
  	putc ('
  ');
81a8824f2   wdenk   Initial revision
710

6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
711
  #if defined(CONFIG_SYS_I2C_NOPROBES)
81a8824f2   wdenk   Initial revision
712
  	puts ("Excluded chip addresses:");
cfb25cc40   Axel Lin   cmd_i2c: Use ARRA...
713
  	for (k = 0; k < ARRAY_SIZE(i2c_no_probes); k++) {
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
714
  		if (COMPARE_BUS(bus,k))
bb99ad6d8   Ben Warren   Add support for m...
715
716
  			printf(" %02X", NO_PROBE_ADDR(k));
  	}
4b9206ed5   wdenk   * Patches by Thom...
717
718
  	putc ('
  ');
81a8824f2   wdenk   Initial revision
719
  #endif
54b99e51a   Eric Nelson   i2c_probe: update...
720
  	return (0 == found);
81a8824f2   wdenk   Initial revision
721
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
722
723
724
725
726
727
728
729
730
731
  /**
   * do_i2c_loop() - Handle the "i2c loop" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   *
81a8824f2   wdenk   Initial revision
732
   * Syntax:
0f89c54be   Peter Tyser   i2c: Update refer...
733
   *	i2c loop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}]
81a8824f2   wdenk   Initial revision
734
735
736
   *	{length} - Number of bytes to read
   *	{delay}  - A DECIMAL number and defaults to 1000 uSec
   */
54841ab50   Wolfgang Denk   Make sure that ar...
737
  static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
738
739
740
741
742
743
744
  {
  	u_char	chip;
  	ulong	alen;
  	uint	addr;
  	uint	length;
  	u_char	bytes[16];
  	int	delay;
81a8824f2   wdenk   Initial revision
745

47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
746
  	if (argc < 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
747
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
748
749
750
751
752
753
754
755
756
757
  
  	/*
  	 * Chip is always specified.
  	 */
  	chip = simple_strtoul(argv[1], NULL, 16);
  
  	/*
  	 * Address is always specified.
  	 */
  	addr = simple_strtoul(argv[2], NULL, 16);
2c0dc9902   Frans Meulenbroeks   cmd_i2c: introduc...
758
  	alen = get_alen(argv[2]);
7a92e53cd   Reinhard Meyer   CMD_I2C: make ale...
759
  	if (alen > 3)
4c12eeb8b   Simon Glass   Convert cmd_usage...
760
  		return CMD_RET_USAGE;
81a8824f2   wdenk   Initial revision
761
762
763
764
765
766
  
  	/*
  	 * Length is the number of objects, not number of bytes.
  	 */
  	length = 1;
  	length = simple_strtoul(argv[3], NULL, 16);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
767
  	if (length > sizeof(bytes))
81a8824f2   wdenk   Initial revision
768
  		length = sizeof(bytes);
81a8824f2   wdenk   Initial revision
769
770
771
772
773
  
  	/*
  	 * The delay time (uSec) is optional.
  	 */
  	delay = 1000;
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
774
  	if (argc > 3)
81a8824f2   wdenk   Initial revision
775
  		delay = simple_strtoul(argv[4], NULL, 10);
81a8824f2   wdenk   Initial revision
776
777
778
  	/*
  	 * Run the loop...
  	 */
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
779
780
  	while (1) {
  		if (i2c_read(chip, addr, alen, bytes, length) != 0)
4b9206ed5   wdenk   * Patches by Thom...
781
782
  			puts ("Error reading the chip.
  ");
81a8824f2   wdenk   Initial revision
783
784
785
786
787
788
  		udelay(delay);
  	}
  
  	/* NOTREACHED */
  	return 0;
  }
81a8824f2   wdenk   Initial revision
789
790
791
  /*
   * The SDRAM command is separately configured because many
   * (most?) embedded boards don't use SDRAM DIMMs.
06afa388b   Marek Vasut   i2c: kerneldoc: A...
792
793
   *
   * FIXME: Document and probably move elsewhere!
81a8824f2   wdenk   Initial revision
794
   */
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
795
  #if defined(CONFIG_CMD_SDRAM)
632de0672   Larry Johnson   Refactor code for...
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
  static void print_ddr2_tcyc (u_char const b)
  {
  	printf ("%d.", (b >> 4) & 0x0F);
  	switch (b & 0x0F) {
  	case 0x0:
  	case 0x1:
  	case 0x2:
  	case 0x3:
  	case 0x4:
  	case 0x5:
  	case 0x6:
  	case 0x7:
  	case 0x8:
  	case 0x9:
  		printf ("%d ns
  ", b & 0x0F);
  		break;
  	case 0xA:
  		puts ("25 ns
  ");
  		break;
  	case 0xB:
  		puts ("33 ns
  ");
  		break;
  	case 0xC:
  		puts ("66 ns
  ");
  		break;
  	case 0xD:
  		puts ("75 ns
  ");
  		break;
  	default:
  		puts ("?? ns
  ");
  		break;
  	}
  }
  
  static void decode_bits (u_char const b, char const *str[], int const do_once)
  {
  	u_char mask;
  
  	for (mask = 0x80; mask != 0x00; mask >>= 1, ++str) {
  		if (b & mask) {
  			puts (*str);
  			if (do_once)
  				return;
  		}
  	}
  }
81a8824f2   wdenk   Initial revision
848
849
850
  
  /*
   * Syntax:
0f89c54be   Peter Tyser   i2c: Update refer...
851
   *	i2c sdram {i2c_chip}
81a8824f2   wdenk   Initial revision
852
   */
54841ab50   Wolfgang Denk   Make sure that ar...
853
  static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
81a8824f2   wdenk   Initial revision
854
  {
632de0672   Larry Johnson   Refactor code for...
855
  	enum { unknown, EDO, SDRAM, DDR2 } type;
81a8824f2   wdenk   Initial revision
856
857
858
859
  	u_char	chip;
  	u_char	data[128];
  	u_char	cksum;
  	int	j;
632de0672   Larry Johnson   Refactor code for...
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
  	static const char *decode_CAS_DDR2[] = {
  		" TBD", " 6", " 5", " 4", " 3", " 2", " TBD", " TBD"
  	};
  
  	static const char *decode_CAS_default[] = {
  		" TBD", " 7", " 6", " 5", " 4", " 3", " 2", " 1"
  	};
  
  	static const char *decode_CS_WE_default[] = {
  		" TBD", " 6", " 5", " 4", " 3", " 2", " 1", " 0"
  	};
  
  	static const char *decode_byte21_default[] = {
  		"  TBD (bit 7)
  ",
  		"  Redundant row address
  ",
  		"  Differential clock input
  ",
  		"  Registerd DQMB inputs
  ",
  		"  Buffered DQMB inputs
  ",
  		"  On-card PLL
  ",
  		"  Registered address/control lines
  ",
  		"  Buffered address/control lines
  "
  	};
  
  	static const char *decode_byte22_DDR2[] = {
  		"  TBD (bit 7)
  ",
  		"  TBD (bit 6)
  ",
  		"  TBD (bit 5)
  ",
  		"  TBD (bit 4)
  ",
  		"  TBD (bit 3)
  ",
  		"  Supports partial array self refresh
  ",
  		"  Supports 50 ohm ODT
  ",
  		"  Supports weak driver
  "
  	};
  
  	static const char *decode_row_density_DDR2[] = {
  		"512 MiB", "256 MiB", "128 MiB", "16 GiB",
  		"8 GiB", "4 GiB", "2 GiB", "1 GiB"
  	};
  
  	static const char *decode_row_density_default[] = {
  		"512 MiB", "256 MiB", "128 MiB", "64 MiB",
  		"32 MiB", "16 MiB", "8 MiB", "4 MiB"
  	};
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
919
  	if (argc < 2)
4c12eeb8b   Simon Glass   Convert cmd_usage...
920
  		return CMD_RET_USAGE;
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
921

81a8824f2   wdenk   Initial revision
922
923
  	/*
  	 * Chip is always specified.
632de0672   Larry Johnson   Refactor code for...
924
925
  	 */
  	chip = simple_strtoul (argv[1], NULL, 16);
81a8824f2   wdenk   Initial revision
926

632de0672   Larry Johnson   Refactor code for...
927
  	if (i2c_read (chip, 0, 1, data, sizeof (data)) != 0) {
4b9206ed5   wdenk   * Patches by Thom...
928
929
  		puts ("No SDRAM Serial Presence Detect found.
  ");
81a8824f2   wdenk   Initial revision
930
931
932
933
934
935
936
  		return 1;
  	}
  
  	cksum = 0;
  	for (j = 0; j < 63; j++) {
  		cksum += data[j];
  	}
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
937
  	if (cksum != data[63]) {
81a8824f2   wdenk   Initial revision
938
939
  		printf ("WARNING: Configuration data checksum failure:
  "
632de0672   Larry Johnson   Refactor code for...
940
941
  			"  is 0x%02x, calculated 0x%02x
  ", data[63], cksum);
81a8824f2   wdenk   Initial revision
942
  	}
632de0672   Larry Johnson   Refactor code for...
943
944
  	printf ("SPD data revision            %d.%d
  ",
81a8824f2   wdenk   Initial revision
945
  		(data[62] >> 4) & 0x0F, data[62] & 0x0F);
632de0672   Larry Johnson   Refactor code for...
946
947
948
949
  	printf ("Bytes used                   0x%02X
  ", data[0]);
  	printf ("Serial memory size           0x%02X
  ", 1 << data[1]);
4b9206ed5   wdenk   * Patches by Thom...
950
  	puts ("Memory type                  ");
632de0672   Larry Johnson   Refactor code for...
951
  	switch (data[2]) {
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  	case 2:
  		type = EDO;
  		puts ("EDO
  ");
  		break;
  	case 4:
  		type = SDRAM;
  		puts ("SDRAM
  ");
  		break;
  	case 8:
  		type = DDR2;
  		puts ("DDR2
  ");
  		break;
  	default:
  		type = unknown;
  		puts ("unknown
  ");
  		break;
81a8824f2   wdenk   Initial revision
972
  	}
632de0672   Larry Johnson   Refactor code for...
973

4b9206ed5   wdenk   * Patches by Thom...
974
  	puts ("Row address bits             ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
975
  	if ((data[3] & 0x00F0) == 0)
632de0672   Larry Johnson   Refactor code for...
976
977
  		printf ("%d
  ", data[3] & 0x0F);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
978
  	else
632de0672   Larry Johnson   Refactor code for...
979
980
  		printf ("%d/%d
  ", data[3] & 0x0F, (data[3] >> 4) & 0x0F);
4b9206ed5   wdenk   * Patches by Thom...
981
  	puts ("Column address bits          ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
982
  	if ((data[4] & 0x00F0) == 0)
632de0672   Larry Johnson   Refactor code for...
983
984
  		printf ("%d
  ", data[4] & 0x0F);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
985
  	else
632de0672   Larry Johnson   Refactor code for...
986
987
  		printf ("%d/%d
  ", data[4] & 0x0F, (data[4] >> 4) & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
988
989
990
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
991
992
993
  		printf ("Number of ranks              %d
  ",
  			(data[5] & 0x07) + 1);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
994
995
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
996
997
  		printf ("Module rows                  %d
  ", data[5]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
998
999
1000
1001
1002
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1003
1004
  		printf ("Module data width            %d bits
  ", data[6]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1005
1006
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1007
1008
1009
  		printf ("Module data width            %d bits
  ",
  			(data[7] << 8) | data[6]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1010
1011
  		break;
  	}
4b9206ed5   wdenk   * Patches by Thom...
1012
  	puts ("Interface signal levels      ");
81a8824f2   wdenk   Initial revision
1013
  	switch(data[8]) {
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1014
1015
  		case 0:  puts ("TTL 5.0 V
  ");	break;
4b9206ed5   wdenk   * Patches by Thom...
1016
1017
  		case 1:  puts ("LVTTL
  ");	break;
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1018
1019
1020
1021
1022
1023
1024
1025
  		case 2:  puts ("HSTL 1.5 V
  ");	break;
  		case 3:  puts ("SSTL 3.3 V
  ");	break;
  		case 4:  puts ("SSTL 2.5 V
  ");	break;
  		case 5:  puts ("SSTL 1.8 V
  ");	break;
4b9206ed5   wdenk   * Patches by Thom...
1026
1027
  		default: puts ("unknown
  ");	break;
81a8824f2   wdenk   Initial revision
1028
  	}
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1029
1030
1031
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1032
1033
  		printf ("SDRAM cycle time             ");
  		print_ddr2_tcyc (data[9]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1034
1035
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1036
1037
1038
  		printf ("SDRAM cycle time             %d.%d ns
  ",
  			(data[9] >> 4) & 0x0F, data[9] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1039
1040
1041
1042
1043
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1044
1045
1046
  		printf ("SDRAM access time            0.%d%d ns
  ",
  			(data[10] >> 4) & 0x0F, data[10] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1047
1048
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1049
1050
1051
  		printf ("SDRAM access time            %d.%d ns
  ",
  			(data[10] >> 4) & 0x0F, data[10] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1052
1053
  		break;
  	}
4b9206ed5   wdenk   * Patches by Thom...
1054
  	puts ("EDC configuration            ");
632de0672   Larry Johnson   Refactor code for...
1055
  	switch (data[11]) {
4b9206ed5   wdenk   * Patches by Thom...
1056
1057
1058
1059
1060
1061
1062
1063
  		case 0:  puts ("None
  ");	break;
  		case 1:  puts ("Parity
  ");	break;
  		case 2:  puts ("ECC
  ");	break;
  		default: puts ("unknown
  ");	break;
81a8824f2   wdenk   Initial revision
1064
  	}
632de0672   Larry Johnson   Refactor code for...
1065

e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1066
  	if ((data[12] & 0x80) == 0)
4b9206ed5   wdenk   * Patches by Thom...
1067
  		puts ("No self refresh, rate        ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1068
  	else
4b9206ed5   wdenk   * Patches by Thom...
1069
  		puts ("Self refresh, rate           ");
632de0672   Larry Johnson   Refactor code for...
1070

81a8824f2   wdenk   Initial revision
1071
  	switch(data[12] & 0x7F) {
632de0672   Larry Johnson   Refactor code for...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
  		case 0:  puts ("15.625 us
  ");	break;
  		case 1:  puts ("3.9 us
  ");	break;
  		case 2:  puts ("7.8 us
  ");	break;
  		case 3:  puts ("31.3 us
  ");	break;
  		case 4:  puts ("62.5 us
  ");	break;
  		case 5:  puts ("125 us
  ");	break;
4b9206ed5   wdenk   * Patches by Thom...
1084
1085
  		default: puts ("unknown
  ");	break;
81a8824f2   wdenk   Initial revision
1086
  	}
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1087
1088
1089
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1090
1091
  		printf ("SDRAM width (primary)        %d
  ", data[13]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1092
1093
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1094
1095
  		printf ("SDRAM width (primary)        %d
  ", data[13] & 0x7F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1096
  		if ((data[13] & 0x80) != 0) {
632de0672   Larry Johnson   Refactor code for...
1097
1098
1099
  			printf ("  (second bank)              %d
  ",
  				2 * (data[13] & 0x7F));
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1100
1101
1102
1103
1104
1105
1106
  		}
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
  		if (data[14] != 0)
632de0672   Larry Johnson   Refactor code for...
1107
1108
  			printf ("EDC width                    %d
  ", data[14]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1109
1110
1111
  		break;
  	default:
  		if (data[14] != 0) {
632de0672   Larry Johnson   Refactor code for...
1112
1113
1114
  			printf ("EDC width                    %d
  ",
  				data[14] & 0x7F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1115
1116
  
  			if ((data[14] & 0x80) != 0) {
632de0672   Larry Johnson   Refactor code for...
1117
1118
1119
  				printf ("  (second bank)              %d
  ",
  					2 * (data[14] & 0x7F));
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1120
1121
1122
  			}
  		}
  		break;
81a8824f2   wdenk   Initial revision
1123
  	}
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1124

632de0672   Larry Johnson   Refactor code for...
1125
1126
1127
1128
  	if (DDR2 != type) {
  		printf ("Min clock delay, back-to-back random column addresses "
  			"%d
  ", data[15]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1129
  	}
4b9206ed5   wdenk   * Patches by Thom...
1130
1131
1132
1133
1134
1135
1136
1137
  	puts ("Burst length(s)             ");
  	if (data[16] & 0x80) puts (" Page");
  	if (data[16] & 0x08) puts (" 8");
  	if (data[16] & 0x04) puts (" 4");
  	if (data[16] & 0x02) puts (" 2");
  	if (data[16] & 0x01) puts (" 1");
  	putc ('
  ');
632de0672   Larry Johnson   Refactor code for...
1138
1139
  	printf ("Number of banks              %d
  ", data[17]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1140
1141
1142
1143
  
  	switch (type) {
  	case DDR2:
  		puts ("CAS latency(s)              ");
632de0672   Larry Johnson   Refactor code for...
1144
  		decode_bits (data[18], decode_CAS_DDR2, 0);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1145
1146
1147
1148
1149
  		putc ('
  ');
  		break;
  	default:
  		puts ("CAS latency(s)              ");
632de0672   Larry Johnson   Refactor code for...
1150
  		decode_bits (data[18], decode_CAS_default, 0);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1151
1152
1153
1154
1155
1156
1157
  		putc ('
  ');
  		break;
  	}
  
  	if (DDR2 != type) {
  		puts ("CS latency(s)               ");
632de0672   Larry Johnson   Refactor code for...
1158
  		decode_bits (data[19], decode_CS_WE_default, 0);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1159
1160
1161
1162
1163
1164
  		putc ('
  ');
  	}
  
  	if (DDR2 != type) {
  		puts ("WE latency(s)               ");
632de0672   Larry Johnson   Refactor code for...
1165
  		decode_bits (data[20], decode_CS_WE_default, 0);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
  		putc ('
  ');
  	}
  
  	switch (type) {
  	case DDR2:
  		puts ("Module attributes:
  ");
  		if (data[21] & 0x80)
  			puts ("  TBD (bit 7)
  ");
  		if (data[21] & 0x40)
  			puts ("  Analysis probe installed
  ");
  		if (data[21] & 0x20)
  			puts ("  TBD (bit 5)
  ");
  		if (data[21] & 0x10)
  			puts ("  FET switch external enable
  ");
632de0672   Larry Johnson   Refactor code for...
1186
1187
  		printf ("  %d PLLs on DIMM
  ", (data[21] >> 2) & 0x03);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1188
  		if (data[20] & 0x11) {
632de0672   Larry Johnson   Refactor code for...
1189
1190
1191
  			printf ("  %d active registers on DIMM
  ",
  				(data[21] & 0x03) + 1);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1192
1193
1194
1195
1196
1197
1198
1199
  		}
  		break;
  	default:
  		puts ("Module attributes:
  ");
  		if (!data[21])
  			puts ("  (none)
  ");
632de0672   Larry Johnson   Refactor code for...
1200
1201
  		else
  			decode_bits (data[21], decode_byte21_default, 0);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1202
1203
1204
1205
1206
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1207
  		decode_bits (data[22], decode_byte22_DDR2, 0);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
  		break;
  	default:
  		puts ("Device attributes:
  ");
  		if (data[22] & 0x80) puts ("  TBD (bit 7)
  ");
  		if (data[22] & 0x40) puts ("  TBD (bit 6)
  ");
  		if (data[22] & 0x20) puts ("  Upper Vcc tolerance 5%
  ");
  		else                 puts ("  Upper Vcc tolerance 10%
  ");
  		if (data[22] & 0x10) puts ("  Lower Vcc tolerance 5%
  ");
  		else                 puts ("  Lower Vcc tolerance 10%
  ");
  		if (data[22] & 0x08) puts ("  Supports write1/read burst
  ");
  		if (data[22] & 0x04) puts ("  Supports precharge all
  ");
  		if (data[22] & 0x02) puts ("  Supports auto precharge
  ");
  		if (data[22] & 0x01) puts ("  Supports early RAS# precharge
  ");
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1237
1238
  		printf ("SDRAM cycle time (2nd highest CAS latency)        ");
  		print_ddr2_tcyc (data[23]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1239
1240
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1241
1242
1243
  		printf ("SDRAM cycle time (2nd highest CAS latency)        %d."
  			"%d ns
  ", (data[23] >> 4) & 0x0F, data[23] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1244
1245
1246
1247
1248
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1249
1250
1251
  		printf ("SDRAM access from clock (2nd highest CAS latency) 0."
  			"%d%d ns
  ", (data[24] >> 4) & 0x0F, data[24] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1252
1253
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1254
1255
1256
  		printf ("SDRAM access from clock (2nd highest CAS latency) %d."
  			"%d ns
  ", (data[24] >> 4) & 0x0F, data[24] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1257
1258
1259
1260
1261
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1262
1263
  		printf ("SDRAM cycle time (3rd highest CAS latency)        ");
  		print_ddr2_tcyc (data[25]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1264
1265
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1266
1267
1268
  		printf ("SDRAM cycle time (3rd highest CAS latency)        %d."
  			"%d ns
  ", (data[25] >> 4) & 0x0F, data[25] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1269
1270
1271
1272
1273
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1274
1275
1276
  		printf ("SDRAM access from clock (3rd highest CAS latency) 0."
  			"%d%d ns
  ", (data[26] >> 4) & 0x0F, data[26] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1277
1278
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1279
1280
1281
  		printf ("SDRAM access from clock (3rd highest CAS latency) %d."
  			"%d ns
  ", (data[26] >> 4) & 0x0F, data[26] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1282
1283
1284
1285
1286
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1287
1288
1289
  		printf ("Minimum row precharge        %d.%02d ns
  ",
  			(data[27] >> 2) & 0x3F, 25 * (data[27] & 0x03));
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1290
1291
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1292
1293
  		printf ("Minimum row precharge        %d ns
  ", data[27]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1294
1295
1296
1297
1298
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1299
1300
1301
  		printf ("Row active to row active min %d.%02d ns
  ",
  			(data[28] >> 2) & 0x3F, 25 * (data[28] & 0x03));
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1302
1303
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1304
1305
  		printf ("Row active to row active min %d ns
  ", data[28]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1306
1307
1308
1309
1310
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1311
1312
1313
  		printf ("RAS to CAS delay min         %d.%02d ns
  ",
  			(data[29] >> 2) & 0x3F, 25 * (data[29] & 0x03));
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1314
1315
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1316
1317
  		printf ("RAS to CAS delay min         %d ns
  ", data[29]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1318
1319
  		break;
  	}
632de0672   Larry Johnson   Refactor code for...
1320
1321
  	printf ("Minimum RAS pulse width      %d ns
  ", data[30]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1322
1323
1324
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1325
1326
1327
1328
  		puts ("Density of each row          ");
  		decode_bits (data[31], decode_row_density_DDR2, 1);
  		putc ('
  ');
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1329
1330
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1331
1332
1333
1334
  		puts ("Density of each row          ");
  		decode_bits (data[31], decode_row_density_default, 1);
  		putc ('
  ');
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1335
1336
1337
1338
1339
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1340
  		puts ("Command and Address setup    ");
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1341
  		if (data[32] >= 0xA0) {
632de0672   Larry Johnson   Refactor code for...
1342
1343
1344
  			printf ("1.%d%d ns
  ",
  				((data[32] >> 4) & 0x0F) - 10, data[32] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1345
  		} else {
632de0672   Larry Johnson   Refactor code for...
1346
1347
1348
  			printf ("0.%d%d ns
  ",
  				((data[32] >> 4) & 0x0F), data[32] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1349
1350
1351
  		}
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1352
1353
1354
1355
  		printf ("Command and Address setup    %c%d.%d ns
  ",
  			(data[32] & 0x80) ? '-' : '+',
  			(data[32] >> 4) & 0x07, data[32] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1356
1357
1358
1359
1360
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1361
  		puts ("Command and Address hold     ");
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1362
  		if (data[33] >= 0xA0) {
632de0672   Larry Johnson   Refactor code for...
1363
1364
1365
  			printf ("1.%d%d ns
  ",
  				((data[33] >> 4) & 0x0F) - 10, data[33] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1366
  		} else {
632de0672   Larry Johnson   Refactor code for...
1367
1368
1369
  			printf ("0.%d%d ns
  ",
  				((data[33] >> 4) & 0x0F), data[33] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1370
1371
1372
  		}
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1373
1374
1375
1376
  		printf ("Command and Address hold     %c%d.%d ns
  ",
  			(data[33] & 0x80) ? '-' : '+',
  			(data[33] >> 4) & 0x07, data[33] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1377
1378
1379
1380
1381
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1382
1383
1384
  		printf ("Data signal input setup      0.%d%d ns
  ",
  			(data[34] >> 4) & 0x0F, data[34] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1385
1386
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1387
1388
1389
1390
  		printf ("Data signal input setup      %c%d.%d ns
  ",
  			(data[34] & 0x80) ? '-' : '+',
  			(data[34] >> 4) & 0x07, data[34] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1391
1392
1393
1394
1395
  		break;
  	}
  
  	switch (type) {
  	case DDR2:
632de0672   Larry Johnson   Refactor code for...
1396
1397
1398
  		printf ("Data signal input hold       0.%d%d ns
  ",
  			(data[35] >> 4) & 0x0F, data[35] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1399
1400
  		break;
  	default:
632de0672   Larry Johnson   Refactor code for...
1401
1402
1403
1404
  		printf ("Data signal input hold       %c%d.%d ns
  ",
  			(data[35] & 0x80) ? '-' : '+',
  			(data[35] >> 4) & 0x07, data[35] & 0x0F);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1405
1406
  		break;
  	}
4b9206ed5   wdenk   * Patches by Thom...
1407
  	puts ("Manufacturer's JEDEC ID      ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1408
  	for (j = 64; j <= 71; j++)
632de0672   Larry Johnson   Refactor code for...
1409
  		printf ("%02X ", data[j]);
4b9206ed5   wdenk   * Patches by Thom...
1410
1411
  	putc ('
  ');
632de0672   Larry Johnson   Refactor code for...
1412
1413
  	printf ("Manufacturing Location       %02X
  ", data[72]);
4b9206ed5   wdenk   * Patches by Thom...
1414
  	puts ("Manufacturer's Part Number   ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1415
  	for (j = 73; j <= 90; j++)
632de0672   Larry Johnson   Refactor code for...
1416
  		printf ("%02X ", data[j]);
4b9206ed5   wdenk   * Patches by Thom...
1417
1418
  	putc ('
  ');
632de0672   Larry Johnson   Refactor code for...
1419
1420
1421
1422
  	printf ("Revision Code                %02X %02X
  ", data[91], data[92]);
  	printf ("Manufacturing Date           %02X %02X
  ", data[93], data[94]);
4b9206ed5   wdenk   * Patches by Thom...
1423
  	puts ("Assembly Serial Number       ");
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1424
  	for (j = 95; j <= 98; j++)
632de0672   Larry Johnson   Refactor code for...
1425
  		printf ("%02X ", data[j]);
4b9206ed5   wdenk   * Patches by Thom...
1426
1427
  	putc ('
  ');
81a8824f2   wdenk   Initial revision
1428

0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1429
  	if (DDR2 != type) {
632de0672   Larry Johnson   Refactor code for...
1430
1431
1432
  		printf ("Speed rating                 PC%d
  ",
  			data[126] == 0x66 ? 66 : data[126]);
0df6b8446   Larry Johnson   Fix "i2c sdram" c...
1433
  	}
81a8824f2   wdenk   Initial revision
1434
1435
  	return 0;
  }
902531788   Jon Loeliger   common/: Remove l...
1436
  #endif
81a8824f2   wdenk   Initial revision
1437

735987c5a   Tom Wai-Hong Tam   edid: Add I2C com...
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
  /*
   * Syntax:
   *	i2c edid {i2c_chip}
   */
  #if defined(CONFIG_I2C_EDID)
  int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  {
  	u_char chip;
  	struct edid1_info edid;
  
  	if (argc < 2) {
  		cmd_usage(cmdtp);
  		return 1;
  	}
  
  	chip = simple_strtoul(argv[1], NULL, 16);
  	if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
  		puts("Error reading EDID content.
  ");
  		return 1;
  	}
  
  	if (edid_check_info(&edid)) {
  		puts("Content isn't valid EDID.
  ");
  		return 1;
  	}
  
  	edid_print_info(&edid);
  	return 0;
  
  }
  #endif /* CONFIG_I2C_EDID */
06afa388b   Marek Vasut   i2c: kerneldoc: A...
1471
  /**
3f4978c71   Heiko Schocher   i2c: common chang...
1472
   * do_i2c_show_bus() - Handle the "i2c bus" command-line command
06afa388b   Marek Vasut   i2c: kerneldoc: A...
1473
1474
1475
1476
1477
1478
1479
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero always.
   */
3f4978c71   Heiko Schocher   i2c: common chang...
1480
1481
  #if defined(CONFIG_SYS_I2C)
  int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
67b23a322   Heiko Schocher   I2C: adding new "...
1482
  {
3f4978c71   Heiko Schocher   i2c: common chang...
1483
1484
1485
1486
  	int	i;
  #ifndef CONFIG_SYS_I2C_DIRECT_BUS
  	int	j;
  #endif
67b23a322   Heiko Schocher   I2C: adding new "...
1487
1488
1489
  
  	if (argc == 1) {
  		/* show all busses */
3f4978c71   Heiko Schocher   i2c: common chang...
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
  		for (i = 0; i < CONFIG_SYS_NUM_I2C_BUSES; i++) {
  			printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name);
  #ifndef CONFIG_SYS_I2C_DIRECT_BUS
  			for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) {
  				if (i2c_bus[i].next_hop[j].chip == 0)
  					break;
  				printf("->%s@0x%2x:%d",
  				       i2c_bus[i].next_hop[j].mux.name,
  				       i2c_bus[i].next_hop[j].chip,
  				       i2c_bus[i].next_hop[j].channel);
67b23a322   Heiko Schocher   I2C: adding new "...
1500
  			}
3f4978c71   Heiko Schocher   i2c: common chang...
1501
1502
1503
  #endif
  			printf("
  ");
67b23a322   Heiko Schocher   I2C: adding new "...
1504
1505
  		}
  	} else {
3f4978c71   Heiko Schocher   i2c: common chang...
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
  		/* show specific bus */
  		i = simple_strtoul(argv[1], NULL, 10);
  		if (i >= CONFIG_SYS_NUM_I2C_BUSES) {
  			printf("Invalid bus %d
  ", i);
  			return -1;
  		}
  		printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name);
  #ifndef CONFIG_SYS_I2C_DIRECT_BUS
  			for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) {
  				if (i2c_bus[i].next_hop[j].chip == 0)
  					break;
  				printf("->%s@0x%2x:%d",
  				       i2c_bus[i].next_hop[j].mux.name,
  				       i2c_bus[i].next_hop[j].chip,
  				       i2c_bus[i].next_hop[j].channel);
  			}
  #endif
  		printf("
  ");
67b23a322   Heiko Schocher   I2C: adding new "...
1526
  	}
3f4978c71   Heiko Schocher   i2c: common chang...
1527
1528
  
  	return 0;
67b23a322   Heiko Schocher   I2C: adding new "...
1529
  }
3f4978c71   Heiko Schocher   i2c: common chang...
1530
  #endif
67b23a322   Heiko Schocher   I2C: adding new "...
1531

06afa388b   Marek Vasut   i2c: kerneldoc: A...
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
  /**
   * do_i2c_bus_num() - Handle the "i2c dev" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   */
3f4978c71   Heiko Schocher   i2c: common chang...
1542
1543
  #if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS)
  int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
bb99ad6d8   Ben Warren   Add support for m...
1544
  {
3f4978c71   Heiko Schocher   i2c: common chang...
1545
1546
  	int		ret = 0;
  	unsigned int	bus_no;
bb99ad6d8   Ben Warren   Add support for m...
1547

e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1548
1549
  	if (argc == 1)
  		/* querying current setting */
bb99ad6d8   Ben Warren   Add support for m...
1550
1551
  		printf("Current bus is %d
  ", i2c_get_bus_num());
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1552
  	else {
3f4978c71   Heiko Schocher   i2c: common chang...
1553
  		bus_no = simple_strtoul(argv[1], NULL, 10);
880a41273   Heiko Schocher   i2c: fix i2c dev ...
1554
  #if defined(CONFIG_SYS_I2C)
3f4978c71   Heiko Schocher   i2c: common chang...
1555
1556
1557
1558
1559
  		if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES) {
  			printf("Invalid bus %d
  ", bus_no);
  			return -1;
  		}
880a41273   Heiko Schocher   i2c: fix i2c dev ...
1560
  #endif
3f4978c71   Heiko Schocher   i2c: common chang...
1561
1562
1563
  		printf("Setting bus to %d
  ", bus_no);
  		ret = i2c_set_bus_num(bus_no);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1564
  		if (ret)
bb99ad6d8   Ben Warren   Add support for m...
1565
1566
  			printf("Failure changing bus number (%d)
  ", ret);
bb99ad6d8   Ben Warren   Add support for m...
1567
1568
1569
  	}
  	return ret;
  }
3f4978c71   Heiko Schocher   i2c: common chang...
1570
  #endif  /* defined(CONFIG_SYS_I2C) */
bb99ad6d8   Ben Warren   Add support for m...
1571

06afa388b   Marek Vasut   i2c: kerneldoc: A...
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
  /**
   * do_i2c_bus_speed() - Handle the "i2c speed" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
1582
  static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
bb99ad6d8   Ben Warren   Add support for m...
1583
1584
  {
  	int speed, ret=0;
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1585
1586
  	if (argc == 1)
  		/* querying current speed */
bb99ad6d8   Ben Warren   Add support for m...
1587
1588
  		printf("Current bus speed=%d
  ", i2c_get_bus_speed());
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1589
  	else {
bb99ad6d8   Ben Warren   Add support for m...
1590
1591
1592
1593
  		speed = simple_strtoul(argv[1], NULL, 10);
  		printf("Setting bus speed to %d Hz
  ", speed);
  		ret = i2c_set_bus_speed(speed);
e857a5bdb   Timur Tabi   mpc83xx: Miscella...
1594
  		if (ret)
bb99ad6d8   Ben Warren   Add support for m...
1595
1596
  			printf("Failure changing bus speed (%d)
  ", ret);
bb99ad6d8   Ben Warren   Add support for m...
1597
1598
1599
  	}
  	return ret;
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
  /**
   * do_i2c_mm() - Handle the "i2c mm" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
1610
  static int do_i2c_mm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
bb99ad6d8   Ben Warren   Add support for m...
1611
  {
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1612
1613
  	return mod_i2c_mem (cmdtp, 1, flag, argc, argv);
  }
06afa388b   Marek Vasut   i2c: kerneldoc: A...
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
  /**
   * do_i2c_nm() - Handle the "i2c nm" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
1624
  static int do_i2c_nm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1625
1626
1627
  {
  	return mod_i2c_mem (cmdtp, 0, flag, argc, argv);
  }
e96ad5d3a   Peter Tyser   cmd_i2c: Clean up...
1628

06afa388b   Marek Vasut   i2c: kerneldoc: A...
1629
1630
1631
1632
1633
1634
1635
1636
1637
  /**
   * do_i2c_reset() - Handle the "i2c reset" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero always.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
1638
  static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1639
  {
3f4978c71   Heiko Schocher   i2c: common chang...
1640
1641
1642
  #if defined(CONFIG_SYS_I2C)
  	i2c_init(I2C_ADAP->speed, I2C_ADAP->slaveaddr);
  #else
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1643
  	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
3f4978c71   Heiko Schocher   i2c: common chang...
1644
  #endif
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1645
1646
1647
1648
  	return 0;
  }
  
  static cmd_tbl_t cmd_i2c_sub[] = {
3f4978c71   Heiko Schocher   i2c: common chang...
1649
1650
  #if defined(CONFIG_SYS_I2C)
  	U_BOOT_CMD_MKENT(bus, 1, 1, do_i2c_show_bus, "", ""),
9a2accb44   Heiko Schocher   i2c, multibus: ge...
1651
  #endif
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1652
  	U_BOOT_CMD_MKENT(crc32, 3, 1, do_i2c_crc, "", ""),
3f4978c71   Heiko Schocher   i2c: common chang...
1653
1654
  #if defined(CONFIG_SYS_I2C) || \
  	defined(CONFIG_I2C_MULTI_BUS)
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1655
  	U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""),
bb99ad6d8   Ben Warren   Add support for m...
1656
  #endif  /* CONFIG_I2C_MULTI_BUS */
735987c5a   Tom Wai-Hong Tam   edid: Add I2C com...
1657
1658
1659
  #if defined(CONFIG_I2C_EDID)
  	U_BOOT_CMD_MKENT(edid, 1, 1, do_edid, "", ""),
  #endif  /* CONFIG_I2C_EDID */
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1660
1661
1662
1663
1664
1665
  	U_BOOT_CMD_MKENT(loop, 3, 1, do_i2c_loop, "", ""),
  	U_BOOT_CMD_MKENT(md, 3, 1, do_i2c_md, "", ""),
  	U_BOOT_CMD_MKENT(mm, 2, 1, do_i2c_mm, "", ""),
  	U_BOOT_CMD_MKENT(mw, 3, 1, do_i2c_mw, "", ""),
  	U_BOOT_CMD_MKENT(nm, 2, 1, do_i2c_nm, "", ""),
  	U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""),
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
1666
  	U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""),
ff5d2dce1   York Sun   common/i2c: Add i...
1667
  	U_BOOT_CMD_MKENT(write, 5, 0, do_i2c_write, "", ""),
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1668
  	U_BOOT_CMD_MKENT(reset, 0, 1, do_i2c_reset, "", ""),
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1669
  #if defined(CONFIG_CMD_SDRAM)
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1670
  	U_BOOT_CMD_MKENT(sdram, 1, 1, do_sdram, "", ""),
902531788   Jon Loeliger   common/: Remove l...
1671
  #endif
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1672
1673
  	U_BOOT_CMD_MKENT(speed, 1, 1, do_i2c_bus_speed, "", ""),
  };
2e5167cca   Wolfgang Denk   Replace CONFIG_RE...
1674
  #ifdef CONFIG_NEEDS_MANUAL_RELOC
f1d2b313c   Heiko Schocher   ARM: add relocati...
1675
1676
1677
1678
  void i2c_reloc(void) {
  	fixup_cmdtable(cmd_i2c_sub, ARRAY_SIZE(cmd_i2c_sub));
  }
  #endif
06afa388b   Marek Vasut   i2c: kerneldoc: A...
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
  /**
   * do_i2c() - Handle the "i2c" command-line command
   * @cmdtp:	Command data struct pointer
   * @flag:	Command flag
   * @argc:	Command-line argument count
   * @argv:	Array of command-line arguments
   *
   * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
   * on error.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
1689
  static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1690
1691
  {
  	cmd_tbl_t *c;
4444b221f   Heiko Schocher   i2c: fix command ...
1692
  	if (argc < 2)
4c12eeb8b   Simon Glass   Convert cmd_usage...
1693
  		return CMD_RET_USAGE;
4444b221f   Heiko Schocher   i2c: fix command ...
1694

bfc3b77eb   Frans Meulenbroeks   cmd_i2c.c: rework...
1695
1696
1697
1698
1699
  	/* Strip off leading 'i2c' command argument */
  	argc--;
  	argv++;
  
  	c = find_cmd_tbl(argv[0], &cmd_i2c_sub[0], ARRAY_SIZE(cmd_i2c_sub));
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
1700
  	if (c)
4c12eeb8b   Simon Glass   Convert cmd_usage...
1701
  		return c->cmd(cmdtp, flag, argc, argv);
47e26b1bf   Wolfgang Denk   cmd_usage(): simp...
1702
  	else
4c12eeb8b   Simon Glass   Convert cmd_usage...
1703
  		return CMD_RET_USAGE;
bb99ad6d8   Ben Warren   Add support for m...
1704
  }
8bde7f776   wdenk   * Code cleanup:
1705
1706
  
  /***************************************************/
088f1b199   Kim Phillips   common/cmd_*.c: s...
1707
1708
  #ifdef CONFIG_SYS_LONGHELP
  static char i2c_help_text[] =
3f4978c71   Heiko Schocher   i2c: common chang...
1709
1710
1711
  #if defined(CONFIG_SYS_I2C)
  	"bus [muxtype:muxaddr:muxchannel] - show I2C bus info
  "
9a2accb44   Heiko Schocher   i2c, multibus: ge...
1712
  #endif
fb0070e91   Frans Meulenbroeks   cmd_i2c.c: sorted...
1713
1714
  	"crc32 chip address[.0, .1, .2] count - compute CRC32 checksum
  "
3f4978c71   Heiko Schocher   i2c: common chang...
1715
1716
  #if defined(CONFIG_SYS_I2C) || \
  	defined(CONFIG_I2C_MULTI_BUS)
9bc2e4eee   Peter Tyser   cmd_i2c: Fix help...
1717
1718
  	"i2c dev [dev] - show or set current I2C bus
  "
d9fc70324   Matthias Fuchs   [PATCH] I2C: disa...
1719
  #endif  /* CONFIG_I2C_MULTI_BUS */
735987c5a   Tom Wai-Hong Tam   edid: Add I2C com...
1720
1721
1722
1723
  #if defined(CONFIG_I2C_EDID)
  	"i2c edid chip - print EDID configuration information
  "
  #endif  /* CONFIG_I2C_EDID */
fb0070e91   Frans Meulenbroeks   cmd_i2c.c: sorted...
1724
1725
  	"i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device
  "
d9fc70324   Matthias Fuchs   [PATCH] I2C: disa...
1726
1727
1728
1729
1730
1731
1732
1733
  	"i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device
  "
  	"i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)
  "
  	"i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)
  "
  	"i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)
  "
54b99e51a   Eric Nelson   i2c_probe: update...
1734
1735
  	"i2c probe [address] - test for and show device(s) on the I2C bus
  "
652e53546   Frans Meulenbroeks   cmd_i2c.c: added ...
1736
1737
  	"i2c read chip address[.0, .1, .2] length memaddress - read to memory 
  "
ff5d2dce1   York Sun   common/i2c: Add i...
1738
1739
  	"i2c write memaddress chip address[.0, .1, .2] length - write memory to i2c
  "
e43a27c49   Heiko Schocher   I2C: add new comm...
1740
1741
  	"i2c reset - re-init the I2C Controller
  "
c76fe4742   Jon Loeliger   common/cmd_[i-n]*...
1742
  #if defined(CONFIG_CMD_SDRAM)
fb0070e91   Frans Meulenbroeks   cmd_i2c.c: sorted...
1743
1744
  	"i2c sdram chip - print SDRAM configuration information
  "
902531788   Jon Loeliger   common/: Remove l...
1745
  #endif
088f1b199   Kim Phillips   common/cmd_*.c: s...
1746
1747
1748
1749
1750
1751
1752
  	"i2c speed [speed] - show or set I2C bus speed";
  #endif
  
  U_BOOT_CMD(
  	i2c, 6, 1, do_i2c,
  	"I2C sub-system",
  	i2c_help_text
d9fc70324   Matthias Fuchs   [PATCH] I2C: disa...
1753
  );