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