-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[POWERPC] 4xx: Add PPC4xx L2-cache support (440GX)
This patch adds support for the 256k L2 cache found on some IBM/AMCC 4xx PPC's. It introduces a common 4xx SoC file (sysdev/ppc4xx_soc.c) which currently "only" adds the L2 cache init code. Other common 4xx stuff can be added later here. The L2 cache handling code is a copy of Eugene's code in arch/ppc with small modifications. Tested on AMCC Taishan 440GX. Signed-off-by: Stefan Roese <sr@denx.de> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
- Loading branch information
Stefan Roese
authored and
Josh Boyer
committed
Mar 26, 2008
1 parent
145692a
commit 2a70691
Showing
5 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
/* | ||
* IBM/AMCC PPC4xx SoC setup code | ||
* | ||
* Copyright 2008 DENX Software Engineering, Stefan Roese <sr@denx.de> | ||
* | ||
* L2 cache routines cloned from arch/ppc/syslib/ibm440gx_common.c which is: | ||
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
* Copyright (c) 2003 - 2006 Zultys Technologies | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License as published by the | ||
* Free Software Foundation; either version 2 of the License, or (at your | ||
* option) any later version. | ||
*/ | ||
|
||
#include <linux/stddef.h> | ||
#include <linux/kernel.h> | ||
#include <linux/init.h> | ||
#include <linux/errno.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/irq.h> | ||
#include <linux/of_platform.h> | ||
|
||
#include <asm/dcr.h> | ||
#include <asm/dcr-regs.h> | ||
|
||
static u32 dcrbase_l2c; | ||
|
||
/* | ||
* L2-cache | ||
*/ | ||
|
||
/* Issue L2C diagnostic command */ | ||
static inline u32 l2c_diag(u32 addr) | ||
{ | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, addr); | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_DIAG); | ||
while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC)) | ||
; | ||
|
||
return mfdcr(dcrbase_l2c + DCRN_L2C0_DATA); | ||
} | ||
|
||
static irqreturn_t l2c_error_handler(int irq, void *dev) | ||
{ | ||
u32 sr = mfdcr(dcrbase_l2c + DCRN_L2C0_SR); | ||
|
||
if (sr & L2C_SR_CPE) { | ||
/* Read cache trapped address */ | ||
u32 addr = l2c_diag(0x42000000); | ||
printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", | ||
addr); | ||
} | ||
if (sr & L2C_SR_TPE) { | ||
/* Read tag trapped address */ | ||
u32 addr = l2c_diag(0x82000000) >> 16; | ||
printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", | ||
addr); | ||
} | ||
|
||
/* Clear parity errors */ | ||
if (sr & (L2C_SR_CPE | L2C_SR_TPE)){ | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0); | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); | ||
} else { | ||
printk(KERN_EMERG "L2C: LRU error\n"); | ||
} | ||
|
||
return IRQ_HANDLED; | ||
} | ||
|
||
static int __init ppc4xx_l2c_probe(void) | ||
{ | ||
struct device_node *np; | ||
u32 r; | ||
unsigned long flags; | ||
int irq; | ||
const u32 *dcrreg; | ||
u32 dcrbase_isram; | ||
int len; | ||
const u32 *prop; | ||
u32 l2_size; | ||
|
||
np = of_find_compatible_node(NULL, NULL, "ibm,l2-cache"); | ||
if (!np) | ||
return 0; | ||
|
||
/* Get l2 cache size */ | ||
prop = of_get_property(np, "cache-size", NULL); | ||
if (prop == NULL) { | ||
printk(KERN_ERR "%s: Can't get cache-size!\n", np->full_name); | ||
of_node_put(np); | ||
return -ENODEV; | ||
} | ||
l2_size = prop[0]; | ||
|
||
/* Map DCRs */ | ||
dcrreg = of_get_property(np, "dcr-reg", &len); | ||
if (!dcrreg || (len != 4 * sizeof(u32))) { | ||
printk(KERN_ERR "%s: Can't get DCR register base !", | ||
np->full_name); | ||
of_node_put(np); | ||
return -ENODEV; | ||
} | ||
dcrbase_isram = dcrreg[0]; | ||
dcrbase_l2c = dcrreg[2]; | ||
|
||
/* Get and map irq number from device tree */ | ||
irq = irq_of_parse_and_map(np, 0); | ||
if (irq == NO_IRQ) { | ||
printk(KERN_ERR "irq_of_parse_and_map failed\n"); | ||
of_node_put(np); | ||
return -ENODEV; | ||
} | ||
|
||
/* Install error handler */ | ||
if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) { | ||
printk(KERN_ERR "Cannot install L2C error handler" | ||
", cache is not enabled\n"); | ||
of_node_put(np); | ||
return -ENODEV; | ||
} | ||
|
||
local_irq_save(flags); | ||
asm volatile ("sync" ::: "memory"); | ||
|
||
/* Disable SRAM */ | ||
mtdcr(dcrbase_isram + DCRN_SRAM0_DPC, | ||
mfdcr(dcrbase_isram + DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE); | ||
mtdcr(dcrbase_isram + DCRN_SRAM0_SB0CR, | ||
mfdcr(dcrbase_isram + DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK); | ||
mtdcr(dcrbase_isram + DCRN_SRAM0_SB1CR, | ||
mfdcr(dcrbase_isram + DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK); | ||
mtdcr(dcrbase_isram + DCRN_SRAM0_SB2CR, | ||
mfdcr(dcrbase_isram + DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK); | ||
mtdcr(dcrbase_isram + DCRN_SRAM0_SB3CR, | ||
mfdcr(dcrbase_isram + DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK); | ||
|
||
/* Enable L2_MODE without ICU/DCU */ | ||
r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG) & | ||
~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK); | ||
r |= L2C_CFG_L2M | L2C_CFG_SS_256; | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r); | ||
|
||
mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0); | ||
|
||
/* Hardware Clear Command */ | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_HCC); | ||
while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC)) | ||
; | ||
|
||
/* Clear Cache Parity and Tag Errors */ | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); | ||
|
||
/* Enable 64G snoop region starting at 0 */ | ||
r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP0) & | ||
~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK); | ||
r |= L2C_SNP_SSR_32G | L2C_SNP_ESR; | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_SNP0, r); | ||
|
||
r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP1) & | ||
~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK); | ||
r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR; | ||
mtdcr(dcrbase_l2c + DCRN_L2C0_SNP1, r); | ||
|
||
asm volatile ("sync" ::: "memory"); | ||
|
||
/* Enable ICU/DCU ports */ | ||
r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG); | ||
r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | ||
| L2C_CFG_TPEI | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM); | ||
r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN | ||
| L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM; | ||
|
||
/* Check for 460EX/GT special handling */ | ||
if (of_device_is_compatible(np, "ibm,l2-cache-460ex")) | ||
r |= L2C_CFG_RDBW; | ||
|
||
mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r); | ||
|
||
asm volatile ("sync; isync" ::: "memory"); | ||
local_irq_restore(flags); | ||
|
||
printk(KERN_INFO "%dk L2-cache enabled\n", l2_size >> 10); | ||
|
||
of_node_put(np); | ||
return 0; | ||
} | ||
arch_initcall(ppc4xx_l2c_probe); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters