1/*- 2 * Copyright (c) 2011-2012 Semihalf. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/types.h> 31#include <sys/systm.h> 32 33#include <machine/machdep.h> 34 35#include <powerpc/booke/dcr.h> 36#include <powerpc/apm86xxx/apm86xxx.h> 37 38#include <dev/fdt/fdt_common.h> 39 40#define OCP_ADDR_WORDLO(addr) ((uint32_t)((uint64_t)(addr) & 0xFFFFFFFF)) 41#define OCP_ADDR_WORDHI(addr) ((uint32_t)((uint64_t)(addr) >> 32)) 42 43extern void tlb_write(u_int, uint32_t, uint32_t, uint32_t, tlbtid_t, uint32_t, 44 uint32_t); 45extern void tlb_read(u_int, uint32_t *, uint32_t *, uint32_t *, uint32_t *, 46 uint32_t *, uint32_t *); 47 48unsigned int tlb_static_entries; 49unsigned int tlb_current_entry = TLB_SIZE; 50unsigned int tlb_misses = 0; 51unsigned int tlb_invals = 0; 52 53void tlb_map(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); 54void tlb_map_mem(uint32_t, uint32_t, uint32_t); 55void tlb_dump(void); 56 57void 58booke_init_tlb(vm_paddr_t fdt_immr_pa) 59{ 60 61 /* Map register space */ 62 tlb_map(APM86XXX_DEEP_SLEEP_VA, 63 OCP_ADDR_WORDLO(APM86XXX_DEEP_SLEEP_PA), 64 OCP_ADDR_WORDHI(APM86XXX_DEEP_SLEEP_PA), TLB_VALID | TLB_SIZE_16M, 65 TLB_SW | TLB_SR | TLB_I | TLB_G); 66 67 tlb_map(APM86XXX_CSR_VA, OCP_ADDR_WORDLO(APM86XXX_CSR_PA), 68 OCP_ADDR_WORDHI(APM86XXX_CSR_PA), TLB_VALID | TLB_SIZE_16M, 69 TLB_SW | TLB_SR | TLB_I | TLB_G); 70 71 tlb_map(APM86XXX_PRIMARY_FABRIC_VA, 72 OCP_ADDR_WORDLO(APM86XXX_PRIMARY_FABRIC_PA), 73 OCP_ADDR_WORDHI(APM86XXX_PRIMARY_FABRIC_PA), 74 TLB_VALID | TLB_SIZE_16M, 75 TLB_SW | TLB_SR | TLB_I | TLB_G); 76 77 tlb_map(APM86XXX_AHB_VA, OCP_ADDR_WORDLO(APM86XXX_AHB_PA), 78 OCP_ADDR_WORDHI(APM86XXX_AHB_PA), 79 TLB_VALID | TLB_SIZE_16M, 80 TLB_SW | TLB_SR | TLB_I | TLB_G); 81 82 /* Map MailBox space */ 83 tlb_map(APM86XXX_MBOX_VA, OCP_ADDR_WORDLO(APM86XXX_MBOX_PA), 84 OCP_ADDR_WORDHI(APM86XXX_MBOX_PA), 85 TLB_VALID | TLB_SIZE_4K, 86 TLB_UX | TLB_UW | TLB_UR | 87 TLB_SX | TLB_SW | TLB_SR | 88 TLB_I | TLB_G); 89 90 tlb_map(APM86XXX_MBOX_VA + 0x1000, 91 OCP_ADDR_WORDLO(APM86XXX_MBOX_PA) + 0x1000, 92 OCP_ADDR_WORDHI(APM86XXX_MBOX_PA), 93 TLB_VALID | TLB_SIZE_4K, 94 TLB_UX | TLB_UW | TLB_UR | 95 TLB_SX | TLB_SW | TLB_SR | 96 TLB_I | TLB_G); 97 98 tlb_map(APM86XXX_MBOX_VA + 0x2000, 99 OCP_ADDR_WORDLO(APM86XXX_MBOX_PA)+ 0x2000, 100 OCP_ADDR_WORDHI(APM86XXX_MBOX_PA), 101 TLB_VALID | TLB_SIZE_4K, 102 TLB_UX | TLB_UW | TLB_UR | 103 TLB_SX | TLB_SW | TLB_SR | 104 TLB_I | TLB_G); 105} 106 107void 108booke_enable_l1_cache(void) 109{ 110} 111 112void 113booke_enable_l2_cache(void) 114{ 115} 116 117void 118booke_enable_l3_cache(void) 119{ 120} 121 122void 123booke_disable_l2_cache(void) 124{ 125 uint32_t ccr1,l2cr0; 126 127 /* Disable L2 cache op broadcast */ 128 ccr1 = mfspr(SPR_CCR1); 129 ccr1 &= ~CCR1_L2COBE; 130 mtspr(SPR_CCR1, ccr1); 131 132 /* Set L2 array size to 0 i.e. disable L2 cache */ 133 mtdcr(DCR_L2DCDCRAI, DCR_L2CR0); 134 l2cr0 = mfdcr(DCR_L2DCDCRDI); 135 l2cr0 &= ~L2CR0_AS; 136 mtdcr(DCR_L2DCDCRDI, l2cr0); 137} 138 139void tlb_map(uint32_t epn, uint32_t rpn, uint32_t erpn, uint32_t flags, 140 uint32_t perms) 141{ 142 143 tlb_write(++tlb_static_entries, epn, rpn, erpn, 0, flags, perms); 144} 145 146static void tlb_dump_entry(u_int entry) 147{ 148 uint32_t epn, rpn, erpn, tid, flags, perms; 149 const char *size; 150 151 tlb_read(entry, &epn, &rpn, &erpn, &tid, &flags, &perms); 152 153 switch (flags & TLB_SIZE_MASK) { 154 case TLB_SIZE_1K: 155 size = " 1k"; 156 break; 157 case TLB_SIZE_4K: 158 size = " 4k"; 159 break; 160 case TLB_SIZE_16K: 161 size = " 16k"; 162 break; 163 case TLB_SIZE_256K: 164 size = "256k"; 165 break; 166 case TLB_SIZE_1M: 167 size = " 1M"; 168 break; 169 case TLB_SIZE_16M: 170 size = " 16M"; 171 break; 172 case TLB_SIZE_256M: 173 size = "256M"; 174 break; 175 case TLB_SIZE_1G: 176 size = " 1G"; 177 break; 178 default: 179 size = "????"; 180 break; 181 } 182 183 184 printf("TLB[%02u]: 0x%08X => " 185 "0x%01X_%08X %s %c %c %s %s %s %s %s " 186 "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c (%u)\n", 187 entry, epn, erpn, rpn, size, 188 (flags & TLB_TS) ? '1' : '0', 189 (flags & TLB_VALID) ? 'V' : '.', 190 (perms & TLB_WL1) ? "WL1" : "___", 191 (perms & TLB_IL1I) ? "IL1I" : "____", 192 (perms & TLB_IL1D) ? "IL1D" : "____", 193 (perms & TLB_IL2I) ? "IL2I" : "____", 194 (perms & TLB_IL2D) ? "IL2D" : "____", 195 (perms & TLB_U0) ? '1' : '.', 196 (perms & TLB_U1) ? '2' : '.', 197 (perms & TLB_U2) ? '3' : '.', 198 (perms & TLB_U3) ? '4' : '.', 199 (perms & TLB_W) ? 'W' : '.', 200 (perms & TLB_I) ? 'I' : '.', 201 (perms & TLB_M) ? 'M' : '.', 202 (perms & TLB_G) ? 'G' : '.', 203 (perms & TLB_E) ? 'E' : '.', 204 (perms & TLB_UX) ? 'x' : '.', 205 (perms & TLB_UW) ? 'w' : '.', 206 (perms & TLB_UR) ? 'r' : '.', 207 (perms & TLB_SX) ? 'X' : '.', 208 (perms & TLB_SW) ? 'W' : '.', 209 (perms & TLB_SR) ? 'R' : '.', 210 tid); 211} 212 213void tlb_dump(void) 214{ 215 int i; 216 217 for (i = 0; i < TLB_SIZE; i++) 218 tlb_dump_entry(i); 219} 220