0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/stddef.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/errno.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/irq.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/of_platform.h>
0020
0021 #include <asm/dcr.h>
0022 #include <asm/dcr-regs.h>
0023 #include <asm/reg.h>
0024
0025 static u32 dcrbase_l2c;
0026
0027
0028
0029
0030
0031
0032 static inline u32 l2c_diag(u32 addr)
0033 {
0034 mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, addr);
0035 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_DIAG);
0036 while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
0037 ;
0038
0039 return mfdcr(dcrbase_l2c + DCRN_L2C0_DATA);
0040 }
0041
0042 static irqreturn_t l2c_error_handler(int irq, void *dev)
0043 {
0044 u32 sr = mfdcr(dcrbase_l2c + DCRN_L2C0_SR);
0045
0046 if (sr & L2C_SR_CPE) {
0047
0048 u32 addr = l2c_diag(0x42000000);
0049 printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n",
0050 addr);
0051 }
0052 if (sr & L2C_SR_TPE) {
0053
0054 u32 addr = l2c_diag(0x82000000) >> 16;
0055 printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n",
0056 addr);
0057 }
0058
0059
0060 if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
0061 mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
0062 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
0063 } else {
0064 printk(KERN_EMERG "L2C: LRU error\n");
0065 }
0066
0067 return IRQ_HANDLED;
0068 }
0069
0070 static int __init ppc4xx_l2c_probe(void)
0071 {
0072 struct device_node *np;
0073 u32 r;
0074 unsigned long flags;
0075 int irq;
0076 const u32 *dcrreg;
0077 u32 dcrbase_isram;
0078 int len;
0079 const u32 *prop;
0080 u32 l2_size;
0081
0082 np = of_find_compatible_node(NULL, NULL, "ibm,l2-cache");
0083 if (!np)
0084 return 0;
0085
0086
0087 prop = of_get_property(np, "cache-size", NULL);
0088 if (prop == NULL) {
0089 printk(KERN_ERR "%pOF: Can't get cache-size!\n", np);
0090 of_node_put(np);
0091 return -ENODEV;
0092 }
0093 l2_size = prop[0];
0094
0095
0096 dcrreg = of_get_property(np, "dcr-reg", &len);
0097 if (!dcrreg || (len != 4 * sizeof(u32))) {
0098 printk(KERN_ERR "%pOF: Can't get DCR register base !", np);
0099 of_node_put(np);
0100 return -ENODEV;
0101 }
0102 dcrbase_isram = dcrreg[0];
0103 dcrbase_l2c = dcrreg[2];
0104
0105
0106 irq = irq_of_parse_and_map(np, 0);
0107 if (!irq) {
0108 printk(KERN_ERR "irq_of_parse_and_map failed\n");
0109 of_node_put(np);
0110 return -ENODEV;
0111 }
0112
0113
0114 if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
0115 printk(KERN_ERR "Cannot install L2C error handler"
0116 ", cache is not enabled\n");
0117 of_node_put(np);
0118 return -ENODEV;
0119 }
0120
0121 local_irq_save(flags);
0122 asm volatile ("sync" ::: "memory");
0123
0124
0125 mtdcr(dcrbase_isram + DCRN_SRAM0_DPC,
0126 mfdcr(dcrbase_isram + DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE);
0127 mtdcr(dcrbase_isram + DCRN_SRAM0_SB0CR,
0128 mfdcr(dcrbase_isram + DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
0129 mtdcr(dcrbase_isram + DCRN_SRAM0_SB1CR,
0130 mfdcr(dcrbase_isram + DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
0131 mtdcr(dcrbase_isram + DCRN_SRAM0_SB2CR,
0132 mfdcr(dcrbase_isram + DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
0133 mtdcr(dcrbase_isram + DCRN_SRAM0_SB3CR,
0134 mfdcr(dcrbase_isram + DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
0135
0136
0137 r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG) &
0138 ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
0139 r |= L2C_CFG_L2M | L2C_CFG_SS_256;
0140 mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
0141
0142 mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
0143
0144
0145 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_HCC);
0146 while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
0147 ;
0148
0149
0150 mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
0151
0152
0153 r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP0) &
0154 ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
0155 r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
0156 mtdcr(dcrbase_l2c + DCRN_L2C0_SNP0, r);
0157
0158 r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP1) &
0159 ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
0160 r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
0161 mtdcr(dcrbase_l2c + DCRN_L2C0_SNP1, r);
0162
0163 asm volatile ("sync" ::: "memory");
0164
0165
0166 r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG);
0167 r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM
0168 | L2C_CFG_TPEI | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
0169 r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
0170 | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
0171
0172
0173 if (of_device_is_compatible(np, "ibm,l2-cache-460ex") ||
0174 of_device_is_compatible(np, "ibm,l2-cache-460gt"))
0175 r |= L2C_CFG_RDBW;
0176
0177 mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
0178
0179 asm volatile ("sync; isync" ::: "memory");
0180 local_irq_restore(flags);
0181
0182 printk(KERN_INFO "%dk L2-cache enabled\n", l2_size >> 10);
0183
0184 of_node_put(np);
0185 return 0;
0186 }
0187 arch_initcall(ppc4xx_l2c_probe);
0188
0189
0190
0191
0192
0193 void ppc4xx_reset_system(char *cmd)
0194 {
0195 struct device_node *np;
0196 u32 reset_type = DBCR0_RST_SYSTEM;
0197 const u32 *prop;
0198
0199 np = of_get_cpu_node(0, NULL);
0200 if (np) {
0201 prop = of_get_property(np, "reset-type", NULL);
0202
0203
0204
0205
0206
0207
0208
0209 if ((prop) && ((prop[0] >= 1) && (prop[0] <= 3)))
0210 reset_type = prop[0] << 28;
0211 }
0212
0213 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | reset_type);
0214
0215 while (1)
0216 ;
0217 }