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