aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-zynq
diff options
context:
space:
mode:
authorJohn Linn <john.linn@xilinx.com>2011-06-20 13:47:27 -0400
committerJohn Linn <john.linn@xilinx.com>2011-06-20 13:52:30 -0400
commitb85a3ef4ac65169b65fd2fe9bec7912bbf475ba4 (patch)
tree4a629040873bf9f0c34c8e7c970617dcce9b30e9 /arch/arm/mach-zynq
parent2c53b436a30867eb6b47dd7bab23ba638d1fb0d2 (diff)
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 <john.linn@xilinx.com>
Diffstat (limited to 'arch/arm/mach-zynq')
-rw-r--r--arch/arm/mach-zynq/Makefile6
-rw-r--r--arch/arm/mach-zynq/Makefile.boot3
-rw-r--r--arch/arm/mach-zynq/board_dt.c37
-rw-r--r--arch/arm/mach-zynq/common.c102
-rw-r--r--arch/arm/mach-zynq/common.h29
-rw-r--r--arch/arm/mach-zynq/include/mach/clkdev.h32
-rw-r--r--arch/arm/mach-zynq/include/mach/debug-macro.S36
-rw-r--r--arch/arm/mach-zynq/include/mach/entry-macro.S30
-rw-r--r--arch/arm/mach-zynq/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-zynq/include/mach/io.h33
-rw-r--r--arch/arm/mach-zynq/include/mach/irqs.h21
-rw-r--r--arch/arm/mach-zynq/include/mach/memory.h22
-rw-r--r--arch/arm/mach-zynq/include/mach/system.h28
-rw-r--r--arch/arm/mach-zynq/include/mach/timex.h23
-rw-r--r--arch/arm/mach-zynq/include/mach/uart.h25
-rw-r--r--arch/arm/mach-zynq/include/mach/uncompress.h51
-rw-r--r--arch/arm/mach-zynq/include/mach/vmalloc.h20
-rw-r--r--arch/arm/mach-zynq/include/mach/zynq_soc.h48
-rw-r--r--arch/arm/mach-zynq/timer.c298
19 files changed, 862 insertions, 0 deletions
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644
index 000000000000..c550c67aa893
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Common support
6obj-y := common.o timer.o board_dt.o
diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
new file mode 100644
index 000000000000..67039c3e0c48
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile.boot
@@ -0,0 +1,3 @@
1 zreladdr-y := 0x00008000
2params_phys-y := 0x00000100
3initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
new file mode 100644
index 000000000000..5b4710d09258
--- /dev/null
+++ b/arch/arm/mach-zynq/board_dt.c
@@ -0,0 +1,37 @@
1/*
2 * This file contains code for boards with device tree support.
3 *
4 * Copyright (C) 2011 Xilinx
5 *
6 * based on arch/arm/mach-realview/core.c
7 *
8 * Copyright (C) 1999 - 2003 ARM Limited
9 * Copyright (C) 2000 Deep Blue Solutions Ltd
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/of.h>
22#include <asm/mach/arch.h>
23#include <asm/mach-types.h>
24#include "common.h"
25
26static const char *xilinx_dt_match[] = {
27 "xlnx,zynq-ep107",
28 NULL
29};
30
31MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
32 .map_io = xilinx_map_io,
33 .init_irq = xilinx_irq_init,
34 .init_machine = xilinx_init_machine,
35 .timer = &xttcpss_sys_timer,
36 .dt_compat = xilinx_dt_match,
37MACHINE_END
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
new file mode 100644
index 000000000000..b3ac5c2e12dc
--- /dev/null
+++ b/arch/arm/mach-zynq/common.c
@@ -0,0 +1,102 @@
1/*
2 * This file contains common code that is intended to be used across
3 * boards so that it's not replicated.
4 *
5 * Copyright (C) 2011 Xilinx
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/cpumask.h>
20#include <linux/platform_device.h>
21#include <linux/clk.h>
22#include <linux/of_irq.h>
23#include <linux/of_platform.h>
24
25#include <asm/mach/map.h>
26#include <asm/page.h>
27#include <asm/hardware/gic.h>
28#include <asm/hardware/cache-l2x0.h>
29
30#include <mach/zynq_soc.h>
31#include <mach/clkdev.h>
32#include "common.h"
33
34static struct of_device_id zynq_of_bus_ids[] __initdata = {
35 { .compatible = "simple-bus", },
36 {}
37};
38
39/**
40 * xilinx_init_machine() - System specific initialization, intended to be
41 * called from board specific initialization.
42 */
43void __init xilinx_init_machine(void)
44{
45#ifdef CONFIG_CACHE_L2X0
46 /*
47 * 64KB way size, 8-way associativity, parity disabled
48 */
49 l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
50#endif
51
52 of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
53}
54
55/**
56 * xilinx_irq_init() - Interrupt controller initialization for the GIC.
57 */
58void __init xilinx_irq_init(void)
59{
60 gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
61}
62
63/* The minimum devices needed to be mapped before the VM system is up and
64 * running include the GIC, UART and Timer Counter.
65 */
66
67static struct map_desc io_desc[] __initdata = {
68 {
69 .virtual = TTC0_VIRT,
70 .pfn = __phys_to_pfn(TTC0_PHYS),
71 .length = SZ_4K,
72 .type = MT_DEVICE,
73 }, {
74 .virtual = SCU_PERIPH_VIRT,
75 .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
76 .length = SZ_8K,
77 .type = MT_DEVICE,
78 }, {
79 .virtual = PL310_L2CC_VIRT,
80 .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
81 .length = SZ_4K,
82 .type = MT_DEVICE,
83 },
84
85#ifdef CONFIG_DEBUG_LL
86 {
87 .virtual = UART0_VIRT,
88 .pfn = __phys_to_pfn(UART0_PHYS),
89 .length = SZ_4K,
90 .type = MT_DEVICE,
91 },
92#endif
93
94};
95
96/**
97 * xilinx_map_io() - Create memory mappings needed for early I/O.
98 */
99void __init xilinx_map_io(void)
100{
101 iotable_init(io_desc, ARRAY_SIZE(io_desc));
102}
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
new file mode 100644
index 000000000000..bca21968f80b
--- /dev/null
+++ b/arch/arm/mach-zynq/common.h
@@ -0,0 +1,29 @@
1/*
2 * This file contains common function prototypes to avoid externs
3 * in the c files.
4 *
5 * Copyright (C) 2011 Xilinx
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef __MACH_ZYNQ_COMMON_H__
18#define __MACH_ZYNQ_COMMON_H__
19
20#include <linux/init.h>
21#include <asm/mach/time.h>
22
23extern void xilinx_init_machine(void);
24extern void xilinx_irq_init(void);
25extern void xilinx_map_io(void);
26
27extern struct sys_timer xttcpss_sys_timer;
28
29#endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644
index 000000000000..c6e73d81a459
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/clkdev.h
@@ -0,0 +1,32 @@
1/*
2 * arch/arm/mach-zynq/include/mach/clkdev.h
3 *
4 * Copyright (C) 2011 Xilinx, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __MACH_CLKDEV_H__
18#define __MACH_CLKDEV_H__
19
20#include <plat/clock.h>
21
22struct clk {
23 unsigned long rate;
24 const struct clk_ops *ops;
25 const struct icst_params *params;
26 void __iomem *vcoreg;
27};
28
29#define __clk_get(clk) ({ 1; })
30#define __clk_put(clk) do { } while (0)
31
32#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
new file mode 100644
index 000000000000..9f664d5eb81d
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
1/* arch/arm/mach-zynq/include/mach/debug-macro.S
2 *
3 * Debugging macro include header
4 *
5 * Copyright (C) 2011 Xilinx
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <mach/zynq_soc.h>
18#include <mach/uart.h>
19
20 .macro addruart, rp, rv
21 ldr \rp, =LL_UART_PADDR @ physical
22 ldr \rv, =LL_UART_VADDR @ virtual
23 .endm
24
25 .macro senduart,rd,rx
26 str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
27 .endm
28
29 .macro waituart,rd,rx
30 .endm
31
32 .macro busyuart,rd,rx
331002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register
34 tst \rd, #UART_SR_TXFULL @
35 bne 1002b @ wait if FIFO is full
36 .endm
diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
new file mode 100644
index 000000000000..3cfc01b37461
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/entry-macro.S
@@ -0,0 +1,30 @@
1/*
2 * arch/arm/mach-zynq/include/mach/entry-macro.S
3 *
4 * Low-level IRQ helper macros
5 *
6 * Copyright (C) 2011 Xilinx
7 *
8 * based on arch/plat-mxc/include/mach/entry-macro.S
9 *
10 * Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
11 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
12 *
13 * This software is licensed under the terms of the GNU General Public
14 * License version 2, as published by the Free Software Foundation, and
15 * may be copied, distributed, and modified under those terms.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 */
22
23#include <mach/hardware.h>
24#include <asm/hardware/entry-macro-gic.S>
25
26 .macro disable_fiq
27 .endm
28
29 .macro arch_ret_to_user, tmp1, tmp2
30 .endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
new file mode 100644
index 000000000000..d558d8a94be7
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/hardware.h
@@ -0,0 +1,18 @@
1/* arch/arm/mach-zynq/include/mach/hardware.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_HARDWARE_H__
16#define __MACH_HARDWARE_H__
17
18#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
new file mode 100644
index 000000000000..39d9885e0e9a
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/io.h
@@ -0,0 +1,33 @@
1/* arch/arm/mach-zynq/include/mach/io.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_IO_H__
16#define __MACH_IO_H__
17
18/* Allow IO space to be anywhere in the memory */
19
20#define IO_SPACE_LIMIT 0xffff
21
22/* IO address mapping macros, nothing special at this time but required */
23
24#ifdef __ASSEMBLER__
25#define IOMEM(x) (x)
26#else
27#define IOMEM(x) ((void __force __iomem *)(x))
28#endif
29
30#define __io(a) __typesafe_io(a)
31#define __mem_pci(a) (a)
32
33#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
new file mode 100644
index 000000000000..5fb04fd3bac8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/irqs.h
@@ -0,0 +1,21 @@
1/* arch/arm/mach-zynq/include/mach/irqs.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_IRQS_H
16#define __MACH_IRQS_H
17
18#define ARCH_NR_GPIOS 118
19#define NR_IRQS (128 + ARCH_NR_GPIOS)
20
21#endif
diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
new file mode 100644
index 000000000000..35a92634dcc1
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/memory.h
@@ -0,0 +1,22 @@
1/* arch/arm/mach-zynq/include/mach/memory.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_MEMORY_H__
16#define __MACH_MEMORY_H__
17
18#include <asm/sizes.h>
19
20#define PLAT_PHYS_OFFSET UL(0x0)
21
22#endif
diff --git a/arch/arm/mach-zynq/include/mach/system.h b/arch/arm/mach-zynq/include/mach/system.h
new file mode 100644
index 000000000000..1b84d705c675
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/system.h
@@ -0,0 +1,28 @@
1/* arch/arm/mach-zynq/include/mach/system.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_SYSTEM_H__
16#define __MACH_SYSTEM_H__
17
18static inline void arch_idle(void)
19{
20 cpu_do_idle();
21}
22
23static inline void arch_reset(char mode, const char *cmd)
24{
25 /* Add architecture specific reset processing here */
26}
27
28#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
new file mode 100644
index 000000000000..6c0245e42a5e
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/timex.h
@@ -0,0 +1,23 @@
1/* arch/arm/mach-zynq/include/mach/timex.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_TIMEX_H__
16#define __MACH_TIMEX_H__
17
18/* the following is needed for the system to build but will be removed
19 in the future, the value is not important but won't hurt
20*/
21#define CLOCK_TICK_RATE (100 * HZ)
22
23#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
new file mode 100644
index 000000000000..5c47c97156f3
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uart.h
@@ -0,0 +1,25 @@
1/* arch/arm/mach-zynq/include/mach/uart.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_UART_H__
16#define __MACH_UART_H__
17
18#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
19#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
20#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
21
22#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
23#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
24
25#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
new file mode 100644
index 000000000000..af4e8447bfa3
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uncompress.h
@@ -0,0 +1,51 @@
1/* arch/arm/mach-zynq/include/mach/uncompress.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_UNCOMPRESS_H__
16#define __MACH_UNCOMPRESS_H__
17
18#include <linux/io.h>
19#include <asm/processor.h>
20#include <mach/zynq_soc.h>
21#include <mach/uart.h>
22
23void arch_decomp_setup(void)
24{
25}
26
27static inline void flush(void)
28{
29 /*
30 * Wait while the FIFO is not empty
31 */
32 while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
33 UART_SR_TXEMPTY))
34 cpu_relax();
35}
36
37#define arch_decomp_wdog()
38
39static void putc(char ch)
40{
41 /*
42 * Wait for room in the FIFO, then write the char into the FIFO
43 */
44 while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
45 UART_SR_TXFULL)
46 cpu_relax();
47
48 __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
49}
50
51#endif
diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
new file mode 100644
index 000000000000..2398eff1e8b8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
1/* arch/arm/mach-zynq/include/mach/vmalloc.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_VMALLOC_H__
16#define __MACH_VMALLOC_H__
17
18#define VMALLOC_END 0xE0000000UL
19
20#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
new file mode 100644
index 000000000000..d0d3f8fb06dd
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq_soc.h
@@ -0,0 +1,48 @@
1/* arch/arm/mach-zynq/include/mach/zynq_soc.h
2 *
3 * Copyright (C) 2011 Xilinx
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __MACH_XILINX_SOC_H__
16#define __MACH_XILINX_SOC_H__
17
18#define PERIPHERAL_CLOCK_RATE 2500000
19
20/* For now, all mappings are flat (physical = virtual)
21 */
22#define UART0_PHYS 0xE0000000
23#define UART0_VIRT UART0_PHYS
24
25#define TTC0_PHYS 0xF8001000
26#define TTC0_VIRT TTC0_PHYS
27
28#define PL310_L2CC_PHYS 0xF8F02000
29#define PL310_L2CC_VIRT PL310_L2CC_PHYS
30
31#define SCU_PERIPH_PHYS 0xF8F00000
32#define SCU_PERIPH_VIRT SCU_PERIPH_PHYS
33
34/* The following are intended for the devices that are mapped early */
35
36#define TTC0_BASE IOMEM(TTC0_VIRT)
37#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT)
38#define SCU_GIC_CPU_BASE (SCU_PERIPH_BASE + 0x100)
39#define SCU_GIC_DIST_BASE (SCU_PERIPH_BASE + 0x1000)
40#define PL310_L2CC_BASE IOMEM(PL310_L2CC_VIRT)
41
42/*
43 * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
44 */
45#define LL_UART_PADDR UART0_PHYS
46#define LL_UART_VADDR UART0_VIRT
47
48#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
new file mode 100644
index 000000000000..c2c96cc7d6e7
--- /dev/null
+++ b/arch/arm/mach-zynq/timer.c
@@ -0,0 +1,298 @@
1/*
2 * This file contains driver for the Xilinx PS Timer Counter IP.
3 *
4 * Copyright (C) 2011 Xilinx
5 *
6 * based on arch/mips/kernel/time.c timer driver
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22#include <linux/types.h>
23#include <linux/clocksource.h>
24#include <linux/clockchips.h>
25#include <linux/io.h>
26
27#include <asm/mach/time.h>
28#include <mach/zynq_soc.h>
29#include "common.h"
30
31#define IRQ_TIMERCOUNTER0 42
32
33/*
34 * This driver configures the 2 16-bit count-up timers as follows:
35 *
36 * T1: Timer 1, clocksource for generic timekeeping
37 * T2: Timer 2, clockevent source for hrtimers
38 * T3: Timer 3, <unused>
39 *
40 * The input frequency to the timer module for emulation is 2.5MHz which is
41 * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
42 * the timers are clocked at 78.125KHz (12.8 us resolution).
43 *
44 * The input frequency to the timer module in silicon will be 200MHz. With the
45 * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
46 */
47#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
48#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
49
50#define XTTCPSS_TIMER_BASE TTC0_BASE
51#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
52/*
53 * Timer Register Offset Definitions of Timer 1, Increment base address by 4
54 * and use same offsets for Timer 2
55 */
56#define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */
57#define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */
58#define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */
59#define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */
60#define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */
61#define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */
62#define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */
63#define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */
64#define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */
65
66#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
67
68/* Setup the timers to use pre-scaling */
69
70#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
71
72/**
73 * struct xttcpss_timer - This definition defines local timer structure
74 *
75 * @base_addr: Base address of timer
76 **/
77struct xttcpss_timer {
78 void __iomem *base_addr;
79};
80
81static struct xttcpss_timer timers[2];
82static struct clock_event_device xttcpss_clockevent;
83
84/**
85 * xttcpss_set_interval - Set the timer interval value
86 *
87 * @timer: Pointer to the timer instance
88 * @cycles: Timer interval ticks
89 **/
90static void xttcpss_set_interval(struct xttcpss_timer *timer,
91 unsigned long cycles)
92{
93 u32 ctrl_reg;
94
95 /* Disable the counter, set the counter value and re-enable counter */
96 ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
97 ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
98 __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
99
100 __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
101
102 /* Reset the counter (0x10) so that it starts from 0, one-shot
103 mode makes this needed for timing to be right. */
104 ctrl_reg |= 0x10;
105 ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
106 __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
107}
108
109/**
110 * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
111 *
112 * @irq: IRQ number of the Timer
113 * @dev_id: void pointer to the xttcpss_timer instance
114 *
115 * returns: Always IRQ_HANDLED - success
116 **/
117static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
118{
119 struct clock_event_device *evt = &xttcpss_clockevent;
120 struct xttcpss_timer *timer = dev_id;
121
122 /* Acknowledge the interrupt and call event handler */
123 __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
124 timer->base_addr + XTTCPSS_ISR_OFFSET);
125
126 evt->event_handler(evt);
127
128 return IRQ_HANDLED;
129}
130
131static struct irqaction event_timer_irq = {
132 .name = "xttcpss clockevent",
133 .flags = IRQF_DISABLED | IRQF_TIMER,
134 .handler = xttcpss_clock_event_interrupt,
135};
136
137/**
138 * xttcpss_timer_hardware_init - Initialize the timer hardware
139 *
140 * Initialize the hardware to start the clock source, get the clock
141 * event timer ready to use, and hook up the interrupt.
142 **/
143static void __init xttcpss_timer_hardware_init(void)
144{
145 /* Setup the clock source counter to be an incrementing counter
146 * with no interrupt and it rolls over at 0xFFFF. Pre-scale
147 it by 32 also. Let it start running now.
148 */
149 timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
150
151 __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
152 XTTCPSS_IER_OFFSET);
153 __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
154 XTTCPSS_CLK_CNTRL_OFFSET);
155 __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
156 XTTCPSS_CNT_CNTRL_OFFSET);
157
158 /* Setup the clock event timer to be an interval timer which
159 * is prescaled by 32 using the interval interrupt. Leave it
160 * disabled for now.
161 */
162
163 timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
164
165 __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
166 XTTCPSS_CNT_CNTRL_OFFSET);
167 __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
168 XTTCPSS_CLK_CNTRL_OFFSET);
169 __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
170 XTTCPSS_IER_OFFSET);
171
172 /* Setup IRQ the clock event timer */
173 event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
174 setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
175}
176
177/**
178 * __raw_readl_cycles - Reads the timer counter register
179 *
180 * returns: Current timer counter register value
181 **/
182static cycle_t __raw_readl_cycles(struct clocksource *cs)
183{
184 struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
185
186 return (cycle_t)__raw_readl(timer->base_addr +
187 XTTCPSS_COUNT_VAL_OFFSET);
188}
189
190
191/*
192 * Instantiate and initialize the clock source structure
193 */
194static struct clocksource clocksource_xttcpss = {
195 .name = "xttcpss_timer1",
196 .rating = 200, /* Reasonable clock source */
197 .read = __raw_readl_cycles,
198 .mask = CLOCKSOURCE_MASK(16),
199 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
200};
201
202
203/**
204 * xttcpss_set_next_event - Sets the time interval for next event
205 *
206 * @cycles: Timer interval ticks
207 * @evt: Address of clock event instance
208 *
209 * returns: Always 0 - success
210 **/
211static int xttcpss_set_next_event(unsigned long cycles,
212 struct clock_event_device *evt)
213{
214 struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
215
216 xttcpss_set_interval(timer, cycles);
217 return 0;
218}
219
220/**
221 * xttcpss_set_mode - Sets the mode of timer
222 *
223 * @mode: Mode to be set
224 * @evt: Address of clock event instance
225 **/
226static void xttcpss_set_mode(enum clock_event_mode mode,
227 struct clock_event_device *evt)
228{
229 struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
230 u32 ctrl_reg;
231
232 switch (mode) {
233 case CLOCK_EVT_MODE_PERIODIC:
234 xttcpss_set_interval(timer, TIMER_RATE / HZ);
235 break;
236 case CLOCK_EVT_MODE_ONESHOT:
237 case CLOCK_EVT_MODE_UNUSED:
238 case CLOCK_EVT_MODE_SHUTDOWN:
239 ctrl_reg = __raw_readl(timer->base_addr +
240 XTTCPSS_CNT_CNTRL_OFFSET);
241 ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
242 __raw_writel(ctrl_reg,
243 timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
244 break;
245 case CLOCK_EVT_MODE_RESUME:
246 ctrl_reg = __raw_readl(timer->base_addr +
247 XTTCPSS_CNT_CNTRL_OFFSET);
248 ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
249 __raw_writel(ctrl_reg,
250 timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
251 break;
252 }
253}
254
255/*
256 * Instantiate and initialize the clock event structure
257 */
258static struct clock_event_device xttcpss_clockevent = {
259 .name = "xttcpss_timer2",
260 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
261 .set_next_event = xttcpss_set_next_event,
262 .set_mode = xttcpss_set_mode,
263 .rating = 200,
264};
265
266/**
267 * xttcpss_timer_init - Initialize the timer
268 *
269 * Initializes the timer hardware and register the clock source and clock event
270 * timers with Linux kernal timer framework
271 **/
272static void __init xttcpss_timer_init(void)
273{
274 xttcpss_timer_hardware_init();
275 clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
276
277 /* Calculate the parameters to allow the clockevent to operate using
278 integer math
279 */
280 clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
281
282 xttcpss_clockevent.max_delta_ns =
283 clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
284 xttcpss_clockevent.min_delta_ns =
285 clockevent_delta2ns(1, &xttcpss_clockevent);
286
287 /* Indicate that clock event is on 1st CPU as SMP boot needs it */
288
289 xttcpss_clockevent.cpumask = cpumask_of(0);
290 clockevents_register_device(&xttcpss_clockevent);
291}
292
293/*
294 * Instantiate and initialize the system timer structure
295 */
296struct sys_timer xttcpss_sys_timer = {
297 .init = xttcpss_timer_init,
298};