From e50d64097b6e63278789ee3a4394d127bd6e4254 Mon Sep 17 00:00:00 2001 From: Assaf Hoffman Date: Tue, 23 Oct 2007 15:14:41 -0400 Subject: [ARM] Marvell Feroceon CPU core support The Feroceon is a family of independent ARMv5TE compliant CPU core implementations, supporting a variable depth pipeline and out-of-order execution. The Feroceon is configurable with VFP support, and the later models in the series are superscalar with up to two instructions per clock cycle. This patch adds the initial low-level cache/TLB handling for this core. Signed-off-by: Assaf Hoffman Reviewed-by: Tzachi Perelstein Reviewed-by: Nicolas Pitre Reviewed-by: Lennert Buytenhek Acked-by: Russell King --- arch/arm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/Kconfig') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a04f507e7f2c..fae3f164218f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -951,7 +951,7 @@ config FPE_FASTFPE config VFP bool "VFP-format floating point maths" - depends on CPU_V6 || CPU_ARM926T + depends on CPU_V6 || CPU_ARM926T || CPU_FEROCEON help Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. -- cgit v1.2.3-55-g7522 From 585cf17561d3174a745bec49c422c1a621c95fc4 Mon Sep 17 00:00:00 2001 From: Tzachi Perelstein Date: Tue, 23 Oct 2007 15:14:41 -0400 Subject: [ARM] basic support for the Marvell Orion SoC family The Marvell Orion is a family of ARM SoCs with a DDR/DDR2 memory controller, 10/100/1000 ethernet MAC, and USB 2.0 interfaces, and, depending on the specific model, PCI-E interface, PCI-X interface, SATA controllers, crypto unit, SPI interface, SDIO interface, device bus, NAND controller, DMA engine and/or XOR engine. This contains the basic structure and architecture register definitions. Signed-off-by: Tzachi Perelstein Reviewed-by: Nicolas Pitre Reviewed-by: Lennert Buytenhek Acked-by: Russell King --- arch/arm/Kconfig | 8 ++ arch/arm/Makefile | 1 + arch/arm/mach-orion/Kconfig | 7 ++ arch/arm/mach-orion/Makefile | 1 + arch/arm/mach-orion/Makefile.boot | 3 + arch/arm/mach-orion/common.c | 53 ++++++++++++ arch/arm/mach-orion/common.h | 9 ++ include/asm-arm/arch-orion/debug-macro.S | 17 ++++ include/asm-arm/arch-orion/dma.h | 1 + include/asm-arm/arch-orion/entry-macro.S | 31 +++++++ include/asm-arm/arch-orion/hardware.h | 24 ++++++ include/asm-arm/arch-orion/io.h | 27 ++++++ include/asm-arm/arch-orion/irqs.h | 61 ++++++++++++++ include/asm-arm/arch-orion/memory.h | 15 ++++ include/asm-arm/arch-orion/orion.h | 140 +++++++++++++++++++++++++++++++ include/asm-arm/arch-orion/system.h | 31 +++++++ include/asm-arm/arch-orion/timex.h | 12 +++ include/asm-arm/arch-orion/uncompress.h | 44 ++++++++++ include/asm-arm/arch-orion/vmalloc.h | 5 ++ 19 files changed, 490 insertions(+) create mode 100644 arch/arm/mach-orion/Kconfig create mode 100644 arch/arm/mach-orion/Makefile create mode 100644 arch/arm/mach-orion/Makefile.boot create mode 100644 arch/arm/mach-orion/common.c create mode 100644 arch/arm/mach-orion/common.h create mode 100644 include/asm-arm/arch-orion/debug-macro.S create mode 100644 include/asm-arm/arch-orion/dma.h create mode 100644 include/asm-arm/arch-orion/entry-macro.S create mode 100644 include/asm-arm/arch-orion/hardware.h create mode 100644 include/asm-arm/arch-orion/io.h create mode 100644 include/asm-arm/arch-orion/irqs.h create mode 100644 include/asm-arm/arch-orion/memory.h create mode 100644 include/asm-arm/arch-orion/orion.h create mode 100644 include/asm-arm/arch-orion/system.h create mode 100644 include/asm-arm/arch-orion/timex.h create mode 100644 include/asm-arm/arch-orion/uncompress.h create mode 100644 include/asm-arm/arch-orion/vmalloc.h (limited to 'arch/arm/Kconfig') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fae3f164218f..036239150ff8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -333,6 +333,12 @@ config ARCH_MXC help Support for Freescale MXC/iMX-based family of processors +config ARCH_ORION + bool "Marvell Orion" + depends on MMU + help + Support for Marvell Orion System on Chip family. + config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" help @@ -441,6 +447,8 @@ source "arch/arm/mach-omap1/Kconfig" source "arch/arm/mach-omap2/Kconfig" +source "arch/arm/mach-orion/Kconfig" + source "arch/arm/plat-s3c24xx/Kconfig" source "arch/arm/plat-s3c/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 35e56c99ad1d..2daa278149e0 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -139,6 +139,7 @@ endif machine-$(CONFIG_ARCH_KS8695) := ks8695 incdir-$(CONFIG_ARCH_MXC) := mxc machine-$(CONFIG_ARCH_MX3) := mx3 + machine-$(CONFIG_ARCH_ORION) := orion ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/mach-orion/Kconfig b/arch/arm/mach-orion/Kconfig new file mode 100644 index 000000000000..c2af02125ce9 --- /dev/null +++ b/arch/arm/mach-orion/Kconfig @@ -0,0 +1,7 @@ +if ARCH_ORION + +menu "Orion Implementations" + +endmenu + +endif diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile new file mode 100644 index 000000000000..69eb30187738 --- /dev/null +++ b/arch/arm/mach-orion/Makefile @@ -0,0 +1 @@ +obj-y += common.o diff --git a/arch/arm/mach-orion/Makefile.boot b/arch/arm/mach-orion/Makefile.boot new file mode 100644 index 000000000000..67039c3e0c48 --- /dev/null +++ b/arch/arm/mach-orion/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-orion/common.c b/arch/arm/mach-orion/common.c new file mode 100644 index 000000000000..e04f3f07cac0 --- /dev/null +++ b/arch/arm/mach-orion/common.c @@ -0,0 +1,53 @@ +/* + * arch/arm/mach-orion/common.c + * + * Core functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein + * + * 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 +#include +#include +#include +#include +#include "common.h" + +/***************************************************************************** + * I/O Address Mapping + ****************************************************************************/ +static struct map_desc orion_io_desc[] __initdata = { + { + .virtual = ORION_REGS_BASE, + .pfn = __phys_to_pfn(ORION_REGS_BASE), + .length = ORION_REGS_SIZE, + .type = MT_DEVICE + }, + { + .virtual = ORION_PCIE_IO_BASE, + .pfn = __phys_to_pfn(ORION_PCIE_IO_BASE), + .length = ORION_PCIE_IO_SIZE, + .type = MT_DEVICE + }, + { + .virtual = ORION_PCI_IO_BASE, + .pfn = __phys_to_pfn(ORION_PCI_IO_BASE), + .length = ORION_PCI_IO_SIZE, + .type = MT_DEVICE + }, + { + .virtual = ORION_PCIE_WA_BASE, + .pfn = __phys_to_pfn(ORION_PCIE_WA_BASE), + .length = ORION_PCIE_WA_SIZE, + .type = MT_DEVICE + }, +}; + +void __init orion_map_io(void) +{ + iotable_init(orion_io_desc, ARRAY_SIZE(orion_io_desc)); +} diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h new file mode 100644 index 000000000000..224b44618a72 --- /dev/null +++ b/arch/arm/mach-orion/common.h @@ -0,0 +1,9 @@ +#ifndef __ARCH_ORION_COMMON_H__ +#define __ARCH_ORION_COMMON_H__ + +/* + * Basic Orion init functions used early by machine-setup. + */ +void __init orion_map_io(void); + +#endif /* __ARCH_ORION_COMMON_H__ */ diff --git a/include/asm-arm/arch-orion/debug-macro.S b/include/asm-arm/arch-orion/debug-macro.S new file mode 100644 index 000000000000..e2a80641f214 --- /dev/null +++ b/include/asm-arm/arch-orion/debug-macro.S @@ -0,0 +1,17 @@ +/* + * linux/include/asm-arm/arch-orion/debug-macro.S + * + * Debugging macro include header + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + + .macro addruart,rx + mov \rx, #0xf1000000 + orr \rx, \rx, #0x00012000 + .endm + +#define UART_SHIFT 2 +#include diff --git a/include/asm-arm/arch-orion/dma.h b/include/asm-arm/arch-orion/dma.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/include/asm-arm/arch-orion/dma.h @@ -0,0 +1 @@ +/* empty */ diff --git a/include/asm-arm/arch-orion/entry-macro.S b/include/asm-arm/arch-orion/entry-macro.S new file mode 100644 index 000000000000..b76075a7e44b --- /dev/null +++ b/include/asm-arm/arch-orion/entry-macro.S @@ -0,0 +1,31 @@ +/* + * include/asm-arm/arch-orion/entry-macro.S + * + * Low-level IRQ helper macros for Orion platforms + * + * 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 + + .macro disable_fiq + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =MAIN_IRQ_CAUSE + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, [\base, #0] @ main cause + ldr \tmp, [\base, #(MAIN_IRQ_MASK - MAIN_IRQ_CAUSE)] @ main mask + mov \irqnr, #0 @ default irqnr + @ find cause bits that are unmasked + ands \irqstat, \irqstat, \tmp @ clear Z flag if any + clzne \irqnr, \irqstat @ calc irqnr + rsbne \irqnr, \irqnr, #31 + .endm diff --git a/include/asm-arm/arch-orion/hardware.h b/include/asm-arm/arch-orion/hardware.h new file mode 100644 index 000000000000..8a12d213fbdc --- /dev/null +++ b/include/asm-arm/arch-orion/hardware.h @@ -0,0 +1,24 @@ +/* + * include/asm-arm/arch-orion/hardware.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __ASM_ARCH_HARDWARE_H__ +#define __ASM_ARCH_HARDWARE_H__ + +#include "orion.h" + +#define PCI_MEMORY_VADDR ORION_PCI_SYS_MEM_BASE +#define PCI_IO_VADDR ORION_PCI_SYS_IO_BASE + +#define pcibios_assign_all_busses() 1 + +#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_MEM 0x01000000 +#define PCIMEM_BASE PCI_MEMORY_VADDR /* mem base for VGA */ + +#endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/include/asm-arm/arch-orion/io.h b/include/asm-arm/arch-orion/io.h new file mode 100644 index 000000000000..e0b8c39b9167 --- /dev/null +++ b/include/asm-arm/arch-orion/io.h @@ -0,0 +1,27 @@ +/* + * include/asm-arm/arch-orion/io.h + * + * Tzachi Perelstein + * + * 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 __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#include "orion.h" + +#define IO_SPACE_LIMIT 0xffffffff +#define IO_SPACE_REMAP ORION_PCI_SYS_IO_BASE + +static inline void __iomem *__io(unsigned long addr) +{ + return (void __iomem *)addr; +} + +#define __io(a) __io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/include/asm-arm/arch-orion/irqs.h b/include/asm-arm/arch-orion/irqs.h new file mode 100644 index 000000000000..eea65ca6076a --- /dev/null +++ b/include/asm-arm/arch-orion/irqs.h @@ -0,0 +1,61 @@ +/* + * include/asm-arm/arch-orion/irqs.h + * + * IRQ definitions for Orion SoC + * + * Maintainer: Tzachi Perelstein + * + * 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 __ASM_ARCH_IRQS_H__ +#define __ASM_ARCH_IRQS_H__ + +#include "orion.h" /* need GPIO_MAX */ + +/* + * Orion Main Interrupt Controller + */ +#define IRQ_ORION_BRIDGE 0 +#define IRQ_ORION_DOORBELL_H2C 1 +#define IRQ_ORION_DOORBELL_C2H 2 +#define IRQ_ORION_UART0 3 +#define IRQ_ORION_UART1 4 +#define IRQ_ORION_I2C 5 +#define IRQ_ORION_GPIO_0_7 6 +#define IRQ_ORION_GPIO_8_15 7 +#define IRQ_ORION_GPIO_16_23 8 +#define IRQ_ORION_GPIO_24_31 9 +#define IRQ_ORION_PCIE0_ERR 10 +#define IRQ_ORION_PCIE0_INT 11 +#define IRQ_ORION_USB1_CTRL 12 +#define IRQ_ORION_DEV_BUS_ERR 14 +#define IRQ_ORION_PCI_ERR 15 +#define IRQ_ORION_USB_BR_ERR 16 +#define IRQ_ORION_USB0_CTRL 17 +#define IRQ_ORION_ETH_RX 18 +#define IRQ_ORION_ETH_TX 19 +#define IRQ_ORION_ETH_MISC 20 +#define IRQ_ORION_ETH_SUM 21 +#define IRQ_ORION_ETH_ERR 22 +#define IRQ_ORION_IDMA_ERR 23 +#define IRQ_ORION_IDMA_0 24 +#define IRQ_ORION_IDMA_1 25 +#define IRQ_ORION_IDMA_2 26 +#define IRQ_ORION_IDMA_3 27 +#define IRQ_ORION_CESA 28 +#define IRQ_ORION_SATA 29 +#define IRQ_ORION_XOR0 30 +#define IRQ_ORION_XOR1 31 + +/* + * Orion General Purpose Pins + */ +#define IRQ_ORION_GPIO_START 32 +#define NR_GPIO_IRQS GPIO_MAX + +#define NR_IRQS (IRQ_ORION_GPIO_START + NR_GPIO_IRQS) + +#endif /* __ASM_ARCH_IRQS_H__ */ diff --git a/include/asm-arm/arch-orion/memory.h b/include/asm-arm/arch-orion/memory.h new file mode 100644 index 000000000000..d954dba87ced --- /dev/null +++ b/include/asm-arm/arch-orion/memory.h @@ -0,0 +1,15 @@ +/* + * include/asm-arm/arch-orion/memory.h + * + * Marvell Orion memory definitions + */ + +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +#define PHYS_OFFSET UL(0x00000000) + +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif diff --git a/include/asm-arm/arch-orion/orion.h b/include/asm-arm/arch-orion/orion.h new file mode 100644 index 000000000000..061c03c5a17e --- /dev/null +++ b/include/asm-arm/arch-orion/orion.h @@ -0,0 +1,140 @@ +/* + * include/asm-arm/arch-orion/orion.h + * + * Generic definitions of Orion SoC flavors: + * Orion-1, Orion-NAS, Orion-VoIP, and Orion-2. + * + * Maintainer: Tzachi Perelstein + * + * 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 __ASM_ARCH_ORION_H__ +#define __ASM_ARCH_ORION_H__ + +/******************************************************************************* + * Orion Address Map + * Use the same mapping (1:1 virtual:physical) of internal registers and + * PCI system (PCI+PCIE) for all machines. + * Each machine defines the rest of its mapping (e.g. device bus flashes) + ******************************************************************************/ +#define ORION_REGS_BASE 0xf1000000 +#define ORION_REGS_SIZE SZ_1M + +#define ORION_PCI_SYS_MEM_BASE 0xe0000000 +#define ORION_PCIE_MEM_BASE ORION_PCI_SYS_MEM_BASE +#define ORION_PCIE_MEM_SIZE SZ_128M +#define ORION_PCI_MEM_BASE (ORION_PCIE_MEM_BASE + ORION_PCIE_MEM_SIZE) +#define ORION_PCI_MEM_SIZE SZ_128M + +#define ORION_PCI_SYS_IO_BASE 0xf2000000 +#define ORION_PCIE_IO_BASE ORION_PCI_SYS_IO_BASE +#define ORION_PCIE_IO_SIZE SZ_1M +#define ORION_PCIE_IO_REMAP (ORION_PCIE_IO_BASE - ORION_PCI_SYS_IO_BASE) +#define ORION_PCI_IO_BASE (ORION_PCIE_IO_BASE + ORION_PCIE_IO_SIZE) +#define ORION_PCI_IO_SIZE SZ_1M +#define ORION_PCI_IO_REMAP (ORION_PCI_IO_BASE - ORION_PCI_SYS_IO_BASE) +/* Relevant only for Orion-NAS */ +#define ORION_PCIE_WA_BASE 0xf0000000 +#define ORION_PCIE_WA_SIZE SZ_16M + +/******************************************************************************* + * Supported Devices & Revisions + ******************************************************************************/ +/* Orion-NAS (88F5182) */ +#define MV88F5182_DEV_ID 0x5182 +#define MV88F5182_REV_A2 2 +/* Orion-2 (88F5281) */ +#define MV88F5281_DEV_ID 0x5281 +#define MV88F5281_REV_D1 5 +#define MV88F5281_REV_D2 6 + +/******************************************************************************* + * Orion Registers Map + ******************************************************************************/ +#define ORION_DDR_REG_BASE (ORION_REGS_BASE | 0x00000) +#define ORION_DEV_BUS_REG_BASE (ORION_REGS_BASE | 0x10000) +#define ORION_BRIDGE_REG_BASE (ORION_REGS_BASE | 0x20000) +#define ORION_PCI_REG_BASE (ORION_REGS_BASE | 0x30000) +#define ORION_PCIE_REG_BASE (ORION_REGS_BASE | 0x40000) +#define ORION_USB0_REG_BASE (ORION_REGS_BASE | 0x50000) +#define ORION_ETH_REG_BASE (ORION_REGS_BASE | 0x70000) +#define ORION_SATA_REG_BASE (ORION_REGS_BASE | 0x80000) +#define ORION_USB1_REG_BASE (ORION_REGS_BASE | 0xa0000) + +#define ORION_DDR_REG(x) (ORION_DDR_REG_BASE | (x)) +#define ORION_DEV_BUS_REG(x) (ORION_DEV_BUS_REG_BASE | (x)) +#define ORION_BRIDGE_REG(x) (ORION_BRIDGE_REG_BASE | (x)) +#define ORION_PCI_REG(x) (ORION_PCI_REG_BASE | (x)) +#define ORION_PCIE_REG(x) (ORION_PCIE_REG_BASE | (x)) +#define ORION_USB0_REG(x) (ORION_USB0_REG_BASE | (x)) +#define ORION_USB1_REG(x) (ORION_USB1_REG_BASE | (x)) +#define ORION_ETH_REG(x) (ORION_ETH_REG_BASE | (x)) +#define ORION_SATA_REG(x) (ORION_SATA_REG_BASE | (x)) + +/******************************************************************************* + * Device Bus Registers + ******************************************************************************/ +#define MPP_0_7_CTRL ORION_DEV_BUS_REG(0x000) +#define MPP_8_15_CTRL ORION_DEV_BUS_REG(0x004) +#define MPP_16_19_CTRL ORION_DEV_BUS_REG(0x050) +#define MPP_DEV_CTRL ORION_DEV_BUS_REG(0x008) +#define MPP_RESET_SAMPLE ORION_DEV_BUS_REG(0x010) +#define GPIO_OUT ORION_DEV_BUS_REG(0x100) +#define GPIO_IO_CONF ORION_DEV_BUS_REG(0x104) +#define GPIO_BLINK_EN ORION_DEV_BUS_REG(0x108) +#define GPIO_IN_POL ORION_DEV_BUS_REG(0x10c) +#define GPIO_DATA_IN ORION_DEV_BUS_REG(0x110) +#define GPIO_EDGE_CAUSE ORION_DEV_BUS_REG(0x114) +#define GPIO_EDGE_MASK ORION_DEV_BUS_REG(0x118) +#define GPIO_LEVEL_MASK ORION_DEV_BUS_REG(0x11c) +#define DEV_BANK_0_PARAM ORION_DEV_BUS_REG(0x45c) +#define DEV_BANK_1_PARAM ORION_DEV_BUS_REG(0x460) +#define DEV_BANK_2_PARAM ORION_DEV_BUS_REG(0x464) +#define DEV_BANK_BOOT_PARAM ORION_DEV_BUS_REG(0x46c) +#define DEV_BUS_CTRL ORION_DEV_BUS_REG(0x4c0) +#define DEV_BUS_INT_CAUSE ORION_DEV_BUS_REG(0x4d0) +#define DEV_BUS_INT_MASK ORION_DEV_BUS_REG(0x4d4) +#define I2C_BASE ORION_DEV_BUS_REG(0x1000) +#define UART0_BASE ORION_DEV_BUS_REG(0x2000) +#define UART1_BASE ORION_DEV_BUS_REG(0x2100) +#define GPIO_MAX 32 + +/*************************************************************************** + * Orion CPU Bridge Registers + **************************************************************************/ +#define CPU_CONF ORION_BRIDGE_REG(0x100) +#define CPU_CTRL ORION_BRIDGE_REG(0x104) +#define CPU_RESET_MASK ORION_BRIDGE_REG(0x108) +#define CPU_SOFT_RESET ORION_BRIDGE_REG(0x10c) +#define POWER_MNG_CTRL_REG ORION_BRIDGE_REG(0x11C) +#define BRIDGE_CAUSE ORION_BRIDGE_REG(0x110) +#define BRIDGE_MASK ORION_BRIDGE_REG(0x114) +#define MAIN_IRQ_CAUSE ORION_BRIDGE_REG(0x200) +#define MAIN_IRQ_MASK ORION_BRIDGE_REG(0x204) +#define TIMER_CTRL ORION_BRIDGE_REG(0x300) +#define TIMER_VAL(x) ORION_BRIDGE_REG(0x314 + ((x) * 8)) +#define TIMER_VAL_RELOAD(x) ORION_BRIDGE_REG(0x310 + ((x) * 8)) + +#ifndef __ASSEMBLY__ + +/******************************************************************************* + * Helpers to access Orion registers + ******************************************************************************/ +#include +#include + +#define orion_read(r) __raw_readl(r) +#define orion_write(r, val) __raw_writel(val, r) + +/* + * These are not preempt safe. Locks, if needed, must be taken care by caller. + */ +#define orion_setbits(r, mask) orion_write((r), orion_read(r) | (mask)) +#define orion_clrbits(r, mask) orion_write((r), orion_read(r) & ~(mask)) + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARCH_ORION_H__ */ diff --git a/include/asm-arm/arch-orion/system.h b/include/asm-arm/arch-orion/system.h new file mode 100644 index 000000000000..17704c68f90e --- /dev/null +++ b/include/asm-arm/arch-orion/system.h @@ -0,0 +1,31 @@ +/* + * include/asm-arm/arch-orion/system.h + * + * Tzachi Perelstein + * + * 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 __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + /* + * Enable and issue soft reset + */ + orion_setbits(CPU_RESET_MASK, (1 << 2)); + orion_setbits(CPU_SOFT_RESET, 1); +} + +#endif diff --git a/include/asm-arm/arch-orion/timex.h b/include/asm-arm/arch-orion/timex.h new file mode 100644 index 000000000000..26c2c91eecf0 --- /dev/null +++ b/include/asm-arm/arch-orion/timex.h @@ -0,0 +1,12 @@ +/* + * include/asm-arm/arch-orion/timex.h + * + * Tzachi Perelstein + * + * 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. + */ + +#define ORION_TCLK 166666667 +#define CLOCK_TICK_RATE ORION_TCLK diff --git a/include/asm-arm/arch-orion/uncompress.h b/include/asm-arm/arch-orion/uncompress.h new file mode 100644 index 000000000000..a1a222fb438c --- /dev/null +++ b/include/asm-arm/arch-orion/uncompress.h @@ -0,0 +1,44 @@ +/* + * include/asm-arm/arch-orion/uncompress.h + * + * Tzachi Perelstein + * + * 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 + +#define MV_UART_LSR ((volatile unsigned char *)(UART0_BASE + 0x14)) +#define MV_UART_THR ((volatile unsigned char *)(UART0_BASE + 0x0)) + +#define LSR_THRE 0x20 + +static void putc(const char c) +{ + int j = 0x1000; + while (--j && !(*MV_UART_LSR & LSR_THRE)) + barrier(); + *MV_UART_THR = c; +} + +static void flush(void) +{ +} + +static void orion_early_putstr(const char *ptr) +{ + char c; + while ((c = *ptr++) != '\0') { + if (c == '\n') + putc('\r'); + putc(c); + } +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-orion/vmalloc.h b/include/asm-arm/arch-orion/vmalloc.h new file mode 100644 index 000000000000..23e2a102fe0c --- /dev/null +++ b/include/asm-arm/arch-orion/vmalloc.h @@ -0,0 +1,5 @@ +/* + * include/asm-arm/arch-orion/vmalloc.h + */ + +#define VMALLOC_END 0xf0000000 -- cgit v1.2.3-55-g7522 From 038ee0832ee1b1e2bd2be4599cd535ea9aaaf658 Mon Sep 17 00:00:00 2001 From: Tzachi Perelstein Date: Tue, 23 Oct 2007 15:14:42 -0400 Subject: [ARM] Orion: PCI support This patch adds support for PCI and PCI-E controllers in the Orion, Orion-NAS and Orion2. Signed-off-by: Tzachi Perelstein Reviewed-by: Nicolas Pitre Reviewed-by: Lennert Buytenhek Acked-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-orion/Makefile | 2 +- arch/arm/mach-orion/common.h | 17 ++ arch/arm/mach-orion/pci.c | 557 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-orion/pci.c (limited to 'arch/arm/Kconfig') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 036239150ff8..37aa3c606c0c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -336,6 +336,7 @@ config ARCH_MXC config ARCH_ORION bool "Marvell Orion" depends on MMU + select PCI help Support for Marvell Orion System on Chip family. diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile index 69eb30187738..2937f05b868e 100644 --- a/arch/arm/mach-orion/Makefile +++ b/arch/arm/mach-orion/Makefile @@ -1 +1 @@ -obj-y += common.o +obj-y += common.o pci.o diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h index 224b44618a72..02d0fec44a40 100644 --- a/arch/arm/mach-orion/common.h +++ b/arch/arm/mach-orion/common.h @@ -6,4 +6,21 @@ */ void __init orion_map_io(void); +/* + * Shared code used internally by other Orion core functions. + * (/mach-orion/pci.c) + */ + +struct pci_sys_data; +struct pci_bus; + +void orion_pcie_id(u32 *dev, u32 *rev); +u32 orion_pcie_local_bus_nr(void); +u32 orion_pci_local_bus_nr(void); +u32 orion_pci_local_dev_nr(void); +int orion_pci_sys_setup(int nr, struct pci_sys_data *sys); +struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); +int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val); +int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val); + #endif /* __ARCH_ORION_COMMON_H__ */ diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c new file mode 100644 index 000000000000..cf569c647112 --- /dev/null +++ b/arch/arm/mach-orion/pci.c @@ -0,0 +1,557 @@ +/* + * arch/arm/mach-orion/pci.c + * + * PCI and PCIE functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein + * + * 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 +#include +#include +#include "common.h" + +/***************************************************************************** + * Orion has one PCIE controller and one PCI controller. + * + * Note1: The local PCIE bus number is '0'. The local PCI bus number + * follows the scanned PCIE bridged busses, if any. + * + * Note2: It is possible for PCI/PCIE agents to access many subsystem's + * space, by configuring BARs and Address Decode Windows, e.g. flashes on + * device bus, Orion registers, etc. However this code only enable the + * access to DDR banks. + ****************************************************************************/ + + +/***************************************************************************** + * PCIE controller + ****************************************************************************/ +#define PCIE_CTRL ORION_PCIE_REG(0x1a00) +#define PCIE_STAT ORION_PCIE_REG(0x1a04) +#define PCIE_DEV_ID ORION_PCIE_REG(0x0000) +#define PCIE_CMD_STAT ORION_PCIE_REG(0x0004) +#define PCIE_DEV_REV ORION_PCIE_REG(0x0008) +#define PCIE_MASK ORION_PCIE_REG(0x1910) +#define PCIE_CONF_ADDR ORION_PCIE_REG(0x18f8) +#define PCIE_CONF_DATA ORION_PCIE_REG(0x18fc) + +/* + * PCIE_STAT bits + */ +#define PCIE_STAT_LINK_DOWN 1 +#define PCIE_STAT_BUS_OFFS 8 +#define PCIE_STAT_BUS_MASK (0xff << PCIE_STAT_BUS_OFFS) +#define PCIE_STAT_DEV_OFFS 20 +#define PCIE_STAT_DEV_MASK (0x1f << PCIE_STAT_DEV_OFFS) + +/* + * PCIE_CONF_ADDR bits + */ +#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 24) | ((r) & 0xfc)) +#define PCIE_CONF_FUNC(f) (((f) & 0x3) << 8) +#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11) +#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16) +#define PCIE_CONF_ADDR_EN (1 << 31) + +/* + * PCIE config cycles are done by programming the PCIE_CONF_ADDR register + * and then reading the PCIE_CONF_DATA register. Need to make sure these + * transactions are atomic. + */ +static DEFINE_SPINLOCK(orion_pcie_lock); + +void orion_pcie_id(u32 *dev, u32 *rev) +{ + *dev = orion_read(PCIE_DEV_ID) >> 16; + *rev = orion_read(PCIE_DEV_REV) & 0xff; +} + +u32 orion_pcie_local_bus_nr(void) +{ + u32 stat = orion_read(PCIE_STAT); + return((stat & PCIE_STAT_BUS_MASK) >> PCIE_STAT_BUS_OFFS); +} + +static u32 orion_pcie_local_dev_nr(void) +{ + u32 stat = orion_read(PCIE_STAT); + return((stat & PCIE_STAT_DEV_MASK) >> PCIE_STAT_DEV_OFFS); +} + +static u32 orion_pcie_no_link(void) +{ + u32 stat = orion_read(PCIE_STAT); + return(stat & PCIE_STAT_LINK_DOWN); +} + +static void orion_pcie_set_bus_nr(int nr) +{ + orion_clrbits(PCIE_STAT, PCIE_STAT_BUS_MASK); + orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS); +} + +static void orion_pcie_master_slave_enable(void) +{ + orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER | + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY); +} + +static void orion_pcie_enable_interrupts(void) +{ + /* + * Enable interrupts lines + * INTA[24] INTB[25] INTC[26] INTD[27] + */ + orion_setbits(PCIE_MASK, 0xf<<24); +} + +static int orion_pcie_valid_config(u32 bus, u32 dev) +{ + /* + * Don't go out when trying to access -- + * 1. our own device + * 2. where there's no device connected (no link) + * 3. nonexisting devices on local bus + */ + + if ((orion_pcie_local_bus_nr() == bus) && + (orion_pcie_local_dev_nr() == dev)) + return 0; + + if (orion_pcie_no_link()) + return 0; + + if (bus == orion_pcie_local_bus_nr()) + if (((orion_pcie_local_dev_nr() == 0) && (dev != 1)) || + ((orion_pcie_local_dev_nr() != 0) && (dev != 0))) + return 0; + + return 1; +} + +static int orion_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, + int size, u32 *val) +{ + unsigned long flags; + unsigned int dev, rev, pcie_addr; + + if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + spin_lock_irqsave(&orion_pcie_lock, flags); + + orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN); + + orion_pcie_id(&dev, &rev); + if (dev == MV88F5182_DEV_ID) { + /* extended register space */ + pcie_addr = ORION_PCIE_WA_BASE; + pcie_addr |= PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where); + *val = orion_read(pcie_addr); + } else + *val = orion_read(PCIE_CONF_DATA); + + if (size == 1) + *val = (*val >> (8*(where & 0x3))) & 0xff; + else if (size == 2) + *val = (*val >> (8*(where & 0x3))) & 0xffff; + + spin_unlock_irqrestore(&orion_pcie_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + + +static int orion_pcie_wr_conf(struct pci_bus *bus, u32 devfn, int where, + int size, u32 val) +{ + unsigned long flags; + int ret; + + if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + spin_lock_irqsave(&orion_pcie_lock, flags); + + ret = PCIBIOS_SUCCESSFUL; + + orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) | + PCIE_CONF_DEV(PCI_SLOT(devfn)) | + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN); + + if (size == 4) { + __raw_writel(val, PCIE_CONF_DATA); + } else if (size == 2) { + __raw_writew(val, PCIE_CONF_DATA + (where & 0x3)); + } else if (size == 1) { + __raw_writeb(val, PCIE_CONF_DATA + (where & 0x3)); + } else { + ret = PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&orion_pcie_lock, flags); + + return ret; +} + +struct pci_ops orion_pcie_ops = { + .read = orion_pcie_rd_conf, + .write = orion_pcie_wr_conf, +}; + + +static int orion_pcie_setup(struct pci_sys_data *sys) +{ + struct resource *res; + + /* + * Master + Slave enable + */ + orion_pcie_master_slave_enable(); + + /* + * Enable interrupts lines A-D + */ + orion_pcie_enable_interrupts(); + + /* + * Request resource + */ + res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); + if (!res) + panic("orion_pci_setup unable to alloc resources"); + + /* + * IORESOURCE_IO + */ + res[0].name = "PCI-EX I/O Space"; + res[0].flags = IORESOURCE_IO; + res[0].start = ORION_PCIE_IO_REMAP; + res[0].end = res[0].start + ORION_PCIE_IO_SIZE - 1; + if (request_resource(&ioport_resource, &res[0])) + panic("Request PCIE IO resource failed\n"); + sys->resource[0] = &res[0]; + + /* + * IORESOURCE_MEM + */ + res[1].name = "PCI-EX Memory Space"; + res[1].flags = IORESOURCE_MEM; + res[1].start = ORION_PCIE_MEM_BASE; + res[1].end = res[1].start + ORION_PCIE_MEM_SIZE - 1; + if (request_resource(&iomem_resource, &res[1])) + panic("Request PCIE Memory resource failed\n"); + sys->resource[1] = &res[1]; + + sys->resource[2] = NULL; + sys->io_offset = 0; + + return 1; +} + +/***************************************************************************** + * PCI controller + ****************************************************************************/ +#define PCI_MODE ORION_PCI_REG(0xd00) +#define PCI_CMD ORION_PCI_REG(0xc00) +#define PCI_P2P_CONF ORION_PCI_REG(0x1d14) +#define PCI_CONF_ADDR ORION_PCI_REG(0xc78) +#define PCI_CONF_DATA ORION_PCI_REG(0xc7c) + +/* + * PCI_MODE bits + */ +#define PCI_MODE_64BIT (1 << 2) +#define PCI_MODE_PCIX ((1 << 4) | (1 << 5)) + +/* + * PCI_CMD bits + */ +#define PCI_CMD_HOST_REORDER (1 << 29) + +/* + * PCI_P2P_CONF bits + */ +#define PCI_P2P_BUS_OFFS 16 +#define PCI_P2P_BUS_MASK (0xff << PCI_P2P_BUS_OFFS) +#define PCI_P2P_DEV_OFFS 24 +#define PCI_P2P_DEV_MASK (0x1f << PCI_P2P_DEV_OFFS) + +/* + * PCI_CONF_ADDR bits + */ +#define PCI_CONF_REG(reg) ((reg) & 0xfc) +#define PCI_CONF_FUNC(func) (((func) & 0x3) << 8) +#define PCI_CONF_DEV(dev) (((dev) & 0x1f) << 11) +#define PCI_CONF_BUS(bus) (((bus) & 0xff) << 16) +#define PCI_CONF_ADDR_EN (1 << 31) + +/* + * Internal configuration space + */ +#define PCI_CONF_FUNC_STAT_CMD 0 +#define PCI_CONF_REG_STAT_CMD 4 +#define PCIX_STAT 0x64 +#define PCIX_STAT_BUS_OFFS 8 +#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS) + +/* + * PCI config cycles are done by programming the PCI_CONF_ADDR register + * and then reading the PCI_CONF_DATA register. Need to make sure these + * transactions are atomic. + */ +static DEFINE_SPINLOCK(orion_pci_lock); + +u32 orion_pci_local_bus_nr(void) +{ + u32 conf = orion_read(PCI_P2P_CONF); + return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); +} + +u32 orion_pci_local_dev_nr(void) +{ + u32 conf = orion_read(PCI_P2P_CONF); + return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS); +} + +int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, + u32 where, u32 size, u32 *val) +{ + unsigned long flags; + spin_lock_irqsave(&orion_pci_lock, flags); + + orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) | + PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | + PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN); + + *val = orion_read(PCI_CONF_DATA); + + if (size == 1) + *val = (*val >> (8*(where & 0x3))) & 0xff; + else if (size == 2) + *val = (*val >> (8*(where & 0x3))) & 0xffff; + + spin_unlock_irqrestore(&orion_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, + u32 where, u32 size, u32 val) +{ + unsigned long flags; + int ret = PCIBIOS_SUCCESSFUL; + + spin_lock_irqsave(&orion_pci_lock, flags); + + orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) | + PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | + PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN); + + if (size == 4) { + __raw_writel(val, PCI_CONF_DATA); + } else if (size == 2) { + __raw_writew(val, PCI_CONF_DATA + (where & 0x3)); + } else if (size == 1) { + __raw_writeb(val, PCI_CONF_DATA + (where & 0x3)); + } else { + ret = PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&orion_pci_lock, flags); + + return ret; +} + +static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 *val) +{ + /* + * Don't go out for local device + */ + if ((orion_pci_local_bus_nr() == bus->number) && + (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return orion_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where, size, val); +} + +static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 val) +{ + /* + * Don't go out for local device + */ + if ((orion_pci_local_bus_nr() == bus->number) && + (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) + return PCIBIOS_DEVICE_NOT_FOUND; + + return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where, size, val); +} + +struct pci_ops orion_pci_ops = { + .read = orion_pci_rd_conf, + .write = orion_pci_wr_conf, +}; + +static void orion_pci_set_bus_nr(int nr) +{ + u32 p2p = orion_read(PCI_P2P_CONF); + + if (orion_read(PCI_MODE) & PCI_MODE_PCIX) { + /* + * PCI-X mode + */ + u32 pcix_status, bus, dev; + bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS; + dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS; + orion_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status); + pcix_status &= ~PCIX_STAT_BUS_MASK; + pcix_status |= (nr << PCIX_STAT_BUS_OFFS); + orion_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status); + } else { + /* + * PCI Conventional mode + */ + p2p &= ~PCI_P2P_BUS_MASK; + p2p |= (nr << PCI_P2P_BUS_OFFS); + orion_write(PCI_P2P_CONF, p2p); + } +} + +static void orion_pci_master_slave_enable(void) +{ + u32 bus_nr, dev_nr, func, reg, val; + + bus_nr = orion_pci_local_bus_nr(); + dev_nr = orion_pci_local_dev_nr(); + func = PCI_CONF_FUNC_STAT_CMD; + reg = PCI_CONF_REG_STAT_CMD; + orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val); + val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7); +} + +static int orion_pci_setup(struct pci_sys_data *sys) +{ + struct resource *res; + + /* + * Master + Slave enable + */ + orion_pci_master_slave_enable(); + + /* + * Force ordering + */ + orion_setbits(PCI_CMD, PCI_CMD_HOST_REORDER); + + /* + * Request resources + */ + res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); + if (!res) + panic("orion_pci_setup unable to alloc resources"); + + /* + * IORESOURCE_IO + */ + res[0].name = "PCI I/O Space"; + res[0].flags = IORESOURCE_IO; + res[0].start = ORION_PCI_IO_REMAP; + res[0].end = res[0].start + ORION_PCI_IO_SIZE - 1; + if (request_resource(&ioport_resource, &res[0])) + panic("Request PCI IO resource failed\n"); + sys->resource[0] = &res[0]; + + /* + * IORESOURCE_MEM + */ + res[1].name = "PCI Memory Space"; + res[1].flags = IORESOURCE_MEM; + res[1].start = ORION_PCI_MEM_BASE; + res[1].end = res[1].start + ORION_PCI_MEM_SIZE - 1; + if (request_resource(&iomem_resource, &res[1])) + panic("Request PCI Memory resource failed\n"); + sys->resource[1] = &res[1]; + + sys->resource[2] = NULL; + sys->io_offset = 0; + + return 1; +} + + +/***************************************************************************** + * General PCIE + PCI + ****************************************************************************/ +int orion_pci_sys_setup(int nr, struct pci_sys_data *sys) +{ + int ret = 0; + + if (nr == 0) { + /* + * PCIE setup + */ + orion_pcie_set_bus_nr(0); + ret = orion_pcie_setup(sys); + } else if (nr == 1) { + /* + * PCI setup + */ + ret = orion_pci_setup(sys); + } + + return ret; +} + +struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys) +{ + struct pci_ops *ops; + struct pci_bus *bus; + + + if (nr == 0) { + u32 pci_bus; + /* + * PCIE scan + */ + ops = &orion_pcie_ops; + bus = pci_scan_bus(sys->busnr, ops, sys); + /* + * Set local PCI bus number to follow PCIE bridges (if any) + */ + pci_bus = bus->number + bus->subordinate - bus->secondary + 1; + orion_pci_set_bus_nr(pci_bus); + } else if (nr == 1) { + /* + * PCI scan + */ + ops = &orion_pci_ops; + bus = pci_scan_bus(sys->busnr, ops, sys); + } else { + BUG(); + bus = NULL; + } + + return bus; +} -- cgit v1.2.3-55-g7522 From 01af72e4e36fba66cd7cfc2a628efee866c346d1 Mon Sep 17 00:00:00 2001 From: Tzachi Perelstein Date: Tue, 23 Oct 2007 15:14:42 -0400 Subject: [ARM] Orion: GPIO support Signed-off-by: Tzachi Perelstein Signed-off-by: Nicolas Pitre Acked-by: David Brownell --- arch/arm/Kconfig | 1 + arch/arm/mach-orion/Makefile | 2 +- arch/arm/mach-orion/common.h | 8 ++ arch/arm/mach-orion/gpio.c | 206 ++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-orion/gpio.h | 27 +++++ 5 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-orion/gpio.c create mode 100644 include/asm-arm/arch-orion/gpio.h (limited to 'arch/arm/Kconfig') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 37aa3c606c0c..71e905ebcc05 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -337,6 +337,7 @@ config ARCH_ORION bool "Marvell Orion" depends on MMU select PCI + select GENERIC_GPIO help Support for Marvell Orion System on Chip family. diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile index 1d4b5570067e..d6a6c86faafc 100644 --- a/arch/arm/mach-orion/Makefile +++ b/arch/arm/mach-orion/Makefile @@ -1 +1 @@ -obj-y += common.o addr-map.o pci.o +obj-y += common.o addr-map.o pci.o gpio.o diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h index 056043464ca1..a6a7af189b0e 100644 --- a/arch/arm/mach-orion/common.h +++ b/arch/arm/mach-orion/common.h @@ -53,4 +53,12 @@ struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val); int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val); +/* + * Valid GPIO pins according to MPP setup, used by machine-setup. + * (/mach-orion/gpio.c). + */ + +void __init orion_gpio_set_valid_pins(u32 pins); +void gpio_display(void); /* debug */ + #endif /* __ARCH_ORION_COMMON_H__ */ diff --git a/arch/arm/mach-orion/gpio.c b/arch/arm/mach-orion/gpio.c new file mode 100644 index 000000000000..af8553ccd230 --- /dev/null +++ b/arch/arm/mach-orion/gpio.c @@ -0,0 +1,206 @@ +/* + * arch/arm/mach-orion/gpio.c + * + * GPIO functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein + * + * 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 +#include +#include +#include +#include +#include +#include +#include "common.h" + +static DEFINE_SPINLOCK(gpio_lock); +static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; +static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ + +void __init orion_gpio_set_valid_pins(u32 pins) +{ + gpio_valid[0] = pins; +} + +/* + * GENERIC_GPIO primitives + */ +int gpio_direction_input(unsigned pin) +{ + unsigned long flags; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might have not used the gpio_request(), + * so flag this pin as requested now. + */ + if (!gpio_label[pin]) + gpio_label[pin] = "?"; + + orion_setbits(GPIO_IO_CONF, 1 << pin); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned pin, int value) +{ + unsigned long flags; + int mask; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might have not used the gpio_request(), + * so flag this pin as requested now. + */ + if (!gpio_label[pin]) + gpio_label[pin] = "?"; + + mask = 1 << pin; + if (value) + orion_setbits(GPIO_OUT, mask); + else + orion_clrbits(GPIO_OUT, mask); + orion_clrbits(GPIO_IO_CONF, mask); + + spin_unlock_irqrestore(&gpio_lock, flags); + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned pin) +{ + int val, mask = 1 << pin; + + if (orion_read(GPIO_IO_CONF) & mask) + val = orion_read(GPIO_DATA_IN); + else + val = orion_read(GPIO_OUT); + + return val & mask; +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned pin, int value) +{ + unsigned long flags; + int mask = 1 << pin; + + spin_lock_irqsave(&gpio_lock, flags); + + if (value) + orion_setbits(GPIO_OUT, mask); + else + orion_clrbits(GPIO_OUT, mask); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(gpio_set_value); + +int gpio_request(unsigned pin, const char *label) +{ + int ret = 0; + unsigned long flags; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + if (gpio_label[pin]) { + pr_debug("%s: GPIO %d already used as %s\n", + __FUNCTION__, pin, gpio_label[pin]); + ret = -EBUSY; + } else + gpio_label[pin] = label ? label : "?"; + + spin_unlock_irqrestore(&gpio_lock, flags); + return ret; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned pin) +{ + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin); + return; + } + + if (!gpio_label[pin]) + pr_warning("%s: GPIO %d already freed\n", __FUNCTION__, pin); + else + gpio_label[pin] = NULL; +} +EXPORT_SYMBOL(gpio_free); + +/* Debug helper */ +void gpio_display(void) +{ + int i; + + for (i = 0; i < GPIO_MAX; i++) { + printk(KERN_DEBUG "Pin-%d: ", i); + + if (!test_bit(i, gpio_valid)) { + printk("non-GPIO\n"); + } else if (!gpio_label[i]) { + printk("GPIO, free\n"); + } else { + printk("GPIO, used by %s, ", gpio_label[i]); + if (orion_read(GPIO_IO_CONF) & (1 << i)) { + printk("input, active %s, level %s, edge %s\n", + ((orion_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high", + ((orion_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked", + ((orion_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked"); + } else { + printk("output, val=%d\n", (orion_read(GPIO_OUT) >> i) & 1); + } + } + } + + printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n", + MPP_0_7_CTRL, orion_read(MPP_0_7_CTRL)); + printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n", + MPP_8_15_CTRL, orion_read(MPP_8_15_CTRL)); + printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n", + MPP_16_19_CTRL, orion_read(MPP_16_19_CTRL)); + printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n", + MPP_DEV_CTRL, orion_read(MPP_DEV_CTRL)); + printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n", + GPIO_OUT, orion_read(GPIO_OUT)); + printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n", + GPIO_IO_CONF, orion_read(GPIO_IO_CONF)); + printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n", + GPIO_BLINK_EN, orion_read(GPIO_BLINK_EN)); + printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n", + GPIO_IN_POL, orion_read(GPIO_IN_POL)); + printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n", + GPIO_DATA_IN, orion_read(GPIO_DATA_IN)); + printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n", + GPIO_LEVEL_MASK, orion_read(GPIO_LEVEL_MASK)); + printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n", + GPIO_EDGE_CAUSE, orion_read(GPIO_EDGE_CAUSE)); + printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n", + GPIO_EDGE_MASK, orion_read(GPIO_EDGE_MASK)); +} diff --git a/include/asm-arm/arch-orion/gpio.h b/include/asm-arm/arch-orion/gpio.h new file mode 100644 index 000000000000..6d5848ed9a39 --- /dev/null +++ b/include/asm-arm/arch-orion/gpio.h @@ -0,0 +1,27 @@ +/* + * include/asm-arm/arch-orion/gpio.h + * + * 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. + */ + +extern int gpio_request(unsigned pin, const char *label); +extern void gpio_free(unsigned pin); +extern int gpio_direction_input(unsigned pin); +extern int gpio_direction_output(unsigned pin, int value); +extern int gpio_get_value(unsigned pin); +extern void gpio_set_value(unsigned pin, int value); +extern void gpio_display(void); /* debug */ + +static inline int gpio_to_irq(int pin) +{ + return pin + IRQ_ORION_GPIO_START; +} + +static inline int irq_to_gpio(int irq) +{ + return irq - IRQ_ORION_GPIO_START; +} + +#include /* cansleep wrappers */ -- cgit v1.2.3-55-g7522 From 51cbff1d6f1946f97b847f9a144737eca20ede84 Mon Sep 17 00:00:00 2001 From: Tzachi Perelstein Date: Tue, 23 Oct 2007 15:14:42 -0400 Subject: [ARM] Orion: system timer support Signed-off-by: Tzachi Perelstein Reviewed-by: Nicolas Pitre Reviewed-by: Lennert Buytenhek Acked-by: Russell King --- arch/arm/Kconfig | 2 + arch/arm/mach-orion/Makefile | 2 +- arch/arm/mach-orion/common.h | 5 ++ arch/arm/mach-orion/time.c | 181 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-orion/time.c (limited to 'arch/arm/Kconfig') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 71e905ebcc05..20084f273d8e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -338,6 +338,8 @@ config ARCH_ORION depends on MMU select PCI select GENERIC_GPIO + select GENERIC_TIME + select GENERIC_CLOCKEVENTS help Support for Marvell Orion System on Chip family. diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile index 57d459a2090e..3b2a3eef39dd 100644 --- a/arch/arm/mach-orion/Makefile +++ b/arch/arm/mach-orion/Makefile @@ -1 +1 @@ -obj-y += common.o addr-map.o pci.o gpio.o irq.o +obj-y += common.o addr-map.o pci.o gpio.o irq.o time.o diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h index 155371e1d672..2b452facadd1 100644 --- a/arch/arm/mach-orion/common.h +++ b/arch/arm/mach-orion/common.h @@ -62,4 +62,9 @@ int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 va void __init orion_gpio_set_valid_pins(u32 pins); void gpio_display(void); /* debug */ +/* + * Orion system timer (clocksource + clockevnt, /mach-orion/time.c) + */ +extern struct sys_timer orion_timer; + #endif /* __ARCH_ORION_COMMON_H__ */ diff --git a/arch/arm/mach-orion/time.c b/arch/arm/mach-orion/time.c new file mode 100644 index 000000000000..bd4262da4f40 --- /dev/null +++ b/arch/arm/mach-orion/time.c @@ -0,0 +1,181 @@ +/* + * arch/arm/mach-orion/time.c + * + * Core time functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein + * + * 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 +#include +#include +#include +#include +#include +#include "common.h" + +/* + * Timer0: clock_event_device, Tick. + * Timer1: clocksource, Free running. + * WatchDog: Not used. + * + * Timers are counting down. + */ +#define CLOCKEVENT 0 +#define CLOCKSOURCE 1 + +/* + * Timers bits + */ +#define BRIDGE_INT_TIMER(x) (1 << ((x) + 1)) +#define TIMER_EN(x) (1 << ((x) * 2)) +#define TIMER_RELOAD_EN(x) (1 << (((x) * 2) + 1)) +#define BRIDGE_INT_TIMER_WD (1 << 3) +#define TIMER_WD_EN (1 << 4) +#define TIMER_WD_RELOAD_EN (1 << 5) + +static cycle_t orion_clksrc_read(void) +{ + return (0xffffffff - orion_read(TIMER_VAL(CLOCKSOURCE))); +} + +static struct clocksource orion_clksrc = { + .name = "orion_clocksource", + .shift = 20, + .rating = 300, + .read = orion_clksrc_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int +orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) +{ + unsigned long flags; + + if (delta == 0) + return -ETIME; + + local_irq_save(flags); + + /* + * Clear and enable timer interrupt bit + */ + orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); + + /* + * Setup new timer value + */ + orion_write(TIMER_VAL(CLOCKEVENT), delta); + + /* + * Disable auto reload and kickoff the timer + */ + orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT)); + orion_setbits(TIMER_CTRL, TIMER_EN(CLOCKEVENT)); + + local_irq_restore(flags); + + return 0; +} + +static void +orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + + if (mode == CLOCK_EVT_MODE_PERIODIC) { + /* + * Setup latch cycles in timer and enable reload interrupt. + */ + orion_write(TIMER_VAL_RELOAD(CLOCKEVENT), LATCH); + orion_write(TIMER_VAL(CLOCKEVENT), LATCH); + orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) | + TIMER_EN(CLOCKEVENT)); + } else { + /* + * Disable timer and interrupt + */ + orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) | + TIMER_EN(CLOCKEVENT)); + } + + local_irq_restore(flags); +} + +static struct clock_event_device orion_clkevt = { + .name = "orion_tick", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .rating = 300, + .cpumask = CPU_MASK_CPU0, + .set_next_event = orion_clkevt_next_event, + .set_mode = orion_clkevt_mode, +}; + +static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) +{ + /* + * Clear cause bit and do event + */ + orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT)); + orion_clkevt.event_handler(&orion_clkevt); + return IRQ_HANDLED; +} + +static struct irqaction orion_timer_irq = { + .name = "orion_tick", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = orion_timer_interrupt +}; + +static void orion_timer_init(void) +{ + /* + * Setup clocksource free running timer (no interrupt on reload) + */ + orion_write(TIMER_VAL(CLOCKSOURCE), 0xffffffff); + orion_write(TIMER_VAL_RELOAD(CLOCKSOURCE), 0xffffffff); + orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKSOURCE)); + orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKSOURCE) | + TIMER_EN(CLOCKSOURCE)); + + /* + * Register clocksource + */ + orion_clksrc.mult = + clocksource_hz2mult(CLOCK_TICK_RATE, orion_clksrc.shift); + + clocksource_register(&orion_clksrc); + + /* + * Connect and enable tick handler + */ + setup_irq(IRQ_ORION_BRIDGE, &orion_timer_irq); + + /* + * Register clockevent + */ + orion_clkevt.mult = + div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, orion_clkevt.shift); + orion_clkevt.max_delta_ns = + clockevent_delta2ns(0xfffffffe, &orion_clkevt); + orion_clkevt.min_delta_ns = + clockevent_delta2ns(1, &orion_clkevt); + + clockevents_register_device(&orion_clkevt); +} + +struct sys_timer orion_timer = { + .init = orion_timer_init, +}; -- cgit v1.2.3-55-g7522 From 817eb2109d28fcac8f4fd84a9ef3a761de4f8b50 Mon Sep 17 00:00:00 2001 From: Ronen Shitrit Date: Wed, 17 Oct 2007 14:51:34 -0400 Subject: [ARM] OrionNAS RD board support serial, NOR, PCI and Ethernet is activated at the moment. Signed-off-by: Ronen Shitrit Reviewed-by: Tzachi Perelstein Reviewed-by: Nicolas Pitre Reviewed-by: Lennert Buytenhek Acked-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm/mach-orion/Kconfig | 7 + arch/arm/mach-orion/Makefile | 1 + arch/arm/mach-orion/rd88f5182-setup.c | 306 ++++++++++++++++++++++++++++++++++ 4 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-orion/rd88f5182-setup.c (limited to 'arch/arm/Kconfig') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 20084f273d8e..a32b3b52c5c0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -728,7 +728,7 @@ config LEDS ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ ARCH_AT91 || MACH_TRIZEPS4 || ARCH_DAVINCI || \ - ARCH_KS8695 + ARCH_KS8695 || MACH_RD88F5182 help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. diff --git a/arch/arm/mach-orion/Kconfig b/arch/arm/mach-orion/Kconfig index 5c1dee8724c1..73d9f9aa283f 100644 --- a/arch/arm/mach-orion/Kconfig +++ b/arch/arm/mach-orion/Kconfig @@ -9,6 +9,13 @@ config MACH_DB88F5281 Say 'Y' here if you want your kernel to support the Marvell Orion-2 (88F5281) Development Board +config MACH_RD88F5182 + bool "Marvell Orion-NAS Reference Design" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-NAS (88F5182) RD2 + endmenu endif diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile index 55c59bb7f1d9..1cbdd7513120 100644 --- a/arch/arm/mach-orion/Makefile +++ b/arch/arm/mach-orion/Makefile @@ -1,2 +1,3 @@ obj-y += common.o addr-map.o pci.o gpio.o irq.o time.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o +obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o diff --git a/arch/arm/mach-orion/rd88f5182-setup.c b/arch/arm/mach-orion/rd88f5182-setup.c new file mode 100644 index 000000000000..026d74325d01 --- /dev/null +++ b/arch/arm/mach-orion/rd88f5182-setup.c @@ -0,0 +1,306 @@ +/* + * arch/arm/mach-orion/rd88f5182-setup.c + * + * Marvell Orion-NAS Reference Design Setup + * + * Maintainer: Ronen Shitrit + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +/***************************************************************************** + * RD-88F5182 Info + ****************************************************************************/ + +/* + * 512K NOR flash Device bus boot chip select + */ + +#define RD88F5182_NOR_BOOT_BASE 0xf4000000 +#define RD88F5182_NOR_BOOT_SIZE SZ_512K + +/* + * 16M NOR flash on Device bus chip select 1 + */ + +#define RD88F5182_NOR_BASE 0xfc000000 +#define RD88F5182_NOR_SIZE SZ_16M + +/* + * PCI + */ + +#define RD88F5182_PCI_SLOT0_OFFS 7 +#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7 +#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6 + +/* + * GPIO Debug LED + */ + +#define RD88F5182_GPIO_DBG_LED 0 + +/***************************************************************************** + * 16M NOR Flash on Device bus CS1 + ****************************************************************************/ + +static struct physmap_flash_data rd88f5182_nor_flash_data = { + .width = 1, +}; + +static struct resource rd88f5182_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = RD88F5182_NOR_BASE, + .end = RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1, +}; + +static struct platform_device rd88f5182_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &rd88f5182_nor_flash_data, + }, + .num_resources = 1, + .resource = &rd88f5182_nor_flash_resource, +}; + +#ifdef CONFIG_LEDS + +/***************************************************************************** + * Use GPIO debug led as CPU active indication + ****************************************************************************/ + +static void rd88f5182_dbgled_event(led_event_t evt) +{ + int val; + + if (evt == led_idle_end) + val = 1; + else if (evt == led_idle_start) + val = 0; + else + return; + + gpio_set_value(RD88F5182_GPIO_DBG_LED, val); +} + +static int __init rd88f5182_dbgled_init(void) +{ + int pin; + + if (machine_is_rd88f5182()) { + pin = RD88F5182_GPIO_DBG_LED; + + if (gpio_request(pin, "DBGLED") == 0) { + if (gpio_direction_output(pin, 0) != 0) { + printk(KERN_ERR "rd88f5182_dbgled_init failed " + "to set output pin %d\n", pin); + gpio_free(pin); + return 0; + } + } else { + printk(KERN_ERR "rd88f5182_dbgled_init failed " + "to request gpio %d\n", pin); + return 0; + } + + leds_event = rd88f5182_dbgled_event; + } + return 0; +} + +__initcall(rd88f5182_dbgled_init); + +#endif + +/***************************************************************************** + * PCI + ****************************************************************************/ + +void __init rd88f5182_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN; + if (gpio_request(pin, "PCI IntA") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "rd88f5182_pci_preinit faield to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin); + } + + pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN; + if (gpio_request(pin, "PCI IntB") == 0) { + if (gpio_direction_input(pin) == 0) { + set_irq_type(gpio_to_irq(pin), IRQT_LOW); + } else { + printk(KERN_ERR "rd88f5182_pci_preinit faield to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin); + } +} + +static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* + * PCI-E isn't used on the RD2 + */ + if (dev->bus->number == orion_pcie_local_bus_nr()) + return IRQ_ORION_PCIE0_INT; + + /* + * PCI IRQs are connected via GPIOs + */ + switch (slot - RD88F5182_PCI_SLOT0_OFFS) { + case 0: + if (pin == 1) + return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN); + else + return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN); + default: + return -1; + } +} + +static struct hw_pci rd88f5182_pci __initdata = { + .nr_controllers = 2, + .preinit = rd88f5182_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = orion_pci_sys_setup, + .scan = orion_pci_sys_scan_bus, + .map_irq = rd88f5182_pci_map_irq, +}; + +static int __init rd88f5182_pci_init(void) +{ + if (machine_is_rd88f5182()) + pci_common_init(&rd88f5182_pci); + + return 0; +} + +subsys_initcall(rd88f5182_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data rd88f5182_eth_data = { + .phy_addr = 8, + .force_phy_addr = 1, +}; + +/***************************************************************************** + * RTC DS1338 on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata rd88f5182_i2c_rtc = { + .driver_name = "rtc-ds1307", + .type = "ds1338", + .addr = 0x68, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct platform_device *rd88f5182_devices[] __initdata = { + &rd88f5182_nor_flash, +}; + +static void __init rd88f5182_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion_init(); + + /* + * Setup the CPU address decode windows for our devices + */ + orion_setup_cpu_win(ORION_DEV_BOOT, RD88F5182_NOR_BOOT_BASE, + RD88F5182_NOR_BOOT_SIZE, -1); + orion_setup_cpu_win(ORION_DEV1, RD88F5182_NOR_BASE, + RD88F5182_NOR_SIZE, -1); + + /* + * Open a special address decode windows for the PCIE WA. + */ + orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE); + orion_write(ORION_REGS_BASE | 0x20070, (0x7941 | + (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16)); + + /* + * Setup Multiplexing Pins -- + * MPP[0] Debug Led (GPIO - Out) + * MPP[1] Debug Led (GPIO - Out) + * MPP[2] N/A + * MPP[3] RTC_Int (GPIO - In) + * MPP[4] GPIO + * MPP[5] GPIO + * MPP[6] PCI_intA (GPIO - In) + * MPP[7] PCI_intB (GPIO - In) + * MPP[8-11] N/A + * MPP[12] SATA 0 presence Indication + * MPP[13] SATA 1 presence Indication + * MPP[14] SATA 0 active Indication + * MPP[15] SATA 1 active indication + * MPP[16-19] Not used + * MPP[20] PCI Clock to MV88F5182 + * MPP[21] PCI Clock to mini PCI CON11 + * MPP[22] USB 0 over current indication + * MPP[23] USB 1 over current indication + * MPP[24] USB 1 over current enable + * MPP[25] USB 0 over current enable + */ + + orion_write(MPP_0_7_CTRL, 0x00000003); + orion_write(MPP_8_15_CTRL, 0x55550000); + orion_write(MPP_16_19_CTRL, 0x5555); + + orion_gpio_set_valid_pins(0x000000fb); + + platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices)); + i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1); + orion_eth_init(&rd88f5182_eth_data); +} + +MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design") + /* Maintainer: Ronen Shitrit */ + .phys_io = ORION_REGS_BASE, + .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = rd88f5182_init, + .map_io = orion_map_io, + .init_irq = orion_init_irq, + .timer = &orion_timer, +MACHINE_END -- cgit v1.2.3-55-g7522