1236324Sraj/*- 2236324Sraj * Copyright (c) 2011-2012 Semihalf. 3236324Sraj * All rights reserved. 4236324Sraj * 5236324Sraj * Redistribution and use in source and binary forms, with or without 6236324Sraj * modification, are permitted provided that the following conditions 7236324Sraj * are met: 8236324Sraj * 1. Redistributions of source code must retain the above copyright 9236324Sraj * notice, this list of conditions and the following disclaimer. 10236324Sraj * 2. Redistributions in binary form must reproduce the above copyright 11236324Sraj * notice, this list of conditions and the following disclaimer in the 12236324Sraj * documentation and/or other materials provided with the distribution. 13236324Sraj * 14236324Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15236324Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16236324Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17236324Sraj * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18236324Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19236324Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20236324Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21236324Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22236324Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23236324Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24236324Sraj * SUCH DAMAGE. 25236324Sraj */ 26236324Sraj 27236324Sraj#include <sys/cdefs.h> 28236324Sraj__FBSDID("$FreeBSD$"); 29236324Sraj 30236324Sraj#include <sys/types.h> 31236324Sraj#include <sys/systm.h> 32236324Sraj 33236324Sraj#include <machine/machdep.h> 34236324Sraj 35236324Sraj#include <powerpc/booke/dcr.h> 36236324Sraj#include <powerpc/apm86xxx/apm86xxx.h> 37236324Sraj 38236324Sraj#include <dev/fdt/fdt_common.h> 39236324Sraj 40236324Sraj#define OCP_ADDR_WORDLO(addr) ((uint32_t)((uint64_t)(addr) & 0xFFFFFFFF)) 41236324Sraj#define OCP_ADDR_WORDHI(addr) ((uint32_t)((uint64_t)(addr) >> 32)) 42236324Sraj 43236324Srajextern void tlb_write(u_int, uint32_t, uint32_t, uint32_t, tlbtid_t, uint32_t, 44236324Sraj uint32_t); 45236324Srajextern void tlb_read(u_int, uint32_t *, uint32_t *, uint32_t *, uint32_t *, 46236324Sraj uint32_t *, uint32_t *); 47236324Sraj 48236324Srajunsigned int tlb_static_entries; 49236324Srajunsigned int tlb_current_entry = TLB_SIZE; 50236324Srajunsigned int tlb_misses = 0; 51236324Srajunsigned int tlb_invals = 0; 52236324Sraj 53236324Srajvoid tlb_map(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); 54236324Srajvoid tlb_map_mem(uint32_t, uint32_t, uint32_t); 55236324Srajvoid tlb_dump(void); 56236324Sraj 57236324Srajvoid 58236324Srajbooke_init_tlb(vm_paddr_t fdt_immr_pa) 59236324Sraj{ 60236324Sraj 61236324Sraj /* Map register space */ 62236324Sraj tlb_map(APM86XXX_DEEP_SLEEP_VA, 63236324Sraj OCP_ADDR_WORDLO(APM86XXX_DEEP_SLEEP_PA), 64236324Sraj OCP_ADDR_WORDHI(APM86XXX_DEEP_SLEEP_PA), TLB_VALID | TLB_SIZE_16M, 65236324Sraj TLB_SW | TLB_SR | TLB_I | TLB_G); 66236324Sraj 67236324Sraj tlb_map(APM86XXX_CSR_VA, OCP_ADDR_WORDLO(APM86XXX_CSR_PA), 68236324Sraj OCP_ADDR_WORDHI(APM86XXX_CSR_PA), TLB_VALID | TLB_SIZE_16M, 69236324Sraj TLB_SW | TLB_SR | TLB_I | TLB_G); 70236324Sraj 71236324Sraj tlb_map(APM86XXX_PRIMARY_FABRIC_VA, 72236324Sraj OCP_ADDR_WORDLO(APM86XXX_PRIMARY_FABRIC_PA), 73236324Sraj OCP_ADDR_WORDHI(APM86XXX_PRIMARY_FABRIC_PA), 74236324Sraj TLB_VALID | TLB_SIZE_16M, 75236324Sraj TLB_SW | TLB_SR | TLB_I | TLB_G); 76236324Sraj 77236324Sraj tlb_map(APM86XXX_AHB_VA, OCP_ADDR_WORDLO(APM86XXX_AHB_PA), 78236324Sraj OCP_ADDR_WORDHI(APM86XXX_AHB_PA), 79236324Sraj TLB_VALID | TLB_SIZE_16M, 80236324Sraj TLB_SW | TLB_SR | TLB_I | TLB_G); 81236324Sraj 82236324Sraj /* Map MailBox space */ 83236324Sraj tlb_map(APM86XXX_MBOX_VA, OCP_ADDR_WORDLO(APM86XXX_MBOX_PA), 84236324Sraj OCP_ADDR_WORDHI(APM86XXX_MBOX_PA), 85236324Sraj TLB_VALID | TLB_SIZE_4K, 86236324Sraj TLB_UX | TLB_UW | TLB_UR | 87236324Sraj TLB_SX | TLB_SW | TLB_SR | 88236324Sraj TLB_I | TLB_G); 89236324Sraj 90236324Sraj tlb_map(APM86XXX_MBOX_VA + 0x1000, 91236324Sraj OCP_ADDR_WORDLO(APM86XXX_MBOX_PA) + 0x1000, 92236324Sraj OCP_ADDR_WORDHI(APM86XXX_MBOX_PA), 93236324Sraj TLB_VALID | TLB_SIZE_4K, 94236324Sraj TLB_UX | TLB_UW | TLB_UR | 95236324Sraj TLB_SX | TLB_SW | TLB_SR | 96236324Sraj TLB_I | TLB_G); 97236324Sraj 98236324Sraj tlb_map(APM86XXX_MBOX_VA + 0x2000, 99236324Sraj OCP_ADDR_WORDLO(APM86XXX_MBOX_PA)+ 0x2000, 100236324Sraj OCP_ADDR_WORDHI(APM86XXX_MBOX_PA), 101236324Sraj TLB_VALID | TLB_SIZE_4K, 102236324Sraj TLB_UX | TLB_UW | TLB_UR | 103236324Sraj TLB_SX | TLB_SW | TLB_SR | 104236324Sraj TLB_I | TLB_G); 105236324Sraj} 106236324Sraj 107236324Srajvoid 108236324Srajbooke_enable_l1_cache(void) 109236324Sraj{ 110236324Sraj} 111236324Sraj 112236324Srajvoid 113236324Srajbooke_enable_l2_cache(void) 114236324Sraj{ 115236324Sraj} 116236324Sraj 117236324Srajvoid 118236324Srajbooke_enable_l3_cache(void) 119236324Sraj{ 120236324Sraj} 121236324Sraj 122236324Srajvoid 123236324Srajbooke_disable_l2_cache(void) 124236324Sraj{ 125236324Sraj uint32_t ccr1,l2cr0; 126236324Sraj 127236324Sraj /* Disable L2 cache op broadcast */ 128236324Sraj ccr1 = mfspr(SPR_CCR1); 129236324Sraj ccr1 &= ~CCR1_L2COBE; 130236324Sraj mtspr(SPR_CCR1, ccr1); 131236324Sraj 132236324Sraj /* Set L2 array size to 0 i.e. disable L2 cache */ 133236324Sraj mtdcr(DCR_L2DCDCRAI, DCR_L2CR0); 134236324Sraj l2cr0 = mfdcr(DCR_L2DCDCRDI); 135236324Sraj l2cr0 &= ~L2CR0_AS; 136236324Sraj mtdcr(DCR_L2DCDCRDI, l2cr0); 137236324Sraj} 138236324Sraj 139236324Srajvoid tlb_map(uint32_t epn, uint32_t rpn, uint32_t erpn, uint32_t flags, 140236324Sraj uint32_t perms) 141236324Sraj{ 142236324Sraj 143236324Sraj tlb_write(++tlb_static_entries, epn, rpn, erpn, 0, flags, perms); 144236324Sraj} 145236324Sraj 146236324Srajstatic void tlb_dump_entry(u_int entry) 147236324Sraj{ 148236324Sraj uint32_t epn, rpn, erpn, tid, flags, perms; 149236324Sraj const char *size; 150236324Sraj 151236324Sraj tlb_read(entry, &epn, &rpn, &erpn, &tid, &flags, &perms); 152236324Sraj 153236324Sraj switch (flags & TLB_SIZE_MASK) { 154236324Sraj case TLB_SIZE_1K: 155236324Sraj size = " 1k"; 156236324Sraj break; 157236324Sraj case TLB_SIZE_4K: 158236324Sraj size = " 4k"; 159236324Sraj break; 160236324Sraj case TLB_SIZE_16K: 161236324Sraj size = " 16k"; 162236324Sraj break; 163236324Sraj case TLB_SIZE_256K: 164236324Sraj size = "256k"; 165236324Sraj break; 166236324Sraj case TLB_SIZE_1M: 167236324Sraj size = " 1M"; 168236324Sraj break; 169236324Sraj case TLB_SIZE_16M: 170236324Sraj size = " 16M"; 171236324Sraj break; 172236324Sraj case TLB_SIZE_256M: 173236324Sraj size = "256M"; 174236324Sraj break; 175236324Sraj case TLB_SIZE_1G: 176236324Sraj size = " 1G"; 177236324Sraj break; 178236324Sraj default: 179236324Sraj size = "????"; 180236324Sraj break; 181236324Sraj } 182236324Sraj 183236324Sraj 184236324Sraj printf("TLB[%02u]: 0x%08X => " 185236324Sraj "0x%01X_%08X %s %c %c %s %s %s %s %s " 186236324Sraj "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c (%u)\n", 187236324Sraj entry, epn, erpn, rpn, size, 188236324Sraj (flags & TLB_TS) ? '1' : '0', 189236324Sraj (flags & TLB_VALID) ? 'V' : '.', 190236324Sraj (perms & TLB_WL1) ? "WL1" : "___", 191236324Sraj (perms & TLB_IL1I) ? "IL1I" : "____", 192236324Sraj (perms & TLB_IL1D) ? "IL1D" : "____", 193236324Sraj (perms & TLB_IL2I) ? "IL2I" : "____", 194236324Sraj (perms & TLB_IL2D) ? "IL2D" : "____", 195236324Sraj (perms & TLB_U0) ? '1' : '.', 196236324Sraj (perms & TLB_U1) ? '2' : '.', 197236324Sraj (perms & TLB_U2) ? '3' : '.', 198236324Sraj (perms & TLB_U3) ? '4' : '.', 199236324Sraj (perms & TLB_W) ? 'W' : '.', 200236324Sraj (perms & TLB_I) ? 'I' : '.', 201236324Sraj (perms & TLB_M) ? 'M' : '.', 202236324Sraj (perms & TLB_G) ? 'G' : '.', 203236324Sraj (perms & TLB_E) ? 'E' : '.', 204236324Sraj (perms & TLB_UX) ? 'x' : '.', 205236324Sraj (perms & TLB_UW) ? 'w' : '.', 206236324Sraj (perms & TLB_UR) ? 'r' : '.', 207236324Sraj (perms & TLB_SX) ? 'X' : '.', 208236324Sraj (perms & TLB_SW) ? 'W' : '.', 209236324Sraj (perms & TLB_SR) ? 'R' : '.', 210236324Sraj tid); 211236324Sraj} 212236324Sraj 213236324Srajvoid tlb_dump(void) 214236324Sraj{ 215236324Sraj int i; 216236324Sraj 217236324Sraj for (i = 0; i < TLB_SIZE; i++) 218236324Sraj tlb_dump_entry(i); 219236324Sraj} 220