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