tlb.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2008-2011 Freescale Semiconductor, Inc.
  4. *
  5. * (C) Copyright 2000
  6. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  7. */
  8. #include <common.h>
  9. #include <asm/bitops.h>
  10. #include <asm/processor.h>
  11. #include <asm/mmu.h>
  12. #ifdef CONFIG_ADDR_MAP
  13. #include <addr_map.h>
  14. #endif
  15. #include <linux/log2.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. void invalidate_tlb(u8 tlb)
  18. {
  19. if (tlb == 0)
  20. mtspr(MMUCSR0, 0x4);
  21. if (tlb == 1)
  22. mtspr(MMUCSR0, 0x2);
  23. }
  24. __weak void init_tlbs(void)
  25. {
  26. int i;
  27. for (i = 0; i < num_tlb_entries; i++) {
  28. write_tlb(tlb_table[i].mas0,
  29. tlb_table[i].mas1,
  30. tlb_table[i].mas2,
  31. tlb_table[i].mas3,
  32. tlb_table[i].mas7);
  33. }
  34. return ;
  35. }
  36. #if !defined(CONFIG_NAND_SPL) && \
  37. (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_INIT_MINIMAL))
  38. void read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, unsigned long *epn,
  39. phys_addr_t *rpn)
  40. {
  41. u32 _mas1;
  42. mtspr(MAS0, FSL_BOOKE_MAS0(1, idx, 0));
  43. asm volatile("tlbre;isync");
  44. _mas1 = mfspr(MAS1);
  45. *valid = (_mas1 & MAS1_VALID);
  46. *tsize = (_mas1 >> 7) & 0x1f;
  47. *epn = mfspr(MAS2) & MAS2_EPN;
  48. *rpn = mfspr(MAS3) & MAS3_RPN;
  49. #ifdef CONFIG_ENABLE_36BIT_PHYS
  50. *rpn |= ((u64)mfspr(MAS7)) << 32;
  51. #endif
  52. }
  53. void print_tlbcam(void)
  54. {
  55. int i;
  56. unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
  57. /* walk all the entries */
  58. printf("TLBCAM entries\n");
  59. for (i = 0; i < num_cam; i++) {
  60. unsigned long epn;
  61. u32 tsize, valid;
  62. phys_addr_t rpn;
  63. read_tlbcam_entry(i, &valid, &tsize, &epn, &rpn);
  64. printf("entry %02d: V: %d EPN 0x%08x RPN 0x%08llx size:",
  65. i, (valid == 0) ? 0 : 1, (unsigned int)epn,
  66. (unsigned long long)rpn);
  67. print_size(TSIZE_TO_BYTES(tsize), "\n");
  68. }
  69. }
  70. static inline void use_tlb_cam(u8 idx)
  71. {
  72. int i = idx / 32;
  73. int bit = idx % 32;
  74. gd->arch.used_tlb_cams[i] |= (1 << bit);
  75. }
  76. static inline void free_tlb_cam(u8 idx)
  77. {
  78. int i = idx / 32;
  79. int bit = idx % 32;
  80. gd->arch.used_tlb_cams[i] &= ~(1 << bit);
  81. }
  82. void init_used_tlb_cams(void)
  83. {
  84. int i;
  85. unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
  86. for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++)
  87. gd->arch.used_tlb_cams[i] = 0;
  88. /* walk all the entries */
  89. for (i = 0; i < num_cam; i++) {
  90. mtspr(MAS0, FSL_BOOKE_MAS0(1, i, 0));
  91. asm volatile("tlbre;isync");
  92. if (mfspr(MAS1) & MAS1_VALID)
  93. use_tlb_cam(i);
  94. }
  95. }
  96. int find_free_tlbcam(void)
  97. {
  98. int i;
  99. u32 idx;
  100. for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++) {
  101. idx = ffz(gd->arch.used_tlb_cams[i]);
  102. if (idx != 32)
  103. break;
  104. }
  105. idx += i * 32;
  106. if (idx >= CONFIG_SYS_NUM_TLBCAMS)
  107. return -1;
  108. return idx;
  109. }
  110. void set_tlb(u8 tlb, u32 epn, u64 rpn,
  111. u8 perms, u8 wimge,
  112. u8 ts, u8 esel, u8 tsize, u8 iprot)
  113. {
  114. u32 _mas0, _mas1, _mas2, _mas3, _mas7;
  115. if (tlb == 1)
  116. use_tlb_cam(esel);
  117. if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1 &&
  118. tsize & 1) {
  119. printf("%s: bad tsize %d on entry %d at 0x%08x\n",
  120. __func__, tsize, tlb, epn);
  121. return;
  122. }
  123. _mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
  124. _mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
  125. _mas2 = FSL_BOOKE_MAS2(epn, wimge);
  126. _mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
  127. _mas7 = FSL_BOOKE_MAS7(rpn);
  128. write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7);
  129. #ifdef CONFIG_ADDR_MAP
  130. if ((tlb == 1) && (gd->flags & GD_FLG_RELOC))
  131. addrmap_set_entry(epn, rpn, TSIZE_TO_BYTES(tsize), esel);
  132. #endif
  133. }
  134. void disable_tlb(u8 esel)
  135. {
  136. u32 _mas0, _mas1, _mas2, _mas3;
  137. free_tlb_cam(esel);
  138. _mas0 = FSL_BOOKE_MAS0(1, esel, 0);
  139. _mas1 = 0;
  140. _mas2 = 0;
  141. _mas3 = 0;
  142. mtspr(MAS0, _mas0);
  143. mtspr(MAS1, _mas1);
  144. mtspr(MAS2, _mas2);
  145. mtspr(MAS3, _mas3);
  146. #ifdef CONFIG_ENABLE_36BIT_PHYS
  147. mtspr(MAS7, 0);
  148. #endif
  149. asm volatile("isync;msync;tlbwe;isync");
  150. #ifdef CONFIG_ADDR_MAP
  151. if (gd->flags & GD_FLG_RELOC)
  152. addrmap_set_entry(0, 0, 0, esel);
  153. #endif
  154. }
  155. static void tlbsx (const volatile unsigned *addr)
  156. {
  157. __asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr));
  158. }
  159. /* return -1 if we didn't find anything */
  160. int find_tlb_idx(void *addr, u8 tlbsel)
  161. {
  162. u32 _mas0, _mas1;
  163. /* zero out Search PID, AS */
  164. mtspr(MAS6, 0);
  165. tlbsx(addr);
  166. _mas0 = mfspr(MAS0);
  167. _mas1 = mfspr(MAS1);
  168. /* we found something, and its in the TLB we expect */
  169. if ((MAS1_VALID & _mas1) &&
  170. (MAS0_TLBSEL(tlbsel) == (_mas0 & MAS0_TLBSEL_MSK))) {
  171. return ((_mas0 & MAS0_ESEL_MSK) >> 16);
  172. }
  173. return -1;
  174. }
  175. #ifdef CONFIG_ADDR_MAP
  176. void init_addr_map(void)
  177. {
  178. int i;
  179. unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
  180. /* walk all the entries */
  181. for (i = 0; i < num_cam; i++) {
  182. unsigned long epn;
  183. u32 tsize, valid;
  184. phys_addr_t rpn;
  185. read_tlbcam_entry(i, &valid, &tsize, &epn, &rpn);
  186. if (valid & MAS1_VALID)
  187. addrmap_set_entry(epn, rpn, TSIZE_TO_BYTES(tsize), i);
  188. }
  189. return ;
  190. }
  191. #endif
  192. uint64_t tlb_map_range(ulong v_addr, phys_addr_t p_addr, uint64_t size,
  193. enum tlb_map_type map_type)
  194. {
  195. int i;
  196. unsigned int tlb_size;
  197. unsigned int wimge;
  198. unsigned int perm;
  199. unsigned int max_cam, tsize_mask;
  200. if (map_type == TLB_MAP_RAM) {
  201. perm = MAS3_SX|MAS3_SW|MAS3_SR;
  202. wimge = MAS2_M;
  203. #ifdef CONFIG_SYS_PPC_DDR_WIMGE
  204. wimge = CONFIG_SYS_PPC_DDR_WIMGE;
  205. #endif
  206. } else {
  207. perm = MAS3_SW|MAS3_SR;
  208. wimge = MAS2_I|MAS2_G;
  209. }
  210. if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
  211. /* Convert (4^max) kB to (2^max) bytes */
  212. max_cam = ((mfspr(SPRN_TLB1CFG) >> 16) & 0xf) * 2 + 10;
  213. tsize_mask = ~1U;
  214. } else {
  215. /* Convert (2^max) kB to (2^max) bytes */
  216. max_cam = __ilog2(mfspr(SPRN_TLB1PS)) + 10;
  217. tsize_mask = ~0U;
  218. }
  219. for (i = 0; size && i < 8; i++) {
  220. int tlb_index = find_free_tlbcam();
  221. u32 camsize = __ilog2_u64(size) & tsize_mask;
  222. u32 align = __ilog2(v_addr) & tsize_mask;
  223. if (tlb_index == -1)
  224. break;
  225. if (align == -2) align = max_cam;
  226. if (camsize > align)
  227. camsize = align;
  228. if (camsize > max_cam)
  229. camsize = max_cam;
  230. tlb_size = camsize - 10;
  231. set_tlb(1, v_addr, p_addr, perm, wimge,
  232. 0, tlb_index, tlb_size, 1);
  233. size -= 1ULL << camsize;
  234. v_addr += 1UL << camsize;
  235. p_addr += 1UL << camsize;
  236. }
  237. return size;
  238. }
  239. unsigned int setup_ddr_tlbs_phys(phys_addr_t p_addr,
  240. unsigned int memsize_in_meg)
  241. {
  242. unsigned int ram_tlb_address = (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE;
  243. u64 memsize = (u64)memsize_in_meg << 20;
  244. u64 size;
  245. size = min(memsize, (u64)CONFIG_MAX_MEM_MAPPED);
  246. size = tlb_map_range(ram_tlb_address, p_addr, size, TLB_MAP_RAM);
  247. if (size || memsize > CONFIG_MAX_MEM_MAPPED) {
  248. print_size(memsize > CONFIG_MAX_MEM_MAPPED ?
  249. memsize - CONFIG_MAX_MEM_MAPPED + size : size,
  250. " left unmapped\n");
  251. }
  252. return memsize_in_meg;
  253. }
  254. unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg)
  255. {
  256. return
  257. setup_ddr_tlbs_phys(CONFIG_SYS_DDR_SDRAM_BASE, memsize_in_meg);
  258. }
  259. /* Invalidate the DDR TLBs for the requested size */
  260. void clear_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg)
  261. {
  262. u32 vstart = CONFIG_SYS_DDR_SDRAM_BASE;
  263. unsigned long epn;
  264. u32 tsize, valid, ptr;
  265. phys_addr_t rpn = 0;
  266. int ddr_esel;
  267. u64 memsize = (u64)memsize_in_meg << 20;
  268. ptr = vstart;
  269. while (ptr < (vstart + memsize)) {
  270. ddr_esel = find_tlb_idx((void *)ptr, 1);
  271. if (ddr_esel != -1) {
  272. read_tlbcam_entry(ddr_esel, &valid, &tsize, &epn, &rpn);
  273. disable_tlb(ddr_esel);
  274. }
  275. ptr += TSIZE_TO_BYTES(tsize);
  276. }
  277. }
  278. void clear_ddr_tlbs(unsigned int memsize_in_meg)
  279. {
  280. clear_ddr_tlbs_phys(CONFIG_SYS_DDR_SDRAM_BASE, memsize_in_meg);
  281. }
  282. #endif /* not SPL */