diff options
author | Olof Johansson <olof@lixom.net> | 2012-11-21 14:49:45 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-11-21 14:49:45 -0500 |
commit | 3f54db784a6af9a6d53396949cbecf62edbad247 (patch) | |
tree | 2be84e7be0c83a76432d9b2b00b0bd1ba0328839 /arch/arm | |
parent | 46e8a79eb5449204f4b20d71c38c96b981b04e96 (diff) | |
parent | acda38aab6a4e2a7ba56a07e27791384030acb4b (diff) |
Merge branch 'zynq/multiplatform' of git://git.monstr.eu/linux-2.6-microblaze into next/multiplatform
From Michal Simek:
This branch depends on arm-soc devel/debug_ll_init branch because
we needed Rob's "ARM: implement debug_ll_io_init()"
(sha1: afaee03511ba8002b26a9c6b1fe7d6baf33eac86)
patch.
This branch also depends on zynq/dt branch because of previous major
zynq changes.
zynq/cleanup branch is subset of zynq/dt.
* 'zynq/multiplatform' of git://git.monstr.eu/linux-2.6-microblaze:
ARM: zynq: Remove all unused mach headers
ARM: zynq: add support for ARCH_MULTIPLATFORM
ARM: zynq: make use of debug_ll_io_init()
ARM: zynq: remove TTC early mapping
ARM: zynq: add clk binding support to the ttc
ARM: zynq: use zynq clk bindings
clk: Add support for fundamental zynq clks
ARM: zynq: dts: split up device tree
ARM: zynq: Allow UART1 to be used as DEBUG_LL console.
ARM: zynq: dts: add description of the second uart
ARM: zynq: move arm-specific sys_timer out of ttc
zynq: move static peripheral mappings
zynq: remove use of CLKDEV_LOOKUP
zynq: use pl310 device tree bindings
zynq: use GIC device tree bindings
Add/add conflict in arch/arm/Kconfig.debug.
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 14 | ||||
-rw-r--r-- | arch/arm/Kconfig.debug | 18 | ||||
-rw-r--r-- | arch/arm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/zynq-7000.dtsi | 166 | ||||
-rw-r--r-- | arch/arm/boot/dts/zynq-ep107.dts | 52 | ||||
-rw-r--r-- | arch/arm/boot/dts/zynq-zc702.dts | 44 | ||||
-rw-r--r-- | arch/arm/include/debug/zynq.S (renamed from arch/arm/mach-zynq/include/mach/debug-macro.S) | 23 | ||||
-rw-r--r-- | arch/arm/mach-zynq/Kconfig | 13 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.c | 80 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/clkdev.h | 32 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/hardware.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/irqs.h | 21 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/timex.h | 23 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/uart.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/uncompress.h | 51 | ||||
-rw-r--r-- | arch/arm/mach-zynq/include/mach/zynq_soc.h | 48 | ||||
-rw-r--r-- | arch/arm/mach-zynq/timer.c | 298 |
19 files changed, 473 insertions, 459 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9277f503481c..d244249178b6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -960,18 +960,6 @@ config ARCH_VT8500_SINGLE | |||
960 | help | 960 | help |
961 | Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. | 961 | Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. |
962 | 962 | ||
963 | config ARCH_ZYNQ | ||
964 | bool "Xilinx Zynq ARM Cortex A9 Platform" | ||
965 | select ARM_AMBA | ||
966 | select ARM_GIC | ||
967 | select CLKDEV_LOOKUP | ||
968 | select CPU_V7 | ||
969 | select GENERIC_CLOCKEVENTS | ||
970 | select ICST | ||
971 | select MIGHT_HAVE_CACHE_L2X0 | ||
972 | select USE_OF | ||
973 | help | ||
974 | Support for Xilinx Zynq ARM Cortex A9 Platform | ||
975 | endchoice | 963 | endchoice |
976 | 964 | ||
977 | menu "Multiple platform selection" | 965 | menu "Multiple platform selection" |
@@ -1134,6 +1122,8 @@ source "arch/arm/mach-vt8500/Kconfig" | |||
1134 | 1122 | ||
1135 | source "arch/arm/mach-w90x900/Kconfig" | 1123 | source "arch/arm/mach-w90x900/Kconfig" |
1136 | 1124 | ||
1125 | source "arch/arm/mach-zynq/Kconfig" | ||
1126 | |||
1137 | # Definitions to make life easier | 1127 | # Definitions to make life easier |
1138 | config ARCH_ACORN | 1128 | config ARCH_ACORN |
1139 | bool | 1129 | bool |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 96b9425219d9..be70fe56bbeb 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -132,6 +132,23 @@ choice | |||
132 | their output to UART1 serial port on DaVinci TNETV107X | 132 | their output to UART1 serial port on DaVinci TNETV107X |
133 | devices. | 133 | devices. |
134 | 134 | ||
135 | config DEBUG_ZYNQ_UART0 | ||
136 | bool "Kernel low-level debugging on Xilinx Zynq using UART0" | ||
137 | depends on ARCH_ZYNQ | ||
138 | help | ||
139 | Say Y here if you want the debug print routines to direct | ||
140 | their output to UART0 on the Zynq platform. | ||
141 | |||
142 | config DEBUG_ZYNQ_UART1 | ||
143 | bool "Kernel low-level debugging on Xilinx Zynq using UART1" | ||
144 | depends on ARCH_ZYNQ | ||
145 | help | ||
146 | Say Y here if you want the debug print routines to direct | ||
147 | their output to UART1 on the Zynq platform. | ||
148 | |||
149 | If you have a ZC702 board and want early boot messages to | ||
150 | appear on the USB serial adaptor, select this option. | ||
151 | |||
135 | config DEBUG_DC21285_PORT | 152 | config DEBUG_DC21285_PORT |
136 | bool "Kernel low-level debugging messages via footbridge serial port" | 153 | bool "Kernel low-level debugging messages via footbridge serial port" |
137 | depends on FOOTBRIDGE | 154 | depends on FOOTBRIDGE |
@@ -456,6 +473,7 @@ config DEBUG_LL_INCLUDE | |||
456 | default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \ | 473 | default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \ |
457 | DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 | 474 | DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 |
458 | default "debug/tegra.S" if DEBUG_TEGRA_UART | 475 | default "debug/tegra.S" if DEBUG_TEGRA_UART |
476 | default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 | ||
459 | default "mach/debug-macro.S" | 477 | default "mach/debug-macro.S" |
460 | 478 | ||
461 | config EARLY_PRINTK | 479 | config EARLY_PRINTK |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 89087d599ad2..aa90b6670794 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -199,7 +199,6 @@ machine-$(CONFIG_ARCH_ZYNQ) += zynq | |||
199 | plat-$(CONFIG_ARCH_MXC) += mxc | 199 | plat-$(CONFIG_ARCH_MXC) += mxc |
200 | plat-$(CONFIG_ARCH_OMAP) += omap | 200 | plat-$(CONFIG_ARCH_OMAP) += omap |
201 | plat-$(CONFIG_ARCH_S3C64XX) += samsung | 201 | plat-$(CONFIG_ARCH_S3C64XX) += samsung |
202 | plat-$(CONFIG_ARCH_ZYNQ) += versatile | ||
203 | plat-$(CONFIG_PLAT_IOP) += iop | 202 | plat-$(CONFIG_PLAT_IOP) += iop |
204 | plat-$(CONFIG_PLAT_ORION) += orion | 203 | plat-$(CONFIG_PLAT_ORION) += orion |
205 | plat-$(CONFIG_PLAT_PXA) += pxa | 204 | plat-$(CONFIG_PLAT_PXA) += pxa |
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f37cf9fa5fa0..76ed11e68f72 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile | |||
@@ -103,5 +103,6 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ | |||
103 | dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ | 103 | dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ |
104 | wm8505-ref.dtb \ | 104 | wm8505-ref.dtb \ |
105 | wm8650-mid.dtb | 105 | wm8650-mid.dtb |
106 | dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb | ||
106 | 107 | ||
107 | endif | 108 | endif |
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi new file mode 100644 index 000000000000..401c1262d4ed --- /dev/null +++ b/arch/arm/boot/dts/zynq-7000.dtsi | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Xilinx | ||
3 | * | ||
4 | * This software is licensed under the terms of the GNU General Public | ||
5 | * License version 2, as published by the Free Software Foundation, and | ||
6 | * may be copied, distributed, and modified under those terms. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | /include/ "skeleton.dtsi" | ||
14 | |||
15 | / { | ||
16 | compatible = "xlnx,zynq-7000"; | ||
17 | |||
18 | amba { | ||
19 | compatible = "simple-bus"; | ||
20 | #address-cells = <1>; | ||
21 | #size-cells = <1>; | ||
22 | interrupt-parent = <&intc>; | ||
23 | ranges; | ||
24 | |||
25 | intc: interrupt-controller@f8f01000 { | ||
26 | compatible = "arm,cortex-a9-gic"; | ||
27 | #interrupt-cells = <3>; | ||
28 | #address-cells = <1>; | ||
29 | interrupt-controller; | ||
30 | reg = <0xF8F01000 0x1000>, | ||
31 | <0xF8F00100 0x100>; | ||
32 | }; | ||
33 | |||
34 | L2: cache-controller { | ||
35 | compatible = "arm,pl310-cache"; | ||
36 | reg = <0xF8F02000 0x1000>; | ||
37 | arm,data-latency = <2 3 2>; | ||
38 | arm,tag-latency = <2 3 2>; | ||
39 | cache-unified; | ||
40 | cache-level = <2>; | ||
41 | }; | ||
42 | |||
43 | uart0: uart@e0000000 { | ||
44 | compatible = "xlnx,xuartps"; | ||
45 | reg = <0xE0000000 0x1000>; | ||
46 | interrupts = <0 27 4>; | ||
47 | clock = <50000000>; | ||
48 | }; | ||
49 | |||
50 | uart1: uart@e0001000 { | ||
51 | compatible = "xlnx,xuartps"; | ||
52 | reg = <0xE0001000 0x1000>; | ||
53 | interrupts = <0 50 4>; | ||
54 | clock = <50000000>; | ||
55 | }; | ||
56 | |||
57 | slcr: slcr@f8000000 { | ||
58 | compatible = "xlnx,zynq-slcr"; | ||
59 | reg = <0xF8000000 0x1000>; | ||
60 | |||
61 | clocks { | ||
62 | #address-cells = <1>; | ||
63 | #size-cells = <0>; | ||
64 | |||
65 | ps_clk: ps_clk { | ||
66 | #clock-cells = <0>; | ||
67 | compatible = "fixed-clock"; | ||
68 | /* clock-frequency set in board-specific file */ | ||
69 | clock-output-names = "ps_clk"; | ||
70 | }; | ||
71 | armpll: armpll { | ||
72 | #clock-cells = <0>; | ||
73 | compatible = "xlnx,zynq-pll"; | ||
74 | clocks = <&ps_clk>; | ||
75 | reg = <0x100 0x110>; | ||
76 | clock-output-names = "armpll"; | ||
77 | }; | ||
78 | ddrpll: ddrpll { | ||
79 | #clock-cells = <0>; | ||
80 | compatible = "xlnx,zynq-pll"; | ||
81 | clocks = <&ps_clk>; | ||
82 | reg = <0x104 0x114>; | ||
83 | clock-output-names = "ddrpll"; | ||
84 | }; | ||
85 | iopll: iopll { | ||
86 | #clock-cells = <0>; | ||
87 | compatible = "xlnx,zynq-pll"; | ||
88 | clocks = <&ps_clk>; | ||
89 | reg = <0x108 0x118>; | ||
90 | clock-output-names = "iopll"; | ||
91 | }; | ||
92 | uart_clk: uart_clk { | ||
93 | #clock-cells = <1>; | ||
94 | compatible = "xlnx,zynq-periph-clock"; | ||
95 | clocks = <&iopll &armpll &ddrpll>; | ||
96 | reg = <0x154>; | ||
97 | clock-output-names = "uart0_ref_clk", | ||
98 | "uart1_ref_clk"; | ||
99 | }; | ||
100 | cpu_clk: cpu_clk { | ||
101 | #clock-cells = <1>; | ||
102 | compatible = "xlnx,zynq-cpu-clock"; | ||
103 | clocks = <&iopll &armpll &ddrpll>; | ||
104 | reg = <0x120 0x1C4>; | ||
105 | clock-output-names = "cpu_6x4x", | ||
106 | "cpu_3x2x", | ||
107 | "cpu_2x", | ||
108 | "cpu_1x"; | ||
109 | }; | ||
110 | }; | ||
111 | }; | ||
112 | |||
113 | ttc0: ttc0@f8001000 { | ||
114 | #address-cells = <1>; | ||
115 | #size-cells = <0>; | ||
116 | compatible = "xlnx,ttc"; | ||
117 | reg = <0xF8001000 0x1000>; | ||
118 | clocks = <&cpu_clk 3>; | ||
119 | clock-names = "cpu_1x"; | ||
120 | clock-ranges; | ||
121 | |||
122 | ttc0_0: ttc0.0 { | ||
123 | status = "disabled"; | ||
124 | reg = <0>; | ||
125 | interrupts = <0 10 4>; | ||
126 | }; | ||
127 | ttc0_1: ttc0.1 { | ||
128 | status = "disabled"; | ||
129 | reg = <1>; | ||
130 | interrupts = <0 11 4>; | ||
131 | }; | ||
132 | ttc0_2: ttc0.2 { | ||
133 | status = "disabled"; | ||
134 | reg = <2>; | ||
135 | interrupts = <0 12 4>; | ||
136 | }; | ||
137 | }; | ||
138 | |||
139 | ttc1: ttc1@f8002000 { | ||
140 | #interrupt-parent = <&intc>; | ||
141 | #address-cells = <1>; | ||
142 | #size-cells = <0>; | ||
143 | compatible = "xlnx,ttc"; | ||
144 | reg = <0xF8002000 0x1000>; | ||
145 | clocks = <&cpu_clk 3>; | ||
146 | clock-names = "cpu_1x"; | ||
147 | clock-ranges; | ||
148 | |||
149 | ttc1_0: ttc1.0 { | ||
150 | status = "disabled"; | ||
151 | reg = <0>; | ||
152 | interrupts = <0 37 4>; | ||
153 | }; | ||
154 | ttc1_1: ttc1.1 { | ||
155 | status = "disabled"; | ||
156 | reg = <1>; | ||
157 | interrupts = <0 38 4>; | ||
158 | }; | ||
159 | ttc1_2: ttc1.2 { | ||
160 | status = "disabled"; | ||
161 | reg = <2>; | ||
162 | interrupts = <0 39 4>; | ||
163 | }; | ||
164 | }; | ||
165 | }; | ||
166 | }; | ||
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts deleted file mode 100644 index 37ca192fb193..000000000000 --- a/arch/arm/boot/dts/zynq-ep107.dts +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Xilinx | ||
3 | * | ||
4 | * This software is licensed under the terms of the GNU General Public | ||
5 | * License version 2, as published by the Free Software Foundation, and | ||
6 | * may be copied, distributed, and modified under those terms. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | /dts-v1/; | ||
15 | / { | ||
16 | model = "Xilinx Zynq EP107"; | ||
17 | compatible = "xlnx,zynq-ep107"; | ||
18 | #address-cells = <1>; | ||
19 | #size-cells = <1>; | ||
20 | interrupt-parent = <&intc>; | ||
21 | |||
22 | memory { | ||
23 | device_type = "memory"; | ||
24 | reg = <0x0 0x10000000>; | ||
25 | }; | ||
26 | |||
27 | chosen { | ||
28 | bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk"; | ||
29 | linux,stdout-path = &uart0; | ||
30 | }; | ||
31 | |||
32 | amba { | ||
33 | compatible = "simple-bus"; | ||
34 | #address-cells = <1>; | ||
35 | #size-cells = <1>; | ||
36 | ranges; | ||
37 | |||
38 | intc: interrupt-controller@f8f01000 { | ||
39 | interrupt-controller; | ||
40 | compatible = "arm,gic"; | ||
41 | reg = <0xF8F01000 0x1000>; | ||
42 | #interrupt-cells = <2>; | ||
43 | }; | ||
44 | |||
45 | uart0: uart@e0000000 { | ||
46 | compatible = "xlnx,xuartps"; | ||
47 | reg = <0xE0000000 0x1000>; | ||
48 | interrupts = <59 0>; | ||
49 | clock = <50000000>; | ||
50 | }; | ||
51 | }; | ||
52 | }; | ||
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts new file mode 100644 index 000000000000..c772942a399a --- /dev/null +++ b/arch/arm/boot/dts/zynq-zc702.dts | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Xilinx | ||
3 | * Copyright (C) 2012 National Instruments Corp. | ||
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 | /dts-v1/; | ||
15 | /include/ "zynq-7000.dtsi" | ||
16 | |||
17 | / { | ||
18 | model = "Zynq ZC702 Development Board"; | ||
19 | compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000"; | ||
20 | |||
21 | memory { | ||
22 | device_type = "memory"; | ||
23 | reg = <0x0 0x40000000>; | ||
24 | }; | ||
25 | |||
26 | chosen { | ||
27 | bootargs = "console=ttyPS1,115200 earlyprintk"; | ||
28 | }; | ||
29 | |||
30 | }; | ||
31 | |||
32 | &ps_clk { | ||
33 | clock-frequency = <33333330>; | ||
34 | }; | ||
35 | |||
36 | &ttc0_0 { | ||
37 | status = "ok"; | ||
38 | compatible = "xlnx,ttc-counter-clocksource"; | ||
39 | }; | ||
40 | |||
41 | &ttc0_1 { | ||
42 | status = "ok"; | ||
43 | compatible = "xlnx,ttc-counter-clockevent"; | ||
44 | }; | ||
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/include/debug/zynq.S index 3ab0be1f6191..f9aa9740a73f 100644 --- a/arch/arm/mach-zynq/include/mach/debug-macro.S +++ b/arch/arm/include/debug/zynq.S | |||
@@ -1,5 +1,4 @@ | |||
1 | /* arch/arm/mach-zynq/include/mach/debug-macro.S | 1 | /* |
2 | * | ||
3 | * Debugging macro include header | 2 | * Debugging macro include header |
4 | * | 3 | * |
5 | * Copyright (C) 2011 Xilinx | 4 | * Copyright (C) 2011 Xilinx |
@@ -13,9 +12,25 @@ | |||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
15 | */ | 14 | */ |
15 | #define UART_CR_OFFSET 0x00 /* Control Register [8:0] */ | ||
16 | #define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */ | ||
17 | #define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */ | ||
18 | |||
19 | #define UART_SR_TXFULL 0x00000010 /* TX FIFO full */ | ||
20 | #define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ | ||
21 | |||
22 | #define UART0_PHYS 0xE0000000 | ||
23 | #define UART1_PHYS 0xE0001000 | ||
24 | #define UART_SIZE SZ_4K | ||
25 | #define UART_VIRT 0xF0001000 | ||
26 | |||
27 | #if IS_ENABLED(CONFIG_DEBUG_ZYNQ_UART1) | ||
28 | # define LL_UART_PADDR UART1_PHYS | ||
29 | #else | ||
30 | # define LL_UART_PADDR UART0_PHYS | ||
31 | #endif | ||
16 | 32 | ||
17 | #include <mach/zynq_soc.h> | 33 | #define LL_UART_VADDR UART_VIRT |
18 | #include <mach/uart.h> | ||
19 | 34 | ||
20 | .macro addruart, rp, rv, tmp | 35 | .macro addruart, rp, rv, tmp |
21 | ldr \rp, =LL_UART_PADDR @ physical | 36 | ldr \rp, =LL_UART_PADDR @ physical |
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig new file mode 100644 index 000000000000..adb6c0ea0e53 --- /dev/null +++ b/arch/arm/mach-zynq/Kconfig | |||
@@ -0,0 +1,13 @@ | |||
1 | config ARCH_ZYNQ | ||
2 | bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7 | ||
3 | select ARM_AMBA | ||
4 | select ARM_GIC | ||
5 | select COMMON_CLK | ||
6 | select CPU_V7 | ||
7 | select GENERIC_CLOCKEVENTS | ||
8 | select ICST | ||
9 | select MIGHT_HAVE_CACHE_L2X0 | ||
10 | select USE_OF | ||
11 | select SPARSE_IRQ | ||
12 | help | ||
13 | Support for Xilinx Zynq ARM Cortex A9 Platform | ||
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index ab5cfddc0d7b..e16d4bed0f7a 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c | |||
@@ -19,19 +19,21 @@ | |||
19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/clk/zynq.h> | ||
23 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
23 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
24 | #include <linux/of.h> | 26 | #include <linux/of.h> |
25 | 27 | ||
26 | #include <asm/mach/arch.h> | 28 | #include <asm/mach/arch.h> |
27 | #include <asm/mach/map.h> | 29 | #include <asm/mach/map.h> |
30 | #include <asm/mach/time.h> | ||
28 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
29 | #include <asm/page.h> | 32 | #include <asm/page.h> |
33 | #include <asm/pgtable.h> | ||
30 | #include <asm/hardware/gic.h> | 34 | #include <asm/hardware/gic.h> |
31 | #include <asm/hardware/cache-l2x0.h> | 35 | #include <asm/hardware/cache-l2x0.h> |
32 | 36 | ||
33 | #include <mach/zynq_soc.h> | ||
34 | #include <mach/clkdev.h> | ||
35 | #include "common.h" | 37 | #include "common.h" |
36 | 38 | ||
37 | static struct of_device_id zynq_of_bus_ids[] __initdata = { | 39 | static struct of_device_id zynq_of_bus_ids[] __initdata = { |
@@ -45,55 +47,57 @@ static struct of_device_id zynq_of_bus_ids[] __initdata = { | |||
45 | */ | 47 | */ |
46 | static void __init xilinx_init_machine(void) | 48 | static void __init xilinx_init_machine(void) |
47 | { | 49 | { |
48 | #ifdef CONFIG_CACHE_L2X0 | ||
49 | /* | 50 | /* |
50 | * 64KB way size, 8-way associativity, parity disabled | 51 | * 64KB way size, 8-way associativity, parity disabled |
51 | */ | 52 | */ |
52 | l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF); | 53 | l2x0_of_init(0x02060000, 0xF0F0FFFF); |
53 | #endif | ||
54 | 54 | ||
55 | of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); | 55 | of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); |
56 | } | 56 | } |
57 | 57 | ||
58 | static struct of_device_id irq_match[] __initdata = { | ||
59 | { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, | ||
60 | { } | ||
61 | }; | ||
62 | |||
58 | /** | 63 | /** |
59 | * xilinx_irq_init() - Interrupt controller initialization for the GIC. | 64 | * xilinx_irq_init() - Interrupt controller initialization for the GIC. |
60 | */ | 65 | */ |
61 | static void __init xilinx_irq_init(void) | 66 | static void __init xilinx_irq_init(void) |
62 | { | 67 | { |
63 | gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE); | 68 | of_irq_init(irq_match); |
64 | } | 69 | } |
65 | 70 | ||
66 | /* The minimum devices needed to be mapped before the VM system is up and | 71 | #define SCU_PERIPH_PHYS 0xF8F00000 |
67 | * running include the GIC, UART and Timer Counter. | 72 | #define SCU_PERIPH_SIZE SZ_8K |
68 | */ | 73 | #define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE) |
74 | |||
75 | static struct map_desc scu_desc __initdata = { | ||
76 | .virtual = SCU_PERIPH_VIRT, | ||
77 | .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), | ||
78 | .length = SCU_PERIPH_SIZE, | ||
79 | .type = MT_DEVICE, | ||
80 | }; | ||
81 | |||
82 | static void __init xilinx_zynq_timer_init(void) | ||
83 | { | ||
84 | struct device_node *np; | ||
85 | void __iomem *slcr; | ||
86 | |||
87 | np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); | ||
88 | slcr = of_iomap(np, 0); | ||
89 | WARN_ON(!slcr); | ||
90 | |||
91 | xilinx_zynq_clocks_init(slcr); | ||
69 | 92 | ||
70 | static struct map_desc io_desc[] __initdata = { | 93 | xttcpss_timer_init(); |
71 | { | 94 | } |
72 | .virtual = TTC0_VIRT, | ||
73 | .pfn = __phys_to_pfn(TTC0_PHYS), | ||
74 | .length = SZ_4K, | ||
75 | .type = MT_DEVICE, | ||
76 | }, { | ||
77 | .virtual = SCU_PERIPH_VIRT, | ||
78 | .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), | ||
79 | .length = SZ_8K, | ||
80 | .type = MT_DEVICE, | ||
81 | }, { | ||
82 | .virtual = PL310_L2CC_VIRT, | ||
83 | .pfn = __phys_to_pfn(PL310_L2CC_PHYS), | ||
84 | .length = SZ_4K, | ||
85 | .type = MT_DEVICE, | ||
86 | }, | ||
87 | |||
88 | #ifdef CONFIG_DEBUG_LL | ||
89 | { | ||
90 | .virtual = UART0_VIRT, | ||
91 | .pfn = __phys_to_pfn(UART0_PHYS), | ||
92 | .length = SZ_4K, | ||
93 | .type = MT_DEVICE, | ||
94 | }, | ||
95 | #endif | ||
96 | 95 | ||
96 | /* | ||
97 | * Instantiate and initialize the system timer structure | ||
98 | */ | ||
99 | static struct sys_timer xttcpss_sys_timer = { | ||
100 | .init = xilinx_zynq_timer_init, | ||
97 | }; | 101 | }; |
98 | 102 | ||
99 | /** | 103 | /** |
@@ -101,11 +105,13 @@ static struct map_desc io_desc[] __initdata = { | |||
101 | */ | 105 | */ |
102 | static void __init xilinx_map_io(void) | 106 | static void __init xilinx_map_io(void) |
103 | { | 107 | { |
104 | iotable_init(io_desc, ARRAY_SIZE(io_desc)); | 108 | debug_ll_io_init(); |
109 | iotable_init(&scu_desc, 1); | ||
105 | } | 110 | } |
106 | 111 | ||
107 | static const char *xilinx_dt_match[] = { | 112 | static const char *xilinx_dt_match[] = { |
108 | "xlnx,zynq-ep107", | 113 | "xlnx,zynq-zc702", |
114 | "xlnx,zynq-7000", | ||
109 | NULL | 115 | NULL |
110 | }; | 116 | }; |
111 | 117 | ||
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index a009644a1555..954b91c13c91 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h | |||
@@ -17,8 +17,6 @@ | |||
17 | #ifndef __MACH_ZYNQ_COMMON_H__ | 17 | #ifndef __MACH_ZYNQ_COMMON_H__ |
18 | #define __MACH_ZYNQ_COMMON_H__ | 18 | #define __MACH_ZYNQ_COMMON_H__ |
19 | 19 | ||
20 | #include <asm/mach/time.h> | 20 | void __init xttcpss_timer_init(void); |
21 | |||
22 | extern struct sys_timer xttcpss_sys_timer; | ||
23 | 21 | ||
24 | #endif | 22 | #endif |
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h deleted file mode 100644 index c6e73d81a459..000000000000 --- a/arch/arm/mach-zynq/include/mach/clkdev.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
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 | |||
22 | struct 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/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h deleted file mode 100644 index d558d8a94be7..000000000000 --- a/arch/arm/mach-zynq/include/mach/hardware.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
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/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h deleted file mode 100644 index 5fb04fd3bac8..000000000000 --- a/arch/arm/mach-zynq/include/mach/irqs.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
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/timex.h b/arch/arm/mach-zynq/include/mach/timex.h deleted file mode 100644 index 6c0245e42a5e..000000000000 --- a/arch/arm/mach-zynq/include/mach/timex.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
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 deleted file mode 100644 index 5c47c97156f3..000000000000 --- a/arch/arm/mach-zynq/include/mach/uart.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
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 deleted file mode 100644 index af4e8447bfa3..000000000000 --- a/arch/arm/mach-zynq/include/mach/uncompress.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
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 | |||
23 | void arch_decomp_setup(void) | ||
24 | { | ||
25 | } | ||
26 | |||
27 | static 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 | |||
39 | static 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/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h deleted file mode 100644 index d0d3f8fb06dd..000000000000 --- a/arch/arm/mach-zynq/include/mach/zynq_soc.h +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
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 index c2c96cc7d6e7..de3df283da74 100644 --- a/arch/arm/mach-zynq/timer.c +++ b/arch/arm/mach-zynq/timer.c | |||
@@ -23,32 +23,14 @@ | |||
23 | #include <linux/clocksource.h> | 23 | #include <linux/clocksource.h> |
24 | #include <linux/clockchips.h> | 24 | #include <linux/clockchips.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/of.h> | ||
27 | #include <linux/of_address.h> | ||
28 | #include <linux/of_irq.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/clk-provider.h> | ||
26 | 31 | ||
27 | #include <asm/mach/time.h> | ||
28 | #include <mach/zynq_soc.h> | ||
29 | #include "common.h" | 32 | #include "common.h" |
30 | 33 | ||
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 | /* | 34 | /* |
53 | * Timer Register Offset Definitions of Timer 1, Increment base address by 4 | 35 | * Timer Register Offset Definitions of Timer 1, Increment base address by 4 |
54 | * and use same offsets for Timer 2 | 36 | * and use same offsets for Timer 2 |
@@ -65,9 +47,14 @@ | |||
65 | 47 | ||
66 | #define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1 | 48 | #define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1 |
67 | 49 | ||
68 | /* Setup the timers to use pre-scaling */ | 50 | /* Setup the timers to use pre-scaling, using a fixed value for now that will |
69 | 51 | * work across most input frequency, but it may need to be more dynamic | |
70 | #define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32) | 52 | */ |
53 | #define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ | ||
54 | #define PRESCALE 2048 /* The exponent must match this */ | ||
55 | #define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) | ||
56 | #define CLK_CNTRL_PRESCALE_EN 1 | ||
57 | #define CNT_CNTRL_RESET (1<<4) | ||
71 | 58 | ||
72 | /** | 59 | /** |
73 | * struct xttcpss_timer - This definition defines local timer structure | 60 | * struct xttcpss_timer - This definition defines local timer structure |
@@ -75,11 +62,25 @@ | |||
75 | * @base_addr: Base address of timer | 62 | * @base_addr: Base address of timer |
76 | **/ | 63 | **/ |
77 | struct xttcpss_timer { | 64 | struct xttcpss_timer { |
78 | void __iomem *base_addr; | 65 | void __iomem *base_addr; |
79 | }; | 66 | }; |
80 | 67 | ||
81 | static struct xttcpss_timer timers[2]; | 68 | struct xttcpss_timer_clocksource { |
82 | static struct clock_event_device xttcpss_clockevent; | 69 | struct xttcpss_timer xttc; |
70 | struct clocksource cs; | ||
71 | }; | ||
72 | |||
73 | #define to_xttcpss_timer_clksrc(x) \ | ||
74 | container_of(x, struct xttcpss_timer_clocksource, cs) | ||
75 | |||
76 | struct xttcpss_timer_clockevent { | ||
77 | struct xttcpss_timer xttc; | ||
78 | struct clock_event_device ce; | ||
79 | struct clk *clk; | ||
80 | }; | ||
81 | |||
82 | #define to_xttcpss_timer_clkevent(x) \ | ||
83 | container_of(x, struct xttcpss_timer_clockevent, ce) | ||
83 | 84 | ||
84 | /** | 85 | /** |
85 | * xttcpss_set_interval - Set the timer interval value | 86 | * xttcpss_set_interval - Set the timer interval value |
@@ -101,7 +102,7 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer, | |||
101 | 102 | ||
102 | /* Reset the counter (0x10) so that it starts from 0, one-shot | 103 | /* Reset the counter (0x10) so that it starts from 0, one-shot |
103 | mode makes this needed for timing to be right. */ | 104 | mode makes this needed for timing to be right. */ |
104 | ctrl_reg |= 0x10; | 105 | ctrl_reg |= CNT_CNTRL_RESET; |
105 | ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK; | 106 | ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK; |
106 | __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 107 | __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); |
107 | } | 108 | } |
@@ -116,90 +117,31 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer, | |||
116 | **/ | 117 | **/ |
117 | static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id) | 118 | static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id) |
118 | { | 119 | { |
119 | struct clock_event_device *evt = &xttcpss_clockevent; | 120 | struct xttcpss_timer_clockevent *xttce = dev_id; |
120 | struct xttcpss_timer *timer = dev_id; | 121 | struct xttcpss_timer *timer = &xttce->xttc; |
121 | 122 | ||
122 | /* Acknowledge the interrupt and call event handler */ | 123 | /* Acknowledge the interrupt and call event handler */ |
123 | __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET), | 124 | __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET), |
124 | timer->base_addr + XTTCPSS_ISR_OFFSET); | 125 | timer->base_addr + XTTCPSS_ISR_OFFSET); |
125 | 126 | ||
126 | evt->event_handler(evt); | 127 | xttce->ce.event_handler(&xttce->ce); |
127 | 128 | ||
128 | return IRQ_HANDLED; | 129 | return IRQ_HANDLED; |
129 | } | 130 | } |
130 | 131 | ||
131 | static struct irqaction event_timer_irq = { | ||
132 | .name = "xttcpss clockevent", | ||
133 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
134 | .handler = xttcpss_clock_event_interrupt, | ||
135 | }; | ||
136 | |||
137 | /** | 132 | /** |
138 | * xttcpss_timer_hardware_init - Initialize the timer hardware | 133 | * __xttc_clocksource_read - Reads the timer counter register |
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 | **/ | ||
143 | static 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 | * | 134 | * |
180 | * returns: Current timer counter register value | 135 | * returns: Current timer counter register value |
181 | **/ | 136 | **/ |
182 | static cycle_t __raw_readl_cycles(struct clocksource *cs) | 137 | static cycle_t __xttc_clocksource_read(struct clocksource *cs) |
183 | { | 138 | { |
184 | struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE]; | 139 | struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc; |
185 | 140 | ||
186 | return (cycle_t)__raw_readl(timer->base_addr + | 141 | return (cycle_t)__raw_readl(timer->base_addr + |
187 | XTTCPSS_COUNT_VAL_OFFSET); | 142 | XTTCPSS_COUNT_VAL_OFFSET); |
188 | } | 143 | } |
189 | 144 | ||
190 | |||
191 | /* | ||
192 | * Instantiate and initialize the clock source structure | ||
193 | */ | ||
194 | static 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 | /** | 145 | /** |
204 | * xttcpss_set_next_event - Sets the time interval for next event | 146 | * xttcpss_set_next_event - Sets the time interval for next event |
205 | * | 147 | * |
@@ -211,7 +153,8 @@ static struct clocksource clocksource_xttcpss = { | |||
211 | static int xttcpss_set_next_event(unsigned long cycles, | 153 | static int xttcpss_set_next_event(unsigned long cycles, |
212 | struct clock_event_device *evt) | 154 | struct clock_event_device *evt) |
213 | { | 155 | { |
214 | struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT]; | 156 | struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt); |
157 | struct xttcpss_timer *timer = &xttce->xttc; | ||
215 | 158 | ||
216 | xttcpss_set_interval(timer, cycles); | 159 | xttcpss_set_interval(timer, cycles); |
217 | return 0; | 160 | return 0; |
@@ -226,12 +169,15 @@ static int xttcpss_set_next_event(unsigned long cycles, | |||
226 | static void xttcpss_set_mode(enum clock_event_mode mode, | 169 | static void xttcpss_set_mode(enum clock_event_mode mode, |
227 | struct clock_event_device *evt) | 170 | struct clock_event_device *evt) |
228 | { | 171 | { |
229 | struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT]; | 172 | struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt); |
173 | struct xttcpss_timer *timer = &xttce->xttc; | ||
230 | u32 ctrl_reg; | 174 | u32 ctrl_reg; |
231 | 175 | ||
232 | switch (mode) { | 176 | switch (mode) { |
233 | case CLOCK_EVT_MODE_PERIODIC: | 177 | case CLOCK_EVT_MODE_PERIODIC: |
234 | xttcpss_set_interval(timer, TIMER_RATE / HZ); | 178 | xttcpss_set_interval(timer, |
179 | DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk), | ||
180 | PRESCALE * HZ)); | ||
235 | break; | 181 | break; |
236 | case CLOCK_EVT_MODE_ONESHOT: | 182 | case CLOCK_EVT_MODE_ONESHOT: |
237 | case CLOCK_EVT_MODE_UNUSED: | 183 | case CLOCK_EVT_MODE_UNUSED: |
@@ -252,15 +198,106 @@ static void xttcpss_set_mode(enum clock_event_mode mode, | |||
252 | } | 198 | } |
253 | } | 199 | } |
254 | 200 | ||
255 | /* | 201 | static void __init zynq_ttc_setup_clocksource(struct device_node *np, |
256 | * Instantiate and initialize the clock event structure | 202 | void __iomem *base) |
257 | */ | 203 | { |
258 | static struct clock_event_device xttcpss_clockevent = { | 204 | struct xttcpss_timer_clocksource *ttccs; |
259 | .name = "xttcpss_timer2", | 205 | struct clk *clk; |
260 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 206 | int err; |
261 | .set_next_event = xttcpss_set_next_event, | 207 | u32 reg; |
262 | .set_mode = xttcpss_set_mode, | 208 | |
263 | .rating = 200, | 209 | ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); |
210 | if (WARN_ON(!ttccs)) | ||
211 | return; | ||
212 | |||
213 | err = of_property_read_u32(np, "reg", ®); | ||
214 | if (WARN_ON(err)) | ||
215 | return; | ||
216 | |||
217 | clk = of_clk_get_by_name(np, "cpu_1x"); | ||
218 | if (WARN_ON(IS_ERR(clk))) | ||
219 | return; | ||
220 | |||
221 | err = clk_prepare_enable(clk); | ||
222 | if (WARN_ON(err)) | ||
223 | return; | ||
224 | |||
225 | ttccs->xttc.base_addr = base + reg * 4; | ||
226 | |||
227 | ttccs->cs.name = np->name; | ||
228 | ttccs->cs.rating = 200; | ||
229 | ttccs->cs.read = __xttc_clocksource_read; | ||
230 | ttccs->cs.mask = CLOCKSOURCE_MASK(16); | ||
231 | ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
232 | |||
233 | __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET); | ||
234 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | ||
235 | ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET); | ||
236 | __raw_writel(CNT_CNTRL_RESET, | ||
237 | ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | ||
238 | |||
239 | err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE); | ||
240 | if (WARN_ON(err)) | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | static void __init zynq_ttc_setup_clockevent(struct device_node *np, | ||
245 | void __iomem *base) | ||
246 | { | ||
247 | struct xttcpss_timer_clockevent *ttcce; | ||
248 | int err, irq; | ||
249 | u32 reg; | ||
250 | |||
251 | ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); | ||
252 | if (WARN_ON(!ttcce)) | ||
253 | return; | ||
254 | |||
255 | err = of_property_read_u32(np, "reg", ®); | ||
256 | if (WARN_ON(err)) | ||
257 | return; | ||
258 | |||
259 | ttcce->xttc.base_addr = base + reg * 4; | ||
260 | |||
261 | ttcce->clk = of_clk_get_by_name(np, "cpu_1x"); | ||
262 | if (WARN_ON(IS_ERR(ttcce->clk))) | ||
263 | return; | ||
264 | |||
265 | err = clk_prepare_enable(ttcce->clk); | ||
266 | if (WARN_ON(err)) | ||
267 | return; | ||
268 | |||
269 | irq = irq_of_parse_and_map(np, 0); | ||
270 | if (WARN_ON(!irq)) | ||
271 | return; | ||
272 | |||
273 | ttcce->ce.name = np->name; | ||
274 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | ||
275 | ttcce->ce.set_next_event = xttcpss_set_next_event; | ||
276 | ttcce->ce.set_mode = xttcpss_set_mode; | ||
277 | ttcce->ce.rating = 200; | ||
278 | ttcce->ce.irq = irq; | ||
279 | |||
280 | __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | ||
281 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | ||
282 | ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET); | ||
283 | __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET); | ||
284 | |||
285 | err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER, | ||
286 | np->name, ttcce); | ||
287 | if (WARN_ON(err)) | ||
288 | return; | ||
289 | |||
290 | clockevents_config_and_register(&ttcce->ce, | ||
291 | clk_get_rate(ttcce->clk) / PRESCALE, | ||
292 | 1, 0xfffe); | ||
293 | } | ||
294 | |||
295 | static const __initconst struct of_device_id zynq_ttc_match[] = { | ||
296 | { .compatible = "xlnx,ttc-counter-clocksource", | ||
297 | .data = zynq_ttc_setup_clocksource, }, | ||
298 | { .compatible = "xlnx,ttc-counter-clockevent", | ||
299 | .data = zynq_ttc_setup_clockevent, }, | ||
300 | {} | ||
264 | }; | 301 | }; |
265 | 302 | ||
266 | /** | 303 | /** |
@@ -269,30 +306,27 @@ static struct clock_event_device xttcpss_clockevent = { | |||
269 | * Initializes the timer hardware and register the clock source and clock event | 306 | * Initializes the timer hardware and register the clock source and clock event |
270 | * timers with Linux kernal timer framework | 307 | * timers with Linux kernal timer framework |
271 | **/ | 308 | **/ |
272 | static void __init xttcpss_timer_init(void) | 309 | void __init xttcpss_timer_init(void) |
273 | { | 310 | { |
274 | xttcpss_timer_hardware_init(); | 311 | struct device_node *np; |
275 | clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE); | 312 | |
276 | 313 | for_each_compatible_node(np, NULL, "xlnx,ttc") { | |
277 | /* Calculate the parameters to allow the clockevent to operate using | 314 | struct device_node *np_chld; |
278 | integer math | 315 | void __iomem *base; |
279 | */ | 316 | |
280 | clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4); | 317 | base = of_iomap(np, 0); |
281 | 318 | if (WARN_ON(!base)) | |
282 | xttcpss_clockevent.max_delta_ns = | 319 | return; |
283 | clockevent_delta2ns(0xfffe, &xttcpss_clockevent); | 320 | |
284 | xttcpss_clockevent.min_delta_ns = | 321 | for_each_available_child_of_node(np, np_chld) { |
285 | clockevent_delta2ns(1, &xttcpss_clockevent); | 322 | int (*cb)(struct device_node *np, void __iomem *base); |
286 | 323 | const struct of_device_id *match; | |
287 | /* Indicate that clock event is on 1st CPU as SMP boot needs it */ | 324 | |
288 | 325 | match = of_match_node(zynq_ttc_match, np_chld); | |
289 | xttcpss_clockevent.cpumask = cpumask_of(0); | 326 | if (match) { |
290 | clockevents_register_device(&xttcpss_clockevent); | 327 | cb = match->data; |
328 | cb(np_chld, base); | ||
329 | } | ||
330 | } | ||
331 | } | ||
291 | } | 332 | } |
292 | |||
293 | /* | ||
294 | * Instantiate and initialize the system timer structure | ||
295 | */ | ||
296 | struct sys_timer xttcpss_sys_timer = { | ||
297 | .init = xttcpss_timer_init, | ||
298 | }; | ||