From b85a3ef4ac65169b65fd2fe9bec7912bbf475ba4 Mon Sep 17 00:00:00 2001 From: John Linn Date: Mon, 20 Jun 2011 11:47:27 -0600 Subject: ARM: Xilinx: Adding Xilinx board support The 1st board support is minimal to get a system up and running on the Xilinx platform. This platform reuses the clock implementation from plat-versatile, and it depends entirely on CONFIG_OF support. There is only one board support file which obtains all device information from a device tree dtb file which is passed to the kernel at boot time. Signed-off-by: John Linn --- arch/arm/boot/dts/zynq-ep107.dts | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-ep107.dts (limited to 'arch/arm/boot') diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts new file mode 100644 index 00000000000..37ca192fb19 --- /dev/null +++ b/arch/arm/boot/dts/zynq-ep107.dts @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 Xilinx + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +/dts-v1/; +/ { + model = "Xilinx Zynq EP107"; + compatible = "xlnx,zynq-ep107"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + + memory { + device_type = "memory"; + reg = <0x0 0x10000000>; + }; + + chosen { + bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk"; + linux,stdout-path = &uart0; + }; + + amba { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + intc: interrupt-controller@f8f01000 { + interrupt-controller; + compatible = "arm,gic"; + reg = <0xF8F01000 0x1000>; + #interrupt-cells = <2>; + }; + + uart0: uart@e0000000 { + compatible = "xlnx,xuartps"; + reg = <0xE0000000 0x1000>; + interrupts = <59 0>; + clock = <50000000>; + }; + }; +}; -- cgit v1.2.3-70-g09d2 From 02c981c07bc95ac1e42ec6c817f0c28cf3fe993a Mon Sep 17 00:00:00 2001 From: Binghua Duan Date: Fri, 8 Jul 2011 17:40:12 +0800 Subject: ARM: CSR: Adding CSR SiRFprimaII board support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SiRFprimaII is the latest generation application processor from CSR’s Multifunction SoC product family. Designed around an ARM cortex A9 core, high-speed memory bus, advanced 3D accelerator and full-HD multi-format video decoder, SiRFprimaII is able to meet the needs of complicated applications for modern multifunction devices that require heavy concurrent applications and fluid user experience. Integrated with GPS baseband, analog and PMU, this new platform is designed to provide a cost effective solution for Automotive and Consumer markets. This patch adds the basic support for this SoC and EVB board based on device tree. It is following the ZYNQ of Xilinx in some degree. Signed-off-by: Binghua Duan Signed-off-by: Rongjun Ying Signed-off-by: Zhiwu Song Signed-off-by: Yuping Luo Signed-off-by: Bin Shi Signed-off-by: Huayi Li Signed-off-by: Barry Song Reviewed-by: Arnd Bergmann --- Documentation/devicetree/bindings/arm/sirf.txt | 3 + arch/arm/Kconfig | 14 + arch/arm/Makefile | 1 + arch/arm/boot/dts/prima2-cb.dts | 416 +++++++++++++++++++ arch/arm/mach-prima2/Makefile | 5 + arch/arm/mach-prima2/Makefile.boot | 3 + arch/arm/mach-prima2/clock.c | 509 ++++++++++++++++++++++++ arch/arm/mach-prima2/common.h | 20 + arch/arm/mach-prima2/include/mach/clkdev.h | 15 + arch/arm/mach-prima2/include/mach/debug-macro.S | 29 ++ arch/arm/mach-prima2/include/mach/entry-macro.S | 29 ++ arch/arm/mach-prima2/include/mach/hardware.h | 15 + arch/arm/mach-prima2/include/mach/io.h | 16 + arch/arm/mach-prima2/include/mach/irqs.h | 17 + arch/arm/mach-prima2/include/mach/map.h | 16 + arch/arm/mach-prima2/include/mach/memory.h | 21 + arch/arm/mach-prima2/include/mach/system.h | 29 ++ arch/arm/mach-prima2/include/mach/timex.h | 14 + arch/arm/mach-prima2/include/mach/uart.h | 23 ++ arch/arm/mach-prima2/include/mach/uncompress.h | 40 ++ arch/arm/mach-prima2/include/mach/vmalloc.h | 16 + arch/arm/mach-prima2/irq.c | 71 ++++ arch/arm/mach-prima2/prima2.c | 40 ++ arch/arm/mach-prima2/rstc.c | 69 ++++ arch/arm/mach-prima2/timer.c | 217 ++++++++++ arch/arm/mm/Kconfig | 2 +- 26 files changed, 1649 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/sirf.txt create mode 100644 arch/arm/boot/dts/prima2-cb.dts create mode 100644 arch/arm/mach-prima2/Makefile create mode 100644 arch/arm/mach-prima2/Makefile.boot create mode 100644 arch/arm/mach-prima2/clock.c create mode 100644 arch/arm/mach-prima2/common.h create mode 100644 arch/arm/mach-prima2/include/mach/clkdev.h create mode 100644 arch/arm/mach-prima2/include/mach/debug-macro.S create mode 100644 arch/arm/mach-prima2/include/mach/entry-macro.S create mode 100644 arch/arm/mach-prima2/include/mach/hardware.h create mode 100644 arch/arm/mach-prima2/include/mach/io.h create mode 100644 arch/arm/mach-prima2/include/mach/irqs.h create mode 100644 arch/arm/mach-prima2/include/mach/map.h create mode 100644 arch/arm/mach-prima2/include/mach/memory.h create mode 100644 arch/arm/mach-prima2/include/mach/system.h create mode 100644 arch/arm/mach-prima2/include/mach/timex.h create mode 100644 arch/arm/mach-prima2/include/mach/uart.h create mode 100644 arch/arm/mach-prima2/include/mach/uncompress.h create mode 100644 arch/arm/mach-prima2/include/mach/vmalloc.h create mode 100644 arch/arm/mach-prima2/irq.c create mode 100644 arch/arm/mach-prima2/prima2.c create mode 100644 arch/arm/mach-prima2/rstc.c create mode 100644 arch/arm/mach-prima2/timer.c (limited to 'arch/arm/boot') diff --git a/Documentation/devicetree/bindings/arm/sirf.txt b/Documentation/devicetree/bindings/arm/sirf.txt new file mode 100644 index 00000000000..6b07f65b32d --- /dev/null +++ b/Documentation/devicetree/bindings/arm/sirf.txt @@ -0,0 +1,3 @@ +prima2 "cb" evalutation board +Required root node properties: + - compatible = "sirf,prima2-cb", "sirf,prima2"; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9adc278a22a..aa6c91d0d79 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -879,6 +879,20 @@ config ARCH_VT8500 select HAVE_PWM help Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. + +config ARCH_PRIMA2 + bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform" + select CPU_V7 + select GENERIC_TIME + select NO_IOPORT + select GENERIC_CLOCKEVENTS + select CLKDEV_LOOKUP + select GENERIC_IRQ_CHIP + select USE_OF + select ZONE_DMA + help + Support for CSR SiRFSoC ARM Cortex A9 Platform + endchoice # diff --git a/arch/arm/Makefile b/arch/arm/Makefile index f5b2b390c8f..1d693d06257 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -169,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP3) := omap2 machine-$(CONFIG_ARCH_OMAP4) := omap2 machine-$(CONFIG_ARCH_ORION5X) := orion5x machine-$(CONFIG_ARCH_PNX4008) := pnx4008 +machine-$(CONFIG_ARCH_PRIMA2) := prima2 machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_REALVIEW) := realview machine-$(CONFIG_ARCH_RPC) := rpc diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts new file mode 100644 index 00000000000..6fecc88065b --- /dev/null +++ b/arch/arm/boot/dts/prima2-cb.dts @@ -0,0 +1,416 @@ +/dts-v1/; +/ { + model = "SiRF Prima2 eVB"; + compatible = "sirf,prima2-cb", "sirf,prima2"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + + memory { + reg = <0x00000000 0x20000000>; + }; + + chosen { + bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1 bootsplash=true bpp=16 androidboot.console=ttyS1"; + linux,stdout-path = &uart1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + reg = <0x0>; + d-cache-line-size = <32>; + i-cache-line-size = <32>; + d-cache-size = <32768>; + i-cache-size = <32768>; + /* from bootloader */ + timebase-frequency = <0>; + bus-frequency = <0>; + clock-frequency = <0>; + }; + }; + + axi { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x40000000 0x40000000 0x80000000>; + + l2-cache-controller@80040000 { + compatible = "arm,pl310-cache"; + reg = <0x80040000 0x1000>; + interrupts = <59>; + }; + + intc: interrupt-controller@80020000 { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "sirf,prima2-intc"; + reg = <0x80020000 0x1000>; + }; + + sys-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x88000000 0x88000000 0x40000>; + + clock-controller@88000000 { + compatible = "sirf,prima2-clkc"; + reg = <0x88000000 0x1000>; + interrupts = <3>; + }; + + reset-controller@88010000 { + compatible = "sirf,prima2-rstc"; + reg = <0x88010000 0x1000>; + }; + }; + + mem-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x90000000 0x90000000 0x10000>; + + memory-controller@90000000 { + compatible = "sirf,prima2-memc"; + reg = <0x90000000 0x10000>; + interrupts = <27>; + }; + }; + + disp-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x90010000 0x90010000 0x30000>; + + display@90010000 { + compatible = "sirf,prima2-lcd"; + reg = <0x90010000 0x20000>; + interrupts = <30>; + }; + + vpp@90020000 { + compatible = "sirf,prima2-vpp"; + reg = <0x90020000 0x10000>; + interrupts = <31>; + }; + }; + + graphics-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x98000000 0x98000000 0x8000000>; + + graphics@98000000 { + compatible = "powervr,sgx531"; + reg = <0x98000000 0x8000000>; + interrupts = <6>; + }; + }; + + multimedia-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xa0000000 0xa0000000 0x8000000>; + + multimedia@a0000000 { + compatible = "sirf,prima2-video-codec"; + reg = <0xa0000000 0x8000000>; + interrupts = <5>; + }; + }; + + dsp-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xa8000000 0xa8000000 0x2000000>; + + dspif@a8000000 { + compatible = "sirf,prima2-dspif"; + reg = <0xa8000000 0x10000>; + interrupts = <9>; + }; + + gps@a8010000 { + compatible = "sirf,prima2-gps"; + reg = <0xa8010000 0x10000>; + interrupts = <7>; + }; + + dsp@a9000000 { + compatible = "sirf,prima2-dsp"; + reg = <0xa9000000 0x1000000>; + interrupts = <8>; + }; + }; + + peri-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xb0000000 0xb0000000 0x180000>; + + timer@b0020000 { + compatible = "sirf,prima2-tick"; + reg = <0xb0020000 0x1000>; + interrupts = <0>; + }; + + nand@b0030000 { + compatible = "sirf,prima2-nand"; + reg = <0xb0030000 0x10000>; + interrupts = <41>; + }; + + audio@b0040000 { + compatible = "sirf,prima2-audio"; + reg = <0xb0040000 0x10000>; + interrupts = <35>; + }; + + uart0: uart@b0050000 { + cell-index = <0>; + compatible = "sirf,prima2-uart"; + reg = <0xb0050000 0x10000>; + interrupts = <17>; + }; + + uart1: uart@b0060000 { + cell-index = <1>; + compatible = "sirf,prima2-uart"; + reg = <0xb0060000 0x10000>; + interrupts = <18>; + }; + + uart2: uart@b0070000 { + cell-index = <2>; + compatible = "sirf,prima2-uart"; + reg = <0xb0070000 0x10000>; + interrupts = <19>; + }; + + usp0: usp@b0080000 { + cell-index = <0>; + compatible = "sirf,prima2-usp"; + reg = <0xb0080000 0x10000>; + interrupts = <20>; + }; + + usp1: usp@b0090000 { + cell-index = <1>; + compatible = "sirf,prima2-usp"; + reg = <0xb0090000 0x10000>; + interrupts = <21>; + }; + + usp2: usp@b00a0000 { + cell-index = <2>; + compatible = "sirf,prima2-usp"; + reg = <0xb00a0000 0x10000>; + interrupts = <22>; + }; + + dmac0: dma-controller@b00b0000 { + cell-index = <0>; + compatible = "sirf,prima2-dmac"; + reg = <0xb00b0000 0x10000>; + interrupts = <12>; + }; + + dmac1: dma-controller@b0160000 { + cell-index = <1>; + compatible = "sirf,prima2-dmac"; + reg = <0xb0160000 0x10000>; + interrupts = <13>; + }; + + vip@b00C0000 { + compatible = "sirf,prima2-vip"; + reg = <0xb00C0000 0x10000>; + }; + + spi0: spi@b00d0000 { + cell-index = <0>; + compatible = "sirf,prima2-spi"; + reg = <0xb00d0000 0x10000>; + interrupts = <15>; + }; + + spi1: spi@b0170000 { + cell-index = <1>; + compatible = "sirf,prima2-spi"; + reg = <0xb0170000 0x10000>; + interrupts = <16>; + }; + + i2c0: i2c@b00e0000 { + cell-index = <0>; + compatible = "sirf,prima2-i2c"; + reg = <0xb00e0000 0x10000>; + interrupts = <24>; + }; + + i2c1: i2c@b00f0000 { + cell-index = <1>; + compatible = "sirf,prima2-i2c"; + reg = <0xb00f0000 0x10000>; + interrupts = <25>; + }; + + tsc@b0110000 { + compatible = "sirf,prima2-tsc"; + reg = <0xb0110000 0x10000>; + interrupts = <33>; + }; + + gpio: gpio-controller@b0120000 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "sirf,prima2-gpio"; + reg = <0xb0120000 0x10000>; + gpio-controller; + interrupt-controller; + }; + + pwm@b0130000 { + compatible = "sirf,prima2-pwm"; + reg = <0xb0130000 0x10000>; + }; + + efusesys@b0140000 { + compatible = "sirf,prima2-efuse"; + reg = <0xb0140000 0x10000>; + }; + + pulsec@b0150000 { + compatible = "sirf,prima2-pulsec"; + reg = <0xb0150000 0x10000>; + interrupts = <48>; + }; + + pci-iobg { + compatible = "sirf,prima2-pciiobg", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x56000000 0x56000000 0x1b00000>; + + sd0: sdhci@56000000 { + cell-index = <0>; + compatible = "sirf,prima2-sdhc"; + reg = <0x56000000 0x100000>; + interrupts = <38>; + }; + + sd1: sdhci@56100000 { + cell-index = <1>; + compatible = "sirf,prima2-sdhc"; + reg = <0x56100000 0x100000>; + interrupts = <38>; + }; + + sd2: sdhci@56200000 { + cell-index = <2>; + compatible = "sirf,prima2-sdhc"; + reg = <0x56200000 0x100000>; + interrupts = <23>; + }; + + sd3: sdhci@56300000 { + cell-index = <3>; + compatible = "sirf,prima2-sdhc"; + reg = <0x56300000 0x100000>; + interrupts = <23>; + }; + + sd4: sdhci@56400000 { + cell-index = <4>; + compatible = "sirf,prima2-sdhc"; + reg = <0x56400000 0x100000>; + interrupts = <39>; + }; + + sd5: sdhci@56500000 { + cell-index = <5>; + compatible = "sirf,prima2-sdhc"; + reg = <0x56500000 0x100000>; + interrupts = <39>; + }; + + pci-copy@57900000 { + compatible = "sirf,prima2-pcicp"; + reg = <0x57900000 0x100000>; + interrupts = <40>; + }; + + rom-interface@57a00000 { + compatible = "sirf,prima2-romif"; + reg = <0x57a00000 0x100000>; + }; + }; + }; + + rtc-iobg { + compatible = "sirf,prima2-rtciobg", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80030000 0x10000>; + + gpsrtc@1000 { + compatible = "sirf,prima2-gpsrtc"; + reg = <0x1000 0x1000>; + interrupts = <55 56 57>; + }; + + sysrtc@2000 { + compatible = "sirf,prima2-sysrtc"; + reg = <0x2000 0x1000>; + interrupts = <52 53 54>; + }; + + pwrc@3000 { + compatible = "sirf,prima2-pwrc"; + reg = <0x3000 0x1000>; + interrupts = <32>; + }; + }; + + uus-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xb8000000 0xb8000000 0x40000>; + + usb0: usb@b00e0000 { + compatible = "chipidea,ci13611a-prima2"; + reg = <0xb8000000 0x10000>; + interrupts = <10>; + }; + + usb1: usb@b00f0000 { + compatible = "chipidea,ci13611a-prima2"; + reg = <0xb8010000 0x10000>; + interrupts = <11>; + }; + + sata@b00f0000 { + compatible = "synopsys,dwc-ahsata"; + reg = <0xb8020000 0x10000>; + interrupts = <37>; + }; + + security@b00f0000 { + compatible = "sirf,prima2-security"; + reg = <0xb8030000 0x10000>; + interrupts = <42>; + }; + }; + }; +}; diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile new file mode 100644 index 00000000000..d44f7aedda8 --- /dev/null +++ b/arch/arm/mach-prima2/Makefile @@ -0,0 +1,5 @@ +obj-y := timer.o +obj-y += irq.o +obj-y += clock.o +obj-y += rstc.o +obj-y += prima2.o diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot new file mode 100644 index 00000000000..d023db3ae4f --- /dev/null +++ b/arch/arm/mach-prima2/Makefile.boot @@ -0,0 +1,3 @@ +zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c new file mode 100644 index 00000000000..f9a2aaf63f7 --- /dev/null +++ b/arch/arm/mach-prima2/clock.c @@ -0,0 +1,509 @@ +/* + * Clock tree for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_CLKC_CLK_EN0 0x0000 +#define SIRFSOC_CLKC_CLK_EN1 0x0004 +#define SIRFSOC_CLKC_REF_CFG 0x0014 +#define SIRFSOC_CLKC_CPU_CFG 0x0018 +#define SIRFSOC_CLKC_MEM_CFG 0x001c +#define SIRFSOC_CLKC_SYS_CFG 0x0020 +#define SIRFSOC_CLKC_IO_CFG 0x0024 +#define SIRFSOC_CLKC_DSP_CFG 0x0028 +#define SIRFSOC_CLKC_GFX_CFG 0x002c +#define SIRFSOC_CLKC_MM_CFG 0x0030 +#define SIRFSOC_LKC_LCD_CFG 0x0034 +#define SIRFSOC_CLKC_MMC_CFG 0x0038 +#define SIRFSOC_CLKC_PLL1_CFG0 0x0040 +#define SIRFSOC_CLKC_PLL2_CFG0 0x0044 +#define SIRFSOC_CLKC_PLL3_CFG0 0x0048 +#define SIRFSOC_CLKC_PLL1_CFG1 0x004c +#define SIRFSOC_CLKC_PLL2_CFG1 0x0050 +#define SIRFSOC_CLKC_PLL3_CFG1 0x0054 +#define SIRFSOC_CLKC_PLL1_CFG2 0x0058 +#define SIRFSOC_CLKC_PLL2_CFG2 0x005c +#define SIRFSOC_CLKC_PLL3_CFG2 0x0060 + +#define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000) + +#define KHZ 1000 +#define MHZ (KHZ * KHZ) + +struct clk_ops { + unsigned long (*get_rate)(struct clk *clk); + long (*round_rate)(struct clk *clk, unsigned long rate); + int (*set_rate)(struct clk *clk, unsigned long rate); + int (*enable)(struct clk *clk); + int (*disable)(struct clk *clk); + struct clk *(*get_parent)(struct clk *clk); + int (*set_parent)(struct clk *clk, struct clk *parent); +}; + +struct clk { + struct clk *parent; /* parent clk */ + unsigned long rate; /* clock rate in Hz */ + signed char usage; /* clock enable count */ + signed char enable_bit; /* enable bit: 0 ~ 63 */ + unsigned short regofs; /* register offset */ + struct clk_ops *ops; /* clock operation */ +}; + +static DEFINE_SPINLOCK(clocks_lock); + +static inline unsigned long clkc_readl(unsigned reg) +{ + return readl(SIRFSOC_CLOCK_VA_BASE + reg); +} + +static inline void clkc_writel(u32 val, unsigned reg) +{ + writel(val, SIRFSOC_CLOCK_VA_BASE + reg); +} + +/* + * osc_rtc - real time oscillator - 32.768KHz + * osc_sys - high speed oscillator - 26MHz + */ + +static struct clk clk_rtc = { + .rate = 32768, +}; + +static struct clk clk_osc = { + .rate = 26 * MHZ, +}; + +/* + * std pll + */ +static unsigned long std_pll_get_rate(struct clk *clk) +{ + unsigned long fin = clk_get_rate(clk->parent); + u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - + SIRFSOC_CLKC_PLL1_CFG0; + + if (clkc_readl(regcfg2) & BIT(2)) { + /* pll bypass mode */ + clk->rate = fin; + } else { + /* fout = fin * nf / nr / od */ + u32 cfg0 = clkc_readl(clk->regofs); + u32 nf = (cfg0 & (BIT(13) - 1)) + 1; + u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; + u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; + WARN_ON(fin % MHZ); + clk->rate = fin / MHZ * nf / nr / od * MHZ; + } + + return clk->rate; +} + +static int std_pll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long fin, nf, nr, od, reg; + + /* + * fout = fin * nf / (nr * od); + * set od = 1, nr = fin/MHz, so fout = nf * MHz + */ + + nf = rate / MHZ; + if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) + return -EINVAL; + + fin = clk_get_rate(clk->parent); + BUG_ON(fin < MHZ); + + nr = fin / MHZ; + BUG_ON((fin % MHZ) || nr > BIT(6)); + + od = 1; + + reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); + clkc_writel(reg, clk->regofs); + + reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; + clkc_writel((nf >> 1) - 1, reg); + + reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; + while (!(clkc_readl(reg) & BIT(6))) + cpu_relax(); + + clk->rate = 0; /* set to zero will force recalculation */ + return 0; +} + +static struct clk_ops std_pll_ops = { + .get_rate = std_pll_get_rate, + .set_rate = std_pll_set_rate, +}; + +static struct clk clk_pll1 = { + .parent = &clk_osc, + .regofs = SIRFSOC_CLKC_PLL1_CFG0, + .ops = &std_pll_ops, +}; + +static struct clk clk_pll2 = { + .parent = &clk_osc, + .regofs = SIRFSOC_CLKC_PLL2_CFG0, + .ops = &std_pll_ops, +}; + +static struct clk clk_pll3 = { + .parent = &clk_osc, + .regofs = SIRFSOC_CLKC_PLL3_CFG0, + .ops = &std_pll_ops, +}; + +/* + * clock domains - cpu, mem, sys/io + */ + +static struct clk clk_mem; + +static struct clk *dmn_get_parent(struct clk *clk) +{ + struct clk *clks[] = { + &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 + }; + u32 cfg = clkc_readl(clk->regofs); + WARN_ON((cfg & (BIT(3) - 1)) > 4); + return clks[cfg & (BIT(3) - 1)]; +} + +static int dmn_set_parent(struct clk *clk, struct clk *parent) +{ + const struct clk *clks[] = { + &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 + }; + u32 cfg = clkc_readl(clk->regofs); + int i; + for (i = 0; i < ARRAY_SIZE(clks); i++) { + if (clks[i] == parent) { + cfg &= ~(BIT(3) - 1); + clkc_writel(cfg | i, clk->regofs); + /* BIT(3) - switching status: 1 - busy, 0 - done */ + while (clkc_readl(clk->regofs) & BIT(3)) + cpu_relax(); + return 0; + } + } + return -EINVAL; +} + +static unsigned long dmn_get_rate(struct clk *clk) +{ + unsigned long fin = clk_get_rate(clk->parent); + u32 cfg = clkc_readl(clk->regofs); + if (cfg & BIT(24)) { + /* fcd bypass mode */ + clk->rate = fin; + } else { + /* + * wait count: bit[19:16], hold count: bit[23:20] + */ + u32 wait = (cfg >> 16) & (BIT(4) - 1); + u32 hold = (cfg >> 20) & (BIT(4) - 1); + + clk->rate = fin / (wait + hold + 2); + } + + return clk->rate; +} + +static int dmn_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long fin; + unsigned ratio, wait, hold, reg; + unsigned bits = (clk == &clk_mem) ? 3 : 4; + + fin = clk_get_rate(clk->parent); + ratio = fin / rate; + + if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) + return -EINVAL; + + WARN_ON(fin % rate); + + wait = (ratio >> 1) - 1; + hold = ratio - wait - 2; + + reg = clkc_readl(clk->regofs); + reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); + reg |= (wait << 16) | (hold << 20) | BIT(25); + clkc_writel(reg, clk->regofs); + + /* waiting FCD been effective */ + while (clkc_readl(clk->regofs) & BIT(25)) + cpu_relax(); + + clk->rate = 0; /* set to zero will force recalculation */ + + return 0; +} + +/* + * cpu clock has no FCD register in Prima2, can only change pll + */ +static int cpu_set_rate(struct clk *clk, unsigned long rate) +{ + int ret1, ret2; + struct clk *cur_parent, *tmp_parent; + + cur_parent = dmn_get_parent(clk); + BUG_ON(cur_parent == NULL || cur_parent->usage > 1); + + /* switch to tmp pll before setting parent clock's rate */ + tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1; + ret1 = dmn_set_parent(clk, tmp_parent); + BUG_ON(ret1); + + ret2 = clk_set_rate(cur_parent, rate); + + ret1 = dmn_set_parent(clk, cur_parent); + + clk->rate = 0; /* set to zero will force recalculation */ + + return ret2 ? ret2 : ret1; +} + +static struct clk_ops cpu_ops = { + .get_parent = dmn_get_parent, + .set_parent = dmn_set_parent, + .set_rate = cpu_set_rate, +}; + +static struct clk clk_cpu = { + .parent = &clk_pll1, + .regofs = SIRFSOC_CLKC_CPU_CFG, + .ops = &cpu_ops, +}; + + +static struct clk_ops msi_ops = { + .set_rate = dmn_set_rate, + .get_rate = dmn_get_rate, + .set_parent = dmn_set_parent, + .get_parent = dmn_get_parent, +}; + +static struct clk clk_mem = { + .parent = &clk_pll2, + .regofs = SIRFSOC_CLKC_MEM_CFG, + .ops = &msi_ops, +}; + +static struct clk clk_sys = { + .parent = &clk_pll3, + .regofs = SIRFSOC_CLKC_SYS_CFG, + .ops = &msi_ops, +}; + +static struct clk clk_io = { + .parent = &clk_pll3, + .regofs = SIRFSOC_CLKC_IO_CFG, + .ops = &msi_ops, +}; + +/* + * on-chip clock sets + */ +static struct clk_lookup onchip_clks[] = { + { + .dev_id = "rtc", + .clk = &clk_rtc, + }, { + .dev_id = "osc", + .clk = &clk_osc, + }, { + .dev_id = "pll1", + .clk = &clk_pll1, + }, { + .dev_id = "pll2", + .clk = &clk_pll2, + }, { + .dev_id = "pll3", + .clk = &clk_pll3, + }, { + .dev_id = "cpu", + .clk = &clk_cpu, + }, { + .dev_id = "mem", + .clk = &clk_mem, + }, { + .dev_id = "sys", + .clk = &clk_sys, + }, { + .dev_id = "io", + .clk = &clk_io, + }, +}; + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return -EINVAL; + + if (clk->parent) + clk_enable(clk->parent); + + spin_lock_irqsave(&clocks_lock, flags); + if (!clk->usage++ && clk->ops && clk->ops->enable) + clk->ops->enable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return; + + WARN_ON(!clk->usage); + + spin_lock_irqsave(&clocks_lock, flags); + if (--clk->usage == 0 && clk->ops && clk->ops->disable) + clk->ops->disable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + + if (clk->parent) + clk_disable(clk->parent); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (unlikely(IS_ERR_OR_NULL(clk))) + return 0; + + if (clk->rate) + return clk->rate; + + if (clk->ops && clk->ops->get_rate) + return clk->ops->get_rate(clk); + + return clk_get_rate(clk->parent); +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (unlikely(IS_ERR_OR_NULL(clk))) + return 0; + + if (clk->ops && clk->ops->round_rate) + return clk->ops->round_rate(clk, rate); + + return 0; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (unlikely(IS_ERR_OR_NULL(clk))) + return -EINVAL; + + if (!clk->ops || !clk->ops->set_rate) + return -EINVAL; + + return clk->ops->set_rate(clk, rate); +} +EXPORT_SYMBOL(clk_set_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret; + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return -EINVAL; + + if (!clk->ops || !clk->ops->set_parent) + return -EINVAL; + + spin_lock_irqsave(&clocks_lock, flags); + ret = clk->ops->set_parent(clk, parent); + if (!ret) { + parent->usage += clk->usage; + clk->parent->usage -= clk->usage; + BUG_ON(clk->parent->usage < 0); + clk->parent = parent; + } + spin_unlock_irqrestore(&clocks_lock, flags); + return ret; +} +EXPORT_SYMBOL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + unsigned long flags; + + if (unlikely(IS_ERR_OR_NULL(clk))) + return NULL; + + if (!clk->ops || !clk->ops->get_parent) + return clk->parent; + + spin_lock_irqsave(&clocks_lock, flags); + clk->parent = clk->ops->get_parent(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + return clk->parent; +} +EXPORT_SYMBOL(clk_get_parent); + +static void __init sirfsoc_clk_init(void) +{ + clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks)); +} + +static struct of_device_id clkc_ids[] = { + { .compatible = "sirf,prima2-clkc" }, +}; + +void __init sirfsoc_of_clk_init(void) +{ + struct device_node *np; + struct resource res; + struct map_desc sirfsoc_clkc_iodesc = { + .virtual = SIRFSOC_CLOCK_VA_BASE, + .type = MT_DEVICE, + }; + + np = of_find_matching_node(NULL, clkc_ids); + if (!np) + panic("unable to find compatible clkc node in dtb\n"); + + if (of_address_to_resource(np, 0, &res)) + panic("unable to find clkc range in dtb"); + of_node_put(np); + + sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start); + sirfsoc_clkc_iodesc.length = 1 + res.end - res.start; + + iotable_init(&sirfsoc_clkc_iodesc, 1); + + sirfsoc_clk_init(); +} diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h new file mode 100644 index 00000000000..fa4a3b5c674 --- /dev/null +++ b/arch/arm/mach-prima2/common.h @@ -0,0 +1,20 @@ +/* + * This file contains common function prototypes to avoid externs in the c files. + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_PRIMA2_COMMON_H__ +#define __MACH_PRIMA2_COMMON_H__ + +#include +#include + +extern struct sys_timer sirfsoc_timer; + +extern void __init sirfsoc_of_irq_init(void); +extern void __init sirfsoc_of_clk_init(void); + +#endif diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h new file mode 100644 index 00000000000..66932518b1b --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/clkdev.h @@ -0,0 +1,15 @@ +/* + * arch/arm/mach-prima2/include/mach/clkdev.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_CLKDEV_H +#define __MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S new file mode 100644 index 00000000000..bf75106333f --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/debug-macro.S @@ -0,0 +1,29 @@ +/* + * arch/arm/mach-prima2/include/mach/debug-macro.S + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include + + .macro addruart, rp, rv + ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical + ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA] + .endm + + .macro busyuart,rd,rx + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS] + tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY + beq 1001b + .endm + diff --git a/arch/arm/mach-prima2/include/mach/entry-macro.S b/arch/arm/mach-prima2/include/mach/entry-macro.S new file mode 100644 index 00000000000..1c8a50f102a --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/entry-macro.S @@ -0,0 +1,29 @@ +/* + * arch/arm/mach-prima2/include/mach/entry-macro.S + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include + +#define SIRFSOC_INT_ID 0x38 + + .macro get_irqnr_preamble, base, tmp + ldr \base, =sirfsoc_intc_base + ldr \base, [\base] + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqnr, [\base, #SIRFSOC_INT_ID] @ Get the highest priority irq + cmp \irqnr, #0x40 @ the irq num can't be larger than 0x3f + movges \irqnr, #0 + .endm + + .macro disable_fiq + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h new file mode 100644 index 00000000000..105b96964f2 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/hardware.h @@ -0,0 +1,15 @@ +/* + * arch/arm/mach-prima2/include/mach/hardware.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_HARDWARE_H__ +#define __MACH_HARDWARE_H__ + +#include +#include + +#endif diff --git a/arch/arm/mach-prima2/include/mach/io.h b/arch/arm/mach-prima2/include/mach/io.h new file mode 100644 index 00000000000..6c31e9ec279 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/io.h @@ -0,0 +1,16 @@ +/* + * arch/arm/mach-prima2/include/mach/io.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_PRIMA2_IO_H +#define __MACH_PRIMA2_IO_H + +#define IO_SPACE_LIMIT ((resource_size_t)0) + +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h new file mode 100644 index 00000000000..bb354f952fd --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/irqs.h @@ -0,0 +1,17 @@ +/* + * arch/arm/mach-prima2/include/mach/irqs.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#define SIRFSOC_INTENAL_IRQ_START 0 +#define SIRFSOC_INTENAL_IRQ_END 59 + +#define NR_IRQS 220 + +#endif diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h new file mode 100644 index 00000000000..66b1ae2e553 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/map.h @@ -0,0 +1,16 @@ +/* + * memory & I/O static mapping definitions for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_PRIMA2_MAP_H__ +#define __MACH_PRIMA2_MAP_H__ + +#include + +#define SIRFSOC_VA(x) (VMALLOC_END + ((x) & 0x00FFF000)) + +#endif diff --git a/arch/arm/mach-prima2/include/mach/memory.h b/arch/arm/mach-prima2/include/mach/memory.h new file mode 100644 index 00000000000..368cd5a0601 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/memory.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-prima2/include/mach/memory.h + * + * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PLAT_PHYS_OFFSET UL(0x00000000) + +/* + * Restrict DMA-able region to workaround silicon limitation. + * The limitation restricts buffers available for DMA to SD/MMC + * hardware to be below 256MB + */ +#define ARM_DMA_ZONE_SIZE (SZ_256M) + +#endif diff --git a/arch/arm/mach-prima2/include/mach/system.h b/arch/arm/mach-prima2/include/mach/system.h new file mode 100644 index 00000000000..0dbd257ad16 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/system.h @@ -0,0 +1,29 @@ +/* + * arch/arm/mach-prima2/include/mach/system.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_SYSTEM_H__ +#define __MACH_SYSTEM_H__ + +#include +#include + +#define SIRFSOC_SYS_RST_BIT BIT(31) + +extern void __iomem *sirfsoc_rstc_base; + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base); +} + +#endif diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h new file mode 100644 index 00000000000..d6f98a75e56 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/timex.h @@ -0,0 +1,14 @@ +/* + * arch/arm/mach-prima2/include/mach/timex.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_TIMEX_H__ +#define __MACH_TIMEX_H__ + +#define CLOCK_TICK_RATE 1000000 + +#endif diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h new file mode 100644 index 00000000000..c98b4d5ac24 --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/uart.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-prima2/include/mach/uart.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_PRIMA2_SIRFSOC_UART_H +#define __MACH_PRIMA2_SIRFSOC_UART_H + +/* UART-1: used as serial debug port */ +#define SIRFSOC_UART1_PA_BASE 0xb0060000 +#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000) +#define SIRFSOC_UART1_SIZE SZ_4K + +#define SIRFSOC_UART_TXFIFO_STATUS 0x0114 +#define SIRFSOC_UART_TXFIFO_DATA 0x0118 + +#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5) +#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6) + +#endif diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h new file mode 100644 index 00000000000..83125c6a30b --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/uncompress.h @@ -0,0 +1,40 @@ +/* + * arch/arm/mach-prima2/include/mach/uncompress.h + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include +#include +#include + +void arch_decomp_setup(void) +{ +} + +#define arch_decomp_wdog() + +static __inline__ void putc(char c) +{ + /* + * during kernel decompression, all mappings are flat: + * virt_addr == phys_addr + */ + while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS) + & SIRFSOC_UART1_TXFIFO_FULL) + barrier(); + + __raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA); +} + +static inline void flush(void) +{ +} + +#endif + diff --git a/arch/arm/mach-prima2/include/mach/vmalloc.h b/arch/arm/mach-prima2/include/mach/vmalloc.h new file mode 100644 index 00000000000..c9f90fec78e --- /dev/null +++ b/arch/arm/mach-prima2/include/mach/vmalloc.h @@ -0,0 +1,16 @@ +/* + * arch/arm/ach-prima2/include/mach/vmalloc.h + * + * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef __MACH_VMALLOC_H +#define __MACH_VMALLOC_H + +#include + +#define VMALLOC_END _AC(0xFEC00000, UL) + +#endif diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c new file mode 100644 index 00000000000..c3404cbb6ff --- /dev/null +++ b/arch/arm/mach-prima2/irq.c @@ -0,0 +1,71 @@ +/* + * interrupt controller support for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_INT_RISC_MASK0 0x0018 +#define SIRFSOC_INT_RISC_MASK1 0x001C +#define SIRFSOC_INT_RISC_LEVEL0 0x0020 +#define SIRFSOC_INT_RISC_LEVEL1 0x0024 + +void __iomem *sirfsoc_intc_base; + +static __init void +sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq); + ct = gc->chip_types; + + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->regs.mask = SIRFSOC_INT_RISC_MASK0; + + irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0); +} + +static __init void sirfsoc_irq_init(void) +{ + sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32); + sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32); + + writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); + writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); + + writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); + writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); +} + +static struct of_device_id intc_ids[] = { + { .compatible = "sirf,prima2-intc" }, +}; + +void __init sirfsoc_of_irq_init(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, intc_ids); + if (!np) + panic("unable to find compatible intc node in dtb\n"); + + sirfsoc_intc_base = of_iomap(np, 0); + if (!sirfsoc_intc_base) + panic("unable to map intc cpu registers\n"); + + of_node_put(np); + + sirfsoc_irq_init(); +} diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c new file mode 100644 index 00000000000..c26947d76e1 --- /dev/null +++ b/arch/arm/mach-prima2/prima2.c @@ -0,0 +1,40 @@ +/* + * Defines machines for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include "common.h" + +static struct of_device_id sirfsoc_of_bus_ids[] __initdata = { + { .compatible = "simple-bus", }, + {}, +}; + +void __init sirfsoc_mach_init(void) +{ + of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL); +} + +static const char *prima2cb_dt_match[] __initdata = { + "sirf,prima2-cb", + NULL +}; + +MACHINE_START(PRIMA2_EVB, "prima2cb") + /* Maintainer: Barry Song */ + .boot_params = 0x00000100, + .init_early = sirfsoc_of_clk_init, + .init_irq = sirfsoc_of_irq_init, + .timer = &sirfsoc_timer, + .init_machine = sirfsoc_mach_init, + .dt_compat = prima2cb_dt_match, +MACHINE_END diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c new file mode 100644 index 00000000000..d074786e83d --- /dev/null +++ b/arch/arm/mach-prima2/rstc.c @@ -0,0 +1,69 @@ +/* + * reset controller for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +void __iomem *sirfsoc_rstc_base; +static DEFINE_MUTEX(rstc_lock); + +static struct of_device_id rstc_ids[] = { + { .compatible = "sirf,prima2-rstc" }, +}; + +static int __init sirfsoc_of_rstc_init(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, rstc_ids); + if (!np) + panic("unable to find compatible rstc node in dtb\n"); + + sirfsoc_rstc_base = of_iomap(np, 0); + if (!sirfsoc_rstc_base) + panic("unable to map rstc cpu registers\n"); + + of_node_put(np); + + return 0; +} +early_initcall(sirfsoc_of_rstc_init); + +int sirfsoc_reset_device(struct device *dev) +{ + const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL); + unsigned int reset_bit; + + if (!prop) + return -ENODEV; + + reset_bit = be32_to_cpup(prop); + + mutex_lock(&rstc_lock); + + /* + * Writing 1 to this bit resets corresponding block. Writing 0 to this + * bit de-asserts reset signal of the corresponding block. + * datasheet doesn't require explicit delay between the set and clear + * of reset bit. it could be shorter if tests pass. + */ + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit, + sirfsoc_rstc_base + (reset_bit / 32) * 4); + msleep(10); + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit, + sirfsoc_rstc_base + (reset_bit / 32) * 4); + + mutex_unlock(&rstc_lock); + + return 0; +} diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c new file mode 100644 index 00000000000..44027f34a88 --- /dev/null +++ b/arch/arm/mach-prima2/timer.c @@ -0,0 +1,217 @@ +/* + * System timer for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_TIMER_COUNTER_LO 0x0000 +#define SIRFSOC_TIMER_COUNTER_HI 0x0004 +#define SIRFSOC_TIMER_MATCH_0 0x0008 +#define SIRFSOC_TIMER_MATCH_1 0x000C +#define SIRFSOC_TIMER_MATCH_2 0x0010 +#define SIRFSOC_TIMER_MATCH_3 0x0014 +#define SIRFSOC_TIMER_MATCH_4 0x0018 +#define SIRFSOC_TIMER_MATCH_5 0x001C +#define SIRFSOC_TIMER_STATUS 0x0020 +#define SIRFSOC_TIMER_INT_EN 0x0024 +#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028 +#define SIRFSOC_TIMER_DIV 0x002C +#define SIRFSOC_TIMER_LATCH 0x0030 +#define SIRFSOC_TIMER_LATCHED_LO 0x0034 +#define SIRFSOC_TIMER_LATCHED_HI 0x0038 + +#define SIRFSOC_TIMER_WDT_INDEX 5 + +#define SIRFSOC_TIMER_LATCH_BIT BIT(0) + +static void __iomem *sirfsoc_timer_base; +static void __init sirfsoc_of_timer_map(void); + +/* timer0 interrupt handler */ +static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *ce = dev_id; + + WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0))); + + /* clear timer0 interrupt */ + writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS); + + ce->event_handler(ce); + + return IRQ_HANDLED; +} + +/* read 64-bit timer counter */ +static cycle_t sirfsoc_timer_read(struct clocksource *cs) +{ + u64 cycles; + + /* latch the 64-bit timer counter */ + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI); + cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); + + return cycles; +} + +static int sirfsoc_timer_set_next_event(unsigned long delta, + struct clock_event_device *ce) +{ + unsigned long now, next; + + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); + next = now + delta; + writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0); + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); + + return next - now > delta ? -ETIME : 0; +} + +static void sirfsoc_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *ce) +{ + u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + WARN_ON(1); + break; + case CLOCK_EVT_MODE_ONESHOT: + writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device sirfsoc_clockevent = { + .name = "sirfsoc_clockevent", + .rating = 200, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = sirfsoc_timer_set_mode, + .set_next_event = sirfsoc_timer_set_next_event, +}; + +static struct clocksource sirfsoc_clocksource = { + .name = "sirfsoc_clocksource", + .rating = 200, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .read = sirfsoc_timer_read, +}; + +static struct irqaction sirfsoc_timer_irq = { + .name = "sirfsoc_timer0", + .flags = IRQF_TIMER, + .irq = 0, + .handler = sirfsoc_timer_interrupt, + .dev_id = &sirfsoc_clockevent, +}; + +/* Overwrite weak default sched_clock with more precise one */ +unsigned long long notrace sched_clock(void) +{ + static int is_mapped = 0; + + /* + * sched_clock is called earlier than .init of sys_timer + * if we map timer memory in .init of sys_timer, system + * will panic due to illegal memory access + */ + if(!is_mapped) { + sirfsoc_of_timer_map(); + is_mapped = 1; + } + + return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE); +} + +static void __init sirfsoc_clockevent_init(void) +{ + clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60); + + sirfsoc_clockevent.max_delta_ns = + clockevent_delta2ns(-2, &sirfsoc_clockevent); + sirfsoc_clockevent.min_delta_ns = + clockevent_delta2ns(2, &sirfsoc_clockevent); + + sirfsoc_clockevent.cpumask = cpumask_of(0); + clockevents_register_device(&sirfsoc_clockevent); +} + +/* initialize the kernel jiffy timer source */ +static void __init sirfsoc_timer_init(void) +{ + unsigned long rate; + + /* timer's input clock is io clock */ + struct clk *clk = clk_get_sys("io", NULL); + + BUG_ON(IS_ERR(clk)); + + rate = clk_get_rate(clk); + + BUG_ON(rate < CLOCK_TICK_RATE); + BUG_ON(rate % CLOCK_TICK_RATE); + + writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); + writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS); + + BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE)); + + BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq)); + + sirfsoc_clockevent_init(); +} + +static struct of_device_id timer_ids[] = { + { .compatible = "sirf,prima2-tick" }, +}; + +static void __init sirfsoc_of_timer_map(void) +{ + struct device_node *np; + const unsigned int *intspec; + + np = of_find_matching_node(NULL, timer_ids); + if (!np) + panic("unable to find compatible timer node in dtb\n"); + sirfsoc_timer_base = of_iomap(np, 0); + if (!sirfsoc_timer_base) + panic("unable to map timer cpu registers\n"); + + /* Get the interrupts property */ + intspec = of_get_property(np, "interrupts", NULL); + BUG_ON(!intspec); + sirfsoc_timer_irq.irq = be32_to_cpup(intspec); + + of_node_put(np); +} + +struct sys_timer sirfsoc_timer = { + .init = sirfsoc_timer_init, +}; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 0074b8dba79..edf0681c0e2 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -821,7 +821,7 @@ config CACHE_L2X0 depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \ ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \ - ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE + ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || ARCH_PRIMA2 default y select OUTER_CACHE select OUTER_CACHE_SYNC -- cgit v1.2.3-70-g09d2 From 2b4180af3faaf6088162d8a6b8d3f571bd7c2004 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 25 Jul 2011 09:52:11 -0600 Subject: arm/dt: Add skeleton dtsi file Contains the bare minimum template required to boot with the device tree. Signed-off-by: Grant Likely --- arch/arm/boot/dts/skeleton.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 arch/arm/boot/dts/skeleton.dtsi (limited to 'arch/arm/boot') diff --git a/arch/arm/boot/dts/skeleton.dtsi b/arch/arm/boot/dts/skeleton.dtsi new file mode 100644 index 00000000000..b41d241de2c --- /dev/null +++ b/arch/arm/boot/dts/skeleton.dtsi @@ -0,0 +1,13 @@ +/* + * Skeleton device tree; the bare minimum needed to boot; just include and + * add a compatible value. The bootloader will typically populate the memory + * node. + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { }; + aliases { }; + memory { device_type = "memory"; reg = <0 0>; }; +}; -- cgit v1.2.3-70-g09d2 From 5fd1a2ed0ec6fb5449c71a988cc15edb8671b3d0 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 25 Jul 2011 09:52:12 -0600 Subject: arm/dt: Add dtb make rule Add a make rule to compile dt blobs for ARM. Signed-off-by: Rob Herring Acked-by: Shawn Guo Tested-by: Jason Liu Signed-off-by: Grant Likely --- arch/arm/Makefile | 7 +++++++ arch/arm/boot/Makefile | 6 ++++++ 2 files changed, 13 insertions(+) (limited to 'arch/arm/boot') diff --git a/arch/arm/Makefile b/arch/arm/Makefile index f5b2b390c8f..f7135595eb7 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -281,6 +281,12 @@ zImage Image xipImage bootpImage uImage: vmlinux zinstall uinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ +%.dtb: + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ + +dtbs: + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ + # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) @@ -297,6 +303,7 @@ define archhelp echo ' uImage - U-Boot wrapped zImage' echo ' bootpImage - Combined zImage and initial RAM disk' echo ' (supply initrd image via make variable INITRD=)' + echo ' dtbs - Build device tree blobs for enabled boards' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' echo ' uinstall - Install U-Boot wrapped compressed kernel' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 9128fddf110..a1edfd5a129 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -59,6 +59,12 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE endif +# Rule to build device tree blobs +$(obj)/%.dtb: $(src)/dts/%.dts + $(call cmd,dtc) + +$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y)) + quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ -C none -a $(LOADADDR) -e $(STARTADDR) \ -- cgit v1.2.3-70-g09d2 From 3ba7222ac992d24d09ccd0b55940b54849eef752 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 26 Jul 2011 03:19:06 -0600 Subject: arm/versatile: Add device tree support For testing the dt work, define a dt-enabled versatile platform. This patch adds a new versatile platform for when using the device tree. Add platform and amba devices are discovered and registered by parsing the device tree. Clocks and initial io mappings are still configured statically. This patch still depends on some static platform_data for a few devices which is passed via the auxdata structure to of_platform_populate(), but it is a viable starting point until the drivers can get all configuration data out of the device tree. Signed-off-by: Grant Likely --- Documentation/devicetree/bindings/arm/arm-boards | 20 +++ .../devicetree/bindings/i2c/arm-versatile.txt | 10 ++ .../devicetree/bindings/mtd/arm-versatile.txt | 8 + .../devicetree/bindings/net/smsc-lan91c111.txt | 10 ++ arch/arm/boot/dts/versatile-ab.dts | 192 +++++++++++++++++++++ arch/arm/boot/dts/versatile-pb.dts | 48 ++++++ arch/arm/mach-versatile/Kconfig | 8 + arch/arm/mach-versatile/Makefile | 1 + arch/arm/mach-versatile/core.c | 62 +++++++ arch/arm/mach-versatile/core.h | 4 + arch/arm/mach-versatile/versatile_dt.c | 51 ++++++ 11 files changed, 414 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm-boards create mode 100644 Documentation/devicetree/bindings/i2c/arm-versatile.txt create mode 100644 Documentation/devicetree/bindings/mtd/arm-versatile.txt create mode 100644 Documentation/devicetree/bindings/net/smsc-lan91c111.txt create mode 100644 arch/arm/boot/dts/versatile-ab.dts create mode 100644 arch/arm/boot/dts/versatile-pb.dts create mode 100644 arch/arm/mach-versatile/versatile_dt.c (limited to 'arch/arm/boot') diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards new file mode 100644 index 00000000000..91f26148af7 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm-boards @@ -0,0 +1,20 @@ +ARM Versatile Application and Platform Baseboards +------------------------------------------------- +ARM's development hardware platform with connectors for customizable +core tiles. The hardware configuration of the Versatile boards is +highly customizable. + +Required properties (in root node): + compatible = "arm,versatile-ab"; /* Application baseboard */ + compatible = "arm,versatile-pb"; /* Platform baseboard */ + +Interrupt controllers: +- VIC required properties: + compatible = "arm,versatile-vic"; + interrupt-controller; + #interrupt-cells = <1>; + +- SIC required properties: + compatible = "arm,versatile-sic"; + interrupt-controller; + #interrupt-cells = <1>; diff --git a/Documentation/devicetree/bindings/i2c/arm-versatile.txt b/Documentation/devicetree/bindings/i2c/arm-versatile.txt new file mode 100644 index 00000000000..361d31c51b6 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/arm-versatile.txt @@ -0,0 +1,10 @@ +i2c Controller on ARM Versatile platform: + +Required properties: +- compatible : Must be "arm,versatile-i2c"; +- reg +- #address-cells = <1>; +- #size-cells = <0>; + +Optional properties: +- Child nodes conforming to i2c bus binding diff --git a/Documentation/devicetree/bindings/mtd/arm-versatile.txt b/Documentation/devicetree/bindings/mtd/arm-versatile.txt new file mode 100644 index 00000000000..476845db94d --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/arm-versatile.txt @@ -0,0 +1,8 @@ +Flash device on ARM Versatile board + +Required properties: +- compatible : must be "arm,versatile-flash"; +- bank-width : width in bytes of flash interface. + +Optional properties: +- Subnode partition map from mtd flash binding diff --git a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt new file mode 100644 index 00000000000..953049b4248 --- /dev/null +++ b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt @@ -0,0 +1,10 @@ +SMSC LAN91c111 Ethernet mac + +Required properties: +- compatible = "smsc,lan91c111"; +- reg : physical address and size of registers +- interrupts : interrupt connection + +Optional properties: +- phy-device : phandle to Ethernet phy +- local-mac-address : Ethernet mac address to use diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts new file mode 100644 index 00000000000..0b32925f214 --- /dev/null +++ b/arch/arm/boot/dts/versatile-ab.dts @@ -0,0 +1,192 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + +/ { + model = "ARM Versatile AB"; + compatible = "arm,versatile-ab"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&vic>; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + i2c0 = &i2c0; + }; + + memory { + reg = <0x0 0x08000000>; + }; + + flash@34000000 { + compatible = "arm,versatile-flash"; + reg = <0x34000000 0x4000000>; + bank-width = <4>; + }; + + i2c0: i2c@10002000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,versatile-i2c"; + reg = <0x10002000 0x1000>; + + rtc@68 { + compatible = "dallas,ds1338"; + reg = <0x68>; + }; + }; + + net@10010000 { + compatible = "smsc,lan91c111"; + reg = <0x10010000 0x10000>; + interrupts = <25>; + }; + + lcd@10008000 { + compatible = "arm,versatile-lcd"; + reg = <0x10008000 0x1000>; + }; + + amba { + compatible = "arm,amba-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + vic: intc@10140000 { + compatible = "arm,versatile-vic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x10140000 0x1000>; + }; + + sic: intc@10003000 { + compatible = "arm,versatile-sic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x10003000 0x1000>; + interrupt-parent = <&vic>; + interrupts = <31>; /* Cascaded to vic */ + }; + + dma@10130000 { + compatible = "arm,pl081", "arm,primecell"; + reg = <0x10130000 0x1000>; + interrupts = <17>; + }; + + uart0: uart@101f1000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x101f1000 0x1000>; + interrupts = <12>; + }; + + uart1: uart@101f2000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x101f2000 0x1000>; + interrupts = <13>; + }; + + uart2: uart@101f3000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x101f3000 0x1000>; + interrupts = <14>; + }; + + smc@10100000 { + compatible = "arm,primecell"; + reg = <0x10100000 0x1000>; + }; + + mpmc@10110000 { + compatible = "arm,primecell"; + reg = <0x10110000 0x1000>; + }; + + display@10120000 { + compatible = "arm,pl110", "arm,primecell"; + reg = <0x10120000 0x1000>; + interrupts = <16>; + }; + + sctl@101e0000 { + compatible = "arm,primecell"; + reg = <0x101e0000 0x1000>; + }; + + watchdog@101e1000 { + compatible = "arm,primecell"; + reg = <0x101e1000 0x1000>; + interrupts = <0>; + }; + + gpio0: gpio@101e4000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x101e4000 0x1000>; + gpio-controller; + interrupts = <6>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio@101e5000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x101e5000 0x1000>; + interrupts = <7>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + rtc@101e8000 { + compatible = "arm,pl030", "arm,primecell"; + reg = <0x101e8000 0x1000>; + interrupts = <10>; + }; + + sci@101f0000 { + compatible = "arm,primecell"; + reg = <0x101f0000 0x1000>; + interrupts = <15>; + }; + + ssp@101f4000 { + compatible = "arm,pl022", "arm,primecell"; + reg = <0x101f4000 0x1000>; + interrupts = <11>; + }; + + fpga { + compatible = "arm,versatile-fpga", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x10000000 0x10000>; + + aaci@4000 { + compatible = "arm,primecell"; + reg = <0x4000 0x1000>; + interrupts = <24>; + }; + mmc@5000 { + compatible = "arm,primecell"; + reg = < 0x5000 0x1000>; + interrupts = <22>; + }; + kmi@6000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x6000 0x1000>; + interrupt-parent = <&sic>; + interrupts = <3>; + }; + kmi@7000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x7000 0x1000>; + interrupt-parent = <&sic>; + interrupts = <4>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts new file mode 100644 index 00000000000..8a614e39800 --- /dev/null +++ b/arch/arm/boot/dts/versatile-pb.dts @@ -0,0 +1,48 @@ +/include/ "versatile-ab.dts" + +/ { + model = "ARM Versatile PB"; + compatible = "arm,versatile-pb"; + + amba { + gpio2: gpio@101e6000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x101e6000 0x1000>; + interrupts = <8>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@101e7000 { + compatible = "arm,pl061", "arm,primecell"; + reg = <0x101e7000 0x1000>; + interrupts = <9>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + fpga { + uart@9000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x9000 0x1000>; + interrupt-parent = <&sic>; + interrupts = <6>; + }; + sci@a000 { + compatible = "arm,primecell"; + reg = <0xa000 0x1000>; + interrupt-parent = <&sic>; + interrupts = <5>; + }; + mmc@b000 { + compatible = "arm,primecell"; + reg = <0xb000 0x1000>; + interrupts = <23>; + }; + }; + }; +}; diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig index 9cdec5aa04a..c1f38f6625b 100644 --- a/arch/arm/mach-versatile/Kconfig +++ b/arch/arm/mach-versatile/Kconfig @@ -17,4 +17,12 @@ config MACH_VERSATILE_AB Include support for the ARM(R) Versatile Application Baseboard for the ARM926EJ-S. +config MACH_VERSATILE_DT + bool "Support Versatile platform from device tree" + select USE_OF + select CPU_ARM926T + help + Include support for the ARM(R) Versatile/PB platform, + using the device tree for discovery + endmenu diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile index 97cf4d831b0..81fa3fe25e1 100644 --- a/arch/arm/mach-versatile/Makefile +++ b/arch/arm/mach-versatile/Makefile @@ -5,4 +5,5 @@ obj-y := core.o obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o +obj-$(CONFIG_MACH_VERSATILE_DT) += versatile_dt.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 0c99cf076c6..e340a54251d 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -83,13 +86,26 @@ static struct fpga_irq_data sic_irq = { #define PIC_MASK 0 #endif +/* Lookup table for finding a DT node that represents the vic instance */ +static const struct of_device_id vic_of_match[] __initconst = { + { .compatible = "arm,versatile-vic", }, + {} +}; + +static const struct of_device_id sic_of_match[] __initconst = { + { .compatible = "arm,versatile-sic", }, + {} +}; + void __init versatile_init_irq(void) { vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0); + irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START); writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq); + irq_domain_generate_simple(sic_of_match, VERSATILE_SIC_BASE, IRQ_SIC_START); /* * Interrupts on secondary controller from 0 to 8 are routed to @@ -646,6 +662,52 @@ static struct amba_device *amba_devs[] __initdata = { &kmi1_device, }; +#ifdef CONFIG_OF +/* + * Lookup table for attaching a specific name and platform_data pointer to + * devices as they get created by of_platform_populate(). Ideally this table + * would not exist, but the current clock implementation depends on some devices + * having a specific name. + */ +struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = { + OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI0_BASE, "fpga:06", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI1_BASE, "fpga:07", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART3_BASE, "fpga:09", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", NULL), + + OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART0_BASE, "dev:f1", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART1_BASE, "dev:f2", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART2_BASE, "dev:f3", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", NULL), + +#if 0 + /* + * These entries are unnecessary because no clocks referencing + * them. I've left them in for now as place holders in case + * any of them need to be added back, but they should be + * removed before actually committing this patch. --gcl + */ + OF_DEV_AUXDATA("arm,primecell", VERSATILE_AACI_BASE, "fpga:04", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI1_BASE, "fpga:0a", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_SMC_BASE, "dev:00", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_MPMC_BASE, "dev:10", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_DMAC_BASE, "dev:30", NULL), + + OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCTL_BASE, "dev:e0", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_WATCHDOG_BASE, "dev:e1", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO0_BASE, "dev:e4", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO1_BASE, "dev:e5", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO2_BASE, "dev:e6", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO3_BASE, "dev:e7", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_RTC_BASE, "dev:e8", NULL), + OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI_BASE, "dev:f0", NULL), +#endif + {} +}; +#endif + #ifdef CONFIG_LEDS #define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h index fd6404e5d78..e01422700eb 100644 --- a/arch/arm/mach-versatile/core.h +++ b/arch/arm/mach-versatile/core.h @@ -23,6 +23,7 @@ #define __ASM_ARCH_VERSATILE_H #include +#include extern void __init versatile_init(void); extern void __init versatile_init_early(void); @@ -30,6 +31,9 @@ extern void __init versatile_init_irq(void); extern void __init versatile_map_io(void); extern struct sys_timer versatile_timer; extern unsigned int mmc_status(struct device *dev); +#ifdef CONFIG_OF +extern struct of_dev_auxdata versatile_auxdata_lookup[]; +#endif #define AMBA_DEVICE(name,busid,base,plat) \ static struct amba_device name##_device = { \ diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c new file mode 100644 index 00000000000..54e037c090f --- /dev/null +++ b/arch/arm/mach-versatile/versatile_dt.c @@ -0,0 +1,51 @@ +/* + * Versatile board support using the device tree + * + * Copyright (C) 2010 Secret Lab Technologies Ltd. + * Copyright (C) 2009 Jeremy Kerr + * Copyright (C) 2004 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 + */ + +#include +#include +#include +#include +#include + +#include "core.h" + +static void __init versatile_dt_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, + versatile_auxdata_lookup, NULL); +} + +static const char *versatile_dt_match[] __initconst = { + "arm,versatile-ab", + "arm,versatile-pb", + NULL, +}; + +DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)") + .map_io = versatile_map_io, + .init_early = versatile_init_early, + .init_irq = versatile_init_irq, + .timer = &versatile_timer, + .init_machine = versatile_dt_init, + .dt_compat = versatile_dt_match, +MACHINE_END -- cgit v1.2.3-70-g09d2 From 8e267f3da5f117d2f1316cf6ddf740f93f1c73aa Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 19 Jul 2011 17:26:54 -0600 Subject: arm/dt: tegra devicetree support Everything required to populate NVIDIA Tegra devices from the device tree. This patch adds a new DT_MACHINE_DESC() which matches against a tegra20 device tree. So far it only registers the on-chip devices, but it will be refined in follow on patches to configure clocks and pin IO from the device tree also. Signed-off-by: Grant Likely --- arch/arm/boot/dts/tegra-harmony.dts | 70 ++++++++++++++++++ arch/arm/boot/dts/tegra-seaboard.dts | 28 +++++++ arch/arm/boot/dts/tegra20.dtsi | 139 +++++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/Kconfig | 6 ++ arch/arm/mach-tegra/Makefile | 3 + arch/arm/mach-tegra/Makefile.boot | 3 + arch/arm/mach-tegra/board-dt.c | 119 ++++++++++++++++++++++++++++++ 7 files changed, 368 insertions(+) create mode 100644 arch/arm/boot/dts/tegra-harmony.dts create mode 100644 arch/arm/boot/dts/tegra-seaboard.dts create mode 100644 arch/arm/boot/dts/tegra20.dtsi create mode 100644 arch/arm/mach-tegra/board-dt.c (limited to 'arch/arm/boot') diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts new file mode 100644 index 00000000000..4c053340ce3 --- /dev/null +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -0,0 +1,70 @@ +/dts-v1/; + +/memreserve/ 0x1c000000 0x04000000; +/include/ "tegra20.dtsi" + +/ { + model = "NVIDIA Tegra2 Harmony evaluation board"; + compatible = "nvidia,harmony", "nvidia,tegra20"; + + chosen { + bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait"; + }; + + memory@0 { + reg = < 0x00000000 0x40000000 >; + }; + + i2c@7000c000 { + clock-frequency = <400000>; + + codec: wm8903@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupts = < 347 >; + + gpio-controller; + #gpio-cells = <2>; + + /* 0x8000 = Not configured */ + gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >; + }; + }; + + i2c@7000c400 { + clock-frequency = <400000>; + }; + + i2c@7000c500 { + clock-frequency = <400000>; + }; + + i2c@7000d000 { + clock-frequency = <400000>; + }; + + sound { + compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903"; + + spkr-en-gpios = <&codec 2 0>; + hp-det-gpios = <&gpio 178 0>; + int-mic-en-gpios = <&gpio 184 0>; + ext-mic-en-gpios = <&gpio 185 0>; + }; + + serial@70006300 { + clock-frequency = < 216000000 >; + }; + + sdhci@c8000200 { + gpios = <&gpio 69 0>, /* cd, gpio PI5 */ + <&gpio 57 0>, /* wp, gpio PH1 */ + <&gpio 155 0>; /* power, gpio PT3 */ + }; + + sdhci@c8000600 { + gpios = <&gpio 58 0>, /* cd, gpio PH2 */ + <&gpio 59 0>, /* wp, gpio PH3 */ + <&gpio 70 0>; /* power, gpio PI6 */ + }; +}; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts new file mode 100644 index 00000000000..1940cae0074 --- /dev/null +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -0,0 +1,28 @@ +/dts-v1/; + +/memreserve/ 0x1c000000 0x04000000; +/include/ "tegra20.dtsi" + +/ { + model = "NVIDIA Seaboard"; + compatible = "nvidia,seaboard", "nvidia,tegra20"; + + chosen { + bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait"; + }; + + memory { + device_type = "memory"; + reg = < 0x00000000 0x40000000 >; + }; + + serial@70006300 { + clock-frequency = < 216000000 >; + }; + + sdhci@c8000400 { + gpios = <&gpio 69 0>, /* cd, gpio PI5 */ + <&gpio 57 0>, /* wp, gpio PH1 */ + <&gpio 70 0>; /* power, gpio PI6 */ + }; +}; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi new file mode 100644 index 00000000000..5727595cde6 --- /dev/null +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -0,0 +1,139 @@ +/include/ "skeleton.dtsi" + +/ { + compatible = "nvidia,tegra20"; + interrupt-parent = <&intc>; + + intc: interrupt-controller@50041000 { + compatible = "nvidia,tegra20-gic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = < 0x50041000 0x1000 >, + < 0x50040100 0x0100 >; + }; + + i2c@7000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-i2c"; + reg = <0x7000C000 0x100>; + interrupts = < 70 >; + }; + + i2c@7000c400 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-i2c"; + reg = <0x7000C400 0x100>; + interrupts = < 116 >; + }; + + i2c@7000c500 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-i2c"; + reg = <0x7000C500 0x100>; + interrupts = < 124 >; + }; + + i2c@7000d000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-i2c"; + reg = <0x7000D000 0x200>; + interrupts = < 85 >; + }; + + i2s@70002800 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-i2s"; + reg = <0x70002800 0x200>; + interrupts = < 45 >; + dma-channel = < 2 >; + }; + + i2s@70002a00 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-i2s"; + reg = <0x70002a00 0x200>; + interrupts = < 35 >; + dma-channel = < 1 >; + }; + + das@70000c00 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra20-das"; + reg = <0x70000c00 0x80>; + }; + + gpio: gpio@6000d000 { + compatible = "nvidia,tegra20-gpio"; + reg = < 0x6000d000 0x1000 >; + interrupts = < 64 65 66 67 87 119 121 >; + #gpio-cells = <2>; + gpio-controller; + }; + + serial@70006000 { + compatible = "nvidia,tegra20-uart"; + reg = <0x70006000 0x40>; + reg-shift = <2>; + interrupts = < 68 >; + }; + + serial@70006040 { + compatible = "nvidia,tegra20-uart"; + reg = <0x70006040 0x40>; + reg-shift = <2>; + interrupts = < 69 >; + }; + + serial@70006200 { + compatible = "nvidia,tegra20-uart"; + reg = <0x70006200 0x100>; + reg-shift = <2>; + interrupts = < 78 >; + }; + + serial@70006300 { + compatible = "nvidia,tegra20-uart"; + reg = <0x70006300 0x100>; + reg-shift = <2>; + interrupts = < 122 >; + }; + + serial@70006400 { + compatible = "nvidia,tegra20-uart"; + reg = <0x70006400 0x100>; + reg-shift = <2>; + interrupts = < 123 >; + }; + + sdhci@c8000000 { + compatible = "nvidia,tegra20-sdhci"; + reg = <0xc8000000 0x200>; + interrupts = < 46 >; + }; + + sdhci@c8000200 { + compatible = "nvidia,tegra20-sdhci"; + reg = <0xc8000200 0x200>; + interrupts = < 47 >; + }; + + sdhci@c8000400 { + compatible = "nvidia,tegra20-sdhci"; + reg = <0xc8000400 0x200>; + interrupts = < 51 >; + }; + + sdhci@c8000600 { + compatible = "nvidia,tegra20-sdhci"; + reg = <0xc8000600 0x200>; + interrupts = < 63 >; + }; +}; + diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 5ec1846aa1d..4b8abf93bd9 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -51,6 +51,12 @@ config MACH_SEABOARD also be included for some of the derivative boards that have large similarities with the seaboard design. +config MACH_TEGRA_DT + bool "Generic Tegra board (FDT support)" + select USE_OF + help + Support for generic nVidia Tegra boards using Flattened Device Tree + config MACH_TRIMSLICE bool "TrimSlice board" select TEGRA_PCI diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index ed58ef9019b..f11b9100114 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -29,5 +29,8 @@ obj-${CONFIG_MACH_PAZ00} += board-paz00-pinmux.o obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o +obj-${CONFIG_MACH_TEGRA_DT} += board-dt.o +obj-${CONFIG_MACH_TEGRA_DT} += board-harmony-pinmux.o + obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot index db52d61a738..428ad122be0 100644 --- a/arch/arm/mach-tegra/Makefile.boot +++ b/arch/arm/mach-tegra/Makefile.boot @@ -1,3 +1,6 @@ zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00008000 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000 + +dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb +dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c new file mode 100644 index 00000000000..9f47e04446f --- /dev/null +++ b/arch/arm/mach-tegra/board-dt.c @@ -0,0 +1,119 @@ +/* + * nVidia Tegra device tree board support + * + * Copyright (C) 2010 Secret Lab Technologies, Ltd. + * Copyright (C) 2010 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "board.h" +#include "board-harmony.h" +#include "clock.h" +#include "devices.h" + +void harmony_pinmux_init(void); +void seaboard_pinmux_init(void); + + +struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { + OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_DVC_BASE, "tegra-i2c.3", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL), + {} +}; + +static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { + /* name parent rate enabled */ + { "uartd", "pll_p", 216000000, true }, + { NULL, NULL, 0, 0}, +}; + +static struct of_device_id tegra_dt_match_table[] __initdata = { + { .compatible = "simple-bus", }, + {} +}; + +static struct of_device_id tegra_dt_gic_match[] __initdata = { + { .compatible = "nvidia,tegra20-gic", }, + {} +}; + +static void __init tegra_dt_init(void) +{ + struct device_node *node; + + node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match, + TEGRA_ARM_INT_DIST_BASE); + if (node) + irq_domain_add_simple(node, INT_GIC_BASE); + + tegra_clk_init_from_table(tegra_dt_clk_init_table); + + if (of_machine_is_compatible("nvidia,harmony")) + harmony_pinmux_init(); + else if (of_machine_is_compatible("nvidia,seaboard")) + seaboard_pinmux_init(); + + /* + * Finished with the static registrations now; fill in the missing + * devices + */ + of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL); +} + +static const char * tegra_dt_board_compat[] = { + "nvidia,harmony", + "nvidia,seaboard", + NULL +}; + +DT_MACHINE_START(TEGRA_DT, "nVidia Tegra (Flattened Device Tree)") + .map_io = tegra_map_common_io, + .init_early = tegra_init_early, + .init_irq = tegra_init_irq, + .timer = &tegra_timer, + .init_machine = tegra_dt_init, + .dt_compat = tegra_dt_board_compat, +MACHINE_END -- cgit v1.2.3-70-g09d2