blob: 5a3b5574ee995c5ee33c3e2303b46ec8d8488e48 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
3 * Andreas Heppel <aheppel@sysgo.de>
4 *
5 * (C) Copyright 2002
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de.
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28/*
29 * PCI routines
30 */
31
32#include <common.h>
33
34#ifdef CONFIG_PCI
35
36#include <command.h>
37#include <cmd_boot.h>
38#include <asm/processor.h>
39#include <asm/io.h>
40#include <cmd_pci.h>
41#include <pci.h>
42
43#if (CONFIG_COMMANDS & CFG_CMD_PCI)
44
45extern int cmd_get_data_size(char* arg, int default_size);
46
47unsigned char ShortPCIListing = 1;
48
49/*
50 * Follows routines for the output of infos about devices on PCI bus.
51 */
52
53void pci_header_show(pci_dev_t dev);
54void pci_header_show_brief(pci_dev_t dev);
55
56/*
57 * Subroutine: pciinfo
58 *
59 * Description: Show information about devices on PCI bus.
60 * Depending on the define CFG_SHORT_PCI_LISTING
61 * the output will be more or less exhaustive.
62 *
63 * Inputs: bus_no the number of the bus to be scanned.
64 *
65 * Return: None
66 *
67 */
68void pciinfo(int BusNum, int ShortPCIListing)
69{
70 int Device;
71 int Function;
72 unsigned char HeaderType;
73 unsigned short VendorID;
74 pci_dev_t dev;
75
76 printf("Scanning PCI devices on bus %d\n", BusNum);
77
78 if (ShortPCIListing) {
79 printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
80 printf("_____________________________________________________________\n");
81 }
82
83 for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) {
84 HeaderType = 0;
85 VendorID = 0;
86 for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) {
87 /*
88 * If this is not a multi-function device, we skip the rest.
89 */
90 if (Function && !(HeaderType & 0x80))
91 break;
92
93 dev = PCI_BDF(BusNum, Device, Function);
94
95 pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID);
96 if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
97 continue;
98
wdenkc7de8292002-11-19 11:04:11 +000099 if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
wdenkc6097192002-11-03 00:24:07 +0000100
101 if (ShortPCIListing)
102 {
103 printf("%02x.%02x.%02x ", BusNum, Device, Function);
104 pci_header_show_brief(dev);
105 }
106 else
107 {
108 printf("\nFound PCI device %02x.%02x.%02x:\n",
109 BusNum, Device, Function);
110 pci_header_show(dev);
111 }
112 }
113 }
114}
115
116char* pci_classes_str(u8 class)
117{
118 static char *pci_classes[] = {
119 "Build before PCI Rev2.0",
120 "Mass storage controller",
121 "Network controller ",
122 "Display controller ",
123 "Multimedia device ",
124 "Memory controller ",
125 "Bridge device ",
126 "Simple comm. controller",
127 "Base system peripheral ",
128 "Input device ",
129 "Docking station ",
130 "Processor ",
131 "Serial bus controller ",
132 "Reserved entry ",
133 "Does not fit any class "
134 };
135
136 if (class < (sizeof pci_classes / sizeof *pci_classes))
137 return pci_classes[(int) class];
138
139 return "??? ";
140}
141
142/*
143 * Subroutine: pci_header_show_brief
144 *
145 * Description: Reads and prints the header of the
146 * specified PCI device in short form.
147 *
148 * Inputs: dev Bus+Device+Function number
149 *
150 * Return: None
151 *
152 */
153void pci_header_show_brief(pci_dev_t dev)
154{
155 u16 vendor, device;
156 u8 class, subclass;
157
158 pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
159 pci_read_config_word(dev, PCI_DEVICE_ID, &device);
160 pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
161 pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
162
163 printf("0x%.4x 0x%.4x %s 0x%.2x\n",
164 vendor, device,
165 pci_classes_str(class), subclass);
166}
167
168/*
169 * Subroutine: PCI_Header_Show
170 *
171 * Description: Reads the header of the specified PCI device.
172 *
173 * Inputs: BusDevFunc Bus+Device+Function number
174 *
175 * Return: None
176 *
177 */
178void pci_header_show(pci_dev_t dev)
179{
180 u8 _byte, header_type;
181 u16 _word;
182 u32 _dword;
183
184#define PRINT(msg, type, reg) \
185 pci_read_config_##type(dev, reg, &_##type); \
186 printf(msg, _##type)
187
188#define PRINT2(msg, type, reg, func) \
189 pci_read_config_##type(dev, reg, &_##type); \
190 printf(msg, _##type, func(_##type))
191
192 pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
193
194 PRINT (" vendor ID = 0x%.4x\n", word, PCI_VENDOR_ID);
195 PRINT (" device ID = 0x%.4x\n", word, PCI_DEVICE_ID);
196 PRINT (" command register = 0x%.4x\n", word, PCI_COMMAND);
197 PRINT (" status register = 0x%.4x\n", word, PCI_STATUS);
198 PRINT (" revision ID = 0x%.2x\n", byte, PCI_REVISION_ID);
199 PRINT2(" class code = 0x%.2x (%s)\n", byte, PCI_CLASS_CODE,
200 pci_classes_str);
201 PRINT (" sub class code = 0x%.2x\n", byte, PCI_CLASS_SUB_CODE);
202 PRINT (" programming interface = 0x%.2x\n", byte, PCI_CLASS_PROG);
203 PRINT (" cache line = 0x%.2x\n", byte, PCI_CACHE_LINE_SIZE);
204 PRINT (" latency time = 0x%.2x\n", byte, PCI_LATENCY_TIMER);
205 PRINT (" header type = 0x%.2x\n", byte, PCI_HEADER_TYPE);
206 PRINT (" BIST = 0x%.2x\n", byte, PCI_BIST);
207 PRINT (" base address 0 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_0);
wdenkc6097192002-11-03 00:24:07 +0000208
wdenk7c7a23b2002-12-07 00:20:59 +0000209 switch (header_type & 0x03) {
210 case PCI_HEADER_TYPE_NORMAL: /* "normal" PCI device */
211 PRINT (" base address 1 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
212 PRINT (" base address 2 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_2);
213 PRINT (" base address 3 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_3);
214 PRINT (" base address 4 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_4);
215 PRINT (" base address 5 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_5);
216 PRINT (" cardBus CIS pointer = 0x%.8x\n", dword, PCI_CARDBUS_CIS);
217 PRINT (" sub system vendor ID = 0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID);
218 PRINT (" sub system ID = 0x%.4x\n", word, PCI_SUBSYSTEM_ID);
219 PRINT (" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS);
220 PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
221 PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
222 PRINT (" min Grant = 0x%.2x\n", byte, PCI_MIN_GNT);
223 PRINT (" max Latency = 0x%.2x\n", byte, PCI_MAX_LAT);
224 break;
225
226 case PCI_HEADER_TYPE_BRIDGE: /* PCI-to-PCI bridge */
227
228 PRINT (" base address 1 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
wdenkc6097192002-11-03 00:24:07 +0000229 PRINT (" primary bus number = 0x%.2x\n", byte, PCI_PRIMARY_BUS);
230 PRINT (" secondary bus number = 0x%.2x\n", byte, PCI_SECONDARY_BUS);
231 PRINT (" subordinate bus number = 0x%.2x\n", byte, PCI_SUBORDINATE_BUS);
232 PRINT (" secondary latency timer = 0x%.2x\n", byte, PCI_SEC_LATENCY_TIMER);
233 PRINT (" IO base = 0x%.2x\n", byte, PCI_IO_BASE);
234 PRINT (" IO limit = 0x%.2x\n", byte, PCI_IO_LIMIT);
235 PRINT (" secondary status = 0x%.4x\n", word, PCI_SEC_STATUS);
236 PRINT (" memory base = 0x%.4x\n", word, PCI_MEMORY_BASE);
237 PRINT (" memory limit = 0x%.4x\n", word, PCI_MEMORY_LIMIT);
238 PRINT (" prefetch memory base = 0x%.4x\n", word, PCI_PREF_MEMORY_BASE);
239 PRINT (" prefetch memory limit = 0x%.4x\n", word, PCI_PREF_MEMORY_LIMIT);
240 PRINT (" prefetch memory base upper = 0x%.8x\n", dword, PCI_PREF_BASE_UPPER32);
241 PRINT (" prefetch memory limit upper = 0x%.8x\n", dword, PCI_PREF_LIMIT_UPPER32);
242 PRINT (" IO base upper 16 bits = 0x%.4x\n", word, PCI_IO_BASE_UPPER16);
243 PRINT (" IO limit upper 16 bits = 0x%.4x\n", word, PCI_IO_LIMIT_UPPER16);
244 PRINT (" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS1);
245 PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
246 PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
247 PRINT (" bridge control = 0x%.4x\n", word, PCI_BRIDGE_CONTROL);
wdenk7c7a23b2002-12-07 00:20:59 +0000248 break;
249
250 case PCI_HEADER_TYPE_CARDBUS: /* PCI-to-CardBus bridge */
251
252 PRINT (" capabilities = 0x%.2x\n", byte, PCI_CB_CAPABILITY_LIST);
253 PRINT (" secondary status = 0x%.4x\n", word, PCI_CB_SEC_STATUS);
254 PRINT (" primary bus number = 0x%.2x\n", byte, PCI_CB_PRIMARY_BUS);
255 PRINT (" CardBus number = 0x%.2x\n", byte, PCI_CB_CARD_BUS);
256 PRINT (" subordinate bus number = 0x%.2x\n", byte, PCI_CB_SUBORDINATE_BUS);
257 PRINT (" CardBus latency timer = 0x%.2x\n", byte, PCI_CB_LATENCY_TIMER);
258 PRINT (" CardBus memory base 0 = 0x%.8x\n", dword, PCI_CB_MEMORY_BASE_0);
259 PRINT (" CardBus memory limit 0 = 0x%.8x\n", dword, PCI_CB_MEMORY_LIMIT_0);
260 PRINT (" CardBus memory base 1 = 0x%.8x\n", dword, PCI_CB_MEMORY_BASE_1);
261 PRINT (" CardBus memory limit 1 = 0x%.8x\n", dword, PCI_CB_MEMORY_LIMIT_1);
262 PRINT (" CardBus IO base 0 = 0x%.4x\n", word, PCI_CB_IO_BASE_0);
263 PRINT (" CardBus IO base high 0 = 0x%.4x\n", word, PCI_CB_IO_BASE_0_HI);
264 PRINT (" CardBus IO limit 0 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_0);
265 PRINT (" CardBus IO limit high 0 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_0_HI);
266 PRINT (" CardBus IO base 1 = 0x%.4x\n", word, PCI_CB_IO_BASE_1);
267 PRINT (" CardBus IO base high 1 = 0x%.4x\n", word, PCI_CB_IO_BASE_1_HI);
268 PRINT (" CardBus IO limit 1 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_1);
269 PRINT (" CardBus IO limit high 1 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_1_HI);
270 PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
271 PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
272 PRINT (" bridge control = 0x%.4x\n", word, PCI_CB_BRIDGE_CONTROL);
273 PRINT (" subvendor ID = 0x%.4x\n", word, PCI_CB_SUBSYSTEM_VENDOR_ID);
274 PRINT (" subdevice ID = 0x%.4x\n", word, PCI_CB_SUBSYSTEM_ID);
275 PRINT (" PC Card 16bit base address = 0x%.8x\n", dword, PCI_CB_LEGACY_MODE_BASE);
276 break;
277
278 default:
279 printf("unknown header\n");
280 break;
wdenkc6097192002-11-03 00:24:07 +0000281 }
282
283#undef PRINT
284#undef PRINT2
285}
286
287/* Convert the "bus.device.function" identifier into a number.
288 */
289static pci_dev_t get_pci_dev(char* name)
290{
291 char cnum[12];
292 int len, i, iold, n;
293 int bdfs[3] = {0,0,0};
294
295 len = strlen(name);
296 if (len > 8)
297 return -1;
298 for (i = 0, iold = 0, n = 0; i < len; i++) {
299 if (name[i] == '.') {
300 memcpy(cnum, &name[iold], i - iold);
301 cnum[i - iold] = '\0';
302 bdfs[n++] = simple_strtoul(cnum, NULL, 16);
303 iold = i + 1;
304 }
305 }
306 strcpy(cnum, &name[iold]);
307 if (n == 0)
308 n = 1;
309 bdfs[n] = simple_strtoul(cnum, NULL, 16);
310 return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]);
311}
312
313static int pci_cfg_display(pci_dev_t bdf, ulong addr, ulong size, ulong length)
314{
315#define DISP_LINE_LEN 16
316 ulong i, nbytes, linebytes;
317 int rc = 0;
318
319 if (length == 0)
320 length = 0x40 / size; /* Standard PCI configuration space */
321
322 /* Print the lines.
323 * once, and all accesses are with the specified bus width.
324 */
325 nbytes = length * size;
326 do {
327 uint val4;
328 ushort val2;
329 u_char val1;
330
331 printf("%08lx:", addr);
332 linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
333 for (i=0; i<linebytes; i+= size) {
334 if (size == 4) {
335 pci_read_config_dword(bdf, addr, &val4);
336 printf(" %08x", val4);
337 } else if (size == 2) {
338 pci_read_config_word(bdf, addr, &val2);
339 printf(" %04x", val2);
340 } else {
341 pci_read_config_byte(bdf, addr, &val1);
342 printf(" %02x", val1);
343 }
344 addr += size;
345 }
346 printf("\n");
347 nbytes -= linebytes;
348 if (ctrlc()) {
349 rc = 1;
350 break;
351 }
352 } while (nbytes > 0);
353
354 return (rc);
355}
356
357static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value)
358{
359 if (size == 4) {
360 pci_write_config_dword(bdf, addr, value);
361 }
362 else if (size == 2) {
363 ushort val = value & 0xffff;
364 pci_write_config_word(bdf, addr, val);
365 }
366 else {
367 u_char val = value & 0xff;
368 pci_write_config_byte(bdf, addr, val);
369 }
370 return 0;
371}
372
373static int
374pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag)
375{
376 ulong i;
377 int nbytes;
378 extern char console_buffer[];
379 uint val4;
380 ushort val2;
381 u_char val1;
382
383 /* Print the address, followed by value. Then accept input for
384 * the next value. A non-converted value exits.
385 */
386 do {
387 printf("%08lx:", addr);
388 if (size == 4) {
389 pci_read_config_dword(bdf, addr, &val4);
390 printf(" %08x", val4);
391 }
392 else if (size == 2) {
393 pci_read_config_word(bdf, addr, &val2);
394 printf(" %04x", val2);
395 }
396 else {
397 pci_read_config_byte(bdf, addr, &val1);
398 printf(" %02x", val1);
399 }
400
401 nbytes = readline (" ? ");
402 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
403 /* <CR> pressed as only input, don't modify current
404 * location and move to next. "-" pressed will go back.
405 */
406 if (incrflag)
407 addr += nbytes ? -size : size;
408 nbytes = 1;
409#ifdef CONFIG_BOOT_RETRY_TIME
410 reset_cmd_timeout(); /* good enough to not time out */
411#endif
412 }
413#ifdef CONFIG_BOOT_RETRY_TIME
414 else if (nbytes == -2) {
415 break; /* timed out, exit the command */
416 }
417#endif
418 else {
419 char *endp;
420 i = simple_strtoul(console_buffer, &endp, 16);
421 nbytes = endp - console_buffer;
422 if (nbytes) {
423#ifdef CONFIG_BOOT_RETRY_TIME
424 /* good enough to not time out
425 */
426 reset_cmd_timeout();
427#endif
428 pci_cfg_write (bdf, addr, size, i);
429 if (incrflag)
430 addr += size;
431 }
432 }
433 } while (nbytes);
434
435 return 0;
436}
437
438/* PCI Configuration Space access commands
439 *
440 * Syntax:
441 * pci display[.b, .w, .l] bus.device.function} [addr] [len]
442 * pci next[.b, .w, .l] bus.device.function [addr]
443 * pci modify[.b, .w, .l] bus.device.function [addr]
444 * pci write[.b, .w, .l] bus.device.function addr value
445 */
446int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
447{
448 ulong addr = 0, value = 0, size = 0;
449 pci_dev_t bdf = 0;
450 char cmd = 's';
451
452 if (argc > 1)
453 cmd = argv[1][0];
454
455 switch (cmd) {
456 case 'd': /* display */
457 case 'n': /* next */
458 case 'm': /* modify */
459 case 'w': /* write */
460 /* Check for a size specification. */
461 size = cmd_get_data_size(argv[1], 4);
462 if (argc > 3)
463 addr = simple_strtoul(argv[3], NULL, 16);
464 if (argc > 4)
465 value = simple_strtoul(argv[4], NULL, 16);
466 case 'h': /* header */
467 if (argc < 3)
468 goto usage;
469 if ((bdf = get_pci_dev(argv[2])) == -1)
470 return 1;
471 break;
472 default: /* scan bus */
473 value = 1; /* short listing */
474 bdf = 0; /* bus number */
475 if (argc > 1) {
476 if (argv[argc-1][0] == 'l') {
477 value = 0;
478 argc--;
479 }
480 if (argc > 1)
481 bdf = simple_strtoul(argv[1], NULL, 16);
482 }
483 pciinfo(bdf, value);
484 return 0;
485 }
486
487 switch (argv[1][0]) {
488 case 'h': /* header */
489 pci_header_show(bdf);
490 return 0;
491 case 'd': /* display */
492 return pci_cfg_display(bdf, addr, size, value);
493 case 'n': /* next */
494 if (argc < 4)
495 goto usage;
496 return pci_cfg_modify(bdf, addr, size, value, 0);
497 case 'm': /* modify */
498 if (argc < 4)
499 goto usage;
500 return pci_cfg_modify(bdf, addr, size, value, 1);
501 case 'w': /* write */
502 if (argc < 5)
503 goto usage;
504 return pci_cfg_write(bdf, addr, size, value);
505 }
506
507 return 1;
508 usage:
509 printf ("Usage:\n%s\n", cmdtp->usage);
510 return 1;
511}
512
513#endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */
514
515#endif /* CONFIG_PCI */