pfe_hw.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2015-2016 Freescale Semiconductor, Inc.
  4. * Copyright 2017 NXP
  5. */
  6. #include <net/pfe_eth/pfe_eth.h>
  7. #include <net/pfe_eth/pfe/pfe_hw.h>
  8. static struct pe_info pe[MAX_PE];
  9. /*
  10. * Initializes the PFE library.
  11. * Must be called before using any of the library functions.
  12. */
  13. void pfe_lib_init(void)
  14. {
  15. int pfe_pe_id;
  16. for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) {
  17. pe[pfe_pe_id].dmem_base_addr =
  18. (u32)CLASS_DMEM_BASE_ADDR(pfe_pe_id);
  19. pe[pfe_pe_id].pmem_base_addr =
  20. (u32)CLASS_IMEM_BASE_ADDR(pfe_pe_id);
  21. pe[pfe_pe_id].pmem_size = (u32)CLASS_IMEM_SIZE;
  22. pe[pfe_pe_id].mem_access_wdata =
  23. (void *)CLASS_MEM_ACCESS_WDATA;
  24. pe[pfe_pe_id].mem_access_addr = (void *)CLASS_MEM_ACCESS_ADDR;
  25. pe[pfe_pe_id].mem_access_rdata = (void *)CLASS_MEM_ACCESS_RDATA;
  26. }
  27. for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) {
  28. if (pfe_pe_id == TMU2_ID)
  29. continue;
  30. pe[pfe_pe_id].dmem_base_addr =
  31. (u32)TMU_DMEM_BASE_ADDR(pfe_pe_id - TMU0_ID);
  32. pe[pfe_pe_id].pmem_base_addr =
  33. (u32)TMU_IMEM_BASE_ADDR(pfe_pe_id - TMU0_ID);
  34. pe[pfe_pe_id].pmem_size = (u32)TMU_IMEM_SIZE;
  35. pe[pfe_pe_id].mem_access_wdata = (void *)TMU_MEM_ACCESS_WDATA;
  36. pe[pfe_pe_id].mem_access_addr = (void *)TMU_MEM_ACCESS_ADDR;
  37. pe[pfe_pe_id].mem_access_rdata = (void *)TMU_MEM_ACCESS_RDATA;
  38. }
  39. }
  40. /*
  41. * Writes a buffer to PE internal memory from the host
  42. * through indirect access registers.
  43. *
  44. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  45. * ..., UTIL_ID)
  46. * @param[in] mem_access_addr DMEM destination address (must be 32bit
  47. * aligned)
  48. * @param[in] src Buffer source address
  49. * @param[in] len Number of bytes to copy
  50. */
  51. static void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src,
  52. unsigned int len)
  53. {
  54. u32 offset = 0, val, addr;
  55. unsigned int len32 = len >> 2;
  56. int i;
  57. addr = mem_access_addr | PE_MEM_ACCESS_WRITE |
  58. PE_MEM_ACCESS_BYTE_ENABLE(0, 4);
  59. for (i = 0; i < len32; i++, offset += 4, src += 4) {
  60. val = *(u32 *)src;
  61. writel(cpu_to_be32(val), pe[id].mem_access_wdata);
  62. writel(addr + offset, pe[id].mem_access_addr);
  63. }
  64. len = (len & 0x3);
  65. if (len) {
  66. val = 0;
  67. addr = (mem_access_addr | PE_MEM_ACCESS_WRITE |
  68. PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset;
  69. for (i = 0; i < len; i++, src++)
  70. val |= (*(u8 *)src) << (8 * i);
  71. writel(cpu_to_be32(val), pe[id].mem_access_wdata);
  72. writel(addr, pe[id].mem_access_addr);
  73. }
  74. }
  75. /*
  76. * Writes a buffer to PE internal data memory (DMEM) from the host
  77. * through indirect access registers.
  78. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  79. * ..., UTIL_ID)
  80. * @param[in] dst DMEM destination address (must be 32bit
  81. * aligned)
  82. * @param[in] src Buffer source address
  83. * @param[in] len Number of bytes to copy
  84. */
  85. static void pe_dmem_memcpy_to32(int id, u32 dst, const void *src,
  86. unsigned int len)
  87. {
  88. pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | PE_MEM_ACCESS_DMEM,
  89. src, len);
  90. }
  91. /*
  92. * Writes a buffer to PE internal program memory (PMEM) from the host
  93. * through indirect access registers.
  94. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  95. * ..., TMU3_ID)
  96. * @param[in] dst PMEM destination address (must be 32bit
  97. * aligned)
  98. * @param[in] src Buffer source address
  99. * @param[in] len Number of bytes to copy
  100. */
  101. static void pe_pmem_memcpy_to32(int id, u32 dst, const void *src,
  102. unsigned int len)
  103. {
  104. pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size
  105. - 1)) | PE_MEM_ACCESS_IMEM, src, len);
  106. }
  107. /*
  108. * Reads PE internal program memory (IMEM) from the host
  109. * through indirect access registers.
  110. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  111. * ..., TMU3_ID)
  112. * @param[in] addr PMEM read address (must be aligned on size)
  113. * @param[in] size Number of bytes to read (maximum 4, must not
  114. * cross 32bit boundaries)
  115. * @return the data read (in PE endianness, i.e BE).
  116. */
  117. u32 pe_pmem_read(int id, u32 addr, u8 size)
  118. {
  119. u32 offset = addr & 0x3;
  120. u32 mask = 0xffffffff >> ((4 - size) << 3);
  121. u32 val;
  122. addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1))
  123. | PE_MEM_ACCESS_READ | PE_MEM_ACCESS_IMEM |
  124. PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
  125. writel(addr, pe[id].mem_access_addr);
  126. val = be32_to_cpu(readl(pe[id].mem_access_rdata));
  127. return (val >> (offset << 3)) & mask;
  128. }
  129. /*
  130. * Writes PE internal data memory (DMEM) from the host
  131. * through indirect access registers.
  132. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  133. * ..., UTIL_ID)
  134. * @param[in] val Value to write (in PE endianness, i.e BE)
  135. * @param[in] addr DMEM write address (must be aligned on size)
  136. * @param[in] size Number of bytes to write (maximum 4, must not
  137. * cross 32bit boundaries)
  138. */
  139. void pe_dmem_write(int id, u32 val, u32 addr, u8 size)
  140. {
  141. u32 offset = addr & 0x3;
  142. addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE |
  143. PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
  144. /* Indirect access interface is byte swapping data being written */
  145. writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata);
  146. writel(addr, pe[id].mem_access_addr);
  147. }
  148. /*
  149. * Reads PE internal data memory (DMEM) from the host
  150. * through indirect access registers.
  151. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  152. * ..., UTIL_ID)
  153. * @param[in] addr DMEM read address (must be aligned on size)
  154. * @param[in] size Number of bytes to read (maximum 4, must not
  155. * cross 32bit boundaries)
  156. * @return the data read (in PE endianness, i.e BE).
  157. */
  158. u32 pe_dmem_read(int id, u32 addr, u8 size)
  159. {
  160. u32 offset = addr & 0x3;
  161. u32 mask = 0xffffffff >> ((4 - size) << 3);
  162. u32 val;
  163. addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_READ |
  164. PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
  165. writel(addr, pe[id].mem_access_addr);
  166. /* Indirect access interface is byte swapping data being read */
  167. val = be32_to_cpu(readl(pe[id].mem_access_rdata));
  168. return (val >> (offset << 3)) & mask;
  169. }
  170. /*
  171. * This function is used to write to CLASS internal bus peripherals (ccu,
  172. * pe-lem) from the host
  173. * through indirect access registers.
  174. * @param[in] val value to write
  175. * @param[in] addr Address to write to (must be aligned on size)
  176. * @param[in] size Number of bytes to write (1, 2 or 4)
  177. *
  178. */
  179. static void class_bus_write(u32 val, u32 addr, u8 size)
  180. {
  181. u32 offset = addr & 0x3;
  182. writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE);
  183. addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE |
  184. (size << 24);
  185. writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA);
  186. writel(addr, CLASS_BUS_ACCESS_ADDR);
  187. }
  188. /*
  189. * Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host
  190. * through indirect access registers.
  191. * @param[in] addr Address to read from (must be aligned on size)
  192. * @param[in] size Number of bytes to read (1, 2 or 4)
  193. * @return the read data
  194. */
  195. static u32 class_bus_read(u32 addr, u8 size)
  196. {
  197. u32 offset = addr & 0x3;
  198. u32 mask = 0xffffffff >> ((4 - size) << 3);
  199. u32 val;
  200. writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE);
  201. addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24);
  202. writel(addr, CLASS_BUS_ACCESS_ADDR);
  203. val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA));
  204. return (val >> (offset << 3)) & mask;
  205. }
  206. /*
  207. * Writes data to the cluster memory (PE_LMEM)
  208. * @param[in] dst PE LMEM destination address (must be 32bit aligned)
  209. * @param[in] src Buffer source address
  210. * @param[in] len Number of bytes to copy
  211. */
  212. static void class_pe_lmem_memcpy_to32(u32 dst, const void *src,
  213. unsigned int len)
  214. {
  215. u32 len32 = len >> 2;
  216. int i;
  217. for (i = 0; i < len32; i++, src += 4, dst += 4)
  218. class_bus_write(*(u32 *)src, dst, 4);
  219. if (len & 0x2) {
  220. class_bus_write(*(u16 *)src, dst, 2);
  221. src += 2;
  222. dst += 2;
  223. }
  224. if (len & 0x1) {
  225. class_bus_write(*(u8 *)src, dst, 1);
  226. src++;
  227. dst++;
  228. }
  229. }
  230. /*
  231. * Writes value to the cluster memory (PE_LMEM)
  232. * @param[in] dst PE LMEM destination address (must be 32bit aligned)
  233. * @param[in] val Value to write
  234. * @param[in] len Number of bytes to write
  235. */
  236. static void class_pe_lmem_memset(u32 dst, int val, unsigned int len)
  237. {
  238. u32 len32 = len >> 2;
  239. int i;
  240. val = val | (val << 8) | (val << 16) | (val << 24);
  241. for (i = 0; i < len32; i++, dst += 4)
  242. class_bus_write(val, dst, 4);
  243. if (len & 0x2) {
  244. class_bus_write(val, dst, 2);
  245. dst += 2;
  246. }
  247. if (len & 0x1) {
  248. class_bus_write(val, dst, 1);
  249. dst++;
  250. }
  251. }
  252. /*
  253. * Reads data from the cluster memory (PE_LMEM)
  254. * @param[out] dst pointer to the source buffer data are copied to
  255. * @param[in] len length in bytes of the amount of data to read
  256. * from cluster memory
  257. * @param[in] offset offset in bytes in the cluster memory where data are
  258. * read from
  259. */
  260. void pe_lmem_read(u32 *dst, u32 len, u32 offset)
  261. {
  262. u32 len32 = len >> 2;
  263. int i = 0;
  264. for (i = 0; i < len32; dst++, i++, offset += 4)
  265. *dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, 4);
  266. if (len & 0x03)
  267. *dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, (len & 0x03));
  268. }
  269. /*
  270. * Writes data to the cluster memory (PE_LMEM)
  271. * @param[in] src pointer to the source buffer data are copied from
  272. * @param[in] len length in bytes of the amount of data to write to the
  273. * cluster memory
  274. * @param[in] offset offset in bytes in the cluster memory where data are
  275. * written to
  276. */
  277. void pe_lmem_write(u32 *src, u32 len, u32 offset)
  278. {
  279. u32 len32 = len >> 2;
  280. int i = 0;
  281. for (i = 0; i < len32; src++, i++, offset += 4)
  282. class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, 4);
  283. if (len & 0x03)
  284. class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, (len &
  285. 0x03));
  286. }
  287. /*
  288. * Loads an elf section into pmem
  289. * Code needs to be at least 16bit aligned and only PROGBITS sections are
  290. * supported
  291. *
  292. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ...,
  293. * TMU3_ID)
  294. * @param[in] data pointer to the elf firmware
  295. * @param[in] shdr pointer to the elf section header
  296. */
  297. static int pe_load_pmem_section(int id, const void *data, Elf32_Shdr *shdr)
  298. {
  299. u32 offset = be32_to_cpu(shdr->sh_offset);
  300. u32 addr = be32_to_cpu(shdr->sh_addr);
  301. u32 size = be32_to_cpu(shdr->sh_size);
  302. u32 type = be32_to_cpu(shdr->sh_type);
  303. if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
  304. printf(
  305. "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
  306. __func__, addr, (unsigned long)data + offset);
  307. return -1;
  308. }
  309. if (addr & 0x1) {
  310. printf("%s: load address(%x) is not 16bit aligned\n",
  311. __func__, addr);
  312. return -1;
  313. }
  314. if (size & 0x1) {
  315. printf("%s: load size(%x) is not 16bit aligned\n", __func__,
  316. size);
  317. return -1;
  318. }
  319. debug("pmem pe%d @%x len %d\n", id, addr, size);
  320. switch (type) {
  321. case SHT_PROGBITS:
  322. pe_pmem_memcpy_to32(id, addr, data + offset, size);
  323. break;
  324. default:
  325. printf("%s: unsupported section type(%x)\n", __func__, type);
  326. return -1;
  327. }
  328. return 0;
  329. }
  330. /*
  331. * Loads an elf section into dmem
  332. * Data needs to be at least 32bit aligned, NOBITS sections are correctly
  333. * initialized to 0
  334. *
  335. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  336. * ..., UTIL_ID)
  337. * @param[in] data pointer to the elf firmware
  338. * @param[in] shdr pointer to the elf section header
  339. */
  340. static int pe_load_dmem_section(int id, const void *data, Elf32_Shdr *shdr)
  341. {
  342. u32 offset = be32_to_cpu(shdr->sh_offset);
  343. u32 addr = be32_to_cpu(shdr->sh_addr);
  344. u32 size = be32_to_cpu(shdr->sh_size);
  345. u32 type = be32_to_cpu(shdr->sh_type);
  346. u32 size32 = size >> 2;
  347. int i;
  348. if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
  349. printf(
  350. "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
  351. __func__, addr, (unsigned long)data + offset);
  352. return -1;
  353. }
  354. if (addr & 0x3) {
  355. printf("%s: load address(%x) is not 32bit aligned\n",
  356. __func__, addr);
  357. return -1;
  358. }
  359. switch (type) {
  360. case SHT_PROGBITS:
  361. debug("dmem pe%d @%x len %d\n", id, addr, size);
  362. pe_dmem_memcpy_to32(id, addr, data + offset, size);
  363. break;
  364. case SHT_NOBITS:
  365. debug("dmem zero pe%d @%x len %d\n", id, addr, size);
  366. for (i = 0; i < size32; i++, addr += 4)
  367. pe_dmem_write(id, 0, addr, 4);
  368. if (size & 0x3)
  369. pe_dmem_write(id, 0, addr, size & 0x3);
  370. break;
  371. default:
  372. printf("%s: unsupported section type(%x)\n", __func__, type);
  373. return -1;
  374. }
  375. return 0;
  376. }
  377. /*
  378. * Loads an elf section into DDR
  379. * Data needs to be at least 32bit aligned, NOBITS sections are correctly
  380. * initialized to 0
  381. *
  382. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  383. * ..., UTIL_ID)
  384. * @param[in] data pointer to the elf firmware
  385. * @param[in] shdr pointer to the elf section header
  386. */
  387. static int pe_load_ddr_section(int id, const void *data, Elf32_Shdr *shdr)
  388. {
  389. u32 offset = be32_to_cpu(shdr->sh_offset);
  390. u32 addr = be32_to_cpu(shdr->sh_addr);
  391. u32 size = be32_to_cpu(shdr->sh_size);
  392. u32 type = be32_to_cpu(shdr->sh_type);
  393. u32 flags = be32_to_cpu(shdr->sh_flags);
  394. switch (type) {
  395. case SHT_PROGBITS:
  396. debug("ddr pe%d @%x len %d\n", id, addr, size);
  397. if (flags & SHF_EXECINSTR) {
  398. if (id <= CLASS_MAX_ID) {
  399. /* DO the loading only once in DDR */
  400. if (id == CLASS0_ID) {
  401. debug(
  402. "%s: load address(%x) and elf file address(%lx) rcvd\n"
  403. , __func__, addr,
  404. (unsigned long)data + offset);
  405. if (((unsigned long)(data + offset)
  406. & 0x3) != (addr & 0x3)) {
  407. printf(
  408. "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
  409. __func__, addr,
  410. (unsigned long)data +
  411. offset);
  412. return -1;
  413. }
  414. if (addr & 0x1) {
  415. printf(
  416. "%s: load address(%x) is not 16bit aligned\n"
  417. , __func__, addr);
  418. return -1;
  419. }
  420. if (size & 0x1) {
  421. printf(
  422. "%s: load length(%x) is not 16bit aligned\n"
  423. , __func__, size);
  424. return -1;
  425. }
  426. memcpy((void *)DDR_PFE_TO_VIRT(addr),
  427. data + offset, size);
  428. }
  429. } else {
  430. printf(
  431. "%s: unsupported ddr section type(%x) for PE(%d)\n"
  432. , __func__, type, id);
  433. return -1;
  434. }
  435. } else {
  436. memcpy((void *)DDR_PFE_TO_VIRT(addr), data + offset,
  437. size);
  438. }
  439. break;
  440. case SHT_NOBITS:
  441. debug("ddr zero pe%d @%x len %d\n", id, addr, size);
  442. memset((void *)DDR_PFE_TO_VIRT(addr), 0, size);
  443. break;
  444. default:
  445. printf("%s: unsupported section type(%x)\n", __func__, type);
  446. return -1;
  447. }
  448. return 0;
  449. }
  450. /*
  451. * Loads an elf section into pe lmem
  452. * Data needs to be at least 32bit aligned, NOBITS sections are correctly
  453. * initialized to 0
  454. *
  455. * @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID)
  456. * @param[in] data pointer to the elf firmware
  457. * @param[in] shdr pointer to the elf section header
  458. */
  459. static int pe_load_pe_lmem_section(int id, const void *data, Elf32_Shdr *shdr)
  460. {
  461. u32 offset = be32_to_cpu(shdr->sh_offset);
  462. u32 addr = be32_to_cpu(shdr->sh_addr);
  463. u32 size = be32_to_cpu(shdr->sh_size);
  464. u32 type = be32_to_cpu(shdr->sh_type);
  465. if (id > CLASS_MAX_ID) {
  466. printf("%s: unsupported pe-lmem section type(%x) for PE(%d)\n",
  467. __func__, type, id);
  468. return -1;
  469. }
  470. if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
  471. printf(
  472. "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
  473. __func__, addr, (unsigned long)data + offset);
  474. return -1;
  475. }
  476. if (addr & 0x3) {
  477. printf("%s: load address(%x) is not 32bit aligned\n",
  478. __func__, addr);
  479. return -1;
  480. }
  481. debug("lmem pe%d @%x len %d\n", id, addr, size);
  482. switch (type) {
  483. case SHT_PROGBITS:
  484. class_pe_lmem_memcpy_to32(addr, data + offset, size);
  485. break;
  486. case SHT_NOBITS:
  487. class_pe_lmem_memset(addr, 0, size);
  488. break;
  489. default:
  490. printf("%s: unsupported section type(%x)\n", __func__, type);
  491. return -1;
  492. }
  493. return 0;
  494. }
  495. /*
  496. * Loads an elf section into a PE
  497. * For now only supports loading a section to dmem (all PE's), pmem (class and
  498. * tmu PE's), DDDR (util PE code)
  499. * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
  500. * ..., UTIL_ID)
  501. * @param[in] data pointer to the elf firmware
  502. * @param[in] shdr pointer to the elf section header
  503. */
  504. int pe_load_elf_section(int id, const void *data, Elf32_Shdr *shdr)
  505. {
  506. u32 addr = be32_to_cpu(shdr->sh_addr);
  507. u32 size = be32_to_cpu(shdr->sh_size);
  508. if (IS_DMEM(addr, size))
  509. return pe_load_dmem_section(id, data, shdr);
  510. else if (IS_PMEM(addr, size))
  511. return pe_load_pmem_section(id, data, shdr);
  512. else if (IS_PFE_LMEM(addr, size))
  513. return 0;
  514. else if (IS_PHYS_DDR(addr, size))
  515. return pe_load_ddr_section(id, data, shdr);
  516. else if (IS_PE_LMEM(addr, size))
  517. return pe_load_pe_lmem_section(id, data, shdr);
  518. printf("%s: unsupported memory range(%x)\n", __func__, addr);
  519. return 0;
  520. }
  521. /**************************** BMU ***************************/
  522. /*
  523. * Resets a BMU block.
  524. * @param[in] base BMU block base address
  525. */
  526. static inline void bmu_reset(void *base)
  527. {
  528. writel(CORE_SW_RESET, base + BMU_CTRL);
  529. /* Wait for self clear */
  530. while (readl(base + BMU_CTRL) & CORE_SW_RESET)
  531. ;
  532. }
  533. /*
  534. * Enabled a BMU block.
  535. * @param[in] base BMU block base address
  536. */
  537. void bmu_enable(void *base)
  538. {
  539. writel(CORE_ENABLE, base + BMU_CTRL);
  540. }
  541. /*
  542. * Disables a BMU block.
  543. * @param[in] base BMU block base address
  544. */
  545. static inline void bmu_disable(void *base)
  546. {
  547. writel(CORE_DISABLE, base + BMU_CTRL);
  548. }
  549. /*
  550. * Sets the configuration of a BMU block.
  551. * @param[in] base BMU block base address
  552. * @param[in] cfg BMU configuration
  553. */
  554. static inline void bmu_set_config(void *base, struct bmu_cfg *cfg)
  555. {
  556. writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR);
  557. writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG);
  558. writel(cfg->size & 0xffff, base + BMU_BUF_SIZE);
  559. /* Interrupts are never used */
  560. writel(0x0, base + BMU_INT_ENABLE);
  561. }
  562. /*
  563. * Initializes a BMU block.
  564. * @param[in] base BMU block base address
  565. * @param[in] cfg BMU configuration
  566. */
  567. void bmu_init(void *base, struct bmu_cfg *cfg)
  568. {
  569. bmu_disable(base);
  570. bmu_set_config(base, cfg);
  571. bmu_reset(base);
  572. }
  573. /**************************** GPI ***************************/
  574. /*
  575. * Resets a GPI block.
  576. * @param[in] base GPI base address
  577. */
  578. static inline void gpi_reset(void *base)
  579. {
  580. writel(CORE_SW_RESET, base + GPI_CTRL);
  581. }
  582. /*
  583. * Enables a GPI block.
  584. * @param[in] base GPI base address
  585. */
  586. void gpi_enable(void *base)
  587. {
  588. writel(CORE_ENABLE, base + GPI_CTRL);
  589. }
  590. /*
  591. * Disables a GPI block.
  592. * @param[in] base GPI base address
  593. */
  594. void gpi_disable(void *base)
  595. {
  596. writel(CORE_DISABLE, base + GPI_CTRL);
  597. }
  598. /*
  599. * Sets the configuration of a GPI block.
  600. * @param[in] base GPI base address
  601. * @param[in] cfg GPI configuration
  602. */
  603. static inline void gpi_set_config(void *base, struct gpi_cfg *cfg)
  604. {
  605. writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base
  606. + GPI_LMEM_ALLOC_ADDR);
  607. writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base
  608. + GPI_LMEM_FREE_ADDR);
  609. writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base
  610. + GPI_DDR_ALLOC_ADDR);
  611. writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base
  612. + GPI_DDR_FREE_ADDR);
  613. writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR);
  614. writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET);
  615. writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET);
  616. writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET);
  617. writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET);
  618. writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE);
  619. writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE);
  620. writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) |
  621. GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG);
  622. writel(cfg->tmlf_txthres, base + GPI_TMLF_TX);
  623. writel(cfg->aseq_len, base + GPI_DTX_ASEQ);
  624. /*Make GPI AXI transactions non-bufferable */
  625. writel(0x1, base + GPI_AXI_CTRL);
  626. }
  627. /*
  628. * Initializes a GPI block.
  629. * @param[in] base GPI base address
  630. * @param[in] cfg GPI configuration
  631. */
  632. void gpi_init(void *base, struct gpi_cfg *cfg)
  633. {
  634. gpi_reset(base);
  635. gpi_disable(base);
  636. gpi_set_config(base, cfg);
  637. }
  638. /**************************** CLASSIFIER ***************************/
  639. /*
  640. * Resets CLASSIFIER block.
  641. */
  642. static inline void class_reset(void)
  643. {
  644. writel(CORE_SW_RESET, CLASS_TX_CTRL);
  645. }
  646. /*
  647. * Enables all CLASS-PE's cores.
  648. */
  649. void class_enable(void)
  650. {
  651. writel(CORE_ENABLE, CLASS_TX_CTRL);
  652. }
  653. /*
  654. * Disables all CLASS-PE's cores.
  655. */
  656. void class_disable(void)
  657. {
  658. writel(CORE_DISABLE, CLASS_TX_CTRL);
  659. }
  660. /*
  661. * Sets the configuration of the CLASSIFIER block.
  662. * @param[in] cfg CLASSIFIER configuration
  663. */
  664. static inline void class_set_config(struct class_cfg *cfg)
  665. {
  666. if (PLL_CLK_EN == 0) {
  667. /* Clock ratio: for 1:1 the value is 0 */
  668. writel(0x0, CLASS_PE_SYS_CLK_RATIO);
  669. } else {
  670. /* Clock ratio: for 1:2 the value is 1 */
  671. writel(0x1, CLASS_PE_SYS_CLK_RATIO);
  672. }
  673. writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE);
  674. writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE);
  675. writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) |
  676. CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits),
  677. CLASS_ROUTE_HASH_ENTRY_SIZE);
  678. writel(HASH_CRC_PORT_IP | QB2BUS_LE, CLASS_ROUTE_MULTI);
  679. writel(cfg->route_table_baseaddr, CLASS_ROUTE_TABLE_BASE);
  680. memset((void *)DDR_PFE_TO_VIRT(cfg->route_table_baseaddr), 0,
  681. ROUTE_TABLE_SIZE);
  682. writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0);
  683. writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1);
  684. writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0);
  685. writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1);
  686. writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR);
  687. writel(23, CLASS_AFULL_THRES);
  688. writel(23, CLASS_TSQ_FIFO_THRES);
  689. writel(24, CLASS_MAX_BUF_CNT);
  690. writel(24, CLASS_TSQ_MAX_CNT);
  691. /*Make Class AXI transactions non-bufferable */
  692. writel(0x1, CLASS_AXI_CTRL);
  693. /*Make Util AXI transactions non-bufferable */
  694. /*Util is disabled in U-boot, do it from here */
  695. writel(0x1, UTIL_AXI_CTRL);
  696. }
  697. /*
  698. * Initializes CLASSIFIER block.
  699. * @param[in] cfg CLASSIFIER configuration
  700. */
  701. void class_init(struct class_cfg *cfg)
  702. {
  703. class_reset();
  704. class_disable();
  705. class_set_config(cfg);
  706. }
  707. /**************************** TMU ***************************/
  708. /*
  709. * Enables TMU-PE cores.
  710. * @param[in] pe_mask TMU PE mask
  711. */
  712. void tmu_enable(u32 pe_mask)
  713. {
  714. writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL);
  715. }
  716. /*
  717. * Disables TMU cores.
  718. * @param[in] pe_mask TMU PE mask
  719. */
  720. void tmu_disable(u32 pe_mask)
  721. {
  722. writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL);
  723. }
  724. /*
  725. * Initializes TMU block.
  726. * @param[in] cfg TMU configuration
  727. */
  728. void tmu_init(struct tmu_cfg *cfg)
  729. {
  730. int q, phyno;
  731. /* keep in soft reset */
  732. writel(SW_RESET, TMU_CTRL);
  733. /*Make Class AXI transactions non-bufferable */
  734. writel(0x1, TMU_AXI_CTRL);
  735. /* enable EMAC PHY ports */
  736. writel(0x3, TMU_SYS_GENERIC_CONTROL);
  737. writel(750, TMU_INQ_WATERMARK);
  738. writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + GPI_INQ_PKTPTR),
  739. TMU_PHY0_INQ_ADDR);
  740. writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + GPI_INQ_PKTPTR),
  741. TMU_PHY1_INQ_ADDR);
  742. writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + GPI_INQ_PKTPTR),
  743. TMU_PHY3_INQ_ADDR);
  744. writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR);
  745. writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR);
  746. writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL),
  747. TMU_BMU_INQ_ADDR);
  748. /* enabling all 10 schedulers [9:0] of each TDQ */
  749. writel(0x3FF, TMU_TDQ0_SCH_CTRL);
  750. writel(0x3FF, TMU_TDQ1_SCH_CTRL);
  751. writel(0x3FF, TMU_TDQ3_SCH_CTRL);
  752. if (PLL_CLK_EN == 0) {
  753. /* Clock ratio: for 1:1 the value is 0 */
  754. writel(0x0, TMU_PE_SYS_CLK_RATIO);
  755. } else {
  756. /* Clock ratio: for 1:2 the value is 1 */
  757. writel(0x1, TMU_PE_SYS_CLK_RATIO);
  758. }
  759. /* Extra packet pointers will be stored from this address onwards */
  760. debug("TMU_LLM_BASE_ADDR %x\n", cfg->llm_base_addr);
  761. writel(cfg->llm_base_addr, TMU_LLM_BASE_ADDR);
  762. debug("TMU_LLM_QUE_LEN %x\n", cfg->llm_queue_len);
  763. writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN);
  764. writel(5, TMU_TDQ_IIFG_CFG);
  765. writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE);
  766. writel(0x0, TMU_CTRL);
  767. /* MEM init */
  768. writel(MEM_INIT, TMU_CTRL);
  769. while (!(readl(TMU_CTRL) & MEM_INIT_DONE))
  770. ;
  771. /* LLM init */
  772. writel(LLM_INIT, TMU_CTRL);
  773. while (!(readl(TMU_CTRL) & LLM_INIT_DONE))
  774. ;
  775. /* set up each queue for tail drop */
  776. for (phyno = 0; phyno < 4; phyno++) {
  777. if (phyno == 2)
  778. continue;
  779. for (q = 0; q < 16; q++) {
  780. u32 qmax;
  781. writel((phyno << 8) | q, TMU_TEQ_CTRL);
  782. writel(BIT(22), TMU_TEQ_QCFG);
  783. if (phyno == 3)
  784. qmax = DEFAULT_TMU3_QDEPTH;
  785. else
  786. qmax = (q == 0) ? DEFAULT_Q0_QDEPTH :
  787. DEFAULT_MAX_QDEPTH;
  788. writel(qmax << 18, TMU_TEQ_HW_PROB_CFG2);
  789. writel(qmax >> 14, TMU_TEQ_HW_PROB_CFG3);
  790. }
  791. }
  792. writel(0x05, TMU_TEQ_DISABLE_DROPCHK);
  793. writel(0, TMU_CTRL);
  794. }
  795. /**************************** HIF ***************************/
  796. /*
  797. * Enable hif tx DMA and interrupt
  798. */
  799. void hif_tx_enable(void)
  800. {
  801. writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL);
  802. }
  803. /*
  804. * Disable hif tx DMA and interrupt
  805. */
  806. void hif_tx_disable(void)
  807. {
  808. u32 hif_int;
  809. writel(0, HIF_TX_CTRL);
  810. hif_int = readl(HIF_INT_ENABLE);
  811. hif_int &= HIF_TXPKT_INT_EN;
  812. writel(hif_int, HIF_INT_ENABLE);
  813. }
  814. /*
  815. * Enable hif rx DMA and interrupt
  816. */
  817. void hif_rx_enable(void)
  818. {
  819. writel((HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
  820. }
  821. /*
  822. * Disable hif rx DMA and interrupt
  823. */
  824. void hif_rx_disable(void)
  825. {
  826. u32 hif_int;
  827. writel(0, HIF_RX_CTRL);
  828. hif_int = readl(HIF_INT_ENABLE);
  829. hif_int &= HIF_RXPKT_INT_EN;
  830. writel(hif_int, HIF_INT_ENABLE);
  831. }
  832. /*
  833. * Initializes HIF copy block.
  834. */
  835. void hif_init(void)
  836. {
  837. /* Initialize HIF registers */
  838. writel(HIF_RX_POLL_CTRL_CYCLE << 16 | HIF_TX_POLL_CTRL_CYCLE,
  839. HIF_POLL_CTRL);
  840. /* Make HIF AXI transactions non-bufferable */
  841. writel(0x1, HIF_AXI_CTRL);
  842. }