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 #ifdef CONFIG_DM_PCI 96 int pci_bar_show(struct udevice *dev) 97 { 98 u8 header_type; 99 int bar_cnt, bar_id, mem_type; 100 bool is_64, is_io; 101 u32 base_low, base_high; 102 u32 size_low, size_high; 103 u64 base, size; 104 u32 reg_addr; 105 int prefetchable; 106 107 dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); 108 109 if (header_type == PCI_HEADER_TYPE_CARDBUS) { 110 printf("CardBus doesn't support BARs\n"); 111 return -ENOSYS; 112 } 113 114 bar_cnt = (header_type == PCI_HEADER_TYPE_NORMAL) ? 6 : 2; 115 116 printf("ID Base Size Width Type\n"); 117 printf("----------------------------------------------------------\n"); 118 119 bar_id = 0; 120 reg_addr = PCI_BASE_ADDRESS_0; 121 while (bar_cnt) { 122 dm_pci_read_config32(dev, reg_addr, &base_low); 123 dm_pci_write_config32(dev, reg_addr, 0xffffffff); 124 dm_pci_read_config32(dev, reg_addr, &size_low); 125 dm_pci_write_config32(dev, reg_addr, base_low); 126 reg_addr += 4; 127 128 base = base_low & ~0xf; 129 size = size_low & ~0xf; 130 base_high = 0x0; 131 size_high = 0xffffffff; 132 is_64 = 0; 133 prefetchable = base_low & PCI_BASE_ADDRESS_MEM_PREFETCH; 134 is_io = base_low & PCI_BASE_ADDRESS_SPACE_IO; 135 mem_type = base_low & PCI_BASE_ADDRESS_MEM_TYPE_MASK; 136 137 if (mem_type == PCI_BASE_ADDRESS_MEM_TYPE_64) { 138 dm_pci_read_config32(dev, reg_addr, &base_high); 139 dm_pci_write_config32(dev, reg_addr, 0xffffffff); 140 dm_pci_read_config32(dev, reg_addr, &size_high); 141 dm_pci_write_config32(dev, reg_addr, base_high); 142 bar_cnt--; 143 reg_addr += 4; 144 is_64 = 1; 145 } 146 147 base = base | ((u64)base_high << 32); 148 size = size | ((u64)size_high << 32); 149 150 if ((!is_64 && size_low) || (is_64 && size)) { 151 size = ~size + 1; 152 printf(" %d %#016llx %#016llx %d %s %s\n", 153 bar_id, (unsigned long long)base, 154 (unsigned long long)size, is_64 ? 64 : 32, 155 is_io ? "I/O" : "MEM", 156 prefetchable ? "Prefetchable" : ""); 157 } 158 159 bar_id++; 160 bar_cnt--; 161 } 162 163 return 0; 164 } 165 #endif 166 167 static struct pci_reg_info regs_start[] = { 168 { "vendor ID", PCI_SIZE_16, PCI_VENDOR_ID }, 169 { "device ID", PCI_SIZE_16, PCI_DEVICE_ID }, 170 { "command register ID", PCI_SIZE_16, PCI_COMMAND }, 171 { "status register", PCI_SIZE_16, PCI_STATUS }, 172 { "revision ID", PCI_SIZE_8, PCI_REVISION_ID }, 173 {}, 174 }; 175 176 static struct pci_reg_info regs_rest[] = { 177 { "sub class code", PCI_SIZE_8, PCI_CLASS_SUB_CODE }, 178 { "programming interface", PCI_SIZE_8, PCI_CLASS_PROG }, 179 { "cache line", PCI_SIZE_8, PCI_CACHE_LINE_SIZE }, 180 { "latency time", PCI_SIZE_8, PCI_LATENCY_TIMER }, 181 { "header type", PCI_SIZE_8, PCI_HEADER_TYPE }, 182 { "BIST", PCI_SIZE_8, PCI_BIST }, 183 { "base address 0", PCI_SIZE_32, PCI_BASE_ADDRESS_0 }, 184 {}, 185 }; 186 187 static struct pci_reg_info regs_normal[] = { 188 { "base address 1", PCI_SIZE_32, PCI_BASE_ADDRESS_1 }, 189 { "base address 2", PCI_SIZE_32, PCI_BASE_ADDRESS_2 }, 190 { "base address 3", PCI_SIZE_32, PCI_BASE_ADDRESS_3 }, 191 { "base address 4", PCI_SIZE_32, PCI_BASE_ADDRESS_4 }, 192 { "base address 5", PCI_SIZE_32, PCI_BASE_ADDRESS_5 }, 193 { "cardBus CIS pointer", PCI_SIZE_32, PCI_CARDBUS_CIS }, 194 { "sub system vendor ID", PCI_SIZE_16, PCI_SUBSYSTEM_VENDOR_ID }, 195 { "sub system ID", PCI_SIZE_16, PCI_SUBSYSTEM_ID }, 196 { "expansion ROM base address", PCI_SIZE_32, PCI_ROM_ADDRESS }, 197 { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE }, 198 { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN }, 199 { "min Grant", PCI_SIZE_8, PCI_MIN_GNT }, 200 { "max Latency", PCI_SIZE_8, PCI_MAX_LAT }, 201 {}, 202 }; 203 204 static struct pci_reg_info regs_bridge[] = { 205 { "base address 1", PCI_SIZE_32, PCI_BASE_ADDRESS_1 }, 206 { "primary bus number", PCI_SIZE_8, PCI_PRIMARY_BUS }, 207 { "secondary bus number", PCI_SIZE_8, PCI_SECONDARY_BUS }, 208 { "subordinate bus number", PCI_SIZE_8, PCI_SUBORDINATE_BUS }, 209 { "secondary latency timer", PCI_SIZE_8, PCI_SEC_LATENCY_TIMER }, 210 { "IO base", PCI_SIZE_8, PCI_IO_BASE }, 211 { "IO limit", PCI_SIZE_8, PCI_IO_LIMIT }, 212 { "secondary status", PCI_SIZE_16, PCI_SEC_STATUS }, 213 { "memory base", PCI_SIZE_16, PCI_MEMORY_BASE }, 214 { "memory limit", PCI_SIZE_16, PCI_MEMORY_LIMIT }, 215 { "prefetch memory base", PCI_SIZE_16, PCI_PREF_MEMORY_BASE }, 216 { "prefetch memory limit", PCI_SIZE_16, PCI_PREF_MEMORY_LIMIT }, 217 { "prefetch memory base upper", PCI_SIZE_32, PCI_PREF_BASE_UPPER32 }, 218 { "prefetch memory limit upper", PCI_SIZE_32, PCI_PREF_LIMIT_UPPER32 }, 219 { "IO base upper 16 bits", PCI_SIZE_16, PCI_IO_BASE_UPPER16 }, 220 { "IO limit upper 16 bits", PCI_SIZE_16, PCI_IO_LIMIT_UPPER16 }, 221 { "expansion ROM base address", PCI_SIZE_32, PCI_ROM_ADDRESS1 }, 222 { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE }, 223 { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN }, 224 { "bridge control", PCI_SIZE_16, PCI_BRIDGE_CONTROL }, 225 {}, 226 }; 227 228 static struct pci_reg_info regs_cardbus[] = { 229 { "capabilities", PCI_SIZE_8, PCI_CB_CAPABILITY_LIST }, 230 { "secondary status", PCI_SIZE_16, PCI_CB_SEC_STATUS }, 231 { "primary bus number", PCI_SIZE_8, PCI_CB_PRIMARY_BUS }, 232 { "CardBus number", PCI_SIZE_8, PCI_CB_CARD_BUS }, 233 { "subordinate bus number", PCI_SIZE_8, PCI_CB_SUBORDINATE_BUS }, 234 { "CardBus latency timer", PCI_SIZE_8, PCI_CB_LATENCY_TIMER }, 235 { "CardBus memory base 0", PCI_SIZE_32, PCI_CB_MEMORY_BASE_0 }, 236 { "CardBus memory limit 0", PCI_SIZE_32, PCI_CB_MEMORY_LIMIT_0 }, 237 { "CardBus memory base 1", PCI_SIZE_32, PCI_CB_MEMORY_BASE_1 }, 238 { "CardBus memory limit 1", PCI_SIZE_32, PCI_CB_MEMORY_LIMIT_1 }, 239 { "CardBus IO base 0", PCI_SIZE_16, PCI_CB_IO_BASE_0 }, 240 { "CardBus IO base high 0", PCI_SIZE_16, PCI_CB_IO_BASE_0_HI }, 241 { "CardBus IO limit 0", PCI_SIZE_16, PCI_CB_IO_LIMIT_0 }, 242 { "CardBus IO limit high 0", PCI_SIZE_16, PCI_CB_IO_LIMIT_0_HI }, 243 { "CardBus IO base 1", PCI_SIZE_16, PCI_CB_IO_BASE_1 }, 244 { "CardBus IO base high 1", PCI_SIZE_16, PCI_CB_IO_BASE_1_HI }, 245 { "CardBus IO limit 1", PCI_SIZE_16, PCI_CB_IO_LIMIT_1 }, 246 { "CardBus IO limit high 1", PCI_SIZE_16, PCI_CB_IO_LIMIT_1_HI }, 247 { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE }, 248 { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN }, 249 { "bridge control", PCI_SIZE_16, PCI_CB_BRIDGE_CONTROL }, 250 { "subvendor ID", PCI_SIZE_16, PCI_CB_SUBSYSTEM_VENDOR_ID }, 251 { "subdevice ID", PCI_SIZE_16, PCI_CB_SUBSYSTEM_ID }, 252 { "PC Card 16bit base address", PCI_SIZE_32, PCI_CB_LEGACY_MODE_BASE }, 253 {}, 254 }; 255 256 /** 257 * pci_header_show() - Show the header of the specified PCI device. 258 * 259 * @dev: Bus+Device+Function number 260 */ 261 #ifdef CONFIG_DM_PCI 262 void pci_header_show(struct udevice *dev) 263 #else 264 void pci_header_show(pci_dev_t dev) 265 #endif 266 { 267 #ifdef CONFIG_DM_PCI 268 unsigned long class, header_type; 269 270 dm_pci_read_config(dev, PCI_CLASS_CODE, &class, PCI_SIZE_8); 271 dm_pci_read_config(dev, PCI_HEADER_TYPE, &header_type, PCI_SIZE_8); 272 #else 273 u8 class, header_type; 274 275 pci_read_config_byte(dev, PCI_CLASS_CODE, &class); 276 pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); 277 #endif 278 pci_show_regs(dev, regs_start); 279 printf(" class code = 0x%.2x (%s)\n", (int)class, 280 pci_class_str(class)); 281 pci_show_regs(dev, regs_rest); 282 283 switch (header_type & 0x03) { 284 case PCI_HEADER_TYPE_NORMAL: /* "normal" PCI device */ 285 pci_show_regs(dev, regs_normal); 286 break; 287 case PCI_HEADER_TYPE_BRIDGE: /* PCI-to-PCI bridge */ 288 pci_show_regs(dev, regs_bridge); 289 break; 290 case PCI_HEADER_TYPE_CARDBUS: /* PCI-to-CardBus bridge */ 291 pci_show_regs(dev, regs_cardbus); 292 break; 293 294 default: 295 printf("unknown header\n"); 296 break; 297 } 298 } 299 300 void pciinfo_header(int busnum, bool short_listing) 301 { 302 printf("Scanning PCI devices on bus %d\n", busnum); 303 304 if (short_listing) { 305 printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n"); 306 printf("_____________________________________________________________\n"); 307 } 308 } 309 310 #ifdef CONFIG_DM_PCI 311 /** 312 * pci_header_show_brief() - Show the short-form PCI device header 313 * 314 * Reads and prints the header of the specified PCI device in short form. 315 * 316 * @dev: PCI device to show 317 */ 318 static void pci_header_show_brief(struct udevice *dev) 319 { 320 ulong vendor, device; 321 ulong class, subclass; 322 323 dm_pci_read_config(dev, PCI_VENDOR_ID, &vendor, PCI_SIZE_16); 324 dm_pci_read_config(dev, PCI_DEVICE_ID, &device, PCI_SIZE_16); 325 dm_pci_read_config(dev, PCI_CLASS_CODE, &class, PCI_SIZE_8); 326 dm_pci_read_config(dev, PCI_CLASS_SUB_CODE, &subclass, PCI_SIZE_8); 327 328 printf("0x%.4lx 0x%.4lx %-23s 0x%.2lx\n", 329 vendor, device, 330 pci_class_str(class), subclass); 331 } 332 333 static void pciinfo(struct udevice *bus, bool short_listing) 334 { 335 struct udevice *dev; 336 337 pciinfo_header(bus->seq, short_listing); 338 339 for (device_find_first_child(bus, &dev); 340 dev; 341 device_find_next_child(&dev)) { 342 struct pci_child_platdata *pplat; 343 344 pplat = dev_get_parent_platdata(dev); 345 if (short_listing) { 346 printf("%02x.%02x.%02x ", bus->seq, 347 PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); 348 pci_header_show_brief(dev); 349 } else { 350 printf("\nFound PCI device %02x.%02x.%02x:\n", bus->seq, 351 PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); 352 pci_header_show(dev); 353 } 354 } 355 } 356 357 #else 358 359 /** 360 * pci_header_show_brief() - Show the short-form PCI device header 361 * 362 * Reads and prints the header of the specified PCI device in short form. 363 * 364 * @dev: Bus+Device+Function number 365 */ 366 void pci_header_show_brief(pci_dev_t dev) 367 { 368 u16 vendor, device; 369 u8 class, subclass; 370 371 pci_read_config_word(dev, PCI_VENDOR_ID, &vendor); 372 pci_read_config_word(dev, PCI_DEVICE_ID, &device); 373 pci_read_config_byte(dev, PCI_CLASS_CODE, &class); 374 pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass); 375 376 printf("0x%.4x 0x%.4x %-23s 0x%.2x\n", 377 vendor, device, 378 pci_class_str(class), subclass); 379 } 380 381 /** 382 * pciinfo() - Show a list of devices on the PCI bus 383 * 384 * Show information about devices on PCI bus. Depending on @short_pci_listing 385 * the output will be more or less exhaustive. 386 * 387 * @bus_num: The number of the bus to be scanned 388 * @short_pci_listing: true to use short form, showing only a brief header 389 * for each device 390 */ 391 void pciinfo(int bus_num, int short_pci_listing) 392 { 393 struct pci_controller *hose = pci_bus_to_hose(bus_num); 394 int device; 395 int function; 396 unsigned char header_type; 397 unsigned short vendor_id; 398 pci_dev_t dev; 399 int ret; 400 401 if (!hose) 402 return; 403 404 pciinfo_header(bus_num, short_pci_listing); 405 406 for (device = 0; device < PCI_MAX_PCI_DEVICES; device++) { 407 header_type = 0; 408 vendor_id = 0; 409 for (function = 0; function < PCI_MAX_PCI_FUNCTIONS; 410 function++) { 411 /* 412 * If this is not a multi-function device, we skip 413 * the rest. 414 */ 415 if (function && !(header_type & 0x80)) 416 break; 417 418 dev = PCI_BDF(bus_num, device, function); 419 420 if (pci_skip_dev(hose, dev)) 421 continue; 422 423 ret = pci_read_config_word(dev, PCI_VENDOR_ID, 424 &vendor_id); 425 if (ret) 426 goto error; 427 if ((vendor_id == 0xFFFF) || (vendor_id == 0x0000)) 428 continue; 429 430 if (!function) { 431 pci_read_config_byte(dev, PCI_HEADER_TYPE, 432 &header_type); 433 } 434 435 if (short_pci_listing) { 436 printf("%02x.%02x.%02x ", bus_num, device, 437 function); 438 pci_header_show_brief(dev); 439 } else { 440 printf("\nFound PCI device %02x.%02x.%02x:\n", 441 bus_num, device, function); 442 pci_header_show(dev); 443 } 444 } 445 } 446 447 return; 448 error: 449 printf("Cannot read bus configuration: %d\n", ret); 450 } 451 #endif 452 453 /** 454 * get_pci_dev() - Convert the "bus.device.function" identifier into a number 455 * 456 * @name: Device string in the form "bus.device.function" where each is in hex 457 * @return encoded pci_dev_t or -1 if the string was invalid 458 */ 459 static pci_dev_t get_pci_dev(char *name) 460 { 461 char cnum[12]; 462 int len, i, iold, n; 463 int bdfs[3] = {0,0,0}; 464 465 len = strlen(name); 466 if (len > 8) 467 return -1; 468 for (i = 0, iold = 0, n = 0; i < len; i++) { 469 if (name[i] == '.') { 470 memcpy(cnum, &name[iold], i - iold); 471 cnum[i - iold] = '\0'; 472 bdfs[n++] = simple_strtoul(cnum, NULL, 16); 473 iold = i + 1; 474 } 475 } 476 strcpy(cnum, &name[iold]); 477 if (n == 0) 478 n = 1; 479 bdfs[n] = simple_strtoul(cnum, NULL, 16); 480 481 return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]); 482 } 483 484 #ifdef CONFIG_DM_PCI 485 static int pci_cfg_display(struct udevice *dev, ulong addr, 486 enum pci_size_t size, ulong length) 487 #else 488 static int pci_cfg_display(pci_dev_t bdf, ulong addr, enum pci_size_t size, 489 ulong length) 490 #endif 491 { 492 #define DISP_LINE_LEN 16 493 ulong i, nbytes, linebytes; 494 int byte_size; 495 int rc = 0; 496 497 byte_size = pci_byte_size(size); 498 if (length == 0) 499 length = 0x40 / byte_size; /* Standard PCI config space */ 500 501 /* Print the lines. 502 * once, and all accesses are with the specified bus width. 503 */ 504 nbytes = length * byte_size; 505 do { 506 printf("%08lx:", addr); 507 linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; 508 for (i = 0; i < linebytes; i += byte_size) { 509 unsigned long val; 510 511 #ifdef CONFIG_DM_PCI 512 dm_pci_read_config(dev, addr, &val, size); 513 #else 514 val = pci_read_config(bdf, addr, size); 515 #endif 516 printf(" %0*lx", pci_field_width(size), val); 517 addr += byte_size; 518 } 519 printf("\n"); 520 nbytes -= linebytes; 521 if (ctrlc()) { 522 rc = 1; 523 break; 524 } 525 } while (nbytes > 0); 526 527 return (rc); 528 } 529 530 #ifndef CONFIG_DM_PCI 531 static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value) 532 { 533 if (size == 4) { 534 pci_write_config_dword(bdf, addr, value); 535 } 536 else if (size == 2) { 537 ushort val = value & 0xffff; 538 pci_write_config_word(bdf, addr, val); 539 } 540 else { 541 u_char val = value & 0xff; 542 pci_write_config_byte(bdf, addr, val); 543 } 544 return 0; 545 } 546 #endif 547 548 #ifdef CONFIG_DM_PCI 549 static int pci_cfg_modify(struct udevice *dev, ulong addr, ulong size, 550 ulong value, int incrflag) 551 #else 552 static int pci_cfg_modify(pci_dev_t bdf, ulong addr, ulong size, ulong value, 553 int incrflag) 554 #endif 555 { 556 ulong i; 557 int nbytes; 558 ulong val; 559 560 /* Print the address, followed by value. Then accept input for 561 * the next value. A non-converted value exits. 562 */ 563 do { 564 printf("%08lx:", addr); 565 #ifdef CONFIG_DM_PCI 566 dm_pci_read_config(dev, addr, &val, size); 567 #else 568 val = pci_read_config(bdf, addr, size); 569 #endif 570 printf(" %0*lx", pci_field_width(size), val); 571 572 nbytes = cli_readline(" ? "); 573 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { 574 /* <CR> pressed as only input, don't modify current 575 * location and move to next. "-" pressed will go back. 576 */ 577 if (incrflag) 578 addr += nbytes ? -size : size; 579 nbytes = 1; 580 /* good enough to not time out */ 581 bootretry_reset_cmd_timeout(); 582 } 583 #ifdef CONFIG_BOOT_RETRY_TIME 584 else if (nbytes == -2) { 585 break; /* timed out, exit the command */ 586 } 587 #endif 588 else { 589 char *endp; 590 i = simple_strtoul(console_buffer, &endp, 16); 591 nbytes = endp - console_buffer; 592 if (nbytes) { 593 /* good enough to not time out 594 */ 595 bootretry_reset_cmd_timeout(); 596 #ifdef CONFIG_DM_PCI 597 dm_pci_write_config(dev, addr, i, size); 598 #else 599 pci_cfg_write(bdf, addr, size, i); 600 #endif 601 if (incrflag) 602 addr += size; 603 } 604 } 605 } while (nbytes); 606 607 return 0; 608 } 609 610 #ifdef CONFIG_DM_PCI 611 static const struct pci_flag_info { 612 uint flag; 613 const char *name; 614 } pci_flag_info[] = { 615 { PCI_REGION_IO, "io" }, 616 { PCI_REGION_PREFETCH, "prefetch" }, 617 { PCI_REGION_SYS_MEMORY, "sysmem" }, 618 { PCI_REGION_RO, "readonly" }, 619 { PCI_REGION_IO, "io" }, 620 }; 621 622 static void pci_show_regions(struct udevice *bus) 623 { 624 struct pci_controller *hose = dev_get_uclass_priv(bus); 625 const struct pci_region *reg; 626 int i, j; 627 628 if (!hose) { 629 printf("Bus '%s' is not a PCI controller\n", bus->name); 630 return; 631 } 632 633 printf("# %-16s %-16s %-16s %s\n", "Bus start", "Phys start", "Size", 634 "Flags"); 635 for (i = 0, reg = hose->regions; i < hose->region_count; i++, reg++) { 636 printf("%d %#016llx %#016llx %#016llx ", i, 637 (unsigned long long)reg->bus_start, 638 (unsigned long long)reg->phys_start, 639 (unsigned long long)reg->size); 640 if (!(reg->flags & PCI_REGION_TYPE)) 641 printf("mem "); 642 for (j = 0; j < ARRAY_SIZE(pci_flag_info); j++) { 643 if (reg->flags & pci_flag_info[j].flag) 644 printf("%s ", pci_flag_info[j].name); 645 } 646 printf("\n"); 647 } 648 } 649 #endif 650 651 /* PCI Configuration Space access commands 652 * 653 * Syntax: 654 * pci display[.b, .w, .l] bus.device.function} [addr] [len] 655 * pci next[.b, .w, .l] bus.device.function [addr] 656 * pci modify[.b, .w, .l] bus.device.function [addr] 657 * pci write[.b, .w, .l] bus.device.function addr value 658 */ 659 static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 660 { 661 ulong addr = 0, value = 0, cmd_size = 0; 662 enum pci_size_t size = PCI_SIZE_32; 663 #ifdef CONFIG_DM_PCI 664 struct udevice *dev, *bus; 665 #else 666 pci_dev_t dev; 667 #endif 668 int busnum = 0; 669 pci_dev_t bdf = 0; 670 char cmd = 's'; 671 int ret = 0; 672 673 if (argc > 1) 674 cmd = argv[1][0]; 675 676 switch (cmd) { 677 case 'd': /* display */ 678 case 'n': /* next */ 679 case 'm': /* modify */ 680 case 'w': /* write */ 681 /* Check for a size specification. */ 682 cmd_size = cmd_get_data_size(argv[1], 4); 683 size = (cmd_size == 4) ? PCI_SIZE_32 : cmd_size - 1; 684 if (argc > 3) 685 addr = simple_strtoul(argv[3], NULL, 16); 686 if (argc > 4) 687 value = simple_strtoul(argv[4], NULL, 16); 688 case 'h': /* header */ 689 #ifdef CONFIG_DM_PCI 690 case 'b': /* bars */ 691 #endif 692 if (argc < 3) 693 goto usage; 694 if ((bdf = get_pci_dev(argv[2])) == -1) 695 return 1; 696 break; 697 #if defined(CONFIG_CMD_PCI_ENUM) || defined(CONFIG_DM_PCI) 698 case 'e': 699 pci_init(); 700 return 0; 701 #endif 702 case 'r': /* no break */ 703 default: /* scan bus */ 704 value = 1; /* short listing */ 705 if (argc > 1) { 706 if (cmd != 'r' && argv[argc-1][0] == 'l') { 707 value = 0; 708 argc--; 709 } 710 if (argc > 1) 711 busnum = simple_strtoul(argv[1], NULL, 16); 712 } 713 #ifdef CONFIG_DM_PCI 714 ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus); 715 if (ret) { 716 printf("No such bus\n"); 717 return CMD_RET_FAILURE; 718 } 719 if (cmd == 'r') 720 pci_show_regions(bus); 721 else 722 pciinfo(bus, value); 723 #else 724 pciinfo(busnum, value); 725 #endif 726 return 0; 727 } 728 729 #ifdef CONFIG_DM_PCI 730 ret = dm_pci_bus_find_bdf(bdf, &dev); 731 if (ret) { 732 printf("No such device\n"); 733 return CMD_RET_FAILURE; 734 } 735 #else 736 dev = bdf; 737 #endif 738 739 switch (argv[1][0]) { 740 case 'h': /* header */ 741 pci_header_show(dev); 742 break; 743 case 'd': /* display */ 744 return pci_cfg_display(dev, addr, size, value); 745 case 'n': /* next */ 746 if (argc < 4) 747 goto usage; 748 ret = pci_cfg_modify(dev, addr, size, value, 0); 749 break; 750 case 'm': /* modify */ 751 if (argc < 4) 752 goto usage; 753 ret = pci_cfg_modify(dev, addr, size, value, 1); 754 break; 755 case 'w': /* write */ 756 if (argc < 5) 757 goto usage; 758 #ifdef CONFIG_DM_PCI 759 ret = dm_pci_write_config(dev, addr, value, size); 760 #else 761 ret = pci_cfg_write(dev, addr, size, value); 762 #endif 763 break; 764 #ifdef CONFIG_DM_PCI 765 766 case 'b': /* bars */ 767 return pci_bar_show(dev); 768 #endif 769 default: 770 ret = CMD_RET_USAGE; 771 break; 772 } 773 774 return ret; 775 usage: 776 return CMD_RET_USAGE; 777 } 778 779 /***************************************************/ 780 781 #ifdef CONFIG_SYS_LONGHELP 782 static char pci_help_text[] = 783 "[bus] [long]\n" 784 " - short or long list of PCI devices on bus 'bus'\n" 785 #if defined(CONFIG_CMD_PCI_ENUM) || defined(CONFIG_DM_PCI) 786 "pci enum\n" 787 " - Enumerate PCI buses\n" 788 #endif 789 "pci header b.d.f\n" 790 " - show header of PCI device 'bus.device.function'\n" 791 #ifdef CONFIG_DM_PCI 792 "pci bar b.d.f\n" 793 " - show BARs base and size for device b.d.f'\n" 794 "pci regions\n" 795 " - show PCI regions\n" 796 #endif 797 "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n" 798 " - display PCI configuration space (CFG)\n" 799 "pci next[.b, .w, .l] b.d.f address\n" 800 " - modify, read and keep CFG address\n" 801 "pci modify[.b, .w, .l] b.d.f address\n" 802 " - modify, auto increment CFG address\n" 803 "pci write[.b, .w, .l] b.d.f address value\n" 804 " - write to CFG address"; 805 #endif 806 807 U_BOOT_CMD( 808 pci, 5, 1, do_pci, 809 "list and access PCI Configuration Space", pci_help_text 810 ); 811