~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/platforms/44x/soc.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php