soc.c (5867B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IBM/AMCC PPC4xx SoC setup code 4 * 5 * Copyright 2008 DENX Software Engineering, Stefan Roese <sr@denx.de> 6 * 7 * L2 cache routines cloned from arch/ppc/syslib/ibm440gx_common.c which is: 8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> 9 * Copyright (c) 2003 - 2006 Zultys Technologies 10 */ 11 12#include <linux/stddef.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/errno.h> 16#include <linux/interrupt.h> 17#include <linux/irq.h> 18#include <linux/of_irq.h> 19#include <linux/of_platform.h> 20 21#include <asm/dcr.h> 22#include <asm/dcr-regs.h> 23#include <asm/reg.h> 24 25static u32 dcrbase_l2c; 26 27/* 28 * L2-cache 29 */ 30 31/* Issue L2C diagnostic command */ 32static inline u32 l2c_diag(u32 addr) 33{ 34 mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, addr); 35 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_DIAG); 36 while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC)) 37 ; 38 39 return mfdcr(dcrbase_l2c + DCRN_L2C0_DATA); 40} 41 42static irqreturn_t l2c_error_handler(int irq, void *dev) 43{ 44 u32 sr = mfdcr(dcrbase_l2c + DCRN_L2C0_SR); 45 46 if (sr & L2C_SR_CPE) { 47 /* Read cache trapped address */ 48 u32 addr = l2c_diag(0x42000000); 49 printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", 50 addr); 51 } 52 if (sr & L2C_SR_TPE) { 53 /* Read tag trapped address */ 54 u32 addr = l2c_diag(0x82000000) >> 16; 55 printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", 56 addr); 57 } 58 59 /* Clear parity errors */ 60 if (sr & (L2C_SR_CPE | L2C_SR_TPE)){ 61 mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0); 62 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); 63 } else { 64 printk(KERN_EMERG "L2C: LRU error\n"); 65 } 66 67 return IRQ_HANDLED; 68} 69 70static int __init ppc4xx_l2c_probe(void) 71{ 72 struct device_node *np; 73 u32 r; 74 unsigned long flags; 75 int irq; 76 const u32 *dcrreg; 77 u32 dcrbase_isram; 78 int len; 79 const u32 *prop; 80 u32 l2_size; 81 82 np = of_find_compatible_node(NULL, NULL, "ibm,l2-cache"); 83 if (!np) 84 return 0; 85 86 /* Get l2 cache size */ 87 prop = of_get_property(np, "cache-size", NULL); 88 if (prop == NULL) { 89 printk(KERN_ERR "%pOF: Can't get cache-size!\n", np); 90 of_node_put(np); 91 return -ENODEV; 92 } 93 l2_size = prop[0]; 94 95 /* Map DCRs */ 96 dcrreg = of_get_property(np, "dcr-reg", &len); 97 if (!dcrreg || (len != 4 * sizeof(u32))) { 98 printk(KERN_ERR "%pOF: Can't get DCR register base !", np); 99 of_node_put(np); 100 return -ENODEV; 101 } 102 dcrbase_isram = dcrreg[0]; 103 dcrbase_l2c = dcrreg[2]; 104 105 /* Get and map irq number from device tree */ 106 irq = irq_of_parse_and_map(np, 0); 107 if (!irq) { 108 printk(KERN_ERR "irq_of_parse_and_map failed\n"); 109 of_node_put(np); 110 return -ENODEV; 111 } 112 113 /* Install error handler */ 114 if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) { 115 printk(KERN_ERR "Cannot install L2C error handler" 116 ", cache is not enabled\n"); 117 of_node_put(np); 118 return -ENODEV; 119 } 120 121 local_irq_save(flags); 122 asm volatile ("sync" ::: "memory"); 123 124 /* Disable SRAM */ 125 mtdcr(dcrbase_isram + DCRN_SRAM0_DPC, 126 mfdcr(dcrbase_isram + DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE); 127 mtdcr(dcrbase_isram + DCRN_SRAM0_SB0CR, 128 mfdcr(dcrbase_isram + DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK); 129 mtdcr(dcrbase_isram + DCRN_SRAM0_SB1CR, 130 mfdcr(dcrbase_isram + DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK); 131 mtdcr(dcrbase_isram + DCRN_SRAM0_SB2CR, 132 mfdcr(dcrbase_isram + DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK); 133 mtdcr(dcrbase_isram + DCRN_SRAM0_SB3CR, 134 mfdcr(dcrbase_isram + DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK); 135 136 /* Enable L2_MODE without ICU/DCU */ 137 r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG) & 138 ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK); 139 r |= L2C_CFG_L2M | L2C_CFG_SS_256; 140 mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r); 141 142 mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0); 143 144 /* Hardware Clear Command */ 145 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_HCC); 146 while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC)) 147 ; 148 149 /* Clear Cache Parity and Tag Errors */ 150 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); 151 152 /* Enable 64G snoop region starting at 0 */ 153 r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP0) & 154 ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK); 155 r |= L2C_SNP_SSR_32G | L2C_SNP_ESR; 156 mtdcr(dcrbase_l2c + DCRN_L2C0_SNP0, r); 157 158 r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP1) & 159 ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK); 160 r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR; 161 mtdcr(dcrbase_l2c + DCRN_L2C0_SNP1, r); 162 163 asm volatile ("sync" ::: "memory"); 164 165 /* Enable ICU/DCU ports */ 166 r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG); 167 r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM 168 | L2C_CFG_TPEI | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM); 169 r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN 170 | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM; 171 172 /* Check for 460EX/GT special handling */ 173 if (of_device_is_compatible(np, "ibm,l2-cache-460ex") || 174 of_device_is_compatible(np, "ibm,l2-cache-460gt")) 175 r |= L2C_CFG_RDBW; 176 177 mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r); 178 179 asm volatile ("sync; isync" ::: "memory"); 180 local_irq_restore(flags); 181 182 printk(KERN_INFO "%dk L2-cache enabled\n", l2_size >> 10); 183 184 of_node_put(np); 185 return 0; 186} 187arch_initcall(ppc4xx_l2c_probe); 188 189/* 190 * Apply a system reset. Alternatively a board specific value may be 191 * provided via the "reset-type" property in the cpu node. 192 */ 193void ppc4xx_reset_system(char *cmd) 194{ 195 struct device_node *np; 196 u32 reset_type = DBCR0_RST_SYSTEM; 197 const u32 *prop; 198 199 np = of_get_cpu_node(0, NULL); 200 if (np) { 201 prop = of_get_property(np, "reset-type", NULL); 202 203 /* 204 * Check if property exists and if it is in range: 205 * 1 - PPC4xx core reset 206 * 2 - PPC4xx chip reset 207 * 3 - PPC4xx system reset (default) 208 */ 209 if ((prop) && ((prop[0] >= 1) && (prop[0] <= 3))) 210 reset_type = prop[0] << 28; 211 } 212 213 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | reset_type); 214 215 while (1) 216 ; /* Just in case the reset doesn't work */ 217}