aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/fsl_booke_mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/fsl_booke_mmu.c')
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index f7802c8bba0..66a6fd38e9c 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -101,17 +101,17 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
101 101
102/* 102/*
103 * Set up a variable-size TLB entry (tlbcam). The parameters are not checked; 103 * Set up a variable-size TLB entry (tlbcam). The parameters are not checked;
104 * in particular size must be a power of 4 between 4k and 256M (or 1G, for cpus 104 * in particular size must be a power of 4 between 4k and the max supported by
105 * that support extended page sizes). Note that while some cpus support a 105 * an implementation; max may further be limited by what can be represented in
106 * page size of 4G, we don't allow its use here. 106 * an unsigned long (for example, 32-bit implementations cannot support a 4GB
107 * size).
107 */ 108 */
108static void settlbcam(int index, unsigned long virt, phys_addr_t phys, 109static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
109 unsigned long size, unsigned long flags, unsigned int pid) 110 unsigned long size, unsigned long flags, unsigned int pid)
110{ 111{
111 unsigned int tsize, lz; 112 unsigned int tsize;
112 113
113 asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size)); 114 tsize = __ilog2(size) - 10;
114 tsize = 21 - lz;
115 115
116#ifdef CONFIG_SMP 116#ifdef CONFIG_SMP
117 if ((flags & _PAGE_NO_CACHE) == 0) 117 if ((flags & _PAGE_NO_CACHE) == 0)
@@ -146,29 +146,36 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
146 loadcam_entry(index); 146 loadcam_entry(index);
147} 147}
148 148
149unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
150 phys_addr_t phys)
151{
152 unsigned int camsize = __ilog2(ram) & ~1U;
153 unsigned int align = __ffs(virt | phys) & ~1U;
154 unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
155
156 /* Convert (4^max) kB to (2^max) bytes */
157 max_cam = max_cam * 2 + 10;
158
159 if (camsize > align)
160 camsize = align;
161 if (camsize > max_cam)
162 camsize = max_cam;
163
164 return 1UL << camsize;
165}
166
149unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx) 167unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
150{ 168{
151 int i; 169 int i;
152 unsigned long virt = PAGE_OFFSET; 170 unsigned long virt = PAGE_OFFSET;
153 phys_addr_t phys = memstart_addr; 171 phys_addr_t phys = memstart_addr;
154 unsigned long amount_mapped = 0; 172 unsigned long amount_mapped = 0;
155 unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
156
157 /* Convert (4^max) kB to (2^max) bytes */
158 max_cam = max_cam * 2 + 10;
159 173
160 /* Calculate CAM values */ 174 /* Calculate CAM values */
161 for (i = 0; ram && i < max_cam_idx; i++) { 175 for (i = 0; ram && i < max_cam_idx; i++) {
162 unsigned int camsize = __ilog2(ram) & ~1U;
163 unsigned int align = __ffs(virt | phys) & ~1U;
164 unsigned long cam_sz; 176 unsigned long cam_sz;
165 177
166 if (camsize > align) 178 cam_sz = calc_cam_sz(ram, virt, phys);
167 camsize = align;
168 if (camsize > max_cam)
169 camsize = max_cam;
170
171 cam_sz = 1UL << camsize;
172 settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0); 179 settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0);
173 180
174 ram -= cam_sz; 181 ram -= cam_sz;