diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-11 21:44:53 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-05-02 09:35:38 +0100 |
commit | ceade897f31b8bb66f378cc35859fcfd0d46aaa2 (patch) | |
tree | 44f6fffb4f93ec6247b468e4009e414b4124f585 /arch/arm/mach-vexpress | |
parent | 9bf5b2ef673237e0e43161c56f70ac8bf24e43f9 (diff) |
ARM: Add Versatile Express support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-vexpress')
-rw-r--r-- | arch/arm/mach-vexpress/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/core.h | 26 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/clkdev.h | 15 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/debug-macro.S | 23 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/entry-macro.S | 67 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/hardware.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/io.h | 28 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/irqs.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/memory.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/motherboard.h | 121 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/system.h | 37 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/timex.h | 23 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/uncompress.h | 52 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/include/mach/vmalloc.h | 21 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 361 |
17 files changed, 816 insertions, 0 deletions
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig new file mode 100644 index 000000000000..751858c97e6a --- /dev/null +++ b/arch/arm/mach-vexpress/Kconfig @@ -0,0 +1,4 @@ +menu "Versatile Express platform type" + depends on ARCH_VEXPRESS + +endmenu diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile new file mode 100644 index 000000000000..b47cf732981f --- /dev/null +++ b/arch/arm/mach-vexpress/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the linux kernel. +# + +obj-y := v2m.o diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot new file mode 100644 index 000000000000..07c2d9c457ec --- /dev/null +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x60008000 +params_phys-y := 0x60000100 +initrd_phys-y := 0x60800000 diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h new file mode 100644 index 000000000000..57dd95ce41f9 --- /dev/null +++ b/arch/arm/mach-vexpress/core.h @@ -0,0 +1,26 @@ +#define __MMIO_P2V(x) (((x) & 0xfffff) | (((x) & 0x0f000000) >> 4) | 0xf8000000) +#define MMIO_P2V(x) ((void __iomem *)__MMIO_P2V(x)) + +#define AMBA_DEVICE(name,busid,base,plat) \ +struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0UL, \ + .init_name = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base, \ + .end = base + SZ_4K - 1, \ + .flags = IORESOURCE_MEM, \ + }, \ + .dma_mask = ~0UL, \ + .irq = IRQ_##base, \ + /* .dma = DMA_##base,*/ \ +} + +struct map_desc; + +void v2m_map_io(struct map_desc *tile, size_t num); +extern struct sys_timer v2m_timer; + +extern void __iomem *gic_cpu_base_addr; diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h new file mode 100644 index 000000000000..3f8307d73cad --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/clkdev.h @@ -0,0 +1,15 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#include <plat/clock.h> + +struct clk { + const struct clk_ops *ops; + unsigned long rate; + const struct icst_params *params; +}; + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S new file mode 100644 index 000000000000..5167e2aceeba --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S @@ -0,0 +1,23 @@ +/* arch/arm/mach-realview/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * 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. + */ + +#define DEBUG_LL_UART_OFFSET 0x00009000 + + .macro addruart,rx,tmp + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x10000000 + movne \rx, #0xf8000000 @ virtual base + orr \rx, \rx, #DEBUG_LL_UART_OFFSET + .endm + +#include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S new file mode 100644 index 000000000000..20e9fb514f0a --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S @@ -0,0 +1,67 @@ +#include <asm/hardware/gic.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + ldr \tmp, =1021 + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm + diff --git a/arch/arm/mach-vexpress/include/mach/hardware.h b/arch/arm/mach-vexpress/include/mach/hardware.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/hardware.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/arm/mach-vexpress/include/mach/io.h b/arch/arm/mach-vexpress/include/mach/io.h new file mode 100644 index 000000000000..748bb524ee71 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/io.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-vexpress/include/mach/io.h + * + * Copyright (C) 2003 ARM Limited + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/irqs.h b/arch/arm/mach-vexpress/include/mach/irqs.h new file mode 100644 index 000000000000..7054cbfc9de5 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/irqs.h @@ -0,0 +1,4 @@ +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 + +#define NR_IRQS 128 diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-vexpress/include/mach/memory.h new file mode 100644 index 000000000000..be28232ae639 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/memory.h @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-vexpress/include/mach/memory.h + * + * Copyright (C) 2003 ARM Limited + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x60000000) + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h new file mode 100644 index 000000000000..98a8ded055bf --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h @@ -0,0 +1,121 @@ +#ifndef __MACH_MOTHERBOARD_H +#define __MACH_MOTHERBOARD_H + +/* + * Physical addresses, offset from V2M_PA_CS0-3 + */ +#define V2M_NOR0 (V2M_PA_CS0) +#define V2M_NOR1 (V2M_PA_CS1) +#define V2M_SRAM (V2M_PA_CS2) +#define V2M_VIDEO_SRAM (V2M_PA_CS3 + 0x00000000) +#define V2M_LAN9118 (V2M_PA_CS3 + 0x02000000) +#define V2M_ISP1761 (V2M_PA_CS3 + 0x03000000) + +/* + * Physical addresses, offset from V2M_PA_CS7 + */ +#define V2M_SYSREGS (V2M_PA_CS7 + 0x00000000) +#define V2M_SYSCTL (V2M_PA_CS7 + 0x00001000) +#define V2M_SERIAL_BUS_PCI (V2M_PA_CS7 + 0x00002000) + +#define V2M_AACI (V2M_PA_CS7 + 0x00004000) +#define V2M_MMCI (V2M_PA_CS7 + 0x00005000) +#define V2M_KMI0 (V2M_PA_CS7 + 0x00006000) +#define V2M_KMI1 (V2M_PA_CS7 + 0x00007000) + +#define V2M_UART0 (V2M_PA_CS7 + 0x00009000) +#define V2M_UART1 (V2M_PA_CS7 + 0x0000a000) +#define V2M_UART2 (V2M_PA_CS7 + 0x0000b000) +#define V2M_UART3 (V2M_PA_CS7 + 0x0000c000) + +#define V2M_WDT (V2M_PA_CS7 + 0x0000f000) + +#define V2M_TIMER01 (V2M_PA_CS7 + 0x00011000) +#define V2M_TIMER23 (V2M_PA_CS7 + 0x00012000) + +#define V2M_SERIAL_BUS_DVI (V2M_PA_CS7 + 0x00016000) +#define V2M_RTC (V2M_PA_CS7 + 0x00017000) + +#define V2M_CF (V2M_PA_CS7 + 0x0001a000) +#define V2M_CLCD (V2M_PA_CS7 + 0x0001f000) + +#define V2M_SYS_ID (V2M_SYSREGS + 0x000) +#define V2M_SYS_SW (V2M_SYSREGS + 0x004) +#define V2M_SYS_LED (V2M_SYSREGS + 0x008) +#define V2M_SYS_100HZ (V2M_SYSREGS + 0x024) +#define V2M_SYS_FLAGS (V2M_SYSREGS + 0x030) +#define V2M_SYS_FLAGSSET (V2M_SYSREGS + 0x030) +#define V2M_SYS_FLAGSCLR (V2M_SYSREGS + 0x034) +#define V2M_SYS_NVFLAGS (V2M_SYSREGS + 0x038) +#define V2M_SYS_NVFLAGSSET (V2M_SYSREGS + 0x038) +#define V2M_SYS_NVFLAGSCLR (V2M_SYSREGS + 0x03c) +#define V2M_SYS_MCI (V2M_SYSREGS + 0x048) +#define V2M_SYS_FLASH (V2M_SYSREGS + 0x03c) +#define V2M_SYS_CFGSW (V2M_SYSREGS + 0x058) +#define V2M_SYS_24MHZ (V2M_SYSREGS + 0x05c) +#define V2M_SYS_MISC (V2M_SYSREGS + 0x060) +#define V2M_SYS_DMA (V2M_SYSREGS + 0x064) +#define V2M_SYS_PROCID0 (V2M_SYSREGS + 0x084) +#define V2M_SYS_PROCID1 (V2M_SYSREGS + 0x088) +#define V2M_SYS_CFGDATA (V2M_SYSREGS + 0x0a0) +#define V2M_SYS_CFGCTRL (V2M_SYSREGS + 0x0a4) +#define V2M_SYS_CFGSTAT (V2M_SYSREGS + 0x0a8) + +#define V2M_TIMER0 (V2M_TIMER01 + 0x000) +#define V2M_TIMER1 (V2M_TIMER01 + 0x020) + +#define V2M_TIMER2 (V2M_TIMER23 + 0x000) +#define V2M_TIMER3 (V2M_TIMER23 + 0x020) + + +/* + * Interrupts. Those in {} are for AMBA devices + */ +#define IRQ_V2M_WDT { (32 + 0) } +#define IRQ_V2M_TIMER0 (32 + 2) +#define IRQ_V2M_TIMER1 (32 + 2) +#define IRQ_V2M_TIMER2 (32 + 3) +#define IRQ_V2M_TIMER3 (32 + 3) +#define IRQ_V2M_RTC { (32 + 4) } +#define IRQ_V2M_UART0 { (32 + 5) } +#define IRQ_V2M_UART1 { (32 + 6) } +#define IRQ_V2M_UART2 { (32 + 7) } +#define IRQ_V2M_UART3 { (32 + 8) } +#define IRQ_V2M_MMCI { (32 + 9), (32 + 10) } +#define IRQ_V2M_AACI { (32 + 11) } +#define IRQ_V2M_KMI0 { (32 + 12) } +#define IRQ_V2M_KMI1 { (32 + 13) } +#define IRQ_V2M_CLCD { (32 + 14) } +#define IRQ_V2M_LAN9118 (32 + 15) +#define IRQ_V2M_ISP1761 (32 + 16) +#define IRQ_V2M_PCIE (32 + 17) + + +/* + * Configuration + */ +#define SYS_CFG_START (1 << 31) +#define SYS_CFG_WRITE (1 << 30) +#define SYS_CFG_OSC (1 << 20) +#define SYS_CFG_VOLT (2 << 20) +#define SYS_CFG_AMP (3 << 20) +#define SYS_CFG_TEMP (4 << 20) +#define SYS_CFG_RESET (5 << 20) +#define SYS_CFG_SCC (6 << 20) +#define SYS_CFG_MUXFPGA (7 << 20) +#define SYS_CFG_SHUTDOWN (8 << 20) +#define SYS_CFG_REBOOT (9 << 20) +#define SYS_CFG_DVIMODE (11 << 20) +#define SYS_CFG_POWER (12 << 20) +#define SYS_CFG_SITE_MB (0 << 16) +#define SYS_CFG_SITE_DB1 (1 << 16) +#define SYS_CFG_SITE_DB2 (2 << 16) +#define SYS_CFG_STACK(n) ((n) << 12) + +#define SYS_CFG_ERR (1 << 1) +#define SYS_CFG_COMPLETE (1 << 0) + +int v2m_cfg_write(u32 devfn, u32 data); +int v2m_cfg_read(u32 devfn, u32 *data); + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/system.h b/arch/arm/mach-vexpress/include/mach/system.h new file mode 100644 index 000000000000..899a4e628a4c --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/system.h @@ -0,0 +1,37 @@ +/* + * arch/arm/mach-vexpress/include/mach/system.h + * + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ +} + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/timex.h b/arch/arm/mach-vexpress/include/mach/timex.h new file mode 100644 index 000000000000..00029bacd43c --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/timex.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-vexpress/include/mach/timex.h + * + * RealView architecture timex specifications + * + * Copyright (C) 2003 ARM Limited + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CLOCK_TICK_RATE (50000000 / 16) diff --git a/arch/arm/mach-vexpress/include/mach/uncompress.h b/arch/arm/mach-vexpress/include/mach/uncompress.h new file mode 100644 index 000000000000..7972c5748d0e --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/uncompress.h @@ -0,0 +1,52 @@ +/* + * arch/arm/mach-vexpress/include/mach/uncompress.h + * + * Copyright (C) 2003 ARM Limited + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00)) +#define AMBA_UART_LCRH(base) (*(volatile unsigned char *)((base) + 0x2c)) +#define AMBA_UART_CR(base) (*(volatile unsigned char *)((base) + 0x30)) +#define AMBA_UART_FR(base) (*(volatile unsigned char *)((base) + 0x18)) + +#define get_uart_base() (0x10000000 + 0x00009000) + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 5)) + barrier(); + + AMBA_UART_DR(base) = c; +} + +static inline void flush(void) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 3)) + barrier(); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/mach-vexpress/include/mach/vmalloc.h b/arch/arm/mach-vexpress/include/mach/vmalloc.h new file mode 100644 index 000000000000..f43a36ef678b --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/vmalloc.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-vexpress/include/mach/vmalloc.h + * + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Russell King. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END 0xf8000000UL diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c new file mode 100644 index 000000000000..d250711b8c7a --- /dev/null +++ b/arch/arm/mach-vexpress/v2m.c @@ -0,0 +1,361 @@ +/* + * Versatile Express V2M Motherboard Support + */ +#include <linux/device.h> +#include <linux/amba/bus.h> +#include <linux/amba/mmci.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/smsc911x.h> +#include <linux/spinlock.h> +#include <linux/sysdev.h> +#include <linux/usb/isp1760.h> + +#include <asm/clkdev.h> +#include <asm/sizes.h> +#include <asm/mach/flash.h> +#include <asm/mach/map.h> +#include <asm/mach/time.h> +#include <asm/hardware/arm_timer.h> + +#include <mach/clkdev.h> +#include <mach/motherboard.h> + +#include <plat/timer-sp.h> + +#include "core.h" + +#define V2M_PA_CS0 0x40000000 +#define V2M_PA_CS1 0x44000000 +#define V2M_PA_CS2 0x48000000 +#define V2M_PA_CS3 0x4c000000 +#define V2M_PA_CS7 0x10000000 + +static struct map_desc v2m_io_desc[] __initdata = { + { + .virtual = __MMIO_P2V(V2M_PA_CS7), + .pfn = __phys_to_pfn(V2M_PA_CS7), + .length = SZ_128K, + .type = MT_DEVICE, + }, +}; + +void __init v2m_map_io(struct map_desc *tile, size_t num) +{ + iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); + iotable_init(tile, num); +} + + +static void v2m_timer_init(void) +{ + writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); + writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); + + sp804_clocksource_init(MMIO_P2V(V2M_TIMER1)); + sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0); +} + +struct sys_timer v2m_timer = { + .init = v2m_timer_init, +}; + + +static DEFINE_SPINLOCK(v2m_cfg_lock); + +int v2m_cfg_write(u32 devfn, u32 data) +{ + /* Configuration interface broken? */ + u32 val; + + printk("%s: writing %08x to %08x\n", __func__, data, devfn); + + devfn |= SYS_CFG_START | SYS_CFG_WRITE; + + spin_lock(&v2m_cfg_lock); + val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); + writel(val & ~SYS_CFG_COMPLETE, MMIO_P2V(V2M_SYS_CFGSTAT)); + + writel(data, MMIO_P2V(V2M_SYS_CFGDATA)); + writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); + + do { + val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); + } while (val == 0); + spin_unlock(&v2m_cfg_lock); + + return !!(val & SYS_CFG_ERR); +} + +int v2m_cfg_read(u32 devfn, u32 *data) +{ + u32 val; + + devfn |= SYS_CFG_START; + + spin_lock(&v2m_cfg_lock); + writel(0, MMIO_P2V(V2M_SYS_CFGSTAT)); + writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); + + mb(); + + do { + cpu_relax(); + val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); + } while (val == 0); + + *data = readl(MMIO_P2V(V2M_SYS_CFGDATA)); + spin_unlock(&v2m_cfg_lock); + + return !!(val & SYS_CFG_ERR); +} + + +static struct resource v2m_pcie_i2c_resource = { + .start = V2M_SERIAL_BUS_PCI, + .end = V2M_SERIAL_BUS_PCI + SZ_4K - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device v2m_pcie_i2c_device = { + .name = "versatile-i2c", + .id = 0, + .num_resources = 1, + .resource = &v2m_pcie_i2c_resource, +}; + +static struct resource v2m_ddc_i2c_resource = { + .start = V2M_SERIAL_BUS_DVI, + .end = V2M_SERIAL_BUS_DVI + SZ_4K - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device v2m_ddc_i2c_device = { + .name = "versatile-i2c", + .id = 1, + .num_resources = 1, + .resource = &v2m_ddc_i2c_resource, +}; + +static struct resource v2m_eth_resources[] = { + { + .start = V2M_LAN9118, + .end = V2M_LAN9118 + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_V2M_LAN9118, + .end = IRQ_V2M_LAN9118, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct smsc911x_platform_config v2m_eth_config = { + .flags = SMSC911X_USE_32BIT, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device v2m_eth_device = { + .name = "smsc911x", + .id = -1, + .resource = v2m_eth_resources, + .num_resources = ARRAY_SIZE(v2m_eth_resources), + .dev.platform_data = &v2m_eth_config, +}; + +static struct resource v2m_usb_resources[] = { + { + .start = V2M_ISP1761, + .end = V2M_ISP1761 + SZ_128K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_V2M_ISP1761, + .end = IRQ_V2M_ISP1761, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct isp1760_platform_data v2m_usb_config = { + .is_isp1761 = true, + .bus_width_16 = false, + .port1_otg = true, + .analog_oc = false, + .dack_polarity_high = false, + .dreq_polarity_high = false, +}; + +static struct platform_device v2m_usb_device = { + .name = "isp1760", + .id = -1, + .resource = v2m_usb_resources, + .num_resources = ARRAY_SIZE(v2m_usb_resources), + .dev.platform_data = &v2m_usb_config, +}; + +static int v2m_flash_init(void) +{ + writel(0, MMIO_P2V(V2M_SYS_FLASH)); + return 0; +} + +static void v2m_flash_exit(void) +{ + writel(0, MMIO_P2V(V2M_SYS_FLASH)); +} + +static void v2m_flash_set_vpp(int on) +{ + writel(on != 0, MMIO_P2V(V2M_SYS_FLASH)); +} + +static struct flash_platform_data v2m_flash_data = { + .map_name = "cfi_probe", + .width = 4, + .init = v2m_flash_init, + .exit = v2m_flash_exit, + .set_vpp = v2m_flash_set_vpp, +}; + +static struct resource v2m_flash_resources[] = { + { + .start = V2M_NOR0, + .end = V2M_NOR0 + SZ_64M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = V2M_NOR1, + .end = V2M_NOR1 + SZ_64M - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device v2m_flash_device = { + .name = "armflash", + .id = -1, + .resource = v2m_flash_resources, + .num_resources = ARRAY_SIZE(v2m_flash_resources), + .dev.platform_data = &v2m_flash_data, +}; + + +static unsigned int v2m_mmci_status(struct device *dev) +{ + return !(readl(MMIO_P2V(V2M_SYS_MCI)) & (1 << 0)); +} + +static struct mmci_platform_data v2m_mmci_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .status = v2m_mmci_status, +}; + +static AMBA_DEVICE(aaci, "mb:aaci", V2M_AACI, NULL); +static AMBA_DEVICE(mmci, "mb:mmci", V2M_MMCI, &v2m_mmci_data); +static AMBA_DEVICE(kmi0, "mb:kmi0", V2M_KMI0, NULL); +static AMBA_DEVICE(kmi1, "mb:kmi1", V2M_KMI1, NULL); +static AMBA_DEVICE(uart0, "mb:uart0", V2M_UART0, NULL); +static AMBA_DEVICE(uart1, "mb:uart1", V2M_UART1, NULL); +static AMBA_DEVICE(uart2, "mb:uart2", V2M_UART2, NULL); +static AMBA_DEVICE(uart3, "mb:uart3", V2M_UART3, NULL); +static AMBA_DEVICE(wdt, "mb:wdt", V2M_WDT, NULL); +static AMBA_DEVICE(rtc, "mb:rtc", V2M_RTC, NULL); + +static struct amba_device *v2m_amba_devs[] __initdata = { + &aaci_device, + &mmci_device, + &kmi0_device, + &kmi1_device, + &uart0_device, + &uart1_device, + &uart2_device, + &uart3_device, + &wdt_device, + &rtc_device, +}; + + +static long v2m_osc_round(struct clk *clk, unsigned long rate) +{ + return rate; +} + +static int v2m_osc1_set(struct clk *clk, unsigned long rate) +{ + return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate); +} + +static const struct clk_ops osc1_clk_ops = { + .round = v2m_osc_round, + .set = v2m_osc1_set, +}; + +static struct clk osc1_clk = { + .ops = &osc1_clk_ops, + .rate = 24000000, +}; + +static struct clk osc2_clk = { + .rate = 24000000, +}; + +static struct clk_lookup v2m_lookups[] = { + { /* UART0 */ + .dev_id = "mb:uart0", + .clk = &osc2_clk, + }, { /* UART1 */ + .dev_id = "mb:uart1", + .clk = &osc2_clk, + }, { /* UART2 */ + .dev_id = "mb:uart2", + .clk = &osc2_clk, + }, { /* UART3 */ + .dev_id = "mb:uart3", + .clk = &osc2_clk, + }, { /* KMI0 */ + .dev_id = "mb:kmi0", + .clk = &osc2_clk, + }, { /* KMI1 */ + .dev_id = "mb:kmi1", + .clk = &osc2_clk, + }, { /* MMC0 */ + .dev_id = "mb:mmci", + .clk = &osc2_clk, + }, { /* CLCD */ + .dev_id = "mb:clcd", + .clk = &osc1_clk, + }, +}; + +static void v2m_power_off(void) +{ + if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) + printk(KERN_EMERG "Unable to shutdown\n"); +} + +static void v2m_restart(char str, const char *cmd) +{ + if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0)) + printk(KERN_EMERG "Unable to reboot\n"); +} + +static int __init v2m_init(void) +{ + int i; + + clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); + + platform_device_register(&v2m_pcie_i2c_device); + platform_device_register(&v2m_ddc_i2c_device); + platform_device_register(&v2m_flash_device); + platform_device_register(&v2m_eth_device); + platform_device_register(&v2m_usb_device); + + for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) + amba_device_register(v2m_amba_devs[i], &iomem_resource); + + pm_power_off = v2m_power_off; + arm_pm_restart = v2m_restart; + + return 0; +} +arch_initcall(v2m_init); |