fpcie.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fpcie.c
  15. * Date: 2022-02-10 14:55:11
  16. * LastEditTime: 2022-02-18 08:59:28
  17. * Description:  This files is for
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. /***************************** Include Files *********************************/
  24. #include "fpcie.h"
  25. #include "fpcie_hw.h"
  26. #include "fpcie_common.h"
  27. #include "fparameters.h"
  28. #include "fkernel.h"
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include "fdebug.h"
  32. #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8
  33. #define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
  34. /***************** Macros (Inline Functions) Definitions *********************/
  35. #define FPCIE_DEBUG_TAG "FPCIE"
  36. #define FPCIE_ERROR(format, ...) FT_DEBUG_PRINT_E(FPCIE_DEBUG_TAG, format, ##__VA_ARGS__)
  37. #define FPCIE_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FPCIE_DEBUG_TAG, format, ##__VA_ARGS__)
  38. #define FPCIE_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FPCIE_DEBUG_TAG, format, ##__VA_ARGS__)
  39. #define FPCIE_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FPCIE_DEBUG_TAG, format, ##__VA_ARGS__)
  40. /************************** Constant Definitions *****************************/
  41. /**************************** Type Definitions *******************************/
  42. /************************** Variable Definitions *****************************/
  43. extern int FPcieEpCleanBar(FPcie *instance_p, u32 peu_num, u32 bar_num) ;
  44. static void FPcieShowRegion(const char *name, struct FPcieRegion *region)
  45. {
  46. FPCIE_DEBUG_I("PCI Autoconfig: Bus %s region: [%llx-%llx],\n"
  47. "\t\tPhysical Memory [%llx-%llx]", name,
  48. (unsigned long long)region->bus_start,
  49. (unsigned long long)(region->bus_start + region->size - 1),
  50. (unsigned long long)region->phys_start,
  51. (unsigned long long)(region->phys_start + region->size - 1));
  52. FPCIE_DEBUG_I("bus_lower is %llx ", (unsigned long long)region->bus_lower) ;
  53. }
  54. /**
  55. * @name: FPcieRegionConfigInit
  56. * @msg: 初始化PEU 用于分配的地址空间
  57. * @param {FPcie} *instance_p is a pointer to the FPcie instance.
  58. * @param {FPcieRegion} *regs 地址空间对应的指针
  59. * @param {u32} regs_num 传入regs 结构体的数量
  60. */
  61. //用于资源初始化到instance_p中
  62. static void FPcieRegionConfigInit(FPcie *instance_p, struct FPcieRegion *regs, u32 regs_num)
  63. {
  64. u32 i ;
  65. for (i = 0; i < regs_num; i++)
  66. {
  67. switch (regs[i].flags)
  68. {
  69. case FPCIE_REGION_IO:
  70. memset(&instance_p->mem_io, 0, sizeof(struct FPcieRegion)) ;
  71. memcpy(&instance_p->mem_io, regs, sizeof(struct FPcieRegion)) ;
  72. instance_p->mem_io.exist_flg = FPCIE_REGION_EXIST_FLG ;
  73. instance_p->mem_io.bus_lower = instance_p->mem_io.phys_start;
  74. FPcieShowRegion("I/O", &instance_p->mem_io);
  75. break;
  76. case FPCIE_REGION_MEM:
  77. memset(&instance_p->mem, 0, sizeof(struct FPcieRegion)) ;
  78. memcpy(&instance_p->mem, regs, sizeof(struct FPcieRegion)) ;
  79. instance_p->mem.exist_flg = FPCIE_REGION_EXIST_FLG ;
  80. instance_p->mem.bus_lower = instance_p->mem.phys_start;
  81. FPcieShowRegion("Memory", &instance_p->mem);
  82. break;
  83. case (PCI_REGION_PREFETCH|FPCIE_REGION_MEM):
  84. memset(&instance_p->mem_prefetch, 0, sizeof(struct FPcieRegion)) ;
  85. memcpy(&instance_p->mem_prefetch, regs, sizeof(struct FPcieRegion)) ;
  86. instance_p->mem_prefetch.exist_flg = FPCIE_REGION_EXIST_FLG ;
  87. instance_p->mem_prefetch.bus_lower = instance_p->mem_prefetch.phys_start;
  88. FPcieShowRegion("Prefetchable Mem", &instance_p->mem_prefetch);
  89. break;
  90. default:
  91. break;
  92. }
  93. }
  94. }
  95. /**
  96. * @name: FPcieCfgInitialize
  97. * @msg: This function initializes the config space and PCIe bridge.
  98. * @param {FPcie} *instance_p is a pointer to the FPcie instance.
  99. * @param {FPcieConfig} *config_p pointer to FPcieConfig instrance Pointer.
  100. * @return FError
  101. */
  102. FError FPcieCfgInitialize(FPcie *instance_p, FPcieConfig *config_p) //用于从全局配置数据中获取数据,初始化instance_p
  103. {
  104. fsize_t i;
  105. struct FPcieRegion mem_region = {0} ;
  106. struct FPcieRegion prefetch_region = {0} ;
  107. struct FPcieRegion io_region = {0} ;
  108. /* Assert arguments */
  109. FASSERT(instance_p != NULL);
  110. FASSERT(config_p != NULL);
  111. /* Clear instance memory and make copy of configuration */
  112. memset(instance_p, 0, sizeof(FPcie));
  113. memcpy(&instance_p->config, config_p, sizeof(FPcieConfig));
  114. /* 为枚举过程中,涉及的配置空间提供地址划分 */
  115. /* mem32 地址 */ //使用获取到的硬件信息,来初始化mem32
  116. mem_region.phys_start = instance_p->config.npmem_base_addr ;
  117. mem_region.bus_start = instance_p->config.npmem_base_addr ;
  118. mem_region.size = instance_p->config.npmem_size ;
  119. mem_region.flags = FPCIE_REGION_MEM ;
  120. /* mem64 地址 */ //使用获取到的硬件信息,来初始化mem64
  121. prefetch_region.phys_start = instance_p->config.pmem_base_addr ;
  122. prefetch_region.bus_start = instance_p->config.pmem_base_addr ;
  123. prefetch_region.size = instance_p->config.pmem_size ;
  124. prefetch_region.flags = (PCI_REGION_PREFETCH | FPCIE_REGION_MEM);
  125. /* memio 地址 */ //使用获取到的硬件信息,来初始化io
  126. io_region.phys_start = instance_p->config.io_base_addr ;
  127. io_region.bus_start = instance_p->config.io_base_addr ;
  128. io_region.size = instance_p->config.io_size ;
  129. io_region.flags = FPCIE_REGION_IO;
  130. /* scaned bdf array clean */
  131. instance_p->scaned_bdf_count = 0;
  132. FPcieRegionConfigInit(instance_p, &mem_region, 1) ;
  133. #if defined(__aarch64__)
  134. FPcieRegionConfigInit(instance_p, &prefetch_region, 1) ;
  135. #endif
  136. FPcieRegionConfigInit(instance_p, &io_region, 1) ;
  137. instance_p->is_ready = FT_COMPONENT_IS_READY;
  138. /* 关闭当前所有misc 中断 */
  139. // FPcieMiscIrqDisable(instance_p, FPCIE_PEU0_C0);
  140. // FPcieMiscIrqDisable(instance_p, FPCIE_PEU0_C1);
  141. // FPcieMiscIrqDisable(instance_p, FPCIE_PEU0_C2);
  142. // FPcieMiscIrqDisable(instance_p, FPCIE_PEU1_C0);
  143. // FPcieMiscIrqDisable(instance_p, FPCIE_PEU1_C1);
  144. // FPcieMiscIrqDisable(instance_p, FPCIE_PEU1_C2);
  145. /* 清空ep模式下所有配置地址 */
  146. // for (i = 0; i <= FPCIE_PEU1_C2; i++)
  147. // {
  148. // /* code */
  149. // FPcieEpCleanBar(instance_p, i, FPCIE_BAR_0);
  150. // FPcieEpCleanBar(instance_p, i, FPCIE_BAR_1);
  151. // FPcieEpCleanBar(instance_p, i, FPCIE_BAR_2);
  152. // FPcieEpCleanBar(instance_p, i, FPCIE_BAR_3);
  153. // FPcieEpCleanBar(instance_p, i, FPCIE_BAR_4);
  154. // FPcieEpCleanBar(instance_p, i, FPCIE_BAR_5);
  155. // }
  156. return (FT_SUCCESS);
  157. }
  158. u32 FPcieFindCapability(FPcie *instance_p, u32 bdf, u32 cid_type, u32 cid, u32 *cid_offset)
  159. {
  160. u32 reg_value;
  161. u32 next_cap_offset;
  162. //u32 ret;
  163. if (cid_type == PCIE_CAP)
  164. {
  165. /* Serach in PCIe configuration space */
  166. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, FPCIE_CAPABILITY_LIST, &reg_value);
  167. if (reg_value == 0xffffffff)
  168. return -1;
  169. next_cap_offset = (reg_value & 0xff);
  170. while (next_cap_offset)
  171. {
  172. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, next_cap_offset, &reg_value);
  173. if ((reg_value & 0xff) == cid)
  174. {
  175. *cid_offset = next_cap_offset;
  176. return 0;
  177. }
  178. next_cap_offset = ((reg_value >> 8) & 0xff);
  179. }
  180. }
  181. else if (cid_type == PCIE_ECAP)
  182. {
  183. /* Serach in PCIe extended configuration space */
  184. next_cap_offset = FPCIE_ECAP_START;
  185. while (next_cap_offset)
  186. {
  187. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, next_cap_offset, &reg_value);
  188. if ((reg_value & 0xffff) == cid)
  189. {
  190. *cid_offset = next_cap_offset;
  191. return 0;
  192. }
  193. next_cap_offset = ((reg_value >> 20) & 0xfff);
  194. }
  195. }
  196. /* The capability was not found */
  197. return -1;
  198. }
  199. const char *FPcieClassStr(u8 class)
  200. {
  201. switch (class)
  202. {
  203. case FPCI_CLASS_NOT_DEFINED:
  204. return "Build before PCI Rev2.0";
  205. break;
  206. case FPCI_BASE_CLASS_STORAGE:
  207. return "Mass storage controller";
  208. break;
  209. case FPCI_BASE_CLASS_NETWORK:
  210. return "Network controller";
  211. break;
  212. case FPCI_BASE_CLASS_DISPLAY:
  213. return "Display controller";
  214. break;
  215. case FPCI_BASE_CLASS_MULTIMEDIA:
  216. return "Multimedia device";
  217. break;
  218. case FPCI_BASE_CLASS_MEMORY:
  219. return "Memory controller";
  220. break;
  221. case FPCI_BASE_CLASS_BRIDGE:
  222. return "Bridge device";
  223. break;
  224. case FPCI_BASE_CLASS_COMMUNICATION:
  225. return "Simple comm. controller";
  226. break;
  227. case FPCI_BASE_CLASS_SYSTEM:
  228. return "Base system peripheral";
  229. break;
  230. case FPCI_BASE_CLASS_INPUT:
  231. return "Input device";
  232. break;
  233. case FPCI_BASE_CLASS_DOCKING:
  234. return "Docking station";
  235. break;
  236. case FPCI_BASE_CLASS_PROCESSOR:
  237. return "Processor";
  238. break;
  239. case FPCI_BASE_CLASS_SERIAL:
  240. return "Serial bus controller";
  241. break;
  242. case FPCI_BASE_CLASS_INTELLIGENT:
  243. return "Intelligent controller";
  244. break;
  245. case FPCI_BASE_CLASS_SATELLITE:
  246. return "Satellite controller";
  247. break;
  248. case FPCI_BASE_CLASS_CRYPT:
  249. return "Cryptographic device";
  250. break;
  251. case FPCI_BASE_CLASS_SIGNAL_PROCESSING:
  252. return "DSP";
  253. break;
  254. case FPCI_CLASS_OTHERS:
  255. return "Does not fit any class";
  256. break;
  257. default:
  258. return "???";
  259. break;
  260. };
  261. }
  262. void FPcieAutoRegionAlign(struct FPcieRegion *res, pci_size_t size)
  263. {
  264. res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1;
  265. }
  266. int FPcieAutoRegionAllocate(struct FPcieRegion *res, pci_size_t size,
  267. pci_addr_t *bar, bool supports_64bit)
  268. {
  269. pci_addr_t addr;
  270. if (!res)
  271. {
  272. printf("No resource\n");
  273. goto error;
  274. }
  275. addr = ((res->bus_lower - 1) | (size - 1)) + 1;
  276. if (addr - res->bus_start + size > res->size)
  277. {
  278. printf("No room in resource");
  279. goto error;
  280. }
  281. if (upper_32_bits(addr) && !supports_64bit)
  282. {
  283. printf("Cannot assign 64-bit address to 32-bit-only resource\n");
  284. goto error;
  285. }
  286. res->bus_lower = addr + size;
  287. //printf("address=0x%llx bus_lower=0x%llx\n", (unsigned long long)addr,
  288. // (unsigned long long)res->bus_lower);
  289. *bar = addr;
  290. return 0;
  291. error:
  292. *bar = (pci_addr_t) -1;
  293. return -1;
  294. }
  295. void FPcieAutoSetupDevice(FPcie *instance_p, u32 bdf, int bars_num,
  296. struct FPcieRegion *mem,
  297. struct FPcieRegion *prefetch, struct FPcieRegion *io,
  298. bool enum_only)
  299. {
  300. u32 bar_response;
  301. pci_size_t bar_size;
  302. u16 cmdstat = 0;
  303. int bar, bar_nr = 0;
  304. u8 header_type;
  305. int rom_addr;
  306. pci_addr_t bar_value;
  307. struct FPcieRegion *bar_res = NULL;
  308. int found_mem64 = 0;
  309. u16 class;
  310. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_COMMAND_REG, &cmdstat);
  311. cmdstat = (cmdstat & ~(FPCIE_COMMAND_IO | FPCIE_COMMAND_MEMORY)) |
  312. FPCIE_COMMAND_MASTER;
  313. for (bar = FPCIE_BASE_ADDRESS_0;
  314. bar < FPCIE_BASE_ADDRESS_0 + (bars_num * 4); bar += 4)
  315. {
  316. /* Tickle the BAR and get the response */
  317. if (!enum_only)
  318. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, bar, 0xffffffff);
  319. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, bar, &bar_response);
  320. /* If BAR is not implemented go to the next BAR */
  321. if (!bar_response)
  322. continue;
  323. found_mem64 = 0;
  324. /* Check the BAR type and set our address mask */
  325. if (bar_response & FPCIE_BASE_ADDRESS_SPACE)
  326. {
  327. bar_size = ((~(bar_response & FPCIE_BASE_ADDRESS_IO_MASK))
  328. & 0xffff) + 1;
  329. if (!enum_only)
  330. bar_res = io;
  331. //printf("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ",
  332. // bar_nr, (unsigned long long)bar_size);
  333. }
  334. else
  335. {
  336. if ((bar_response & FPCIE_BASE_ADDRESS_MEM_TYPE_MASK) ==
  337. FPCIE_BASE_ADDRESS_MEM_TYPE_64)
  338. {
  339. u32 bar_response_upper;
  340. u64 bar64;
  341. if (!enum_only)
  342. {
  343. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, bar + 4, 0xffffffff);
  344. }
  345. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, bar + 4, &bar_response_upper);
  346. bar64 = ((u64)bar_response_upper << 32) |
  347. bar_response;
  348. bar_size = ~(bar64 & FPCIE_BASE_ADDRESS_MEM_MASK)
  349. + 1;
  350. if (!enum_only)
  351. found_mem64 = 1;
  352. }
  353. else
  354. {
  355. bar_size = (u32)(~(bar_response &
  356. FPCIE_BASE_ADDRESS_MEM_MASK) + 1);
  357. }
  358. if (!enum_only)
  359. {
  360. if ((prefetch->exist_flg & FPCIE_REGION_EXIST_FLG) & (bar_response &
  361. FPCIE_BASE_ADDRESS_MEM_PREFETCH))
  362. {
  363. bar_res = prefetch;
  364. }
  365. else
  366. {
  367. bar_res = mem;
  368. }
  369. }
  370. //printf("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
  371. // bar_nr, bar_res == prefetch ? "Prf" : "Mem",
  372. // (unsigned long long)bar_size);
  373. }
  374. if (!enum_only && FPcieAutoRegionAllocate(bar_res, bar_size,
  375. &bar_value,
  376. found_mem64) == 0)
  377. {
  378. /* Write it out and update our limit */
  379. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, bar, (u32)bar_value);
  380. if (found_mem64)
  381. {
  382. bar += 4;
  383. #ifdef CONFIG_SYS_PCI_64BIT
  384. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, bar, (u32)(bar_value >> 32));
  385. #else
  386. /*
  387. * If we are a 64-bit decoder then increment to
  388. * the upper 32 bits of the bar and force it to
  389. * locate in the lower 4GB of memory.
  390. */
  391. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, bar, 0x00000000);
  392. #endif
  393. }
  394. }
  395. cmdstat |= (bar_response & FPCIE_BASE_ADDRESS_SPACE) ?
  396. FPCIE_COMMAND_IO : FPCIE_COMMAND_MEMORY;
  397. //printf("\n");
  398. bar_nr++;
  399. }
  400. if (!enum_only)
  401. {
  402. /* Configure the expansion ROM address */
  403. FPcieEcamReadConfig8bit(instance_p->config.ecam, bdf, FPCIE_HEADER_TYPE_REG, &header_type);
  404. header_type &= 0x7f;
  405. if (header_type != FPCIE_HEADER_TYPE_CARDBUS)
  406. {
  407. rom_addr = (header_type == FPCIE_HEADER_TYPE_NORMAL) ?
  408. FPCIE_ROM_ADDRESS : FPCIE_ROM_ADDRESS1;
  409. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, rom_addr, 0xfffffffe);
  410. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, rom_addr, &bar_response);
  411. if (bar_response)
  412. {
  413. bar_size = -(bar_response & ~1);
  414. //printf("PCI Autoconfig: ROM, size=%#x, ",
  415. // (unsigned int)bar_size);
  416. if (FPcieAutoRegionAllocate(mem, bar_size,
  417. &bar_value,
  418. false) == 0)
  419. {
  420. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, rom_addr, bar_value);
  421. }
  422. cmdstat |= FPCIE_COMMAND_MEMORY;
  423. //printf("\n");
  424. }
  425. }
  426. }
  427. /* PCI_COMMAND_IO must be set for VGA device */
  428. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCI_CLASS_DEVICE_REG, &class);
  429. if (class == FPCI_CLASS_DISPLAY_VGA)
  430. cmdstat |= FPCIE_COMMAND_IO;
  431. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_COMMAND_REG, cmdstat);
  432. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_CACHE_LINE_SIZE_REG,
  433. CONFIG_SYS_PCI_CACHE_LINE_SIZE);
  434. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_LATENCY_TIMER_REG, 0x80);
  435. }
  436. void FPcieAutoPrescanSetupBridge(FPcie *instance_p, u32 bdf, int sub_bus)
  437. {
  438. struct FPcieRegion *pci_mem;
  439. struct FPcieRegion *pci_prefetch;
  440. struct FPcieRegion *pci_io;
  441. u16 cmdstat, prefechable_64;
  442. pci_mem = &(instance_p->mem);
  443. pci_prefetch = &(instance_p->mem_prefetch);
  444. pci_io = &(instance_p->mem_io);
  445. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_COMMAND_REG, &cmdstat) ;
  446. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_MEMORY_BASE_REG, &prefechable_64) ;
  447. prefechable_64 &= FPCIE_PREF_RANGE_TYPE_MASK;
  448. /* Configure bus number registers *///暂时只有一个pcie配置空间的做法,如果多个pci配置空间,则需当前bus减去该配置空间对应设备的起始bus号
  449. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_PRIMARY_BUS_REG, FPCIE_BUS(bdf));
  450. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_SECONDARY_BUS_REG, sub_bus);
  451. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_SUBORDINATE_BUS_REG, 0xff);
  452. if (pci_mem->exist_flg & FPCIE_REGION_EXIST_FLG)
  453. {
  454. /* Round memory allocator to 1MB boundary */
  455. FPcieAutoRegionAlign(pci_mem, 0x100000);
  456. /*
  457. * Set up memory and I/O filter limits, assume 32-bit
  458. * I/O space
  459. */
  460. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_MEMORY_BASE_REG,
  461. (pci_mem->bus_lower & 0xfff00000) >> 16);
  462. cmdstat |= FPCIE_COMMAND_MEMORY;
  463. }
  464. if (pci_prefetch->exist_flg & FPCIE_REGION_EXIST_FLG)
  465. {
  466. /* Round memory allocator to 1MB boundary */
  467. FPcieAutoRegionAlign(pci_prefetch, 0x100000);
  468. /*
  469. * Set up memory and I/O filter limits, assume 32-bit
  470. * I/O space
  471. */
  472. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_MEMORY_BASE_REG,
  473. (pci_prefetch->bus_lower & 0xfff00000) >> 16);
  474. if (prefechable_64 == FPCIE_PREF_RANGE_TYPE_64)
  475. #ifdef CONFIG_SYS_PCI_64BIT
  476. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, FPCIE_PREF_BASE_UPPER32_REG,
  477. pci_prefetch->bus_lower >> 32);
  478. #else
  479. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, FPCIE_PREF_BASE_UPPER32_REG,
  480. 0x0);
  481. #endif
  482. cmdstat |= FPCIE_COMMAND_MEMORY;
  483. }
  484. else
  485. {
  486. /* We don't support prefetchable memory for now, so disable */
  487. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_MEMORY_BASE_REG, 0x1000);
  488. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_MEMORY_LIMIT_REG, 0x0);
  489. if (prefechable_64 == FPCIE_PREF_RANGE_TYPE_64)
  490. {
  491. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_BASE_UPPER32_REG, 0x0);
  492. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_LIMIT_UPPER32_REG, 0x0);
  493. }
  494. }
  495. if (pci_io->exist_flg & FPCIE_REGION_EXIST_FLG)
  496. {
  497. /* Round I/O allocator to 4KB boundary */
  498. FPcieAutoRegionAlign(pci_io, 0x1000);
  499. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_IO_BASE_REG,
  500. (pci_io->bus_lower & 0x0000f000) >> 8);
  501. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_IO_BASE_UPPER16_REG,
  502. (pci_io->bus_lower & 0xffff0000) >> 16);
  503. cmdstat |= FPCIE_COMMAND_IO;
  504. }
  505. /* Enable memory and I/O accesses, enable bus master */
  506. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_COMMAND_REG, cmdstat | FPCIE_COMMAND_MASTER);
  507. }
  508. void FPcieAutoPostscanSetupBridge(FPcie *instance_p, u32 bdf, int sub_bus)
  509. {
  510. struct FPcieRegion *pci_mem;
  511. struct FPcieRegion *pci_prefetch;
  512. struct FPcieRegion *pci_io;
  513. pci_mem = &(instance_p->mem);
  514. pci_prefetch = &(instance_p->mem_prefetch);
  515. pci_io = &(instance_p->mem_io);
  516. /* Configure bus number registers */
  517. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_SUBORDINATE_BUS_REG, sub_bus);//配置一下subordinate-bus,可能在固件下不一定必须用
  518. if (pci_mem->exist_flg & FPCIE_REGION_EXIST_FLG)
  519. {
  520. /* Round memory allocator to 1MB boundary */
  521. FPcieAutoRegionAlign(pci_mem, 0x100000);
  522. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_MEMORY_LIMIT_REG, (pci_mem->bus_lower - 1) >> 16);
  523. }
  524. if (pci_prefetch->exist_flg & FPCIE_REGION_EXIST_FLG)
  525. {
  526. u16 prefechable_64;
  527. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_MEMORY_LIMIT_REG, &prefechable_64);
  528. prefechable_64 &= FPCIE_PREF_RANGE_TYPE_MASK;
  529. /* Round memory allocator to 1MB boundary */
  530. FPcieAutoRegionAlign(pci_prefetch, 0x100000);
  531. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_PREF_MEMORY_LIMIT_REG, (pci_prefetch->bus_lower - 1) >> 16);
  532. if (prefechable_64 == FPCIE_PREF_RANGE_TYPE_64)
  533. #ifdef CONFIG_SYS_PCI_64BIT
  534. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, FPCIE_PREF_LIMIT_UPPER32_REG,
  535. (pci_prefetch->bus_lower - 1) >> 32);
  536. #else
  537. FPcieEcamWriteConfig32bit(instance_p->config.ecam, bdf, FPCIE_PREF_LIMIT_UPPER32_REG, 0x0);
  538. #endif
  539. }
  540. if (pci_io->exist_flg & FPCIE_REGION_EXIST_FLG)
  541. {
  542. /* Round I/O allocator to 4KB boundary */
  543. FPcieAutoRegionAlign(pci_io, 0x1000);
  544. FPcieEcamWriteConfig8bit(instance_p->config.ecam, bdf, FPCIE_IO_LIMIT_REG,
  545. ((pci_io->bus_lower - 1) & 0x0000f000) >> 8);
  546. FPcieEcamWriteConfig16bit(instance_p->config.ecam, bdf, FPCIE_IO_LIMIT_UPPER16_REG,
  547. ((pci_io->bus_lower - 1) & 0xffff0000) >> 16);
  548. }
  549. }
  550. int FPcieHoseProbeBus(FPcie *instance_p, u32 bdf)
  551. {
  552. int sub_bus;
  553. int ret;
  554. instance_p->bus_max = instance_p->bus_max + 1;
  555. sub_bus = instance_p->bus_max;
  556. FPcieAutoPrescanSetupBridge(instance_p, bdf, sub_bus);
  557. FPcieScanBus(instance_p, sub_bus, bdf);
  558. sub_bus = instance_p->bus_max;
  559. FPcieAutoPostscanSetupBridge(instance_p, bdf, sub_bus);
  560. return sub_bus;
  561. }
  562. /*
  563. * HJF: Changed this to return int. I think this is required
  564. * to get the correct result when scanning bridges
  565. */
  566. int FPcieAutoConfigDevice(FPcie *instance_p, u32 bdf)
  567. {
  568. u16 class = 0;
  569. struct FPcieRegion *pci_mem;
  570. struct FPcieRegion *pci_prefetch;
  571. struct FPcieRegion *pci_io;
  572. bool enum_only = false;
  573. int n;
  574. #ifdef CONFIG_PCI_ENUM_ONLY
  575. enum_only = true;
  576. #endif
  577. pci_mem = &(instance_p->mem);
  578. pci_prefetch = &(instance_p->mem_prefetch);
  579. pci_io = &(instance_p->mem_io);
  580. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_CLASS_DEVICE_REG, &class) ;//读取classcode编号
  581. switch (class)
  582. {
  583. case FPCI_CLASS_BRIDGE_PCI:
  584. FPcieAutoSetupDevice(instance_p, bdf, 2, pci_mem, pci_prefetch, pci_io,
  585. enum_only);
  586. n = FPcieHoseProbeBus(instance_p, bdf);
  587. if (n < 0)
  588. return n;
  589. break;
  590. case FPCI_CLASS_BRIDGE_CARDBUS:
  591. /*
  592. * just do a minimal setup of the bridge,
  593. * let the OS take care of the rest
  594. */
  595. FPcieAutoSetupDevice(instance_p, bdf, 0, pci_mem, pci_prefetch, pci_io,
  596. enum_only);
  597. printf("PCI Autoconfig: Found P2CardBus bridge, device %d\n", FPCIE_DEV(bdf));
  598. break;
  599. case FPCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
  600. printf("PCI AutoConfig: Found PowerPC device\n");
  601. /* fall through */
  602. default:
  603. FPcieAutoSetupDevice(instance_p, bdf, 6, pci_mem, pci_prefetch, pci_io,
  604. enum_only);
  605. break;
  606. }
  607. return FT_SUCCESS;
  608. }
  609. FError FPcieBindBusDevices(FPcie *instance_p, u32 bus_num, u32 parent_bdf, struct FPcieBus *bus)
  610. {
  611. int dev_count = 0;
  612. u16 vendor, device;
  613. u8 header_type;
  614. s32 bdf, end;
  615. bool found_multi;
  616. FError ret;
  617. u8 class_show;
  618. u32 dev_exp_cap, bus_exp_cap, dev_ext_ari_cap;
  619. u32 data;
  620. char buf_bdf_print[20];
  621. found_multi = false;
  622. end = FPCIE_BDF(bus_num, FT_PCIE_CFG_MAX_NUM_OF_DEV - 1,
  623. FT_PCIE_CFG_MAX_NUM_OF_FUN - 1);
  624. for (bdf = FPCIE_BDF(bus_num, 0, 0); bdf <= end; //使用bus的seq成员来进行扫描,其实相当于secondory_bus号
  625. bdf += FPCIE_BDF(0, 0, 1))
  626. {
  627. u32 class;
  628. /* phytium old pci ip version, need skip in some bus */
  629. if (instance_p->config.need_skip)
  630. {
  631. if (FPcieSkipDevice(instance_p->config.ecam, parent_bdf) == FPCIE_NEED_SKIP)
  632. {
  633. continue;
  634. }
  635. }
  636. if (!FPCIE_FUNC(bdf))
  637. found_multi = false;
  638. if (FPCIE_FUNC(bdf) && !found_multi)
  639. continue;
  640. /* Check only the first access, we don't expect problems */
  641. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_VENDOR_REG, &vendor) ;
  642. if (vendor == 0xffff || vendor == 0x0000)
  643. continue;
  644. FPcieEcamReadConfig8bit(instance_p->config.ecam, bdf, FPCIE_HEADER_TYPE_REG, &header_type) ;
  645. if (!FPCIE_FUNC(bdf))
  646. found_multi = header_type & 0x80;
  647. FPcieEcamReadConfig16bit(instance_p->config.ecam, bdf, FPCIE_DEVICE_ID_REG, &device) ; //读取deviceid
  648. FPcieEcamReadConfig32bit(instance_p->config.ecam, bdf, FPCI_CLASS_REVISION, &class) ; //读取classcode
  649. class >>= 8;
  650. FPcieEcamReadConfig8bit(instance_p->config.ecam, bdf, FPCIE_CLASS_CODE_REG, &class_show) ;
  651. if (parent_bdf == 0xffffffff)
  652. {
  653. strcpy(buf_bdf_print, "root-controller");
  654. }
  655. else
  656. {
  657. sprintf(buf_bdf_print, "pci_%x:%x:%x",
  658. FPCIE_BUS(parent_bdf), FPCIE_DEV(parent_bdf), FPCIE_FUNC(parent_bdf));
  659. }
  660. printf(" %02x:%02x.%02x - %04lx:%04lx %s",
  661. FPCIE_BUS(bdf), FPCIE_DEV(bdf), FPCIE_FUNC(bdf), vendor, device,
  662. buf_bdf_print);
  663. printf(" 0x%.2x (%s)\n", (int)class_show, FPcieClassStr(class_show));
  664. /* ARI function handle */
  665. /* step 1: detect if PCI Express Device */
  666. ret = FPcieFindCapability(instance_p, bdf, PCIE_CAP, FPCI_CAP_ID_EXP, &dev_exp_cap);
  667. if (ret == 0 && dev_exp_cap > 0)
  668. {
  669. /* step2: check if the device is an ARI device */
  670. ret = FPcieFindCapability(instance_p, bdf, PCIE_ECAP, FPCI_EXT_CAP_ID_ARI, &dev_ext_ari_cap);
  671. if (ret == 0 && dev_ext_ari_cap > 0)
  672. {
  673. /* step3: check if its parent supports ARI forwarding */
  674. ret = FPcieFindCapability(instance_p, parent_bdf, PCIE_CAP, FPCI_CAP_ID_EXP, &bus_exp_cap);
  675. /* config bus ARI forwarding */
  676. if (ret == 0 && bus_exp_cap > 0)
  677. {
  678. FPcieEcamReadConfig32bit(instance_p->config.ecam, parent_bdf,
  679. bus_exp_cap + FPCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, &data);
  680. if ((data & FPCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0)
  681. {
  682. /* step4: ARI forwarding support in bridge, so enable it */
  683. FPcieEcamReadConfig32bit(instance_p->config.ecam, parent_bdf,
  684. bus_exp_cap + FPCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, &data);
  685. if (data & FPCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING == 0)
  686. {
  687. data |= FPCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
  688. FPcieEcamWriteConfig32bit(instance_p->config.ecam, parent_bdf,
  689. bus_exp_cap + FPCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, data);
  690. }
  691. }
  692. }
  693. }
  694. }
  695. bus->ChildN[dev_count] = bdf;
  696. dev_count++;
  697. //这里可以将当前的device,保存到全局变量中,供别的驱动来查询。
  698. instance_p->scaned_bdf_array[instance_p->scaned_bdf_count] = bdf;
  699. (instance_p->scaned_bdf_count)++;
  700. }
  701. bus->ChildCount = dev_count;
  702. return FT_SUCCESS;
  703. }
  704. FError FPcieScanBus(FPcie *instance_p, u32 bus_num, u32 parent_bdf)
  705. {
  706. int i = 0;
  707. s32 bdf;
  708. struct FPcieBus bus;
  709. bus.ChildCount = 0;
  710. /* scan bus 0 device */
  711. FPcieBindBusDevices(instance_p, bus_num, parent_bdf, &bus);
  712. if (bus.ChildCount > 0)
  713. {
  714. for (i = 0; i < bus.ChildCount; i++)
  715. {
  716. bdf = bus.ChildN[i];
  717. FPcieAutoConfigDevice(instance_p, bdf);
  718. }
  719. }
  720. instance_p->is_scaned = 1; //表示已经扫描完成
  721. }