dm: block: Adjust device calls to go through helpers function
[platform/kernel/u-boot.git] / cmd / pci.c
1 /*
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  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 /*
13  * PCI routines
14  */
15
16 #include <common.h>
17 #include <bootretry.h>
18 #include <cli.h>
19 #include <command.h>
20 #include <console.h>
21 #include <dm.h>
22 #include <asm/processor.h>
23 #include <asm/io.h>
24 #include <pci.h>
25
26 struct pci_reg_info {
27         const char *name;
28         enum pci_size_t size;
29         u8 offset;
30 };
31
32 static int pci_byte_size(enum pci_size_t size)
33 {
34         switch (size) {
35         case PCI_SIZE_8:
36                 return 1;
37         case PCI_SIZE_16:
38                 return 2;
39         case PCI_SIZE_32:
40         default:
41                 return 4;
42         }
43 }
44
45 static int pci_field_width(enum pci_size_t size)
46 {
47         return pci_byte_size(size) * 2;
48 }
49
50 #ifdef CONFIG_DM_PCI
51 static void pci_show_regs(struct udevice *dev, struct pci_reg_info *regs)
52 {
53         for (; regs->name; regs++) {
54                 unsigned long val;
55
56                 dm_pci_read_config(dev, regs->offset, &val, regs->size);
57                 printf("  %s =%*s%#.*lx\n", regs->name,
58                        (int)(28 - strlen(regs->name)), "",
59                        pci_field_width(regs->size), val);
60         }
61 }
62 #else
63 static unsigned long pci_read_config(pci_dev_t dev, int offset,
64                                      enum pci_size_t size)
65 {
66         u32 val32;
67         u16 val16;
68         u8 val8;
69
70         switch (size) {
71         case PCI_SIZE_8:
72                 pci_read_config_byte(dev, offset, &val8);
73                 return val8;
74         case PCI_SIZE_16:
75                 pci_read_config_word(dev, offset, &val16);
76                 return val16;
77         case PCI_SIZE_32:
78         default:
79                 pci_read_config_dword(dev, offset, &val32);
80                 return val32;
81         }
82 }
83
84 static void pci_show_regs(pci_dev_t dev, struct pci_reg_info *regs)
85 {
86         for (; regs->name; regs++) {
87                 printf("  %s =%*s%#.*lx\n", regs->name,
88                        (int)(28 - strlen(regs->name)), "",
89                        pci_field_width(regs->size),
90                        pci_read_config(dev, regs->offset, regs->size));
91         }
92 }
93 #endif
94
95 static struct pci_reg_info regs_start[] = {
96         { "vendor ID", PCI_SIZE_16, PCI_VENDOR_ID },
97         { "device ID", PCI_SIZE_16, PCI_DEVICE_ID },
98         { "command register ID", PCI_SIZE_16, PCI_COMMAND },
99         { "status register", PCI_SIZE_16, PCI_STATUS },
100         { "revision ID", PCI_SIZE_8, PCI_REVISION_ID },
101         {},
102 };
103
104 static struct pci_reg_info regs_rest[] = {
105         { "sub class code", PCI_SIZE_8, PCI_CLASS_SUB_CODE },
106         { "programming interface", PCI_SIZE_8, PCI_CLASS_PROG },
107         { "cache line", PCI_SIZE_8, PCI_CACHE_LINE_SIZE },
108         { "latency time", PCI_SIZE_8, PCI_LATENCY_TIMER },
109         { "header type", PCI_SIZE_8, PCI_HEADER_TYPE },
110         { "BIST", PCI_SIZE_8, PCI_BIST },
111         { "base address 0", PCI_SIZE_32, PCI_BASE_ADDRESS_0 },
112         {},
113 };
114
115 static struct pci_reg_info regs_normal[] = {
116         { "base address 1", PCI_SIZE_32, PCI_BASE_ADDRESS_1 },
117         { "base address 2", PCI_SIZE_32, PCI_BASE_ADDRESS_2 },
118         { "base address 3", PCI_SIZE_32, PCI_BASE_ADDRESS_3 },
119         { "base address 4", PCI_SIZE_32, PCI_BASE_ADDRESS_4 },
120         { "base address 5", PCI_SIZE_32, PCI_BASE_ADDRESS_5 },
121         { "cardBus CIS pointer", PCI_SIZE_32, PCI_CARDBUS_CIS },
122         { "sub system vendor ID", PCI_SIZE_16, PCI_SUBSYSTEM_VENDOR_ID },
123         { "sub system ID", PCI_SIZE_16, PCI_SUBSYSTEM_ID },
124         { "expansion ROM base address", PCI_SIZE_32, PCI_ROM_ADDRESS },
125         { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE },
126         { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN },
127         { "min Grant", PCI_SIZE_8, PCI_MIN_GNT },
128         { "max Latency", PCI_SIZE_8, PCI_MAX_LAT },
129         {},
130 };
131
132 static struct pci_reg_info regs_bridge[] = {
133         { "base address 1", PCI_SIZE_32, PCI_BASE_ADDRESS_1 },
134         { "primary bus number", PCI_SIZE_8, PCI_PRIMARY_BUS },
135         { "secondary bus number", PCI_SIZE_8, PCI_SECONDARY_BUS },
136         { "subordinate bus number", PCI_SIZE_8, PCI_SUBORDINATE_BUS },
137         { "secondary latency timer", PCI_SIZE_8, PCI_SEC_LATENCY_TIMER },
138         { "IO base", PCI_SIZE_8, PCI_IO_BASE },
139         { "IO limit", PCI_SIZE_8, PCI_IO_LIMIT },
140         { "secondary status", PCI_SIZE_16, PCI_SEC_STATUS },
141         { "memory base", PCI_SIZE_16, PCI_MEMORY_BASE },
142         { "memory limit", PCI_SIZE_16, PCI_MEMORY_LIMIT },
143         { "prefetch memory base", PCI_SIZE_16, PCI_PREF_MEMORY_BASE },
144         { "prefetch memory limit", PCI_SIZE_16, PCI_PREF_MEMORY_LIMIT },
145         { "prefetch memory base upper", PCI_SIZE_32, PCI_PREF_BASE_UPPER32 },
146         { "prefetch memory limit upper", PCI_SIZE_32, PCI_PREF_LIMIT_UPPER32 },
147         { "IO base upper 16 bits", PCI_SIZE_16, PCI_IO_BASE_UPPER16 },
148         { "IO limit upper 16 bits", PCI_SIZE_16, PCI_IO_LIMIT_UPPER16 },
149         { "expansion ROM base address", PCI_SIZE_32, PCI_ROM_ADDRESS1 },
150         { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE },
151         { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN },
152         { "bridge control", PCI_SIZE_16, PCI_BRIDGE_CONTROL },
153         {},
154 };
155
156 static struct pci_reg_info regs_cardbus[] = {
157         { "capabilities", PCI_SIZE_8, PCI_CB_CAPABILITY_LIST },
158         { "secondary status", PCI_SIZE_16, PCI_CB_SEC_STATUS },
159         { "primary bus number", PCI_SIZE_8, PCI_CB_PRIMARY_BUS },
160         { "CardBus number", PCI_SIZE_8, PCI_CB_CARD_BUS },
161         { "subordinate bus number", PCI_SIZE_8, PCI_CB_SUBORDINATE_BUS },
162         { "CardBus latency timer", PCI_SIZE_8, PCI_CB_LATENCY_TIMER },
163         { "CardBus memory base 0", PCI_SIZE_32, PCI_CB_MEMORY_BASE_0 },
164         { "CardBus memory limit 0", PCI_SIZE_32, PCI_CB_MEMORY_LIMIT_0 },
165         { "CardBus memory base 1", PCI_SIZE_32, PCI_CB_MEMORY_BASE_1 },
166         { "CardBus memory limit 1", PCI_SIZE_32, PCI_CB_MEMORY_LIMIT_1 },
167         { "CardBus IO base 0", PCI_SIZE_16, PCI_CB_IO_BASE_0 },
168         { "CardBus IO base high 0", PCI_SIZE_16, PCI_CB_IO_BASE_0_HI },
169         { "CardBus IO limit 0", PCI_SIZE_16, PCI_CB_IO_LIMIT_0 },
170         { "CardBus IO limit high 0", PCI_SIZE_16, PCI_CB_IO_LIMIT_0_HI },
171         { "CardBus IO base 1", PCI_SIZE_16, PCI_CB_IO_BASE_1 },
172         { "CardBus IO base high 1", PCI_SIZE_16, PCI_CB_IO_BASE_1_HI },
173         { "CardBus IO limit 1", PCI_SIZE_16, PCI_CB_IO_LIMIT_1 },
174         { "CardBus IO limit high 1", PCI_SIZE_16, PCI_CB_IO_LIMIT_1_HI },
175         { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE },
176         { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN },
177         { "bridge control", PCI_SIZE_16, PCI_CB_BRIDGE_CONTROL },
178         { "subvendor ID", PCI_SIZE_16, PCI_CB_SUBSYSTEM_VENDOR_ID },
179         { "subdevice ID", PCI_SIZE_16, PCI_CB_SUBSYSTEM_ID },
180         { "PC Card 16bit base address", PCI_SIZE_32, PCI_CB_LEGACY_MODE_BASE },
181         {},
182 };
183
184 /**
185  * pci_header_show() - Show the header of the specified PCI device.
186  *
187  * @dev: Bus+Device+Function number
188  */
189 #ifdef CONFIG_DM_PCI
190 void pci_header_show(struct udevice *dev)
191 #else
192 void pci_header_show(pci_dev_t dev)
193 #endif
194 {
195 #ifdef CONFIG_DM_PCI
196         unsigned long class, header_type;
197
198         dm_pci_read_config(dev, PCI_CLASS_CODE, &class, PCI_SIZE_8);
199         dm_pci_read_config(dev, PCI_HEADER_TYPE, &header_type, PCI_SIZE_8);
200 #else
201         u8 class, header_type;
202
203         pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
204         pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
205 #endif
206         pci_show_regs(dev, regs_start);
207         printf("  class code =                  0x%.2x (%s)\n", (int)class,
208                pci_class_str(class));
209         pci_show_regs(dev, regs_rest);
210
211         switch (header_type & 0x03) {
212         case PCI_HEADER_TYPE_NORMAL:    /* "normal" PCI device */
213                 pci_show_regs(dev, regs_normal);
214                 break;
215         case PCI_HEADER_TYPE_BRIDGE:    /* PCI-to-PCI bridge */
216                 pci_show_regs(dev, regs_bridge);
217                 break;
218         case PCI_HEADER_TYPE_CARDBUS:   /* PCI-to-CardBus bridge */
219                 pci_show_regs(dev, regs_cardbus);
220                 break;
221
222         default:
223                 printf("unknown header\n");
224                 break;
225     }
226 }
227
228 void pciinfo_header(int busnum, bool short_listing)
229 {
230         printf("Scanning PCI devices on bus %d\n", busnum);
231
232         if (short_listing) {
233                 printf("BusDevFun  VendorId   DeviceId   Device Class       Sub-Class\n");
234                 printf("_____________________________________________________________\n");
235         }
236 }
237
238 #ifdef CONFIG_DM_PCI
239 /**
240  * pci_header_show_brief() - Show the short-form PCI device header
241  *
242  * Reads and prints the header of the specified PCI device in short form.
243  *
244  * @dev: PCI device to show
245  */
246 static void pci_header_show_brief(struct udevice *dev)
247 {
248         ulong vendor, device;
249         ulong class, subclass;
250
251         dm_pci_read_config(dev, PCI_VENDOR_ID, &vendor, PCI_SIZE_16);
252         dm_pci_read_config(dev, PCI_DEVICE_ID, &device, PCI_SIZE_16);
253         dm_pci_read_config(dev, PCI_CLASS_CODE, &class, PCI_SIZE_8);
254         dm_pci_read_config(dev, PCI_CLASS_SUB_CODE, &subclass, PCI_SIZE_8);
255
256         printf("0x%.4lx     0x%.4lx     %-23s 0x%.2lx\n",
257                vendor, device,
258                pci_class_str(class), subclass);
259 }
260
261 static void pciinfo(struct udevice *bus, bool short_listing)
262 {
263         struct udevice *dev;
264
265         pciinfo_header(bus->seq, short_listing);
266
267         for (device_find_first_child(bus, &dev);
268              dev;
269              device_find_next_child(&dev)) {
270                 struct pci_child_platdata *pplat;
271
272                 pplat = dev_get_parent_platdata(dev);
273                 if (short_listing) {
274                         printf("%02x.%02x.%02x   ", bus->seq,
275                                PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn));
276                         pci_header_show_brief(dev);
277                 } else {
278                         printf("\nFound PCI device %02x.%02x.%02x:\n", bus->seq,
279                                PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn));
280                         pci_header_show(dev);
281                 }
282         }
283 }
284
285 #else
286
287 /**
288  * pci_header_show_brief() - Show the short-form PCI device header
289  *
290  * Reads and prints the header of the specified PCI device in short form.
291  *
292  * @dev: Bus+Device+Function number
293  */
294 void pci_header_show_brief(pci_dev_t dev)
295 {
296         u16 vendor, device;
297         u8 class, subclass;
298
299         pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
300         pci_read_config_word(dev, PCI_DEVICE_ID, &device);
301         pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
302         pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
303
304         printf("0x%.4x     0x%.4x     %-23s 0x%.2x\n",
305                vendor, device,
306                pci_class_str(class), subclass);
307 }
308
309 /**
310  * pciinfo() - Show a list of devices on the PCI bus
311  *
312  * Show information about devices on PCI bus. Depending on @short_pci_listing
313  * the output will be more or less exhaustive.
314  *
315  * @bus_num: The number of the bus to be scanned
316  * @short_pci_listing: true to use short form, showing only a brief header
317  * for each device
318  */
319 void pciinfo(int bus_num, int short_pci_listing)
320 {
321         struct pci_controller *hose = pci_bus_to_hose(bus_num);
322         int device;
323         int function;
324         unsigned char header_type;
325         unsigned short vendor_id;
326         pci_dev_t dev;
327         int ret;
328
329         if (!hose)
330                 return;
331
332         pciinfo_header(bus_num, short_pci_listing);
333
334         for (device = 0; device < PCI_MAX_PCI_DEVICES; device++) {
335                 header_type = 0;
336                 vendor_id = 0;
337                 for (function = 0; function < PCI_MAX_PCI_FUNCTIONS;
338                      function++) {
339                         /*
340                          * If this is not a multi-function device, we skip
341                          * the rest.
342                          */
343                         if (function && !(header_type & 0x80))
344                                 break;
345
346                         dev = PCI_BDF(bus_num, device, function);
347
348                         if (pci_skip_dev(hose, dev))
349                                 continue;
350
351                         ret = pci_read_config_word(dev, PCI_VENDOR_ID,
352                                                    &vendor_id);
353                         if (ret)
354                                 goto error;
355                         if ((vendor_id == 0xFFFF) || (vendor_id == 0x0000))
356                                 continue;
357
358                         if (!function) {
359                                 pci_read_config_byte(dev, PCI_HEADER_TYPE,
360                                                      &header_type);
361                         }
362
363                         if (short_pci_listing) {
364                                 printf("%02x.%02x.%02x   ", bus_num, device,
365                                        function);
366                                 pci_header_show_brief(dev);
367                         } else {
368                                 printf("\nFound PCI device %02x.%02x.%02x:\n",
369                                        bus_num, device, function);
370                                 pci_header_show(dev);
371                         }
372                 }
373         }
374
375         return;
376 error:
377         printf("Cannot read bus configuration: %d\n", ret);
378 }
379 #endif
380
381 /**
382  * get_pci_dev() - Convert the "bus.device.function" identifier into a number
383  *
384  * @name: Device string in the form "bus.device.function" where each is in hex
385  * @return encoded pci_dev_t or -1 if the string was invalid
386  */
387 static pci_dev_t get_pci_dev(char *name)
388 {
389         char cnum[12];
390         int len, i, iold, n;
391         int bdfs[3] = {0,0,0};
392
393         len = strlen(name);
394         if (len > 8)
395                 return -1;
396         for (i = 0, iold = 0, n = 0; i < len; i++) {
397                 if (name[i] == '.') {
398                         memcpy(cnum, &name[iold], i - iold);
399                         cnum[i - iold] = '\0';
400                         bdfs[n++] = simple_strtoul(cnum, NULL, 16);
401                         iold = i + 1;
402                 }
403         }
404         strcpy(cnum, &name[iold]);
405         if (n == 0)
406                 n = 1;
407         bdfs[n] = simple_strtoul(cnum, NULL, 16);
408
409         return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]);
410 }
411
412 #ifdef CONFIG_DM_PCI
413 static int pci_cfg_display(struct udevice *dev, ulong addr,
414                            enum pci_size_t size, ulong length)
415 #else
416 static int pci_cfg_display(pci_dev_t bdf, ulong addr, enum pci_size_t size,
417                            ulong length)
418 #endif
419 {
420 #define DISP_LINE_LEN   16
421         ulong i, nbytes, linebytes;
422         int byte_size;
423         int rc = 0;
424
425         byte_size = pci_byte_size(size);
426         if (length == 0)
427                 length = 0x40 / byte_size; /* Standard PCI config space */
428
429         /* Print the lines.
430          * once, and all accesses are with the specified bus width.
431          */
432         nbytes = length * byte_size;
433         do {
434                 printf("%08lx:", addr);
435                 linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
436                 for (i = 0; i < linebytes; i += byte_size) {
437                         unsigned long val;
438
439 #ifdef CONFIG_DM_PCI
440                         dm_pci_read_config(dev, addr, &val, size);
441 #else
442                         val = pci_read_config(bdf, addr, size);
443 #endif
444                         printf(" %0*lx", pci_field_width(size), val);
445                         addr += byte_size;
446                 }
447                 printf("\n");
448                 nbytes -= linebytes;
449                 if (ctrlc()) {
450                         rc = 1;
451                         break;
452                 }
453         } while (nbytes > 0);
454
455         return (rc);
456 }
457
458 #ifndef CONFIG_DM_PCI
459 static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value)
460 {
461         if (size == 4) {
462                 pci_write_config_dword(bdf, addr, value);
463         }
464         else if (size == 2) {
465                 ushort val = value & 0xffff;
466                 pci_write_config_word(bdf, addr, val);
467         }
468         else {
469                 u_char val = value & 0xff;
470                 pci_write_config_byte(bdf, addr, val);
471         }
472         return 0;
473 }
474 #endif
475
476 #ifdef CONFIG_DM_PCI
477 static int pci_cfg_modify(struct udevice *dev, ulong addr, ulong size,
478                           ulong value, int incrflag)
479 #else
480 static int pci_cfg_modify(pci_dev_t bdf, ulong addr, ulong size, ulong value,
481                           int incrflag)
482 #endif
483 {
484         ulong   i;
485         int     nbytes;
486         ulong val;
487
488         /* Print the address, followed by value.  Then accept input for
489          * the next value.  A non-converted value exits.
490          */
491         do {
492                 printf("%08lx:", addr);
493 #ifdef CONFIG_DM_PCI
494                 dm_pci_read_config(dev, addr, &val, size);
495 #else
496                 val = pci_read_config(bdf, addr, size);
497 #endif
498                 printf(" %0*lx", pci_field_width(size), val);
499
500                 nbytes = cli_readline(" ? ");
501                 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
502                         /* <CR> pressed as only input, don't modify current
503                          * location and move to next. "-" pressed will go back.
504                          */
505                         if (incrflag)
506                                 addr += nbytes ? -size : size;
507                         nbytes = 1;
508                         /* good enough to not time out */
509                         bootretry_reset_cmd_timeout();
510                 }
511 #ifdef CONFIG_BOOT_RETRY_TIME
512                 else if (nbytes == -2) {
513                         break;  /* timed out, exit the command  */
514                 }
515 #endif
516                 else {
517                         char *endp;
518                         i = simple_strtoul(console_buffer, &endp, 16);
519                         nbytes = endp - console_buffer;
520                         if (nbytes) {
521                                 /* good enough to not time out
522                                  */
523                                 bootretry_reset_cmd_timeout();
524 #ifdef CONFIG_DM_PCI
525                                 dm_pci_write_config(dev, addr, i, size);
526 #else
527                                 pci_cfg_write(bdf, addr, size, i);
528 #endif
529                                 if (incrflag)
530                                         addr += size;
531                         }
532                 }
533         } while (nbytes);
534
535         return 0;
536 }
537
538 /* PCI Configuration Space access commands
539  *
540  * Syntax:
541  *      pci display[.b, .w, .l] bus.device.function} [addr] [len]
542  *      pci next[.b, .w, .l] bus.device.function [addr]
543  *      pci modify[.b, .w, .l] bus.device.function [addr]
544  *      pci write[.b, .w, .l] bus.device.function addr value
545  */
546 static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
547 {
548         ulong addr = 0, value = 0, cmd_size = 0;
549         enum pci_size_t size = PCI_SIZE_32;
550 #ifdef CONFIG_DM_PCI
551         struct udevice *dev, *bus;
552 #else
553         pci_dev_t dev;
554 #endif
555         int busnum = 0;
556         pci_dev_t bdf = 0;
557         char cmd = 's';
558         int ret = 0;
559
560         if (argc > 1)
561                 cmd = argv[1][0];
562
563         switch (cmd) {
564         case 'd':               /* display */
565         case 'n':               /* next */
566         case 'm':               /* modify */
567         case 'w':               /* write */
568                 /* Check for a size specification. */
569                 cmd_size = cmd_get_data_size(argv[1], 4);
570                 size = (cmd_size == 4) ? PCI_SIZE_32 : cmd_size - 1;
571                 if (argc > 3)
572                         addr = simple_strtoul(argv[3], NULL, 16);
573                 if (argc > 4)
574                         value = simple_strtoul(argv[4], NULL, 16);
575         case 'h':               /* header */
576                 if (argc < 3)
577                         goto usage;
578                 if ((bdf = get_pci_dev(argv[2])) == -1)
579                         return 1;
580                 break;
581 #if defined(CONFIG_CMD_PCI_ENUM) || defined(CONFIG_DM_PCI)
582         case 'e':
583                 pci_init();
584                 return 0;
585 #endif
586         default:                /* scan bus */
587                 value = 1; /* short listing */
588                 if (argc > 1) {
589                         if (argv[argc-1][0] == 'l') {
590                                 value = 0;
591                                 argc--;
592                         }
593                         if (argc > 1)
594                                 busnum = simple_strtoul(argv[1], NULL, 16);
595                 }
596 #ifdef CONFIG_DM_PCI
597                 ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus);
598                 if (ret) {
599                         printf("No such bus\n");
600                         return CMD_RET_FAILURE;
601                 }
602                 pciinfo(bus, value);
603 #else
604                 pciinfo(busnum, value);
605 #endif
606                 return 0;
607         }
608
609 #ifdef CONFIG_DM_PCI
610         ret = dm_pci_bus_find_bdf(bdf, &dev);
611         if (ret) {
612                 printf("No such device\n");
613                 return CMD_RET_FAILURE;
614         }
615 #else
616         dev = bdf;
617 #endif
618
619         switch (argv[1][0]) {
620         case 'h':               /* header */
621                 pci_header_show(dev);
622                 break;
623         case 'd':               /* display */
624                 return pci_cfg_display(dev, addr, size, value);
625         case 'n':               /* next */
626                 if (argc < 4)
627                         goto usage;
628                 ret = pci_cfg_modify(dev, addr, size, value, 0);
629                 break;
630         case 'm':               /* modify */
631                 if (argc < 4)
632                         goto usage;
633                 ret = pci_cfg_modify(dev, addr, size, value, 1);
634                 break;
635         case 'w':               /* write */
636                 if (argc < 5)
637                         goto usage;
638 #ifdef CONFIG_DM_PCI
639                 ret = dm_pci_write_config(dev, addr, value, size);
640 #else
641                 ret = pci_cfg_write(dev, addr, size, value);
642 #endif
643                 break;
644         default:
645                 ret = CMD_RET_USAGE;
646                 break;
647         }
648
649         return ret;
650  usage:
651         return CMD_RET_USAGE;
652 }
653
654 /***************************************************/
655
656 #ifdef CONFIG_SYS_LONGHELP
657 static char pci_help_text[] =
658         "[bus] [long]\n"
659         "    - short or long list of PCI devices on bus 'bus'\n"
660 #if defined(CONFIG_CMD_PCI_ENUM) || defined(CONFIG_DM_PCI)
661         "pci enum\n"
662         "    - Enumerate PCI buses\n"
663 #endif
664         "pci header b.d.f\n"
665         "    - show header of PCI device 'bus.device.function'\n"
666         "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n"
667         "    - display PCI configuration space (CFG)\n"
668         "pci next[.b, .w, .l] b.d.f address\n"
669         "    - modify, read and keep CFG address\n"
670         "pci modify[.b, .w, .l] b.d.f address\n"
671         "    -  modify, auto increment CFG address\n"
672         "pci write[.b, .w, .l] b.d.f address value\n"
673         "    - write to CFG address";
674 #endif
675
676 U_BOOT_CMD(
677         pci,    5,      1,      do_pci,
678         "list and access PCI Configuration Space", pci_help_text
679 );