Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 295 lines 8.2 kB view raw
1/* 2 * PPC440GX system library 3 * 4 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> 5 * Copyright (c) 2003 - 2006 Zultys Technologies 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 */ 13#include <linux/config.h> 14#include <linux/kernel.h> 15#include <linux/interrupt.h> 16#include <asm/ibm44x.h> 17#include <asm/mmu.h> 18#include <asm/processor.h> 19#include <syslib/ibm440gx_common.h> 20 21/* 22 * Calculate 440GX clocks 23 */ 24static inline u32 __fix_zero(u32 v, u32 def){ 25 return v ? v : def; 26} 27 28void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, 29 unsigned int ser_clk) 30{ 31 u32 pllc = CPR_READ(DCRN_CPR_PLLC); 32 u32 plld = CPR_READ(DCRN_CPR_PLLD); 33 u32 uart0 = SDR_READ(DCRN_SDR_UART0); 34 u32 uart1 = SDR_READ(DCRN_SDR_UART1); 35#ifdef CONFIG_440EP 36 u32 uart2 = SDR_READ(DCRN_SDR_UART2); 37 u32 uart3 = SDR_READ(DCRN_SDR_UART3); 38#endif 39 40 /* Dividers */ 41 u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32); 42 u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16); 43 u32 fwdvb = __fix_zero((plld >> 8) & 7, 8); 44 u32 lfbdv = __fix_zero(plld & 0x3f, 64); 45 u32 pradv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMAD) >> 24) & 7, 8); 46 u32 prbdv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMBD) >> 24) & 7, 8); 47 u32 opbdv0 = __fix_zero((CPR_READ(DCRN_CPR_OPBD) >> 24) & 3, 4); 48 u32 perdv0 = __fix_zero((CPR_READ(DCRN_CPR_PERD) >> 24) & 3, 4); 49 50 /* Input clocks for primary dividers */ 51 u32 clk_a, clk_b; 52 53 if (pllc & 0x40000000){ 54 u32 m; 55 56 /* Feedback path */ 57 switch ((pllc >> 24) & 7){ 58 case 0: 59 /* PLLOUTx */ 60 m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv; 61 break; 62 case 1: 63 /* CPU */ 64 m = fwdva * pradv0; 65 break; 66 case 5: 67 /* PERClk */ 68 m = fwdvb * prbdv0 * opbdv0 * perdv0; 69 break; 70 default: 71 printk(KERN_EMERG "invalid PLL feedback source\n"); 72 goto bypass; 73 } 74 m *= fbdv; 75 p->vco = sys_clk * m; 76 clk_a = p->vco / fwdva; 77 clk_b = p->vco / fwdvb; 78 } 79 else { 80bypass: 81 /* Bypass system PLL */ 82 p->vco = 0; 83 clk_a = clk_b = sys_clk; 84 } 85 86 p->cpu = clk_a / pradv0; 87 p->plb = clk_b / prbdv0; 88 p->opb = p->plb / opbdv0; 89 p->ebc = p->opb / perdv0; 90 91 /* UARTs clock */ 92 if (uart0 & 0x00800000) 93 p->uart0 = ser_clk; 94 else 95 p->uart0 = p->plb / __fix_zero(uart0 & 0xff, 256); 96 97 if (uart1 & 0x00800000) 98 p->uart1 = ser_clk; 99 else 100 p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256); 101#ifdef CONFIG_440EP 102 if (uart2 & 0x00800000) 103 p->uart2 = ser_clk; 104 else 105 p->uart2 = p->plb / __fix_zero(uart2 & 0xff, 256); 106 107 if (uart3 & 0x00800000) 108 p->uart3 = ser_clk; 109 else 110 p->uart3 = p->plb / __fix_zero(uart3 & 0xff, 256); 111#endif 112} 113 114/* Issue L2C diagnostic command */ 115static inline u32 l2c_diag(u32 addr) 116{ 117 mtdcr(DCRN_L2C0_ADDR, addr); 118 mtdcr(DCRN_L2C0_CMD, L2C_CMD_DIAG); 119 while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ; 120 return mfdcr(DCRN_L2C0_DATA); 121} 122 123static irqreturn_t l2c_error_handler(int irq, void* dev, struct pt_regs* regs) 124{ 125 u32 sr = mfdcr(DCRN_L2C0_SR); 126 if (sr & L2C_SR_CPE){ 127 /* Read cache trapped address */ 128 u32 addr = l2c_diag(0x42000000); 129 printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", addr); 130 } 131 if (sr & L2C_SR_TPE){ 132 /* Read tag trapped address */ 133 u32 addr = l2c_diag(0x82000000) >> 16; 134 printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", addr); 135 } 136 137 /* Clear parity errors */ 138 if (sr & (L2C_SR_CPE | L2C_SR_TPE)){ 139 mtdcr(DCRN_L2C0_ADDR, 0); 140 mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); 141 } else 142 printk(KERN_EMERG "L2C: LRU error\n"); 143 144 return IRQ_HANDLED; 145} 146 147/* Enable L2 cache */ 148void __init ibm440gx_l2c_enable(void){ 149 u32 r; 150 unsigned long flags; 151 152 /* Install error handler */ 153 if (request_irq(87, l2c_error_handler, SA_INTERRUPT, "L2C", 0) < 0){ 154 printk(KERN_ERR "Cannot install L2C error handler, cache is not enabled\n"); 155 return; 156 } 157 158 local_irq_save(flags); 159 asm volatile ("sync" ::: "memory"); 160 161 /* Disable SRAM */ 162 mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE); 163 mtdcr(DCRN_SRAM0_SB0CR, mfdcr(DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK); 164 mtdcr(DCRN_SRAM0_SB1CR, mfdcr(DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK); 165 mtdcr(DCRN_SRAM0_SB2CR, mfdcr(DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK); 166 mtdcr(DCRN_SRAM0_SB3CR, mfdcr(DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK); 167 168 /* Enable L2_MODE without ICU/DCU */ 169 r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK); 170 r |= L2C_CFG_L2M | L2C_CFG_SS_256; 171 mtdcr(DCRN_L2C0_CFG, r); 172 173 mtdcr(DCRN_L2C0_ADDR, 0); 174 175 /* Hardware Clear Command */ 176 mtdcr(DCRN_L2C0_CMD, L2C_CMD_HCC); 177 while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ; 178 179 /* Clear Cache Parity and Tag Errors */ 180 mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); 181 182 /* Enable 64G snoop region starting at 0 */ 183 r = mfdcr(DCRN_L2C0_SNP0) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK); 184 r |= L2C_SNP_SSR_32G | L2C_SNP_ESR; 185 mtdcr(DCRN_L2C0_SNP0, r); 186 187 r = mfdcr(DCRN_L2C0_SNP1) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK); 188 r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR; 189 mtdcr(DCRN_L2C0_SNP1, r); 190 191 asm volatile ("sync" ::: "memory"); 192 193 /* Enable ICU/DCU ports */ 194 r = mfdcr(DCRN_L2C0_CFG); 195 r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI 196 | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM); 197 r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN 198 | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM; 199 mtdcr(DCRN_L2C0_CFG, r); 200 201 asm volatile ("sync; isync" ::: "memory"); 202 local_irq_restore(flags); 203} 204 205/* Disable L2 cache */ 206void __init ibm440gx_l2c_disable(void){ 207 u32 r; 208 unsigned long flags; 209 210 local_irq_save(flags); 211 asm volatile ("sync" ::: "memory"); 212 213 /* Disable L2C mode */ 214 r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_L2M | L2C_CFG_ICU | L2C_CFG_DCU); 215 mtdcr(DCRN_L2C0_CFG, r); 216 217 /* Enable SRAM */ 218 mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) | SRAM_DPC_ENABLE); 219 mtdcr(DCRN_SRAM0_SB0CR, 220 SRAM_SBCR_BAS0 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW); 221 mtdcr(DCRN_SRAM0_SB1CR, 222 SRAM_SBCR_BAS1 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW); 223 mtdcr(DCRN_SRAM0_SB2CR, 224 SRAM_SBCR_BAS2 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW); 225 mtdcr(DCRN_SRAM0_SB3CR, 226 SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW); 227 228 asm volatile ("sync; isync" ::: "memory"); 229 local_irq_restore(flags); 230} 231 232void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p) 233{ 234 /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C, 235 enable it on all other revisions 236 */ 237 if (strcmp(cur_cpu_spec->cpu_name, "440GX Rev. A") == 0 || 238 strcmp(cur_cpu_spec->cpu_name, "440GX Rev. B") == 0 239 || (strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") 240 == 0 && p->cpu > 667000000)) 241 ibm440gx_l2c_disable(); 242 else 243 ibm440gx_l2c_enable(); 244} 245 246int __init ibm440gx_get_eth_grp(void) 247{ 248 return (SDR_READ(DCRN_SDR_PFC1) & DCRN_SDR_PFC1_EPS) >> DCRN_SDR_PFC1_EPS_SHIFT; 249} 250 251void __init ibm440gx_set_eth_grp(int group) 252{ 253 SDR_WRITE(DCRN_SDR_PFC1, (SDR_READ(DCRN_SDR_PFC1) & ~DCRN_SDR_PFC1_EPS) | (group << DCRN_SDR_PFC1_EPS_SHIFT)); 254} 255 256void __init ibm440gx_tah_enable(void) 257{ 258 /* Enable TAH0 and TAH1 */ 259 SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) & 260 ~DCRN_SDR_MFR_TAH0); 261 SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) & 262 ~DCRN_SDR_MFR_TAH1); 263} 264 265int ibm440gx_show_cpuinfo(struct seq_file *m){ 266 267 u32 l2c_cfg = mfdcr(DCRN_L2C0_CFG); 268 const char* s; 269 if (l2c_cfg & L2C_CFG_L2M){ 270 switch (l2c_cfg & (L2C_CFG_ICU | L2C_CFG_DCU)){ 271 case L2C_CFG_ICU: s = "I-Cache only"; break; 272 case L2C_CFG_DCU: s = "D-Cache only"; break; 273 default: s = "I-Cache/D-Cache"; break; 274 } 275 } 276 else 277 s = "disabled"; 278 279 seq_printf(m, "L2-Cache\t: %s (0x%08x 0x%08x)\n", s, 280 l2c_cfg, mfdcr(DCRN_L2C0_SR)); 281 282 return 0; 283} 284 285void __init ibm440gx_platform_init(unsigned long r3, unsigned long r4, 286 unsigned long r5, unsigned long r6, 287 unsigned long r7) 288{ 289 /* Erratum 440_43 workaround, disable L1 cache parity checking */ 290 if (!strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") || 291 !strcmp(cur_cpu_spec->cpu_name, "440GX Rev. F")) 292 mtspr(SPRN_CCR1, mfspr(SPRN_CCR1) | CCR1_DPC); 293 294 ibm44x_platform_init(r3, r4, r5, r6, r7); 295}