diff options
author | Lennert Buytenhek <buytenh@marvell.com> | 2008-06-22 22:45:02 +0200 |
---|---|---|
committer | Lennert Buytenhek <buytenh@marvell.com> | 2008-06-22 22:45:02 +0200 |
commit | 777f9bebad3476b7dbf5cd8abbd3414139ca0e48 (patch) | |
tree | f58bb3a02ae8f30463d33a131d17707cf3308843 /arch | |
parent | 1219715de70956557b9dedf3ee021a73d4f4ec52 (diff) |
[ARM] add Marvell Loki (88RC8480) SoC support
The Marvell Loki (88RC8480) is an ARM SoC based on a Feroceon CPU
core running at between 400 MHz and 1.0 GHz, and features a 64 bit
DDR controller, 512K of internal SRAM, two x4 PCI-Express ports,
two Gigabit Ethernet ports, two 4x SAS/SATA controllers, two UARTs,
two TWSI controllers, and IDMA/XOR engines.
This patch adds support for the Marvell LB88RC8480 Development
Board, enabling the use of the PCIe interfaces, the ethernet
interfaces, the TWSI interfaces and the UARTs.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-loki/Kconfig | 13 | ||||
-rw-r--r-- | arch/arm/mach-loki/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-loki/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-loki/addr-map.c | 121 | ||||
-rw-r--r-- | arch/arm/mach-loki/common.c | 305 | ||||
-rw-r--r-- | arch/arm/mach-loki/common.h | 36 | ||||
-rw-r--r-- | arch/arm/mach-loki/irq.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-loki/lb88rc8480-setup.c | 100 | ||||
-rw-r--r-- | arch/arm/mm/Kconfig | 2 |
11 files changed, 614 insertions, 1 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4bdf598611d..7a725f89b84 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -370,6 +370,14 @@ config ARCH_NS9XXX <http://www.digi.com/products/microprocessors/index.jsp> +config ARCH_LOKI + bool "Marvell Loki (88RC8480)" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select PLAT_ORION + help + Support for the Marvell Loki (88RC8480) SoC. + config ARCH_MXC bool "Freescale MXC/iMX-based" select ARCH_MTD_XIP @@ -508,6 +516,8 @@ source "arch/arm/mach-ixp2000/Kconfig" source "arch/arm/mach-ixp23xx/Kconfig" +source "arch/arm/mach-loki/Kconfig" + source "arch/arm/mach-pxa/Kconfig" source "arch/arm/mach-sa1100/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index e72db27e0ba..2ea32a70c97 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -140,6 +140,7 @@ endif machine-$(CONFIG_ARCH_MX3) := mx3 machine-$(CONFIG_ARCH_ORION5X) := orion5x machine-$(CONFIG_ARCH_MSM7X00A) := msm + machine-$(CONFIG_ARCH_LOKI) := loki ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/mach-loki/Kconfig b/arch/arm/mach-loki/Kconfig new file mode 100644 index 00000000000..0045bdd761c --- /dev/null +++ b/arch/arm/mach-loki/Kconfig @@ -0,0 +1,13 @@ +if ARCH_LOKI + +menu "Marvell Loki (88RC8480) Implementations" + +config MACH_LB88RC8480 + bool "Marvell LB88RC8480 Development Board" + help + Say 'Y' here if you want your kernel to support the + Marvell LB88RC8480 Development Board. + +endmenu + +endif diff --git a/arch/arm/mach-loki/Makefile b/arch/arm/mach-loki/Makefile new file mode 100644 index 00000000000..d43233ee590 --- /dev/null +++ b/arch/arm/mach-loki/Makefile @@ -0,0 +1,3 @@ +obj-y += common.o addr-map.o irq.o + +obj-$(CONFIG_MACH_LB88RC8480) += lb88rc8480-setup.o diff --git a/arch/arm/mach-loki/Makefile.boot b/arch/arm/mach-loki/Makefile.boot new file mode 100644 index 00000000000..67039c3e0c4 --- /dev/null +++ b/arch/arm/mach-loki/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-loki/addr-map.c b/arch/arm/mach-loki/addr-map.c new file mode 100644 index 00000000000..ba25e56ade5 --- /dev/null +++ b/arch/arm/mach-loki/addr-map.c @@ -0,0 +1,121 @@ +/* + * arch/arm/mach-loki/addr-map.c + * + * Address map functions for Marvell Loki (88RC8480) SoCs + * + * 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/mbus.h> +#include <asm/hardware.h> +#include <asm/io.h> +#include "common.h" + +/* + * Generic Address Decode Windows bit settings + */ +#define TARGET_DDR 0 +#define TARGET_DEV_BUS 1 +#define TARGET_PCIE0 3 +#define TARGET_PCIE1 4 +#define ATTR_DEV_BOOT 0x0f +#define ATTR_DEV_CS2 0x1b +#define ATTR_DEV_CS1 0x1d +#define ATTR_DEV_CS0 0x1e +#define ATTR_PCIE_IO 0x51 +#define ATTR_PCIE_MEM 0x59 + +/* + * Helpers to get DDR bank info + */ +#define DDR_SIZE_CS(n) DDR_REG(0x1500 + ((n) << 3)) +#define DDR_BASE_CS(n) DDR_REG(0x1504 + ((n) << 3)) + +/* + * CPU Address Decode Windows registers + */ +#define CPU_WIN_CTRL(n) BRIDGE_REG(0x000 | ((n) << 4)) +#define CPU_WIN_BASE(n) BRIDGE_REG(0x004 | ((n) << 4)) +#define CPU_WIN_REMAP_LO(n) BRIDGE_REG(0x008 | ((n) << 4)) +#define CPU_WIN_REMAP_HI(n) BRIDGE_REG(0x00c | ((n) << 4)) + + +struct mbus_dram_target_info loki_mbus_dram_info; + +static void __init setup_cpu_win(int win, u32 base, u32 size, + u8 target, u8 attr, int remap) +{ + u32 ctrl; + + base &= 0xffff0000; + ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (1 << 5) | target; + + writel(base, CPU_WIN_BASE(win)); + writel(ctrl, CPU_WIN_CTRL(win)); + if (win < 2) { + if (remap < 0) + remap = base; + + writel(remap & 0xffff0000, CPU_WIN_REMAP_LO(win)); + writel(0, CPU_WIN_REMAP_HI(win)); + } +} + +void __init loki_setup_cpu_mbus(void) +{ + int i; + int cs; + + /* + * First, disable and clear windows. + */ + for (i = 0; i < 8; i++) { + writel(0, CPU_WIN_BASE(i)); + writel(0, CPU_WIN_CTRL(i)); + if (i < 2) { + writel(0, CPU_WIN_REMAP_LO(i)); + writel(0, CPU_WIN_REMAP_HI(i)); + } + } + + /* + * Setup windows for PCIe IO+MEM space. + */ + setup_cpu_win(2, LOKI_PCIE0_MEM_PHYS_BASE, LOKI_PCIE0_MEM_SIZE, + TARGET_PCIE0, ATTR_PCIE_MEM, -1); + setup_cpu_win(3, LOKI_PCIE1_MEM_PHYS_BASE, LOKI_PCIE1_MEM_SIZE, + TARGET_PCIE1, ATTR_PCIE_MEM, -1); + + /* + * Setup MBUS dram target info. + */ + loki_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; + + for (i = 0, cs = 0; i < 4; i++) { + u32 base = readl(DDR_BASE_CS(i)); + u32 size = readl(DDR_SIZE_CS(i)); + + /* + * Chip select enabled? + */ + if (size & 1) { + struct mbus_dram_window *w; + + w = &loki_mbus_dram_info.cs[cs++]; + w->cs_index = i; + w->mbus_attr = 0xf & ~(1 << i); + w->base = base & 0xffff0000; + w->size = (size | 0x0000ffff) + 1; + } + } + loki_mbus_dram_info.num_cs = cs; +} + +void __init loki_setup_dev_boot_win(u32 base, u32 size) +{ + setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1); +} diff --git a/arch/arm/mach-loki/common.c b/arch/arm/mach-loki/common.c new file mode 100644 index 00000000000..410f50399dd --- /dev/null +++ b/arch/arm/mach-loki/common.c @@ -0,0 +1,305 @@ +/* + * arch/arm/mach-loki/common.c + * + * Core functions for Marvell Loki (88RC8480) SoCs + * + * 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/serial_8250.h> +#include <linux/mbus.h> +#include <linux/mv643xx_eth.h> +#include <asm/page.h> +#include <asm/timex.h> +#include <asm/mach/map.h> +#include <asm/mach/time.h> +#include <asm/arch/loki.h> +#include <asm/plat-orion/orion_nand.h> +#include <asm/plat-orion/time.h> +#include "common.h" + +/***************************************************************************** + * I/O Address Mapping + ****************************************************************************/ +static struct map_desc loki_io_desc[] __initdata = { + { + .virtual = LOKI_REGS_VIRT_BASE, + .pfn = __phys_to_pfn(LOKI_REGS_PHYS_BASE), + .length = LOKI_REGS_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init loki_map_io(void) +{ + iotable_init(loki_io_desc, ARRAY_SIZE(loki_io_desc)); +} + + +/***************************************************************************** + * GE0 + ****************************************************************************/ +struct mv643xx_eth_shared_platform_data loki_ge0_shared_data = { + .t_clk = LOKI_TCLK, + .dram = &loki_mbus_dram_info, +}; + +static struct resource loki_ge0_shared_resources[] = { + { + .name = "ge0 base", + .start = GE0_PHYS_BASE + 0x2000, + .end = GE0_PHYS_BASE + 0x3fff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device loki_ge0_shared = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .dev = { + .platform_data = &loki_ge0_shared_data, + }, + .num_resources = 1, + .resource = loki_ge0_shared_resources, +}; + +static struct resource loki_ge0_resources[] = { + { + .name = "ge0 irq", + .start = IRQ_LOKI_GBE_A_INT, + .end = IRQ_LOKI_GBE_A_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device loki_ge0 = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = 1, + .resource = loki_ge0_resources, +}; + +void __init loki_ge0_init(struct mv643xx_eth_platform_data *eth_data) +{ + eth_data->shared = &loki_ge0_shared; + loki_ge0.dev.platform_data = eth_data; + + writel(0x00079220, GE0_VIRT_BASE + 0x20b0); + platform_device_register(&loki_ge0_shared); + platform_device_register(&loki_ge0); +} + + +/***************************************************************************** + * GE1 + ****************************************************************************/ +struct mv643xx_eth_shared_platform_data loki_ge1_shared_data = { + .t_clk = LOKI_TCLK, + .dram = &loki_mbus_dram_info, +}; + +static struct resource loki_ge1_shared_resources[] = { + { + .name = "ge1 base", + .start = GE1_PHYS_BASE + 0x2000, + .end = GE1_PHYS_BASE + 0x3fff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device loki_ge1_shared = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 1, + .dev = { + .platform_data = &loki_ge1_shared_data, + }, + .num_resources = 1, + .resource = loki_ge1_shared_resources, +}; + +static struct resource loki_ge1_resources[] = { + { + .name = "ge1 irq", + .start = IRQ_LOKI_GBE_B_INT, + .end = IRQ_LOKI_GBE_B_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device loki_ge1 = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = 1, + .resource = loki_ge1_resources, +}; + +void __init loki_ge1_init(struct mv643xx_eth_platform_data *eth_data) +{ + eth_data->shared = &loki_ge1_shared; + loki_ge1.dev.platform_data = eth_data; + + writel(0x00079220, GE1_VIRT_BASE + 0x20b0); + platform_device_register(&loki_ge1_shared); + platform_device_register(&loki_ge1); +} + + +/***************************************************************************** + * SAS/SATA + ****************************************************************************/ +static struct resource loki_sas_resources[] = { + { + .name = "mvsas0 mem", + .start = SAS0_PHYS_BASE, + .end = SAS0_PHYS_BASE + 0x01ff, + .flags = IORESOURCE_MEM, + }, { + .name = "mvsas0 irq", + .start = IRQ_LOKI_SAS_A, + .end = IRQ_LOKI_SAS_A, + .flags = IORESOURCE_IRQ, + }, { + .name = "mvsas1 mem", + .start = SAS1_PHYS_BASE, + .end = SAS1_PHYS_BASE + 0x01ff, + .flags = IORESOURCE_MEM, + }, { + .name = "mvsas1 irq", + .start = IRQ_LOKI_SAS_B, + .end = IRQ_LOKI_SAS_B, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device loki_sas = { + .name = "mvsas", + .id = 0, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(loki_sas_resources), + .resource = loki_sas_resources, +}; + +void __init loki_sas_init(void) +{ + writel(0x8300f707, DDR_REG(0x1424)); + platform_device_register(&loki_sas); +} + + +/***************************************************************************** + * UART0 + ****************************************************************************/ +static struct plat_serial8250_port loki_uart0_data[] = { + { + .mapbase = UART0_PHYS_BASE, + .membase = (char *)UART0_VIRT_BASE, + .irq = IRQ_LOKI_UART0, + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = LOKI_TCLK, + }, { + }, +}; + +static struct resource loki_uart0_resources[] = { + { + .start = UART0_PHYS_BASE, + .end = UART0_PHYS_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_LOKI_UART0, + .end = IRQ_LOKI_UART0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device loki_uart0 = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = loki_uart0_data, + }, + .resource = loki_uart0_resources, + .num_resources = ARRAY_SIZE(loki_uart0_resources), +}; + +void __init loki_uart0_init(void) +{ + platform_device_register(&loki_uart0); +} + + +/***************************************************************************** + * UART1 + ****************************************************************************/ +static struct plat_serial8250_port loki_uart1_data[] = { + { + .mapbase = UART1_PHYS_BASE, + .membase = (char *)UART1_VIRT_BASE, + .irq = IRQ_LOKI_UART1, + .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = LOKI_TCLK, + }, { + }, +}; + +static struct resource loki_uart1_resources[] = { + { + .start = UART1_PHYS_BASE, + .end = UART1_PHYS_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_LOKI_UART1, + .end = IRQ_LOKI_UART1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device loki_uart1 = { + .name = "serial8250", + .id = 1, + .dev = { + .platform_data = loki_uart1_data, + }, + .resource = loki_uart1_resources, + .num_resources = ARRAY_SIZE(loki_uart1_resources), +}; + +void __init loki_uart1_init(void) +{ + platform_device_register(&loki_uart1); +} + + +/***************************************************************************** + * Time handling + ****************************************************************************/ +static void loki_timer_init(void) +{ + orion_time_init(IRQ_LOKI_BRIDGE, LOKI_TCLK); +} + +struct sys_timer loki_timer = { + .init = loki_timer_init, +}; + + +/***************************************************************************** + * General + ****************************************************************************/ +void __init loki_init(void) +{ + printk(KERN_INFO "Loki ID: 88RC8480. TCLK=%d.\n", LOKI_TCLK); + + loki_setup_cpu_mbus(); +} diff --git a/arch/arm/mach-loki/common.h b/arch/arm/mach-loki/common.h new file mode 100644 index 00000000000..26054fd0f05 --- /dev/null +++ b/arch/arm/mach-loki/common.h @@ -0,0 +1,36 @@ +/* + * arch/arm/mach-loki/common.h + * + * Core functions for Marvell Loki (88RC8480) SoCs + * + * 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. + */ + +#ifndef __ARCH_LOKI_COMMON_H +#define __ARCH_LOKI_COMMON_H + +struct mv643xx_eth_platform_data; + +/* + * Basic Loki init functions used early by machine-setup. + */ +void loki_map_io(void); +void loki_init(void); +void loki_init_irq(void); + +extern struct mbus_dram_target_info loki_mbus_dram_info; +void loki_setup_cpu_mbus(void); +void loki_setup_dev_boot_win(u32 base, u32 size); + +void loki_ge0_init(struct mv643xx_eth_platform_data *eth_data); +void loki_ge1_init(struct mv643xx_eth_platform_data *eth_data); +void loki_sas_init(void); +void loki_uart0_init(void); +void loki_uart1_init(void); + +extern struct sys_timer loki_timer; + + +#endif diff --git a/arch/arm/mach-loki/irq.c b/arch/arm/mach-loki/irq.c new file mode 100644 index 00000000000..d839af91fe0 --- /dev/null +++ b/arch/arm/mach-loki/irq.c @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-loki/irq.c + * + * Marvell Loki (88RC8480) IRQ handling. + * + * 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/irq.h> +#include <asm/io.h> +#include <asm/plat-orion/irq.h> +#include "common.h" + +void __init loki_init_irq(void) +{ + orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_OFF)); +} diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c new file mode 100644 index 00000000000..d1b9e6e6253 --- /dev/null +++ b/arch/arm/mach-loki/lb88rc8480-setup.c @@ -0,0 +1,100 @@ +/* + * arch/arm/mach-loki/lb88rc8480-setup.c + * + * Marvell LB88RC8480 Development Board 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/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/nand.h> +#include <linux/timer.h> +#include <linux/ata_platform.h> +#include <linux/mv643xx_eth.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/arch/loki.h> +#include "common.h" + +#define LB88RC8480_FLASH_BOOT_CS_BASE 0xf8000000 +#define LB88RC8480_FLASH_BOOT_CS_SIZE SZ_128M + +#define LB88RC8480_NOR_BOOT_BASE 0xff000000 +#define LB88RC8480_NOR_BOOT_SIZE SZ_16M + +static struct mtd_partition lb88rc8480_boot_flash_parts[] = { + { + .name = "kernel", + .offset = 0, + .size = SZ_2M, + }, { + .name = "root-fs", + .offset = SZ_2M, + .size = (SZ_8M + SZ_4M + SZ_1M), + }, { + .name = "u-boot", + .offset = (SZ_8M + SZ_4M + SZ_2M + SZ_1M), + .size = SZ_1M, + }, +}; + +static struct physmap_flash_data lb88rc8480_boot_flash_data = { + .parts = lb88rc8480_boot_flash_parts, + .nr_parts = ARRAY_SIZE(lb88rc8480_boot_flash_parts), + .width = 1, /* 8 bit bus width */ +}; + +static struct resource lb88rc8480_boot_flash_resource = { + .flags = IORESOURCE_MEM, + .start = LB88RC8480_NOR_BOOT_BASE, + .end = LB88RC8480_NOR_BOOT_BASE + LB88RC8480_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device lb88rc8480_boot_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &lb88rc8480_boot_flash_data, + }, + .num_resources = 1, + .resource = &lb88rc8480_boot_flash_resource, +}; + +static struct mv643xx_eth_platform_data lb88rc8480_ge0_data = { + .phy_addr = 1, + .mac_addr = { 0x00, 0x50, 0x43, 0x11, 0x22, 0x33 }, +}; + +static void __init lb88rc8480_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + loki_init(); + + loki_ge0_init(&lb88rc8480_ge0_data); + loki_sas_init(); + loki_uart0_init(); + loki_uart1_init(); + + loki_setup_dev_boot_win(LB88RC8480_FLASH_BOOT_CS_BASE, + LB88RC8480_FLASH_BOOT_CS_SIZE); + platform_device_register(&lb88rc8480_boot_flash); +} + +MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board") + /* Maintainer: Ke Wei <kewei@marvell.com> */ + .phys_io = LOKI_REGS_PHYS_BASE, + .io_pg_offst = ((LOKI_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = lb88rc8480_init, + .map_io = loki_map_io, + .init_irq = loki_init_irq, + .timer = &loki_timer, +MACHINE_END diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 33ed048502a..08ca264459b 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -365,7 +365,7 @@ config CPU_XSC3 # Feroceon config CPU_FEROCEON bool - depends on ARCH_ORION5X + depends on ARCH_ORION5X || ARCH_LOKI default y select CPU_32v5 select CPU_ABRT_EV5T |