law.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * Copyright 2008-2011 Freescale Semiconductor, Inc.
  3. *
  4. * (C) Copyright 2000
  5. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <common.h>
  10. #include <linux/compiler.h>
  11. #include <asm/fsl_law.h>
  12. #include <asm/io.h>
  13. DECLARE_GLOBAL_DATA_PTR;
  14. #define FSL_HW_NUM_LAWS CONFIG_SYS_FSL_NUM_LAWS
  15. #ifdef CONFIG_FSL_CORENET
  16. #define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR)
  17. #define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar)
  18. #define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh)
  19. #define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl)
  20. #define LAWBAR_SHIFT 0
  21. #else
  22. #define LAW_BASE (CONFIG_SYS_IMMR + 0xc08)
  23. #define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2)
  24. #define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x)
  25. #define LAWBAR_SHIFT 12
  26. #endif
  27. static inline phys_addr_t get_law_base_addr(int idx)
  28. {
  29. #ifdef CONFIG_FSL_CORENET
  30. return (phys_addr_t)
  31. ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) |
  32. in_be32(LAWBARL_ADDR(idx));
  33. #else
  34. return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
  35. #endif
  36. }
  37. static inline void set_law_base_addr(int idx, phys_addr_t addr)
  38. {
  39. #ifdef CONFIG_FSL_CORENET
  40. out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff);
  41. out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32);
  42. #else
  43. out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
  44. #endif
  45. }
  46. void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
  47. {
  48. gd->arch.used_laws |= (1 << idx);
  49. out_be32(LAWAR_ADDR(idx), 0);
  50. set_law_base_addr(idx, addr);
  51. out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz);
  52. /* Read back so that we sync the writes */
  53. in_be32(LAWAR_ADDR(idx));
  54. }
  55. void disable_law(u8 idx)
  56. {
  57. gd->arch.used_laws &= ~(1 << idx);
  58. out_be32(LAWAR_ADDR(idx), 0);
  59. set_law_base_addr(idx, 0);
  60. /* Read back so that we sync the writes */
  61. in_be32(LAWAR_ADDR(idx));
  62. return;
  63. }
  64. #if !defined(CONFIG_NAND_SPL) && \
  65. (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL))
  66. static int get_law_entry(u8 i, struct law_entry *e)
  67. {
  68. u32 lawar;
  69. lawar = in_be32(LAWAR_ADDR(i));
  70. if (!(lawar & LAW_EN))
  71. return 0;
  72. e->addr = get_law_base_addr(i);
  73. e->size = lawar & 0x3f;
  74. e->trgt_id = (lawar >> 20) & 0xff;
  75. return 1;
  76. }
  77. #endif
  78. int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
  79. {
  80. u32 idx = ffz(gd->arch.used_laws);
  81. if (idx >= FSL_HW_NUM_LAWS)
  82. return -1;
  83. set_law(idx, addr, sz, id);
  84. return idx;
  85. }
  86. #if !defined(CONFIG_NAND_SPL) && \
  87. (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL))
  88. int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
  89. {
  90. u32 idx;
  91. /* we have no LAWs free */
  92. if (gd->arch.used_laws == -1)
  93. return -1;
  94. /* grab the last free law */
  95. idx = __ilog2(~(gd->arch.used_laws));
  96. if (idx >= FSL_HW_NUM_LAWS)
  97. return -1;
  98. set_law(idx, addr, sz, id);
  99. return idx;
  100. }
  101. struct law_entry find_law(phys_addr_t addr)
  102. {
  103. struct law_entry entry;
  104. int i;
  105. entry.index = -1;
  106. entry.addr = 0;
  107. entry.size = 0;
  108. entry.trgt_id = 0;
  109. for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
  110. u64 upper;
  111. if (!get_law_entry(i, &entry))
  112. continue;
  113. upper = entry.addr + (2ull << entry.size);
  114. if ((addr >= entry.addr) && (addr < upper)) {
  115. entry.index = i;
  116. break;
  117. }
  118. }
  119. return entry;
  120. }
  121. void print_laws(void)
  122. {
  123. int i;
  124. u32 lawar;
  125. printf("\nLocal Access Window Configuration\n");
  126. for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
  127. lawar = in_be32(LAWAR_ADDR(i));
  128. #ifdef CONFIG_FSL_CORENET
  129. printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x",
  130. i, in_be32(LAWBARH_ADDR(i)),
  131. i, in_be32(LAWBARL_ADDR(i)));
  132. #else
  133. printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i)));
  134. #endif
  135. printf(" LAWAR%02d: 0x%08x\n", i, lawar);
  136. printf("\t(EN: %d TGT: 0x%02x SIZE: ",
  137. (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff);
  138. print_size(lawar_size(lawar), ")\n");
  139. }
  140. return;
  141. }
  142. /* use up to 2 LAWs for DDR, used the last available LAWs */
  143. int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
  144. {
  145. u64 start_align, law_sz;
  146. int law_sz_enc;
  147. if (start == 0)
  148. start_align = 1ull << (LAW_SIZE_32G + 1);
  149. else
  150. start_align = 1ull << (ffs64(start) - 1);
  151. law_sz = min(start_align, sz);
  152. law_sz_enc = __ilog2_u64(law_sz) - 1;
  153. if (set_last_law(start, law_sz_enc, id) < 0)
  154. return -1;
  155. /* recalculate size based on what was actually covered by the law */
  156. law_sz = 1ull << __ilog2_u64(law_sz);
  157. /* do we still have anything to map */
  158. sz = sz - law_sz;
  159. if (sz) {
  160. start += law_sz;
  161. start_align = 1ull << (ffs64(start) - 1);
  162. law_sz = min(start_align, sz);
  163. law_sz_enc = __ilog2_u64(law_sz) - 1;
  164. if (set_last_law(start, law_sz_enc, id) < 0)
  165. return -1;
  166. } else {
  167. return 0;
  168. }
  169. /* do we still have anything to map */
  170. sz = sz - law_sz;
  171. if (sz)
  172. return 1;
  173. return 0;
  174. }
  175. #endif /* not SPL */
  176. void disable_non_ddr_laws(void)
  177. {
  178. int i;
  179. int id;
  180. for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
  181. u32 lawar = in_be32(LAWAR_ADDR(i));
  182. if (lawar & LAW_EN) {
  183. id = (lawar & ~LAW_EN) >> 20;
  184. switch (id) {
  185. case LAW_TRGT_IF_DDR_1:
  186. case LAW_TRGT_IF_DDR_2:
  187. case LAW_TRGT_IF_DDR_3:
  188. case LAW_TRGT_IF_DDR_4:
  189. case LAW_TRGT_IF_DDR_INTRLV:
  190. case LAW_TRGT_IF_DDR_INTLV_34:
  191. case LAW_TRGT_IF_DDR_INTLV_123:
  192. case LAW_TRGT_IF_DDR_INTLV_1234:
  193. continue;
  194. default:
  195. disable_law(i);
  196. }
  197. }
  198. }
  199. }
  200. void init_laws(void)
  201. {
  202. int i;
  203. #if FSL_HW_NUM_LAWS < 32
  204. gd->arch.used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1);
  205. #elif FSL_HW_NUM_LAWS == 32
  206. gd->arch.used_laws = 0;
  207. #else
  208. #error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
  209. #endif
  210. #if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500) && \
  211. !defined(CONFIG_E500MC)
  212. /* ISBC (Boot ROM) creates a LAW 0 entry for non PBL platforms,
  213. * which is not disabled before transferring the control to uboot.
  214. * Disable the LAW 0 entry here.
  215. */
  216. disable_law(0);
  217. #endif
  218. #if !defined(CONFIG_SECURE_BOOT)
  219. /*
  220. * if any non DDR LAWs has been created earlier, remove them before
  221. * LAW table is parsed.
  222. */
  223. disable_non_ddr_laws();
  224. #endif
  225. /*
  226. * Any LAWs that were set up before we booted assume they are meant to
  227. * be around and mark them used.
  228. */
  229. for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
  230. u32 lawar = in_be32(LAWAR_ADDR(i));
  231. if (lawar & LAW_EN)
  232. gd->arch.used_laws |= (1 << i);
  233. }
  234. for (i = 0; i < num_law_entries; i++) {
  235. if (law_table[i].index == -1)
  236. set_next_law(law_table[i].addr, law_table[i].size,
  237. law_table[i].trgt_id);
  238. else
  239. set_law(law_table[i].index, law_table[i].addr,
  240. law_table[i].size, law_table[i].trgt_id);
  241. }
  242. #ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
  243. /* check RCW to get which port is used for boot */
  244. ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
  245. u32 bootloc = in_be32(&gur->rcwsr[6]);
  246. /*
  247. * in SRIO or PCIE boot we need to set specail LAWs for
  248. * SRIO or PCIE interfaces.
  249. */
  250. switch ((bootloc & FSL_CORENET_RCWSR6_BOOT_LOC) >> 23) {
  251. case 0x0: /* boot from PCIE1 */
  252. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
  253. LAW_SIZE_1M,
  254. LAW_TRGT_IF_PCIE_1);
  255. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
  256. LAW_SIZE_1M,
  257. LAW_TRGT_IF_PCIE_1);
  258. break;
  259. case 0x1: /* boot from PCIE2 */
  260. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
  261. LAW_SIZE_1M,
  262. LAW_TRGT_IF_PCIE_2);
  263. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
  264. LAW_SIZE_1M,
  265. LAW_TRGT_IF_PCIE_2);
  266. break;
  267. case 0x2: /* boot from PCIE3 */
  268. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
  269. LAW_SIZE_1M,
  270. LAW_TRGT_IF_PCIE_3);
  271. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
  272. LAW_SIZE_1M,
  273. LAW_TRGT_IF_PCIE_3);
  274. break;
  275. case 0x8: /* boot from SRIO1 */
  276. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
  277. LAW_SIZE_1M,
  278. LAW_TRGT_IF_RIO_1);
  279. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
  280. LAW_SIZE_1M,
  281. LAW_TRGT_IF_RIO_1);
  282. break;
  283. case 0x9: /* boot from SRIO2 */
  284. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
  285. LAW_SIZE_1M,
  286. LAW_TRGT_IF_RIO_2);
  287. set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
  288. LAW_SIZE_1M,
  289. LAW_TRGT_IF_RIO_2);
  290. break;
  291. default:
  292. break;
  293. }
  294. #endif
  295. return ;
  296. }