pfe_hw.c 25 KB

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