pci.c 21 KB

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