liodn.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2008-2011 Freescale Semiconductor, Inc.
  4. */
  5. #include <common.h>
  6. #include <linux/libfdt.h>
  7. #include <fdt_support.h>
  8. #include <asm/immap_85xx.h>
  9. #include <asm/io.h>
  10. #include <asm/processor.h>
  11. #include <asm/fsl_portals.h>
  12. #include <asm/fsl_liodn.h>
  13. int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset)
  14. {
  15. liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset;
  16. if (liodn_bases[dpaa_dev].num_ids == 2)
  17. liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset;
  18. return liodn_bases[dpaa_dev].num_ids;
  19. }
  20. #ifdef CONFIG_SYS_SRIO
  21. static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size)
  22. {
  23. int i;
  24. for (i = 0; i < size; i++) {
  25. unsigned long reg_off = tbl[i].reg_offset[0];
  26. out_be32((u32 *)reg_off, tbl[i].id[0]);
  27. if (tbl[i].num_ids == 2) {
  28. reg_off = tbl[i].reg_offset[1];
  29. out_be32((u32 *)reg_off, tbl[i].id[1]);
  30. }
  31. }
  32. }
  33. #endif
  34. static void set_liodn(struct liodn_id_table *tbl, int size)
  35. {
  36. int i;
  37. for (i = 0; i < size; i++) {
  38. u32 liodn;
  39. if (tbl[i].num_ids == 2) {
  40. liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
  41. } else {
  42. liodn = tbl[i].id[0];
  43. }
  44. out_be32((volatile u32 *)(tbl[i].reg_offset), liodn);
  45. }
  46. }
  47. #ifdef CONFIG_SYS_DPAA_FMAN
  48. static void set_fman_liodn(struct fman_liodn_id_table *tbl, int size)
  49. {
  50. int i;
  51. for (i = 0; i < size; i++) {
  52. u32 liodn;
  53. if (tbl[i].num_ids == 2)
  54. liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
  55. else
  56. liodn = tbl[i].id[0];
  57. out_be32((volatile u32 *)(tbl[i].reg_offset), liodn);
  58. }
  59. }
  60. #endif
  61. static void setup_sec_liodn_base(void)
  62. {
  63. ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  64. u32 base;
  65. if (!IS_E_PROCESSOR(get_svr()))
  66. return;
  67. /* QILCR[QSLOM] */
  68. sec_out32(&sec->qilcr_ms, 0x3ff<<16);
  69. base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) |
  70. liodn_bases[FSL_HW_PORTAL_SEC].id[1];
  71. sec_out32(&sec->qilcr_ls, base);
  72. }
  73. #ifdef CONFIG_SYS_DPAA_FMAN
  74. static void setup_fman_liodn_base(enum fsl_dpaa_dev dev,
  75. struct fman_liodn_id_table *tbl, int size)
  76. {
  77. int i;
  78. ccsr_fman_t *fm;
  79. u32 base;
  80. switch(dev) {
  81. case FSL_HW_PORTAL_FMAN1:
  82. fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
  83. break;
  84. #if (CONFIG_SYS_NUM_FMAN == 2)
  85. case FSL_HW_PORTAL_FMAN2:
  86. fm = (void *)CONFIG_SYS_FSL_FM2_ADDR;
  87. break;
  88. #endif
  89. default:
  90. printf("Error: Invalid device type to %s\n", __FUNCTION__);
  91. return ;
  92. }
  93. base = (liodn_bases[dev].id[0] << 16) | liodn_bases[dev].id[0];
  94. /* setup all bases the same */
  95. for (i = 0; i < 32; i++) {
  96. out_be32(&fm->fm_dma.fmdmplr[i], base);
  97. }
  98. /* update tbl to ... */
  99. for (i = 0; i < size; i++)
  100. tbl[i].id[0] += liodn_bases[dev].id[0];
  101. }
  102. #endif
  103. static void setup_pme_liodn_base(void)
  104. {
  105. #ifdef CONFIG_SYS_DPAA_PME
  106. ccsr_pme_t *pme = (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
  107. u32 base = (liodn_bases[FSL_HW_PORTAL_PME].id[0] << 16) |
  108. liodn_bases[FSL_HW_PORTAL_PME].id[1];
  109. out_be32(&pme->liodnbr, base);
  110. #endif
  111. }
  112. #ifdef CONFIG_SYS_FSL_RAID_ENGINE
  113. static void setup_raide_liodn_base(void)
  114. {
  115. struct ccsr_raide *raide = (void *)CONFIG_SYS_FSL_RAID_ENGINE_ADDR;
  116. /* setup raid engine liodn base for data/desc ; both set to 47 */
  117. u32 base = (liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0] << 16) |
  118. liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0];
  119. out_be32(&raide->liodnbr, base);
  120. }
  121. #endif
  122. #ifdef CONFIG_SYS_DPAA_RMAN
  123. static void set_rman_liodn(struct liodn_id_table *tbl, int size)
  124. {
  125. int i;
  126. struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
  127. for (i = 0; i < size; i++) {
  128. /* write the RMan block number */
  129. out_be32(&rman->mmitar, i);
  130. /* write the liodn offset corresponding to the block */
  131. out_be32((u32 *)(tbl[i].reg_offset), tbl[i].id[0]);
  132. }
  133. }
  134. static void setup_rman_liodn_base(struct liodn_id_table *tbl, int size)
  135. {
  136. int i;
  137. struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
  138. u32 base = liodn_bases[FSL_HW_PORTAL_RMAN].id[0];
  139. out_be32(&rman->mmliodnbr, base);
  140. /* update liodn offset */
  141. for (i = 0; i < size; i++)
  142. tbl[i].id[0] += base;
  143. }
  144. #endif
  145. void set_liodns(void)
  146. {
  147. /* setup general liodn offsets */
  148. set_liodn(liodn_tbl, liodn_tbl_sz);
  149. #ifdef CONFIG_SYS_SRIO
  150. /* setup SRIO port liodns */
  151. set_srio_liodn(srio_liodn_tbl, srio_liodn_tbl_sz);
  152. #endif
  153. /* setup SEC block liodn bases & offsets if we have one */
  154. if (IS_E_PROCESSOR(get_svr())) {
  155. set_liodn(sec_liodn_tbl, sec_liodn_tbl_sz);
  156. setup_sec_liodn_base();
  157. }
  158. /* setup FMAN block(s) liodn bases & offsets if we have one */
  159. #ifdef CONFIG_SYS_DPAA_FMAN
  160. set_fman_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz);
  161. setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl,
  162. fman1_liodn_tbl_sz);
  163. #if (CONFIG_SYS_NUM_FMAN == 2)
  164. set_fman_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz);
  165. setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl,
  166. fman2_liodn_tbl_sz);
  167. #endif
  168. #endif
  169. /* setup PME liodn base */
  170. setup_pme_liodn_base();
  171. #ifdef CONFIG_SYS_FSL_RAID_ENGINE
  172. /* raid engine ccr addr code for liodn */
  173. set_liodn(raide_liodn_tbl, raide_liodn_tbl_sz);
  174. setup_raide_liodn_base();
  175. #endif
  176. #ifdef CONFIG_SYS_DPAA_RMAN
  177. /* setup RMan liodn offsets */
  178. set_rman_liodn(rman_liodn_tbl, rman_liodn_tbl_sz);
  179. /* setup RMan liodn base */
  180. setup_rman_liodn_base(rman_liodn_tbl, rman_liodn_tbl_sz);
  181. #endif
  182. }
  183. #ifdef CONFIG_SYS_SRIO
  184. static void fdt_fixup_srio_liodn(void *blob, struct srio_liodn_id_table *tbl)
  185. {
  186. int i, srio_off;
  187. /* search for srio node, if doesn't exist just return - nothing todo */
  188. srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio");
  189. if (srio_off < 0)
  190. return ;
  191. for (i = 0; i < srio_liodn_tbl_sz; i++) {
  192. int off, portid = tbl[i].portid;
  193. off = fdt_node_offset_by_prop_value(blob, srio_off,
  194. "cell-index", &portid, 4);
  195. if (off >= 0) {
  196. off = fdt_setprop(blob, off, "fsl,liodn",
  197. &tbl[i].id[0],
  198. sizeof(u32) * tbl[i].num_ids);
  199. if (off > 0)
  200. printf("WARNING unable to set fsl,liodn for "
  201. "fsl,srio port %d: %s\n",
  202. portid, fdt_strerror(off));
  203. } else {
  204. debug("WARNING: couldn't set fsl,liodn for srio: %s.\n",
  205. fdt_strerror(off));
  206. }
  207. }
  208. }
  209. #endif
  210. #define CONFIG_SYS_MAX_PCI_EPS 8
  211. static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat,
  212. int ep_liodn_start)
  213. {
  214. int off, pci_idx = 0, pci_cnt = 0, i, rc;
  215. const uint32_t *base_liodn;
  216. uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 };
  217. /*
  218. * Count the number of pci nodes.
  219. * It's needed later when the interleaved liodn offsets are generated.
  220. */
  221. off = fdt_node_offset_by_compatible(fdt, -1, compat);
  222. while (off != -FDT_ERR_NOTFOUND) {
  223. pci_cnt++;
  224. off = fdt_node_offset_by_compatible(fdt, off, compat);
  225. }
  226. for (off = fdt_node_offset_by_compatible(fdt, -1, compat);
  227. off != -FDT_ERR_NOTFOUND;
  228. off = fdt_node_offset_by_compatible(fdt, off, compat)) {
  229. base_liodn = fdt_getprop(fdt, off, "fsl,liodn", &rc);
  230. if (!base_liodn) {
  231. char path[64];
  232. if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
  233. strcpy(path, "(unknown)");
  234. printf("WARNING Could not get liodn of node %s: %s\n",
  235. path, fdt_strerror(rc));
  236. continue;
  237. }
  238. for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++)
  239. liodn_offs[i + 1] = ep_liodn_start +
  240. i * pci_cnt + pci_idx - *base_liodn;
  241. rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list",
  242. liodn_offs, sizeof(liodn_offs));
  243. if (rc) {
  244. char path[64];
  245. if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
  246. strcpy(path, "(unknown)");
  247. printf("WARNING Unable to set fsl,liodn-offset-list for "
  248. "node %s: %s\n", path, fdt_strerror(rc));
  249. continue;
  250. }
  251. pci_idx++;
  252. }
  253. }
  254. static void fdt_fixup_liodn_tbl(void *blob, struct liodn_id_table *tbl, int sz)
  255. {
  256. int i;
  257. for (i = 0; i < sz; i++) {
  258. int off;
  259. if (tbl[i].compat == NULL)
  260. continue;
  261. off = fdt_node_offset_by_compat_reg(blob,
  262. tbl[i].compat, tbl[i].compat_offset);
  263. if (off >= 0) {
  264. off = fdt_setprop(blob, off, "fsl,liodn",
  265. &tbl[i].id[0],
  266. sizeof(u32) * tbl[i].num_ids);
  267. if (off > 0)
  268. printf("WARNING unable to set fsl,liodn for "
  269. "%s: %s\n",
  270. tbl[i].compat, fdt_strerror(off));
  271. } else {
  272. debug("WARNING: could not set fsl,liodn for %s: %s.\n",
  273. tbl[i].compat, fdt_strerror(off));
  274. }
  275. }
  276. }
  277. #ifdef CONFIG_SYS_DPAA_FMAN
  278. static void fdt_fixup_liodn_tbl_fman(void *blob,
  279. struct fman_liodn_id_table *tbl,
  280. int sz)
  281. {
  282. int i;
  283. for (i = 0; i < sz; i++) {
  284. int off;
  285. if (tbl[i].compat == NULL)
  286. continue;
  287. /* Try the new compatible first.
  288. * If the node is missing, try the old.
  289. */
  290. off = fdt_node_offset_by_compat_reg(blob,
  291. tbl[i].compat[0], tbl[i].compat_offset);
  292. if (off < 0)
  293. off = fdt_node_offset_by_compat_reg(blob,
  294. tbl[i].compat[1], tbl[i].compat_offset);
  295. if (off >= 0) {
  296. off = fdt_setprop(blob, off, "fsl,liodn",
  297. &tbl[i].id[0],
  298. sizeof(u32) * tbl[i].num_ids);
  299. if (off > 0)
  300. printf("WARNING unable to set fsl,liodn for FMan Port: %s\n",
  301. fdt_strerror(off));
  302. } else {
  303. debug("WARNING: could not set fsl,liodn for FMan Portport: %s.\n",
  304. fdt_strerror(off));
  305. }
  306. }
  307. }
  308. #endif
  309. void fdt_fixup_liodn(void *blob)
  310. {
  311. #ifdef CONFIG_SYS_SRIO
  312. fdt_fixup_srio_liodn(blob, srio_liodn_tbl);
  313. #endif
  314. fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz);
  315. #ifdef CONFIG_SYS_DPAA_FMAN
  316. fdt_fixup_liodn_tbl_fman(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz);
  317. #if (CONFIG_SYS_NUM_FMAN == 2)
  318. fdt_fixup_liodn_tbl_fman(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz);
  319. #endif
  320. #endif
  321. fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz);
  322. #ifdef CONFIG_SYS_FSL_RAID_ENGINE
  323. fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz);
  324. #endif
  325. #ifdef CONFIG_SYS_DPAA_RMAN
  326. fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz);
  327. #endif
  328. ccsr_pcix_t *pcix = (ccsr_pcix_t *)CONFIG_SYS_PCIE1_ADDR;
  329. int pci_ver = pcix->ipver1 & 0xffff, liodn_base = 0;
  330. if (pci_ver >= 0x0204) {
  331. if (pci_ver >= 0x0300)
  332. liodn_base = 1024;
  333. else
  334. liodn_base = 256;
  335. }
  336. if (liodn_base) {
  337. char compat[32];
  338. sprintf(compat, "fsl,qoriq-pcie-v%d.%d",
  339. (pci_ver & 0xff00) >> 8, pci_ver & 0xff);
  340. fdt_fixup_pci_liodn_offsets(blob, compat, liodn_base);
  341. fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie", liodn_base);
  342. }
  343. }