diff options
31 files changed, 1305 insertions, 66 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5f6e34925a3..efeed65b4a6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -441,7 +441,7 @@ config ARCH_ORION5X help Support for the following Marvell Orion 5x series SoCs: Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182), - Orion-2 (5281). + Orion-2 (5281), Orion-1-90 (6183). config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig index 4017d83c9d2..b2456ca544c 100644 --- a/arch/arm/configs/orion5x_defconfig +++ b/arch/arm/configs/orion5x_defconfig @@ -176,14 +176,17 @@ CONFIG_MACH_KUROBOX_PRO=y CONFIG_MACH_DNS323=y CONFIG_MACH_TS209=y CONFIG_MACH_LINKSTATION_PRO=y +CONFIG_MACH_LINKSTATION_MINI=y CONFIG_MACH_TS409=y CONFIG_MACH_WRT350N_V2=y CONFIG_MACH_TS78XX=y CONFIG_MACH_MV2120=y +CONFIG_MACH_EDMINI_V2=y CONFIG_MACH_MSS2=y CONFIG_MACH_WNR854T=y CONFIG_MACH_RD88F5181L_GE=y CONFIG_MACH_RD88F5181L_FXO=y +CONFIG_MACH_RD88F6183AP_GE=y # # Boot options diff --git a/arch/arm/mach-kirkwood/addr-map.c b/arch/arm/mach-kirkwood/addr-map.c index c79f492072f..5db4f0bbe5e 100644 --- a/arch/arm/mach-kirkwood/addr-map.c +++ b/arch/arm/mach-kirkwood/addr-map.c @@ -48,6 +48,7 @@ struct mbus_dram_target_info kirkwood_mbus_dram_info; +static int __initdata win_alloc_count; static int __init cpu_win_can_remap(int win) { @@ -111,6 +112,8 @@ void __init kirkwood_setup_cpu_mbus(void) setup_cpu_win(2, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE, TARGET_DEV_BUS, ATTR_DEV_NAND, -1); + win_alloc_count = 3; + /* * Setup MBUS dram target info. */ @@ -137,3 +140,8 @@ void __init kirkwood_setup_cpu_mbus(void) } kirkwood_mbus_dram_info.num_cs = cs; } + +void __init kirkwood_setup_sram_win(u32 base, u32 size) +{ + setup_cpu_win(win_alloc_count++, base, size, 0x03, 0x00, -1); +} diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 189f16f3619..85cad05d8c5 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -98,7 +98,6 @@ void __init kirkwood_ehci_init(void) * GE00 ****************************************************************************/ struct mv643xx_eth_shared_platform_data kirkwood_ge00_shared_data = { - .t_clk = KIRKWOOD_TCLK, .dram = &kirkwood_mbus_dram_info, }; @@ -108,6 +107,11 @@ static struct resource kirkwood_ge00_shared_resources[] = { .start = GE00_PHYS_BASE + 0x2000, .end = GE00_PHYS_BASE + 0x3fff, .flags = IORESOURCE_MEM, + }, { + .name = "ge00 err irq", + .start = IRQ_KIRKWOOD_GE00_ERR, + .end = IRQ_KIRKWOOD_GE00_ERR, + .flags = IORESOURCE_IRQ, }, }; @@ -117,7 +121,7 @@ static struct platform_device kirkwood_ge00_shared = { .dev = { .platform_data = &kirkwood_ge00_shared_data, }, - .num_resources = 1, + .num_resources = ARRAY_SIZE(kirkwood_ge00_shared_resources), .resource = kirkwood_ge00_shared_resources, }; @@ -201,7 +205,6 @@ void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data) * SPI ****************************************************************************/ static struct orion_spi_info kirkwood_spi_plat_data = { - .tclk = KIRKWOOD_TCLK, }; static struct resource kirkwood_spi_resources[] = { @@ -239,7 +242,7 @@ static struct plat_serial8250_port kirkwood_uart0_data[] = { .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = KIRKWOOD_TCLK, + .uartclk = 0, }, { }, }; @@ -283,7 +286,7 @@ static struct plat_serial8250_port kirkwood_uart1_data[] = { .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = KIRKWOOD_TCLK, + .uartclk = 0, }, { }, }; @@ -525,9 +528,23 @@ void __init kirkwood_xor1_init(void) /***************************************************************************** * Time handling ****************************************************************************/ +int kirkwood_tclk; + +int __init kirkwood_find_tclk(void) +{ + u32 dev, rev; + + kirkwood_pcie_id(&dev, &rev); + if (dev == MV88F6281_DEV_ID && rev == MV88F6281_REV_A0) + return 200000000; + + return 166666667; +} + static void kirkwood_timer_init(void) { - orion_time_init(IRQ_KIRKWOOD_BRIDGE, KIRKWOOD_TCLK); + kirkwood_tclk = kirkwood_find_tclk(); + orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); } struct sys_timer kirkwood_timer = { @@ -538,33 +555,62 @@ struct sys_timer kirkwood_timer = { /***************************************************************************** * General ****************************************************************************/ +/* + * Identify device ID and revision. + */ static char * __init kirkwood_id(void) { - switch (readl(DEVICE_ID) & 0x3) { - case 0: - return "88F6180"; - case 1: - return "88F6192"; - case 2: - return "88F6281"; + u32 dev, rev; + + kirkwood_pcie_id(&dev, &rev); + + if (dev == MV88F6281_DEV_ID) { + if (rev == MV88F6281_REV_Z0) + return "MV88F6281-Z0"; + else if (rev == MV88F6281_REV_A0) + return "MV88F6281-A0"; + else + return "MV88F6281-Rev-Unsupported"; + } else if (dev == MV88F6192_DEV_ID) { + if (rev == MV88F6192_REV_Z0) + return "MV88F6192-Z0"; + else if (rev == MV88F6192_REV_A0) + return "MV88F6192-A0"; + else + return "MV88F6192-Rev-Unsupported"; + } else if (dev == MV88F6180_DEV_ID) { + if (rev == MV88F6180_REV_A0) + return "MV88F6180-Rev-A0"; + else + return "MV88F6180-Rev-Unsupported"; + } else { + return "Device-Unknown"; } - - return "unknown 88F6000 variant"; } -static int __init is_l2_writethrough(void) +static void __init kirkwood_l2_init(void) { - return !!(readl(L2_CONFIG_REG) & L2_WRITETHROUGH); +#ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH + writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG); + feroceon_l2_init(1); +#else + writel(readl(L2_CONFIG_REG) & ~L2_WRITETHROUGH, L2_CONFIG_REG); + feroceon_l2_init(0); +#endif } void __init kirkwood_init(void) { printk(KERN_INFO "Kirkwood: %s, TCLK=%d.\n", - kirkwood_id(), KIRKWOOD_TCLK); + kirkwood_id(), kirkwood_tclk); + kirkwood_ge00_shared_data.t_clk = kirkwood_tclk; + kirkwood_spi_plat_data.tclk = kirkwood_tclk; + kirkwood_uart0_data[0].uartclk = kirkwood_tclk; + kirkwood_uart1_data[0].uartclk = kirkwood_tclk; kirkwood_setup_cpu_mbus(); #ifdef CONFIG_CACHE_FEROCEON_L2 - feroceon_l2_init(is_l2_writethrough()); + kirkwood_l2_init(); #endif } diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 69cd113af03..8fa0f6a2763 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -23,10 +23,9 @@ void kirkwood_init_irq(void); extern struct mbus_dram_target_info kirkwood_mbus_dram_info; void kirkwood_setup_cpu_mbus(void); -void kirkwood_setup_pcie_io_win(int window, u32 base, u32 size, - int maj, int min); -void kirkwood_setup_pcie_mem_win(int window, u32 base, u32 size, - int maj, int min); +void kirkwood_setup_sram_win(u32 base, u32 size); + +void kirkwood_pcie_id(u32 *dev, u32 *rev); void kirkwood_ehci_init(void); void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data); diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c index 610fb24d8ae..89d746d13fd 100644 --- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c @@ -44,7 +44,6 @@ static void __init db88f6281_init(void) kirkwood_rtc_init(); kirkwood_sata_init(&db88f6281_sata_data); kirkwood_uart0_init(); - kirkwood_uart1_init(); } static int __init db88f6281_pci_init(void) diff --git a/arch/arm/mach-kirkwood/include/mach/irqs.h b/arch/arm/mach-kirkwood/include/mach/irqs.h index 6fd05838c72..ffab89f21c1 100644 --- a/arch/arm/mach-kirkwood/include/mach/irqs.h +++ b/arch/arm/mach-kirkwood/include/mach/irqs.h @@ -50,6 +50,7 @@ #define IRQ_KIRKWOOD_GPIO_HIGH_0_7 39 #define IRQ_KIRKWOOD_GPIO_HIGH_8_15 40 #define IRQ_KIRKWOOD_GPIO_HIGH_16_23 41 +#define IRQ_KIRKWOOD_GE00_ERR 46 /* * KIRKWOOD General Purpose Pins diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index 5c69992295e..eae42406fd8 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -68,6 +68,20 @@ #define L2_WRITETHROUGH 0x00000010 /* + * Supported devices and revisions. + */ +#define MV88F6281_DEV_ID 0x6281 +#define MV88F6281_REV_Z0 0 +#define MV88F6281_REV_A0 2 + +#define MV88F6192_DEV_ID 0x6192 +#define MV88F6192_REV_Z0 0 +#define MV88F6192_REV_A0 2 + +#define MV88F6180_DEV_ID 0x6180 +#define MV88F6180_REV_A0 2 + +/* * Register Map */ #define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x00000) diff --git a/arch/arm/mach-kirkwood/include/mach/timex.h b/arch/arm/mach-kirkwood/include/mach/timex.h index f77ef4a32c5..c923cd169b9 100644 --- a/arch/arm/mach-kirkwood/include/mach/timex.h +++ b/arch/arm/mach-kirkwood/include/mach/timex.h @@ -8,4 +8,3 @@ #define CLOCK_TICK_RATE (100 * HZ) -#define KIRKWOOD_TCLK 166666667 diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index 2195fa31f6b..f6b08f207c8 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -18,6 +18,12 @@ #define PCIE_BASE ((void __iomem *)PCIE_VIRT_BASE) +void __init kirkwood_pcie_id(u32 *dev, u32 *rev) +{ + *dev = orion_pcie_dev_id(PCIE_BASE); + *rev = orion_pcie_rev(PCIE_BASE); +} + static int pcie_valid_config(int bus, int dev) { /* diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c index d96487a0f18..fb8990f9770 100644 --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -90,7 +90,6 @@ static void __init rd88f6281_init(void) kirkwood_rtc_init(); kirkwood_sata_init(&rd88f6281_sata_data); kirkwood_uart0_init(); - kirkwood_uart1_init(); platform_device_register(&rd88f6281_nand_flash); } diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 953a26c469c..d56a05e8356 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -285,6 +285,11 @@ static struct resource mv78xx0_ge00_shared_resources[] = { .start = GE00_PHYS_BASE + 0x2000, .end = GE00_PHYS_BASE + 0x3fff, .flags = IORESOURCE_MEM, + }, { + .name = "ge err irq", + .start = IRQ_MV78XX0_GE_ERR, + .end = IRQ_MV78XX0_GE_ERR, + .flags = IORESOURCE_IRQ, }, }; @@ -294,7 +299,7 @@ static struct platform_device mv78xx0_ge00_shared = { .dev = { .platform_data = &mv78xx0_ge00_shared_data, }, - .num_resources = 1, + .num_resources = ARRAY_SIZE(mv78xx0_ge00_shared_resources), .resource = mv78xx0_ge00_shared_resources, }; diff --git a/arch/arm/mach-mv78xx0/include/mach/entry-macro.S b/arch/arm/mach-mv78xx0/include/mach/entry-macro.S index ed4a46bcd3b..fbfb2693ce6 100644 --- a/arch/arm/mach-mv78xx0/include/mach/entry-macro.S +++ b/arch/arm/mach-mv78xx0/include/mach/entry-macro.S @@ -26,14 +26,22 @@ ldr \tmp, [\base, #IRQ_MASK_LOW_OFF] mov \irqnr, #31 ands \irqstat, \irqstat, \tmp + bne 1001f @ if no low interrupts set, check high interrupts - ldreq \irqstat, [\base, #IRQ_CAUSE_HIGH_OFF] - ldreq \tmp, [\base, #IRQ_MASK_HIGH_OFF] - moveq \irqnr, #63 - andeqs \irqstat, \irqstat, \tmp + ldr \irqstat, [\base, #IRQ_CAUSE_HIGH_OFF] + ldr \tmp, [\base, #IRQ_MASK_HIGH_OFF] + mov \irqnr, #63 + ands \irqstat, \irqstat, \tmp + bne 1001f + + @ if no high interrupts set, check error interrupts + ldr \irqstat, [\base, #IRQ_CAUSE_ERR_OFF] + ldr \tmp, [\base, #IRQ_MASK_ERR_OFF] + mov \irqnr, #95 + ands \irqstat, \irqstat, \tmp @ find first active interrupt source - clzne \irqstat, \irqstat +1001: clzne \irqstat, \irqstat subne \irqnr, \irqnr, \irqstat .endm diff --git a/arch/arm/mach-mv78xx0/include/mach/irqs.h b/arch/arm/mach-mv78xx0/include/mach/irqs.h index 995d7fb8d06..bebc330281e 100644 --- a/arch/arm/mach-mv78xx0/include/mach/irqs.h +++ b/arch/arm/mach-mv78xx0/include/mach/irqs.h @@ -80,9 +80,14 @@ #define IRQ_MV78XX0_DB_OUT 61 /* + * MV78xx0 Error Interrupt Controller + */ +#define IRQ_MV78XX0_GE_ERR 70 + +/* * MV78XX0 General Purpose Pins */ -#define IRQ_MV78XX0_GPIO_START 64 +#define IRQ_MV78XX0_GPIO_START 96 #define NR_GPIO_IRQS GPIO_MAX #define NR_IRQS (IRQ_MV78XX0_GPIO_START + NR_GPIO_IRQS) diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h index ad664178d6e..ee9c5593ee9 100644 --- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h +++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h @@ -71,8 +71,10 @@ #define BRIDGE_INT_TIMER1 0x0004 #define BRIDGE_INT_TIMER1_CLR (~0x0004) #define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200) +#define IRQ_CAUSE_ERR_OFF 0x0000 #define IRQ_CAUSE_LOW_OFF 0x0004 #define IRQ_CAUSE_HIGH_OFF 0x0008 +#define IRQ_MASK_ERR_OFF 0x000c #define IRQ_MASK_LOW_OFF 0x0010 #define IRQ_MASK_HIGH_OFF 0x0014 #define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c index 28248d37b99..503e5d195ae 100644 --- a/arch/arm/mach-mv78xx0/irq.c +++ b/arch/arm/mach-mv78xx0/irq.c @@ -19,4 +19,5 @@ void __init mv78xx0_init_irq(void) { orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF)); orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF)); + orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF)); } diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index ddcd41b15d1..f59a8d0e082 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig @@ -36,6 +36,12 @@ config MACH_TS209 Say 'Y' here if you want your kernel to support the QNAP TS-109/TS-209 platform. +config MACH_TERASTATION_PRO2 + bool "Buffalo Terastation Pro II/Live" + help + Say 'Y' here if you want your kernel to support the + Buffalo Terastation Pro II/Live platform. + config MACH_LINKSTATION_PRO bool "Buffalo Linkstation Pro/Live" select I2C_BOARDINFO @@ -44,6 +50,13 @@ config MACH_LINKSTATION_PRO Buffalo Linkstation Pro/Live platform. Both v1 and v2 devices are supported. +config MACH_LINKSTATION_MINI + bool "Buffalo Linkstation Mini" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + Buffalo Linkstation Mini platform. + config MACH_TS409 bool "QNAP TS-409" help @@ -68,6 +81,13 @@ config MACH_MV2120 Say 'Y' here if you want your kernel to support the HP Media Vault mv2120 or mv5100. +config MACH_EDMINI_V2 + bool "LaCie Ethernet Disk mini V2" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + LaCie Ethernet Disk mini V2. + config MACH_MSS2 bool "Maxtor Shared Storage II" help @@ -92,6 +112,12 @@ config MACH_RD88F5181L_FXO Say 'Y' here if you want your kernel to support the Marvell Orion-VoIP FXO (88F5181L) RD. +config MACH_RD88F6183AP_GE + bool "Marvell Orion-1-90 AP GE Reference Design" + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-1-90 (88F6183) AP GE RD. + endmenu endif diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile index fcc48a8864f..3d4a1bc1235 100644 --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -2,14 +2,18 @@ obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o +obj-$(CONFIG_MACH_TERASTATION_PRO2) += terastation_pro2-setup.o obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o +obj-$(CONFIG_MACH_LINKSTATION_MINI) += lsmini-setup.o obj-$(CONFIG_MACH_DNS323) += dns323-setup.o obj-$(CONFIG_MACH_TS209) += ts209-setup.o tsx09-common.o obj-$(CONFIG_MACH_TS409) += ts409-setup.o tsx09-common.o obj-$(CONFIG_MACH_WRT350N_V2) += wrt350n-v2-setup.o obj-$(CONFIG_MACH_TS78XX) += ts78xx-setup.o obj-$(CONFIG_MACH_MV2120) += mv2120-setup.o +obj-$(CONFIG_MACH_EDMINI_V2) += edmini_v2-setup.o obj-$(CONFIG_MACH_MSS2) += mss2-setup.o obj-$(CONFIG_MACH_WNR854T) += wnr854t-setup.o obj-$(CONFIG_MACH_RD88F5181L_GE) += rd88f5181l-ge-setup.o obj-$(CONFIG_MACH_RD88F5181L_FXO) += rd88f5181l-fxo-setup.o +obj-$(CONFIG_MACH_RD88F6183AP_GE) += rd88f6183ap-ge-setup.o diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 7b11e552bc5..9625ef5975d 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -18,6 +18,7 @@ #include <linux/mv643xx_eth.h> #include <linux/mv643xx_i2c.h> #include <linux/ata_platform.h> +#include <linux/spi/orion_spi.h> #include <asm/page.h> #include <asm/setup.h> #include <asm/timex.h> @@ -146,7 +147,6 @@ void __init orion5x_ehci1_init(void) ****************************************************************************/ struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = { .dram = &orion5x_mbus_dram_info, - .t_clk = ORION5X_TCLK, }; static struct resource orion5x_eth_shared_resources[] = { @@ -154,6 +154,10 @@ static struct resource orion5x_eth_shared_resources[] = { .start = ORION5X_ETH_PHYS_BASE + 0x2000, .end = ORION5X_ETH_PHYS_BASE + 0x3fff, .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ORION5X_ETH_ERR, + .end = IRQ_ORION5X_ETH_ERR, + .flags = IORESOURCE_IRQ, }, }; @@ -163,7 +167,7 @@ static struct platform_device orion5x_eth_shared = { .dev = { .platform_data = &orion5x_eth_shared_data, }, - .num_resources = 1, + .num_resources = ARRAY_SIZE(orion5x_eth_shared_resources), .resource = orion5x_eth_shared_resources, }; @@ -268,6 +272,38 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data) /***************************************************************************** + * SPI + ****************************************************************************/ +static struct orion_spi_info orion5x_spi_plat_data = { + .tclk = 0, +}; + +static struct resource orion5x_spi_resources[] = { + { + .name = "spi base", + .start = SPI_PHYS_BASE, + .end = SPI_PHYS_BASE + 0x1f, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device orion5x_spi = { + .name = "orion_spi", + .id = 0, + .dev = { + .platform_data = &orion5x_spi_plat_data, + }, + .num_resources = ARRAY_SIZE(orion5x_spi_resources), + .resource = orion5x_spi_resources, +}; + +void __init orion5x_spi_init() +{ + platform_device_register(&orion5x_spi); +} + + +/***************************************************************************** * UART0 ****************************************************************************/ static struct plat_serial8250_port orion5x_uart0_data[] = { @@ -278,7 +314,7 @@ static struct plat_serial8250_port orion5x_uart0_data[] = { .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = ORION5X_TCLK, + .uartclk = 0, }, { }, }; @@ -322,7 +358,7 @@ static struct plat_serial8250_port orion5x_uart1_data[] = { .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = ORION5X_TCLK, + .uartclk = 0, }, { }, }; @@ -455,9 +491,24 @@ void __init orion5x_xor_init(void) /***************************************************************************** * Time handling ****************************************************************************/ +int orion5x_tclk; + +int __init orion5x_find_tclk(void) +{ + u32 dev, rev; + + orion5x_pcie_id(&dev, &rev); + if (dev == MV88F6183_DEV_ID && + (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0) + return 133333333; + + return 166666667; +} + static void orion5x_timer_init(void) { - orion_time_init(IRQ_ORION5X_BRIDGE, ORION5X_TCLK); + orion5x_tclk = orion5x_find_tclk(); + orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk); } struct sys_timer orion5x_timer = { @@ -499,6 +550,12 @@ static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name) } else { *dev_name = "MV88F5181(L)-Rev-Unsupported"; } + } else if (*dev == MV88F6183_DEV_ID) { + if (*rev == MV88F6183_REV_B0) { + *dev_name = "MV88F6183-Rev-B0"; + } else { + *dev_name = "MV88F6183-Rev-Unsupported"; + } } else { *dev_name = "Device-Unknown"; } @@ -510,7 +567,12 @@ void __init orion5x_init(void) u32 dev, rev; orion5x_id(&dev, &rev, &dev_name); - printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION5X_TCLK); + printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk); + + orion5x_eth_shared_data.t_clk = orion5x_tclk; + orion5x_spi_plat_data.tclk = orion5x_tclk; + orion5x_uart0_data[0].uartclk = orion5x_tclk; + orion5x_uart1_data[0].uartclk = orion5x_tclk; /* * Setup Orion address map diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index 0bd195551a2..1f8b2da676a 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -10,6 +10,7 @@ struct mv_sata_platform_data; void orion5x_map_io(void); void orion5x_init_irq(void); void orion5x_init(void); +extern int orion5x_tclk; extern struct sys_timer orion5x_timer; /* @@ -30,6 +31,7 @@ void orion5x_ehci1_init(void); void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data); void orion5x_i2c_init(void); void orion5x_sata_init(struct mv_sata_platform_data *sata_data); +void orion5x_spi_init(void); void orion5x_uart0_init(void); void orion5x_uart1_init(void); void orion5x_xor_init(void); diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c new file mode 100644 index 00000000000..b24ee0c2cd6 --- /dev/null +++ b/arch/arm/mach-orion5x/edmini_v2-setup.c @@ -0,0 +1,262 @@ +/* + * arch/arm/mach-orion5x/edmini_v2-setup.c + * + * LaCie Ethernet Disk mini V2 Setup + * + * Copyright (C) 2008 Christopher Moore <moore@free.fr> + * Copyright (C) 2008 Albert Aribaud <albert.aribaud@free.fr> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/* + * TODO: add Orion USB device port init when kernel.org support is added. + * TODO: add flash write support: see below. + * TODO: add power-off support. + * TODO: add I2C EEPROM support. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/ata_platform.h> +#include <linux/gpio.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <mach/orion5x.h> +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * EDMINI_V2 Info + ****************************************************************************/ + +/* + * 512KB NOR flash Device bus boot chip select + */ + +#define EDMINI_V2_NOR_BOOT_BASE 0xfff80000 +#define EDMINI_V2_NOR_BOOT_SIZE SZ_512K + +/***************************************************************************** + * 512KB NOR Flash on BOOT Device + ****************************************************************************/ + +/* + * Currently the MTD code does not recognize the MX29LV400CBCT as a bottom + * -type device. This could cause risks of accidentally erasing critical + * flash sectors. We thus define a single, write-protected partition covering + * the whole flash. + * TODO: once the flash part TOP/BOTTOM detection issue is sorted out in the MTD + * code, break this into at least three partitions: 'u-boot code', 'u-boot + * environment' and 'whatever is left'. + */ + +static struct mtd_partition edmini_v2_partitions[] = { + { + .name = "Full512kb", + .size = 0x00080000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data edmini_v2_nor_flash_data = { + .width = 1, + .parts = edmini_v2_partitions, + .nr_parts = ARRAY_SIZE(edmini_v2_partitions), +}; + +static struct resource edmini_v2_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = EDMINI_V2_NOR_BOOT_BASE, + .end = EDMINI_V2_NOR_BOOT_BASE + + EDMINI_V2_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device edmini_v2_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edmini_v2_nor_flash_data, + }, + .num_resources = 1, + .resource = &edmini_v2_nor_flash_resource, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data edmini_v2_eth_data = { + .phy_addr = 8, +}; + +/***************************************************************************** + * RTC 5C372a on I2C bus + ****************************************************************************/ + +#define EDMINIV2_RTC_GPIO 3 + +static struct i2c_board_info __initdata edmini_v2_i2c_rtc = { + I2C_BOARD_INFO("rs5c372a", 0x32), + .irq = 0, +}; + +/***************************************************************************** + * Sata + ****************************************************************************/ + +static struct mv_sata_platform_data edmini_v2_sata_data = { + .n_ports = 2, +}; + +/***************************************************************************** + * GPIO LED (simple - doesn't use hardware blinking support) + ****************************************************************************/ + +#define EDMINI_V2_GPIO_LED_POWER 16 + +static struct gpio_led edmini_v2_leds[] = { + { + .name = "power:blue", + .gpio = EDMINI_V2_GPIO_LED_POWER, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data edmini_v2_led_data = { + .num_leds = ARRAY_SIZE(edmini_v2_leds), + .leds = edmini_v2_leds, +}; + +static struct platform_device edmini_v2_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &edmini_v2_led_data, + }, +}; + +/**************************************************************************** + * GPIO key + ****************************************************************************/ + +#define EDMINI_V2_GPIO_KEY_POWER 18 + +static struct gpio_keys_button edmini_v2_buttons[] = { + { + .code = KEY_POWER, + .gpio = EDMINI_V2_GPIO_KEY_POWER, + .desc = "Power Button", + .active_low = 0, + }, +}; + +static struct gpio_keys_platform_data edmini_v2_button_data = { + .buttons = edmini_v2_buttons, + .nbuttons = ARRAY_SIZE(edmini_v2_buttons), +}; + +static struct platform_device edmini_v2_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &edmini_v2_button_data, + }, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ +static struct orion5x_mpp_mode edminiv2_mpp_modes[] __initdata = { + { 0, MPP_UNUSED }, + { 1, MPP_UNUSED }, + { 2, MPP_UNUSED }, + { 3, MPP_GPIO }, /* RTC interrupt */ + { 4, MPP_UNUSED }, + { 5, MPP_UNUSED }, + { 6, MPP_UNUSED }, + { 7, MPP_UNUSED }, + { 8, MPP_UNUSED }, + { 9, MPP_UNUSED }, + { 10, MPP_UNUSED }, + { 11, MPP_UNUSED }, + { 12, MPP_SATA_LED }, /* SATA 0 presence */ + { 13, MPP_SATA_LED }, /* SATA 1 presence */ + { 14, MPP_SATA_LED }, /* SATA 0 active */ + { 15, MPP_SATA_LED }, /* SATA 1 active */ + /* 16: Power LED control (0 = On, 1 = Off) */ + { 16, MPP_GPIO }, + /* 17: Power LED control select (0 = CPLD, 1 = GPIO16) */ + { 17, MPP_GPIO }, + /* 18: Power button status (0 = Released, 1 = Pressed) */ + { 18, MPP_GPIO }, + { 19, MPP_UNUSED }, + { -1 } +}; + +static void __init edmini_v2_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(edminiv2_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_eth_init(&edmini_v2_eth_data); + orion5x_i2c_init(); + orion5x_sata_init(&edmini_v2_sata_data); + orion5x_uart0_init(); + + orion5x_setup_dev_boot_win(EDMINI_V2_NOR_BOOT_BASE, + EDMINI_V2_NOR_BOOT_SIZE); + platform_device_register(&edmini_v2_nor_flash); + platform_device_register(&edmini_v2_gpio_leds); + platform_device_register(&edmini_v2_gpio_buttons); + + pr_notice("edmini_v2: USB device port, flash write and power-off " + "are not yet supported.\n"); + + /* Get RTC IRQ and register the chip */ + if (gpio_request(EDMINIV2_RTC_GPIO, "rtc") == 0) { + if (gpio_direction_input(EDMINIV2_RTC_GPIO) == 0) + edmini_v2_i2c_rtc.irq = gpio_to_irq(EDMINIV2_RTC_GPIO); + else + gpio_free(EDMINIV2_RTC_GPIO); + } + + if (edmini_v2_i2c_rtc.irq == 0) + pr_warning("edmini_v2: failed to get RTC IRQ\n"); + + i2c_register_board_info(0, &edmini_v2_i2c_rtc, 1); +} + +/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */ +MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2") + /* Maintainer: Christopher Moore <moore@free.fr> */ + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = edmini_v2_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index 61eb74a8886..e67c843baa0 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -2,7 +2,7 @@ * arch/arm/mach-orion5x/include/mach/orion5x.h * * Generic definitions of Orion SoC flavors: - * Orion-1, Orion-VoIP, Orion-NAS, and Orion-2. + * Orion-1, Orion-VoIP, Orion-NAS, Orion-2, and Orion-1-90. * * Maintainer: Tzachi Perelstein <tzachi@marvell.com> * @@ -76,6 +76,9 @@ #define MV88F5281_REV_D0 4 #define MV88F5281_REV_D1 5 #define MV88F5281_REV_D2 6 +/* Orion-1-90 (88F6183) */ +#define MV88F6183_DEV_ID 0x6183 +#define MV88F6183_REV_B0 3 /******************************************************************************* * Orion Registers Map @@ -86,6 +89,7 @@ #define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x10000) #define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x10000) #define ORION5X_DEV_BUS_REG(x) (ORION5X_DEV_BUS_VIRT_BASE | (x)) +#define SPI_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE | 0x0600) #define I2C_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE | 0x1000) #define UART0_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE | 0x2000) #define UART0_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE | 0x2000) diff --git a/arch/arm/mach-orion5x/include/mach/timex.h b/arch/arm/mach-orion5x/include/mach/timex.h index e82e44db762..4c69820e081 100644 --- a/arch/arm/mach-orion5x/include/mach/timex.h +++ b/arch/arm/mach-orion5x/include/mach/timex.h @@ -9,5 +9,3 @@ */ #define CLOCK_TICK_RATE (100 * HZ) - -#define ORION5X_TCLK 166666667 diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index e321ec33183..c5bd54d8aa0 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -293,7 +293,7 @@ static void kurobox_pro_power_off(void) const unsigned char shutdownwait[] = {0x00, 0x0c}; const unsigned char poweroff[] = {0x00, 0x06}; /* 38400 baud divisor */ - const unsigned divisor = ((ORION5X_TCLK + (8 * 38400)) / (16 * 38400)); + const unsigned divisor = ((orion5x_tclk + (8 * 38400)) / (16 * 38400)); pr_info("%s: triggering power-off...\n", __func__); diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c new file mode 100644 index 00000000000..e0c43b8beb7 --- /dev/null +++ b/arch/arm/mach-orion5x/lsmini-setup.c @@ -0,0 +1,279 @@ +/* + * arch/arm/mach-orion5x/lsmini-setup.c + * + * Maintainer: Alexey Kopytko <alexey@kopytko.ru> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/ata_platform.h> +#include <asm/mach-types.h> +#include <linux/gpio.h> +#include <asm/mach/arch.h> +#include "common.h" +#include "mpp.h" +#include "include/mach/system.h" + +/***************************************************************************** + * Linkstation Mini Info + ****************************************************************************/ + +/* + * 256K NOR flash Device bus boot chip select + */ + +#define LSMINI_NOR_BOOT_BASE 0xf4000000 +#define LSMINI_NOR_BOOT_SIZE SZ_256K + +/***************************************************************************** + * 256KB NOR Flash on BOOT Device + ****************************************************************************/ + +static struct physmap_flash_data lsmini_nor_flash_data = { + .width = 1, +}; + +static struct resource lsmini_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = LSMINI_NOR_BOOT_BASE, + .end = LSMINI_NOR_BOOT_BASE + LSMINI_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device lsmini_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &lsmini_nor_flash_data, + }, + .num_resources = 1, + .resource = &lsmini_nor_flash_resource, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data lsmini_eth_data = { + .phy_addr = 8, +}; + +/***************************************************************************** + * RTC 5C372a on I2C bus + ****************************************************************************/ + +static struct i2c_board_info __initdata lsmini_i2c_rtc = { + I2C_BOARD_INFO("rs5c372a", 0x32), +}; + +/***************************************************************************** + * LEDs attached to GPIO + ****************************************************************************/ + +#define LSMINI_GPIO_LED_ALARM 2 +#define LSMINI_GPIO_LED_INFO 3 +#define LSMINI_GPIO_LED_FUNC 9 +#define LSMINI_GPIO_LED_PWR 14 + +static struct gpio_led lsmini_led_pins[] = { + { + .name = "alarm:red", + .gpio = LSMINI_GPIO_LED_ALARM, + .active_low = 1, + }, { + .name = "info:amber", + .gpio = LSMINI_GPIO_LED_INFO, + .active_low = 1, + }, { + .name = "func:blue:top", + .gpio = LSMINI_GPIO_LED_FUNC, + .active_low = 1, + }, { + .name = "power:blue:bottom", + .gpio = LSMINI_GPIO_LED_PWR, + }, +}; + +static struct gpio_led_platform_data lsmini_led_data = { + .leds = lsmini_led_pins, + .num_leds = ARRAY_SIZE(lsmini_led_pins), +}; + +static struct platform_device lsmini_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &lsmini_led_data, + }, +}; + +/**************************************************************************** + * GPIO Attached Keys + ****************************************************************************/ + +#define LSMINI_GPIO_KEY_FUNC 15 +#define LSMINI_GPIO_KEY_POWER 18 +#define LSMINI_GPIO_KEY_AUTOPOWER 17 + +#define LSMINI_SW_POWER 0x00 +#define LSMINI_SW_AUTOPOWER 0x01 + +static struct gpio_keys_button lsmini_buttons[] = { + { + .code = KEY_OPTION, + .gpio = LSMINI_GPIO_KEY_FUNC, + .desc = "Function Button", + .active_low = 1, + }, { + .type = EV_SW, + .code = LSMINI_SW_POWER, + .gpio = LSMINI_GPIO_KEY_POWER, + .desc = "Power-on Switch", + .active_low = 1, + }, { + .type = EV_SW, + .code = LSMINI_SW_AUTOPOWER, + .gpio = LSMINI_GPIO_KEY_AUTOPOWER, + .desc = "Power-auto Switch", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data lsmini_button_data = { + .buttons = lsmini_buttons, + .nbuttons = ARRAY_SIZE(lsmini_buttons), +}; + +static struct platform_device lsmini_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &lsmini_button_data, + }, +}; + + +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct mv_sata_platform_data lsmini_sata_data = { + .n_ports = 2, +}; + + +/***************************************************************************** + * Linkstation Mini specific power off method: reboot + ****************************************************************************/ +/* + * On the Linkstation Mini, the shutdown process is following: + * - Userland monitors key events until the power switch goes to off position + * - The board reboots + * - U-boot starts and goes into an idle mode waiting for the user + * to move the switch to ON position + */ + +static void lsmini_power_off(void) +{ + arch_reset(0); +} + + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +#define LSMINI_GPIO_USB_POWER 16 +#define LSMINI_GPIO_AUTO_POWER 17 +#define LSMINI_GPIO_POWER 18 + +#define LSMINI_GPIO_HDD_POWER0 1 +#define LSMINI_GPIO_HDD_POWER1 19 + +static struct orion5x_mpp_mode lsmini_mpp_modes[] __initdata = { + { 0, MPP_UNUSED }, /* LED_RESERVE1 (unused) */ + { 1, MPP_GPIO }, /* HDD_PWR */ + { 2, MPP_GPIO }, /* LED_ALARM */ + { 3, MPP_GPIO }, /* LED_INFO */ + { 4, MPP_UNUSED }, + { 5, MPP_UNUSED }, + { 6, MPP_UNUSED }, + { 7, MPP_UNUSED }, + { 8, MPP_UNUSED }, + { 9, MPP_GPIO }, /* LED_FUNC */ + { 10, MPP_UNUSED }, + { 11, MPP_UNUSED }, /* LED_ETH (dummy) */ + { 12, MPP_UNUSED }, + { 13, MPP_UNUSED }, + { 14, MPP_GPIO }, /* LED_PWR */ + { 15, MPP_GPIO }, /* FUNC */ + { 16, MPP_GPIO }, /* USB_PWR */ + { 17, MPP_GPIO }, /* AUTO_POWER */ + { 18, MPP_GPIO }, /* POWER */ + { 19, MPP_GPIO }, /* HDD_PWR1 */ + { -1 }, +}; + +static void __init lsmini_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(lsmini_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_ehci1_init(); + orion5x_eth_init(&lsmini_eth_data); + orion5x_i2c_init(); + orion5x_sata_init(&lsmini_sata_data); + orion5x_uart0_init(); + orion5x_xor_init(); + + orion5x_setup_dev_boot_win(LSMINI_NOR_BOOT_BASE, + LSMINI_NOR_BOOT_SIZE); + platform_device_register(&lsmini_nor_flash); + + platform_device_register(&lsmini_button_device); + + platform_device_register(&lsmini_leds); + + i2c_register_board_info(0, &lsmini_i2c_rtc, 1); + + /* enable USB power */ + gpio_set_value(LSMINI_GPIO_USB_POWER, 1); + + /* register power-off method */ + pm_power_off = lsmini_power_off; + + pr_info("%s: finished\n", __func__); +} + +#ifdef CONFIG_MACH_LINKSTATION_MINI +MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini") + /* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */ + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = lsmini_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END +#endif diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c new file mode 100644 index 00000000000..40e04953909 --- /dev/null +++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c @@ -0,0 +1,117 @@ +/* + * arch/arm/mach-orion5x/rd88f6183-ap-ge-setup.c + * + * Marvell Orion-1-90 AP GE Reference Design Setup + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/spi/spi.h> +#include <linux/spi/orion_spi.h> +#include <linux/spi/flash.h> +#include <linux/ethtool.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/leds.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <mach/orion5x.h> +#include "common.h" +#include "mpp.h" + +static struct mv643xx_eth_platform_data rd88f6183ap_ge_eth_data = { + .phy_addr = -1, + .speed = SPEED_1000, + .duplex = DUPLEX_FULL, +}; + +static struct mtd_partition rd88f6183ap_ge_partitions[] = { + { + .name = "kernel", + .offset = 0x00000000, + .size = 0x00200000, + }, { + .name = "rootfs", + .offset = 0x00200000, + .size = 0x00500000, + }, { + .name = "nvram", + .offset = 0x00700000, + .size = 0x00080000, + }, +}; + +static struct flash_platform_data rd88f6183ap_ge_spi_slave_data = { + .type = "m25p64", + .nr_parts = ARRAY_SIZE(rd88f6183ap_ge_partitions), + .parts = rd88f6183ap_ge_partitions, +}; + +static struct spi_board_info __initdata rd88f6183ap_ge_spi_slave_info[] = { + { + .modalias = "m25p80", + .platform_data = &rd88f6183ap_ge_spi_slave_data, + .irq = NO_IRQ, + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +static void __init rd88f6183ap_ge_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_eth_init(&rd88f6183ap_ge_eth_data); + spi_register_board_info(rd88f6183ap_ge_spi_slave_info, + ARRAY_SIZE(rd88f6183ap_ge_spi_slave_info)); + orion5x_spi_init(); + orion5x_uart0_init(); +} + +static struct hw_pci rd88f6183ap_ge_pci __initdata = { + .nr_controllers = 2, + .swizzle = pci_std_swizzle, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = orion5x_pci_map_irq, +}; + +static int __init rd88f6183ap_ge_pci_init(void) +{ + if (machine_is_rd88f6183ap_ge()) { + orion5x_pci_disable(); + pci_common_init(&rd88f6183ap_ge_pci); + } + + return 0; +} +subsys_initcall(rd88f6183ap_ge_pci_init); + +MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design") + /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */ + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = rd88f6183ap_ge_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c new file mode 100644 index 00000000000..0b101d7d41c --- /dev/null +++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c @@ -0,0 +1,369 @@ +/* + * Buffalo Terastation Pro II/Live Board Setup + * + * Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/delay.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/i2c.h> +#include <linux/serial_reg.h> +#include <asm/mach-types.h> +#include <asm/gpio.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <mach/orion5x.h> +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * Terastation Pro 2/Live Info + ****************************************************************************/ + +/* + * Terastation Pro 2 hardware : + * - Marvell 88F5281-D0 + * - Marvell 88SX6042 SATA controller (PCI) + * - Marvell 88E1118 Gigabit Ethernet PHY + * - 256KB NOR flash + * - 128MB of DDR RAM + * - PCIe port (not equipped) + */ + +/* + * 256K NOR flash Device bus boot chip select + */ + +#define TSP2_NOR_BOOT_BASE 0xf4000000 +#define TSP2_NOR_BOOT_SIZE SZ_256K + +/***************************************************************************** + * 256KB NOR Flash on BOOT Device + ****************************************************************************/ + +static struct physmap_flash_data tsp2_nor_flash_data = { + .width = 1, +}; + +static struct resource tsp2_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = TSP2_NOR_BOOT_BASE, + .end = TSP2_NOR_BOOT_BASE + TSP2_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device tsp2_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &tsp2_nor_flash_data, + }, + .num_resources = 1, + .resource = &tsp2_nor_flash_resource, +}; + +/***************************************************************************** + * PCI + ****************************************************************************/ +#define TSP2_PCI_SLOT0_OFFS 7 +#define TSP2_PCI_SLOT0_IRQ_PIN 11 + +void __init tsp2_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = TSP2_PCI_SLOT0_IRQ_PIN; + if (gpio_request(pin, "PCI Int1") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); + } else { + printk(KERN_ERR "tsp2_pci_preinit failed " + "to set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "tsp2_pci_preinit failed to " + "gpio_request %d\n", pin); + } +} + +static int __init tsp2_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + + /* + * Check for devices with hard-wired IRQs. + */ + irq = orion5x_pci_map_irq(dev, slot, pin); + if (irq != -1) + return irq; + + /* + * PCI IRQs are connected via GPIOs. + */ + if (slot == TSP2_PCI_SLOT0_OFFS) + return gpio_to_irq(TSP2_PCI_SLOT0_IRQ_PIN); + + return -1; +} + +static struct hw_pci tsp2_pci __initdata = { + .nr_controllers = 2, + .preinit = tsp2_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = tsp2_pci_map_irq, +}; + +static int __init tsp2_pci_init(void) +{ + if (machine_is_terastation_pro2()) + pci_common_init(&tsp2_pci); + + return 0; +} + +subsys_initcall(tsp2_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data tsp2_eth_data = { + .phy_addr = 0, +}; + +/***************************************************************************** + * RTC 5C372a on I2C bus + ****************************************************************************/ + +#define TSP2_RTC_GPIO 9 + +static struct i2c_board_info __initdata tsp2_i2c_rtc = { + I2C_BOARD_INFO("rs5c372a", 0x32), +}; + +/***************************************************************************** + * Terastation Pro II specific power off method via UART1-attached + * microcontroller + ****************************************************************************/ + +#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2)) + +static int tsp2_miconread(unsigned char *buf, int count) +{ + int i; + int timeout; + + for (i = 0; i < count; i++) { + timeout = 10; + + while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) { + if (--timeout == 0) + break; + udelay(1000); + } + + if (timeout == 0) + break; + buf[i] = readl(UART1_REG(RX)); + } + + /* return read bytes */ + return i; +} + +static int tsp2_miconwrite(const unsigned char *buf, int count) +{ + int i = 0; + + while (count--) { + while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE)) + barrier(); + writel(buf[i++], UART1_REG(TX)); + } + + return 0; +} + +static int tsp2_miconsend(const unsigned char *data, int count) +{ + int i; + unsigned char checksum = 0; + unsigned char recv_buf[40]; + unsigned char send_buf[40]; + unsigned char correct_ack[3]; + int retry = 2; + + /* Generate checksum */ + for (i = 0; i < count; i++) + checksum -= data[i]; + + do { + /* Send data */ + tsp2_miconwrite(data, count); + + /* send checksum */ + tsp2_miconwrite(&checksum, 1); + + if (tsp2_miconread(recv_buf, sizeof(recv_buf)) <= 3) { + printk(KERN_ERR ">%s: receive failed.\n", __func__); + + /* send preamble to clear the receive buffer */ + memset(&send_buf, 0xff, sizeof(send_buf)); + tsp2_miconwrite(send_buf, sizeof(send_buf)); + + /* make dummy reads */ + mdelay(100); + tsp2_miconread(recv_buf, sizeof(recv_buf)); + } else { + /* Generate expected ack */ + correct_ack[0] = 0x01; + correct_ack[1] = data[1]; + correct_ack[2] = 0x00; + + /* checksum Check */ + if ((recv_buf[0] + recv_buf[1] + recv_buf[2] + + recv_buf[3]) & 0xFF) { + printk(KERN_ERR ">%s: Checksum Error : " + "Received data[%02x, %02x, %02x, %02x]" + "\n", __func__, recv_buf[0], + recv_buf[1], recv_buf[2], recv_buf[3]); + } else { + /* Check Received Data */ + if (correct_ack[0] == recv_buf[0] && + correct_ack[1] == recv_buf[1] && + correct_ack[2] == recv_buf[2]) { + /* Interval for next command */ + mdelay(10); + + /* Receive ACK */ + return 0; + } + } + /* Received NAK or illegal Data */ + printk(KERN_ERR ">%s: Error : NAK or Illegal Data " + "Received\n", __func__); + } + } while (retry--); + + /* Interval for next command */ + mdelay(10); + + return -1; +} + +static void tsp2_power_off(void) +{ + const unsigned char watchdogkill[] = {0x01, 0x35, 0x00}; + const unsigned char shutdownwait[] = {0x00, 0x0c}; + const unsigned char poweroff[] = {0x00, 0x06}; + /* 38400 baud divisor */ + const unsigned divisor = ((orion5x_tclk + (8 * 38400)) / (16 * 38400)); + + pr_info("%s: triggering power-off...\n", __func__); + + /* hijack uart1 and reset into sane state (38400,8n1,even parity) */ + writel(0x83, UART1_REG(LCR)); + writel(divisor & 0xff, UART1_REG(DLL)); + writel((divisor >> 8) & 0xff, UART1_REG(DLM)); + writel(0x1b, UART1_REG(LCR)); + writel(0x00, UART1_REG(IER)); + writel(0x07, UART1_REG(FCR)); + writel(0x00, UART1_REG(MCR)); + + /* Send the commands to shutdown the Terastation Pro II */ + tsp2_miconsend(watchdogkill, sizeof(watchdogkill)) ; + tsp2_miconsend(shutdownwait, sizeof(shutdownwait)) ; + tsp2_miconsend(poweroff, sizeof(poweroff)); +} + +/***************************************************************************** + * General Setup + ****************************************************************************/ +static struct orion5x_mpp_mode tsp2_mpp_modes[] __initdata = { + { 0, MPP_PCIE_RST_OUTn }, + { 1, MPP_UNUSED }, + { 2, MPP_UNUSED }, + { 3, MPP_UNUSED }, + { 4, MPP_NAND }, /* BOOT NAND Flash REn */ + { 5, MPP_NAND }, /* BOOT NAND Flash WEn */ + { 6, MPP_NAND }, /* BOOT NAND Flash HREn[0] */ + { 7, MPP_NAND }, /* BOOT NAND Flash WEn[0] */ + { 8, MPP_GPIO }, /* MICON int */ + { 9, MPP_GPIO }, /* RTC int */ + { 10, MPP_UNUSED }, + { 11, MPP_GPIO }, /* PCI Int A */ + { 12, MPP_UNUSED }, + { 13, MPP_GPIO }, /* UPS on UART0 enable */ + { 14, MPP_GPIO }, /* UPS low battery detection */ + { 15, MPP_UNUSED }, + { 16, MPP_UART }, /* UART1 RXD */ + { 17, MPP_UART }, /* UART1 TXD */ + { 18, MPP_UART }, /* UART1 CTSn */ + { 19, MPP_UART }, /* UART1 RTSn */ + { -1 }, +}; + +static void __init tsp2_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(tsp2_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_setup_dev_boot_win(TSP2_NOR_BOOT_BASE, + TSP2_NOR_BOOT_SIZE); + platform_device_register(&tsp2_nor_flash); + + orion5x_ehci0_init(); + orion5x_eth_init(&tsp2_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + orion5x_uart1_init(); + + /* Get RTC IRQ and register the chip */ + if (gpio_request(TSP2_RTC_GPIO, "rtc") == 0) { + if (gpio_direction_input(TSP2_RTC_GPIO) == 0) + tsp2_i2c_rtc.irq = gpio_to_irq(TSP2_RTC_GPIO); + else + gpio_free(TSP2_RTC_GPIO); + } + if (tsp2_i2c_rtc.irq == 0) + pr_warning("tsp2_init: failed to get RTC IRQ\n"); + i2c_register_board_info(0, &tsp2_i2c_rtc, 1); + + /* register Terastation Pro II specific power-off method */ + pm_power_off = tsp2_power_off; +} + +MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live") + /* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */ + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = tsp2_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END diff --git a/arch/arm/mach-orion5x/tsx09-common.c b/arch/arm/mach-orion5x/tsx09-common.c index 83feac3147a..5128da1101b 100644 --- a/arch/arm/mach-orion5x/tsx09-common.c +++ b/arch/arm/mach-orion5x/tsx09-common.c @@ -16,6 +16,7 @@ #include <linux/timex.h> #include <linux/serial_reg.h> #include "tsx09-common.h" +#include "common.h" /***************************************************************************** * QNAP TS-x09 specific power off method via UART1-attached PIC @@ -26,7 +27,7 @@ void qnap_tsx09_power_off(void) { /* 19200 baud divisor */ - const unsigned divisor = ((ORION5X_TCLK + (8 * 19200)) / (16 * 19200)); + const unsigned divisor = ((orion5x_tclk + (8 * 19200)) / (16 * 19200)); pr_info("%s: triggering power-off...\n", __func__); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ed15f876c72..330814d1ee2 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -735,6 +735,14 @@ config CACHE_FEROCEON_L2 help This option enables the Feroceon L2 cache controller. +config CACHE_FEROCEON_L2_WRITETHROUGH + bool "Force Feroceon L2 cache write through" + depends on CACHE_FEROCEON_L2 + default n + help + Say Y here to use the Feroceon L2 cache in writethrough mode. + Unless you specifically require this, say N for writeback mode. + config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 7b5a25d8157..13cdae8b0d4 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -48,11 +48,12 @@ static inline void l2_clean_mva_range(unsigned long start, unsigned long end) * L2 is PIPT and range operations only do a TLB lookup on * the start address. */ - BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); + BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); - __asm__("mcr p15, 1, %0, c15, c9, 4" : : "r" (start)); - __asm__("mcr p15, 1, %0, c15, c9, 5" : : "r" (end)); + __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" + "mcr p15, 1, %1, c15, c9, 5" + : : "r" (start), "r" (end)); raw_local_irq_restore(flags); } @@ -80,11 +81,12 @@ static inline void l2_inv_mva_range(unsigned long start, unsigned long end) * L2 is PIPT and range operations only do a TLB lookup on * the start address. */ - BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); + BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); - __asm__("mcr p15, 1, %0, c15, c11, 4" : : "r" (start)); - __asm__("mcr p15, 1, %0, c15, c11, 5" : : "r" (end)); + __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" + "mcr p15, 1, %1, c15, c11, 5" + : : "r" (start), "r" (end)); raw_local_irq_restore(flags); } @@ -205,7 +207,7 @@ static void feroceon_l2_flush_range(unsigned long start, unsigned long end) * time. These are necessary because the L2 cache can only be enabled * or disabled while the L1 Dcache and Icache are both disabled. */ -static void __init invalidate_and_disable_dcache(void) +static int __init flush_and_disable_dcache(void) { u32 cr; @@ -217,7 +219,9 @@ static void __init invalidate_and_disable_dcache(void) flush_cache_all(); set_cr(cr & ~CR_C); raw_local_irq_restore(flags); + return 1; } + return 0; } static void __init enable_dcache(void) @@ -225,18 +229,17 @@ static void __init enable_dcache(void) u32 cr; cr = get_cr(); - if (!(cr & CR_C)) - set_cr(cr | CR_C); + set_cr(cr | CR_C); } static void __init __invalidate_icache(void) { int dummy; - __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0\n" : "=r" (dummy)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0" : "=r" (dummy)); } -static void __init invalidate_and_disable_icache(void) +static int __init invalidate_and_disable_icache(void) { u32 cr; @@ -244,7 +247,9 @@ static void __init invalidate_and_disable_icache(void) if (cr & CR_I) { set_cr(cr & ~CR_I); __invalidate_icache(); + return 1; } + return 0; } static void __init enable_icache(void) @@ -252,8 +257,7 @@ static void __init enable_icache(void) u32 cr; cr = get_cr(); - if (!(cr & CR_I)) - set_cr(cr | CR_I); + set_cr(cr | CR_I); } static inline u32 read_extra_features(void) @@ -291,13 +295,17 @@ static void __init enable_l2(void) u = read_extra_features(); if (!(u & 0x00400000)) { + int i, d; + printk(KERN_INFO "Feroceon L2: Enabling L2\n"); - invalidate_and_disable_dcache(); - invalidate_and_disable_icache(); + d = flush_and_disable_dcache(); + i = invalidate_and_disable_icache(); write_extra_features(u | 0x00400000); - enable_icache(); - enable_dcache(); + if (i) + enable_icache(); + if (d) + enable_dcache(); } } diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index 2b8bb383755..0fe1f8fc348 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S @@ -80,7 +80,8 @@ ENTRY(cpu_feroceon_proc_fin) msr cpsr_c, ip bl feroceon_flush_kern_cache_all -#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) +#if defined(CONFIG_CACHE_FEROCEON_L2) && \ + !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) mov r0, #0 mcr p15, 1, r0, c15, c9, 0 @ clean L2 mcr p15, 0, r0, c7, c10, 4 @ drain WB @@ -389,7 +390,8 @@ ENTRY(feroceon_range_cache_fns) .align 5 ENTRY(cpu_feroceon_dcache_clean_area) -#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) +#if defined(CONFIG_CACHE_FEROCEON_L2) && \ + !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) mov r2, r0 mov r3, r1 #endif @@ -397,7 +399,8 @@ ENTRY(cpu_feroceon_dcache_clean_area) add r0, r0, #CACHE_DLINESIZE subs r1, r1, #CACHE_DLINESIZE bhi 1b -#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) +#if defined(CONFIG_CACHE_FEROCEON_L2) && \ + !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) 1: mcr p15, 1, r2, c15, c9, 1 @ clean L2 entry add r2, r2, #CACHE_DLINESIZE subs r3, r3, #CACHE_DLINESIZE @@ -449,7 +452,8 @@ ENTRY(cpu_feroceon_set_pte_ext) armv3_set_pte_ext wc_disable=0 mov r0, r0 mcr p15, 0, r0, c7, c10, 1 @ clean D entry -#if defined(CONFIG_CACHE_FEROCEON_L2) && !defined(CONFIG_L2_CACHE_WRITETHROUGH) +#if defined(CONFIG_CACHE_FEROCEON_L2) && \ + !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) mcr p15, 1, r0, c15, c9, 1 @ clean L2 entry #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB |