2 * Copyright 2008-2009 Freescale Semiconductor, Inc.
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 * See file CREDITS for list of people who contributed to this
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <asm/processor.h>
29 #ifdef CONFIG_ADDR_MAP
33 DECLARE_GLOBAL_DATA_PTR
;
35 void invalidate_tlb(u8 tlb
)
47 for (i
= 0; i
< num_tlb_entries
; i
++) {
48 write_tlb(tlb_table
[i
].mas0
,
58 #ifndef CONFIG_NAND_SPL
59 static inline void use_tlb_cam(u8 idx
)
64 gd
->used_tlb_cams
[i
] |= (1 << bit
);
67 static inline void free_tlb_cam(u8 idx
)
72 gd
->used_tlb_cams
[i
] &= ~(1 << bit
);
75 void init_used_tlb_cams(void)
78 unsigned int num_cam
= mfspr(SPRN_TLB1CFG
) & 0xfff;
80 for (i
= 0; i
< ((CONFIG_SYS_NUM_TLBCAMS
+31)/32); i
++)
81 gd
->used_tlb_cams
[i
] = 0;
83 /* walk all the entries */
84 for (i
= 0; i
< num_cam
; i
++) {
87 mtspr(MAS0
, FSL_BOOKE_MAS0(1, i
, 0));
89 asm volatile("tlbre;isync");
92 /* if the entry isn't valid skip it */
93 if ((_mas1
& MAS1_VALID
))
98 int find_free_tlbcam(void)
103 for (i
= 0; i
< ((CONFIG_SYS_NUM_TLBCAMS
+31)/32); i
++) {
104 idx
= ffz(gd
->used_tlb_cams
[i
]);
112 if (idx
>= CONFIG_SYS_NUM_TLBCAMS
)
118 void set_tlb(u8 tlb
, u32 epn
, u64 rpn
,
120 u8 ts
, u8 esel
, u8 tsize
, u8 iprot
)
122 u32 _mas0
, _mas1
, _mas2
, _mas3
, _mas7
;
127 _mas0
= FSL_BOOKE_MAS0(tlb
, esel
, 0);
128 _mas1
= FSL_BOOKE_MAS1(1, iprot
, 0, ts
, tsize
);
129 _mas2
= FSL_BOOKE_MAS2(epn
, wimge
);
130 _mas3
= FSL_BOOKE_MAS3(rpn
, 0, perms
);
131 _mas7
= FSL_BOOKE_MAS7(rpn
);
133 write_tlb(_mas0
, _mas1
, _mas2
, _mas3
, _mas7
);
135 #ifdef CONFIG_ADDR_MAP
136 if ((tlb
== 1) && (gd
->flags
& GD_FLG_RELOC
))
137 addrmap_set_entry(epn
, rpn
, (1UL << ((tsize
* 2) + 10)), esel
);
141 void disable_tlb(u8 esel
)
143 u32 _mas0
, _mas1
, _mas2
, _mas3
, _mas7
;
147 _mas0
= FSL_BOOKE_MAS0(1, esel
, 0);
157 #ifdef CONFIG_ENABLE_36BIT_PHYS
160 asm volatile("isync;msync;tlbwe;isync");
162 #ifdef CONFIG_ADDR_MAP
163 if (gd
->flags
& GD_FLG_RELOC
)
164 addrmap_set_entry(0, 0, 0, esel
);
168 static void tlbsx (const volatile unsigned *addr
)
170 __asm__
__volatile__ ("tlbsx 0,%0" : : "r" (addr
), "m" (*addr
));
173 /* return -1 if we didn't find anything */
174 int find_tlb_idx(void *addr
, u8 tlbsel
)
178 /* zero out Search PID, AS */
186 /* we found something, and its in the TLB we expect */
187 if ((MAS1_VALID
& _mas1
) &&
188 (MAS0_TLBSEL(tlbsel
) == (_mas0
& MAS0_TLBSEL_MSK
))) {
189 return ((_mas0
& MAS0_ESEL_MSK
) >> 16);
195 #ifdef CONFIG_ADDR_MAP
196 void init_addr_map(void)
199 unsigned int num_cam
= mfspr(SPRN_TLB1CFG
) & 0xfff;
201 /* walk all the entries */
202 for (i
= 0; i
< num_cam
; i
++) {
207 mtspr(MAS0
, FSL_BOOKE_MAS0(1, i
, 0));
209 asm volatile("tlbre;isync");
212 /* if the entry isn't valid skip it */
213 if (!(_mas1
& MAS1_VALID
))
216 tsize
= (_mas1
>> 8) & 0xf;
217 epn
= mfspr(MAS2
) & MAS2_EPN
;
218 rpn
= mfspr(MAS3
) & MAS3_RPN
;
219 #ifdef CONFIG_ENABLE_36BIT_PHYS
220 rpn
|= ((phys_addr_t
)mfspr(MAS7
)) << 32;
223 addrmap_set_entry(epn
, rpn
, (1UL << ((tsize
* 2) + 10)), i
);
230 unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg
)
233 unsigned int tlb_size
;
234 unsigned int ram_tlb_address
= (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE
;
235 unsigned int max_cam
= (mfspr(SPRN_TLB1CFG
) >> 16) & 0xf;
236 u64 size
, memsize
= (u64
)memsize_in_meg
<< 20;
238 size
= min(memsize
, CONFIG_MAX_MEM_MAPPED
);
240 /* Convert (4^max) kB to (2^max) bytes */
241 max_cam
= max_cam
* 2 + 10;
243 for (i
= 0; size
&& i
< 8; i
++) {
244 int ram_tlb_index
= find_free_tlbcam();
245 u32 camsize
= __ilog2_u64(size
) & ~1U;
246 u32 align
= __ilog2(ram_tlb_address
) & ~1U;
248 if (ram_tlb_index
== -1)
251 if (align
== -2) align
= max_cam
;
255 if (camsize
> max_cam
)
258 tlb_size
= (camsize
- 10) / 2;
260 set_tlb(1, ram_tlb_address
, ram_tlb_address
,
261 MAS3_SX
|MAS3_SW
|MAS3_SR
, 0,
262 0, ram_tlb_index
, tlb_size
, 1);
264 size
-= 1ULL << camsize
;
265 memsize
-= 1ULL << camsize
;
266 ram_tlb_address
+= 1UL << camsize
;
270 print_size(memsize
, " left unmapped\n");
273 * Confirm that the requested amount of memory was mapped.
275 return memsize_in_meg
;
277 #endif /* !CONFIG_NAND_SPL */