2 * Copyright 2008-2011 Freescale Semiconductor, Inc.
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/processor.h>
13 #ifdef CONFIG_ADDR_MAP
17 DECLARE_GLOBAL_DATA_PTR
;
19 void invalidate_tlb(u8 tlb
)
31 for (i
= 0; i
< num_tlb_entries
; i
++) {
32 write_tlb(tlb_table
[i
].mas0
,
42 #if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
43 void read_tlbcam_entry(int idx
, u32
*valid
, u32
*tsize
, unsigned long *epn
,
48 mtspr(MAS0
, FSL_BOOKE_MAS0(1, idx
, 0));
49 asm volatile("tlbre;isync");
52 *valid
= (_mas1
& MAS1_VALID
);
53 *tsize
= (_mas1
>> 7) & 0x1f;
54 *epn
= mfspr(MAS2
) & MAS2_EPN
;
55 *rpn
= mfspr(MAS3
) & MAS3_RPN
;
56 #ifdef CONFIG_ENABLE_36BIT_PHYS
57 *rpn
|= ((u64
)mfspr(MAS7
)) << 32;
61 void print_tlbcam(void)
64 unsigned int num_cam
= mfspr(SPRN_TLB1CFG
) & 0xfff;
66 /* walk all the entries */
67 printf("TLBCAM entries\n");
68 for (i
= 0; i
< num_cam
; i
++) {
73 read_tlbcam_entry(i
, &valid
, &tsize
, &epn
, &rpn
);
74 printf("entry %02d: V: %d EPN 0x%08x RPN 0x%08llx size:",
75 i
, (valid
== 0) ? 0 : 1, (unsigned int)epn
,
76 (unsigned long long)rpn
);
77 print_size(TSIZE_TO_BYTES(tsize
), "\n");
81 static inline void use_tlb_cam(u8 idx
)
86 gd
->arch
.used_tlb_cams
[i
] |= (1 << bit
);
89 static inline void free_tlb_cam(u8 idx
)
94 gd
->arch
.used_tlb_cams
[i
] &= ~(1 << bit
);
97 void init_used_tlb_cams(void)
100 unsigned int num_cam
= mfspr(SPRN_TLB1CFG
) & 0xfff;
102 for (i
= 0; i
< ((CONFIG_SYS_NUM_TLBCAMS
+31)/32); i
++)
103 gd
->arch
.used_tlb_cams
[i
] = 0;
105 /* walk all the entries */
106 for (i
= 0; i
< num_cam
; i
++) {
107 mtspr(MAS0
, FSL_BOOKE_MAS0(1, i
, 0));
108 asm volatile("tlbre;isync");
109 if (mfspr(MAS1
) & MAS1_VALID
)
114 int find_free_tlbcam(void)
119 for (i
= 0; i
< ((CONFIG_SYS_NUM_TLBCAMS
+31)/32); i
++) {
120 idx
= ffz(gd
->arch
.used_tlb_cams
[i
]);
128 if (idx
>= CONFIG_SYS_NUM_TLBCAMS
)
134 void set_tlb(u8 tlb
, u32 epn
, u64 rpn
,
136 u8 ts
, u8 esel
, u8 tsize
, u8 iprot
)
138 u32 _mas0
, _mas1
, _mas2
, _mas3
, _mas7
;
143 if ((mfspr(SPRN_MMUCFG
) & MMUCFG_MAVN
) == MMUCFG_MAVN_V1
&&
145 printf("%s: bad tsize %d on entry %d at 0x%08x\n",
146 __func__
, tsize
, tlb
, epn
);
150 _mas0
= FSL_BOOKE_MAS0(tlb
, esel
, 0);
151 _mas1
= FSL_BOOKE_MAS1(1, iprot
, 0, ts
, tsize
);
152 _mas2
= FSL_BOOKE_MAS2(epn
, wimge
);
153 _mas3
= FSL_BOOKE_MAS3(rpn
, 0, perms
);
154 _mas7
= FSL_BOOKE_MAS7(rpn
);
156 write_tlb(_mas0
, _mas1
, _mas2
, _mas3
, _mas7
);
158 #ifdef CONFIG_ADDR_MAP
159 if ((tlb
== 1) && (gd
->flags
& GD_FLG_RELOC
))
160 addrmap_set_entry(epn
, rpn
, TSIZE_TO_BYTES(tsize
), esel
);
164 void disable_tlb(u8 esel
)
166 u32 _mas0
, _mas1
, _mas2
, _mas3
;
170 _mas0
= FSL_BOOKE_MAS0(1, esel
, 0);
179 #ifdef CONFIG_ENABLE_36BIT_PHYS
182 asm volatile("isync;msync;tlbwe;isync");
184 #ifdef CONFIG_ADDR_MAP
185 if (gd
->flags
& GD_FLG_RELOC
)
186 addrmap_set_entry(0, 0, 0, esel
);
190 static void tlbsx (const volatile unsigned *addr
)
192 __asm__
__volatile__ ("tlbsx 0,%0" : : "r" (addr
), "m" (*addr
));
195 /* return -1 if we didn't find anything */
196 int find_tlb_idx(void *addr
, u8 tlbsel
)
200 /* zero out Search PID, AS */
208 /* we found something, and its in the TLB we expect */
209 if ((MAS1_VALID
& _mas1
) &&
210 (MAS0_TLBSEL(tlbsel
) == (_mas0
& MAS0_TLBSEL_MSK
))) {
211 return ((_mas0
& MAS0_ESEL_MSK
) >> 16);
217 #ifdef CONFIG_ADDR_MAP
218 void init_addr_map(void)
221 unsigned int num_cam
= mfspr(SPRN_TLB1CFG
) & 0xfff;
223 /* walk all the entries */
224 for (i
= 0; i
< num_cam
; i
++) {
229 read_tlbcam_entry(i
, &valid
, &tsize
, &epn
, &rpn
);
230 if (valid
& MAS1_VALID
)
231 addrmap_set_entry(epn
, rpn
, TSIZE_TO_BYTES(tsize
), i
);
239 setup_ddr_tlbs_phys(phys_addr_t p_addr
, unsigned int memsize_in_meg
)
242 unsigned int tlb_size
;
243 unsigned int wimge
= MAS2_M
;
244 unsigned int ram_tlb_address
= (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE
;
245 unsigned int max_cam
, tsize_mask
;
246 u64 size
, memsize
= (u64
)memsize_in_meg
<< 20;
248 #ifdef CONFIG_SYS_PPC_DDR_WIMGE
249 wimge
= CONFIG_SYS_PPC_DDR_WIMGE
;
251 size
= min(memsize
, CONFIG_MAX_MEM_MAPPED
);
252 if ((mfspr(SPRN_MMUCFG
) & MMUCFG_MAVN
) == MMUCFG_MAVN_V1
) {
253 /* Convert (4^max) kB to (2^max) bytes */
254 max_cam
= ((mfspr(SPRN_TLB1CFG
) >> 16) & 0xf) * 2 + 10;
257 /* Convert (2^max) kB to (2^max) bytes */
258 max_cam
= __ilog2(mfspr(SPRN_TLB1PS
)) + 10;
262 for (i
= 0; size
&& i
< 8; i
++) {
263 int ram_tlb_index
= find_free_tlbcam();
264 u32 camsize
= __ilog2_u64(size
) & tsize_mask
;
265 u32 align
= __ilog2(ram_tlb_address
) & tsize_mask
;
267 if (ram_tlb_index
== -1)
270 if (align
== -2) align
= max_cam
;
274 if (camsize
> max_cam
)
277 tlb_size
= camsize
- 10;
279 set_tlb(1, ram_tlb_address
, p_addr
,
280 MAS3_SX
|MAS3_SW
|MAS3_SR
, wimge
,
281 0, ram_tlb_index
, tlb_size
, 1);
283 size
-= 1ULL << camsize
;
284 memsize
-= 1ULL << camsize
;
285 ram_tlb_address
+= 1UL << camsize
;
286 p_addr
+= 1UL << camsize
;
290 print_size(memsize
, " left unmapped\n");
291 return memsize_in_meg
;
294 unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg
)
297 setup_ddr_tlbs_phys(CONFIG_SYS_DDR_SDRAM_BASE
, memsize_in_meg
);
300 /* Invalidate the DDR TLBs for the requested size */
301 void clear_ddr_tlbs_phys(phys_addr_t p_addr
, unsigned int memsize_in_meg
)
303 u32 vstart
= CONFIG_SYS_DDR_SDRAM_BASE
;
305 u32 tsize
, valid
, ptr
;
308 u64 memsize
= (u64
)memsize_in_meg
<< 20;
312 while (ptr
< (vstart
+ memsize
)) {
313 ddr_esel
= find_tlb_idx((void *)ptr
, 1);
314 if (ddr_esel
!= -1) {
315 read_tlbcam_entry(ddr_esel
, &valid
, &tsize
, &epn
, &rpn
);
316 disable_tlb(ddr_esel
);
318 ptr
+= TSIZE_TO_BYTES(tsize
);
322 void clear_ddr_tlbs(unsigned int memsize_in_meg
)
324 clear_ddr_tlbs_phys(CONFIG_SYS_DDR_SDRAM_BASE
, memsize_in_meg
);