diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-05 18:46:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-05 18:46:37 -0400 |
commit | 2bf73dd61a84cdf27e49f48e08739af6ba70ace1 (patch) | |
tree | 225876ce1530ba6c3a96621a531f47e963fee691 /arch/arm/mach-zynq | |
parent | d2b150d0647e055d7a71b1c33140280550b27dd6 (diff) | |
parent | 9dfbff16b422a4bac7ad309847c7bc5d65653392 (diff) |
Merge tag 'tags/cleanup2-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC late cleanups from Arnd Bergmann:
"These could not be part of the first cleanup branch, because they
either came too late in the cycle, or they have dependencies on other
branches. Important changes are:
- The integrator platform is almost multiplatform capable after some
reorganization (Linus Walleij)
- Minor cleanups on Zynq (Michal Simek)
- Lots of changes for Exynos and other Samsung platforms, including
further preparations for multiplatform support and the clocks
bindings are rearranged"
* tag 'tags/cleanup2-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (54 commits)
devicetree: fix newly added exynos sata bindings
ARM: EXYNOS: Fix compilation error in cpuidle.c
ARM: S5P64X0: Explicitly include linux/serial_s3c.h in mach/pm-core.h
ARM: EXYNOS: Remove hardware.h file
ARM: SAMSUNG: Remove hardware.h inclusion
ARM: S3C24XX: Remove invalid code from hardware.h
dt-bindings: clock: Move exynos-audss-clk.h to dt-bindings/clock
ARM: dts: Keep some essential LDOs enabled for arndale-octa board
ARM: dts: Disable MDMA1 node for arndale-octa board
ARM: S3C64XX: Fix build for implicit serial_s3c.h inclusion
serial: s3c: Fix build of header without serial_core.h preinclusion
ARM: EXYNOS: Allow wake-up using GIC interrupts
ARM: EXYNOS: Stop using legacy Samsung PM code
ARM: EXYNOS: Remove PM initcalls and useless indirection
ARM: EXYNOS: Fix abuse of CONFIG_PM
ARM: SAMSUNG: Move s3c_pm_check_* prototypes to plat/pm-common.h
ARM: SAMSUNG: Move common save/restore helpers to separate file
ARM: SAMSUNG: Move Samsung PM debug code into separate file
ARM: SAMSUNG: Consolidate PM debug functions
ARM: SAMSUNG: Use debug_ll_addr() to get UART base address
...
Diffstat (limited to 'arch/arm/mach-zynq')
-rw-r--r-- | arch/arm/mach-zynq/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-zynq/slcr.c | 104 |
4 files changed, 98 insertions, 17 deletions
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 0e001a489a79..58c2b844e0a3 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig | |||
@@ -9,5 +9,6 @@ config ARCH_ZYNQ | |||
9 | select ICST | 9 | select ICST |
10 | select CADENCE_TTC_TIMER | 10 | select CADENCE_TTC_TIMER |
11 | select ARM_GLOBAL_TIMER if !CPU_FREQ | 11 | select ARM_GLOBAL_TIMER if !CPU_FREQ |
12 | select MFD_SYSCON | ||
12 | help | 13 | help |
13 | Support for Xilinx Zynq ARM Cortex A9 Platform | 14 | 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 a39be8e80856..6fcc584c1a11 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c | |||
@@ -19,6 +19,7 @@ | |||
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-provider.h> | ||
22 | #include <linux/clk/zynq.h> | 23 | #include <linux/clk/zynq.h> |
23 | #include <linux/clocksource.h> | 24 | #include <linux/clocksource.h> |
24 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
@@ -75,11 +76,16 @@ static void __init zynq_init_machine(void) | |||
75 | 76 | ||
76 | platform_device_register(&zynq_cpuidle_device); | 77 | platform_device_register(&zynq_cpuidle_device); |
77 | platform_device_register_full(&devinfo); | 78 | platform_device_register_full(&devinfo); |
79 | |||
80 | zynq_slcr_init(); | ||
78 | } | 81 | } |
79 | 82 | ||
80 | static void __init zynq_timer_init(void) | 83 | static void __init zynq_timer_init(void) |
81 | { | 84 | { |
82 | zynq_slcr_init(); | 85 | zynq_early_slcr_init(); |
86 | |||
87 | zynq_clock_init(); | ||
88 | of_clk_init(NULL); | ||
83 | clocksource_of_init(); | 89 | clocksource_of_init(); |
84 | } | 90 | } |
85 | 91 | ||
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index c22c92cea8cb..b097844d3175 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h | |||
@@ -20,6 +20,7 @@ | |||
20 | void zynq_secondary_startup(void); | 20 | void zynq_secondary_startup(void); |
21 | 21 | ||
22 | extern int zynq_slcr_init(void); | 22 | extern int zynq_slcr_init(void); |
23 | extern int zynq_early_slcr_init(void); | ||
23 | extern void zynq_slcr_system_reset(void); | 24 | extern void zynq_slcr_system_reset(void); |
24 | extern void zynq_slcr_cpu_stop(int cpu); | 25 | extern void zynq_slcr_cpu_stop(int cpu); |
25 | extern void zynq_slcr_cpu_start(int cpu); | 26 | extern void zynq_slcr_cpu_start(int cpu); |
@@ -33,7 +34,6 @@ extern int zynq_cpun_start(u32 address, int cpu); | |||
33 | extern struct smp_operations zynq_smp_ops __initdata; | 34 | extern struct smp_operations zynq_smp_ops __initdata; |
34 | #endif | 35 | #endif |
35 | 36 | ||
36 | extern void __iomem *zynq_slcr_base; | ||
37 | extern void __iomem *zynq_scu_base; | 37 | extern void __iomem *zynq_scu_base; |
38 | 38 | ||
39 | /* Hotplug */ | 39 | /* Hotplug */ |
diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 1836d5a34606..a37d49a6e657 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c | |||
@@ -15,7 +15,9 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/mfd/syscon.h> | ||
18 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
20 | #include <linux/regmap.h> | ||
19 | #include <linux/clk/zynq.h> | 21 | #include <linux/clk/zynq.h> |
20 | #include "common.h" | 22 | #include "common.h" |
21 | 23 | ||
@@ -29,7 +31,56 @@ | |||
29 | #define SLCR_A9_CPU_CLKSTOP 0x10 | 31 | #define SLCR_A9_CPU_CLKSTOP 0x10 |
30 | #define SLCR_A9_CPU_RST 0x1 | 32 | #define SLCR_A9_CPU_RST 0x1 |
31 | 33 | ||
32 | void __iomem *zynq_slcr_base; | 34 | static void __iomem *zynq_slcr_base; |
35 | static struct regmap *zynq_slcr_regmap; | ||
36 | |||
37 | /** | ||
38 | * zynq_slcr_write - Write to a register in SLCR block | ||
39 | * | ||
40 | * @val: Value to write to the register | ||
41 | * @offset: Register offset in SLCR block | ||
42 | * | ||
43 | * Return: a negative value on error, 0 on success | ||
44 | */ | ||
45 | static int zynq_slcr_write(u32 val, u32 offset) | ||
46 | { | ||
47 | if (!zynq_slcr_regmap) { | ||
48 | writel(val, zynq_slcr_base + offset); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | return regmap_write(zynq_slcr_regmap, offset, val); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * zynq_slcr_read - Read a register in SLCR block | ||
57 | * | ||
58 | * @val: Pointer to value to be read from SLCR | ||
59 | * @offset: Register offset in SLCR block | ||
60 | * | ||
61 | * Return: a negative value on error, 0 on success | ||
62 | */ | ||
63 | static int zynq_slcr_read(u32 *val, u32 offset) | ||
64 | { | ||
65 | if (zynq_slcr_regmap) | ||
66 | return regmap_read(zynq_slcr_regmap, offset, val); | ||
67 | |||
68 | *val = readl(zynq_slcr_base + offset); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * zynq_slcr_unlock - Unlock SLCR registers | ||
75 | * | ||
76 | * Return: a negative value on error, 0 on success | ||
77 | */ | ||
78 | static inline int zynq_slcr_unlock(void) | ||
79 | { | ||
80 | zynq_slcr_write(SLCR_UNLOCK_MAGIC, SLCR_UNLOCK_OFFSET); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
33 | 84 | ||
34 | /** | 85 | /** |
35 | * zynq_slcr_system_reset - Reset the entire system. | 86 | * zynq_slcr_system_reset - Reset the entire system. |
@@ -43,16 +94,16 @@ void zynq_slcr_system_reset(void) | |||
43 | * Note that this seems to require raw i/o | 94 | * Note that this seems to require raw i/o |
44 | * functions or there's a lockup? | 95 | * functions or there's a lockup? |
45 | */ | 96 | */ |
46 | writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET); | 97 | zynq_slcr_unlock(); |
47 | 98 | ||
48 | /* | 99 | /* |
49 | * Clear 0x0F000000 bits of reboot status register to workaround | 100 | * Clear 0x0F000000 bits of reboot status register to workaround |
50 | * the FSBL not loading the bitstream after soft-reboot | 101 | * the FSBL not loading the bitstream after soft-reboot |
51 | * This is a temporary solution until we know more. | 102 | * This is a temporary solution until we know more. |
52 | */ | 103 | */ |
53 | reboot = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); | 104 | zynq_slcr_read(&reboot, SLCR_REBOOT_STATUS_OFFSET); |
54 | writel(reboot & 0xF0FFFFFF, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); | 105 | zynq_slcr_write(reboot & 0xF0FFFFFF, SLCR_REBOOT_STATUS_OFFSET); |
55 | writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET); | 106 | zynq_slcr_write(1, SLCR_PS_RST_CTRL_OFFSET); |
56 | } | 107 | } |
57 | 108 | ||
58 | /** | 109 | /** |
@@ -61,11 +112,13 @@ void zynq_slcr_system_reset(void) | |||
61 | */ | 112 | */ |
62 | void zynq_slcr_cpu_start(int cpu) | 113 | void zynq_slcr_cpu_start(int cpu) |
63 | { | 114 | { |
64 | u32 reg = readl(zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); | 115 | u32 reg; |
116 | |||
117 | zynq_slcr_read(®, SLCR_A9_CPU_RST_CTRL_OFFSET); | ||
65 | reg &= ~(SLCR_A9_CPU_RST << cpu); | 118 | reg &= ~(SLCR_A9_CPU_RST << cpu); |
66 | writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); | 119 | zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); |
67 | reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu); | 120 | reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu); |
68 | writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); | 121 | zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); |
69 | } | 122 | } |
70 | 123 | ||
71 | /** | 124 | /** |
@@ -74,19 +127,40 @@ void zynq_slcr_cpu_start(int cpu) | |||
74 | */ | 127 | */ |
75 | void zynq_slcr_cpu_stop(int cpu) | 128 | void zynq_slcr_cpu_stop(int cpu) |
76 | { | 129 | { |
77 | u32 reg = readl(zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); | 130 | u32 reg; |
131 | |||
132 | zynq_slcr_read(®, SLCR_A9_CPU_RST_CTRL_OFFSET); | ||
78 | reg |= (SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu; | 133 | reg |= (SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu; |
79 | writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); | 134 | zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); |
80 | } | 135 | } |
81 | 136 | ||
82 | /** | 137 | /** |
83 | * zynq_slcr_init | 138 | * zynq_slcr_init - Regular slcr driver init |
84 | * Returns 0 on success, negative errno otherwise. | 139 | * |
140 | * Return: 0 on success, negative errno otherwise. | ||
85 | * | 141 | * |
86 | * Called early during boot from platform code to remap SLCR area. | 142 | * Called early during boot from platform code to remap SLCR area. |
87 | */ | 143 | */ |
88 | int __init zynq_slcr_init(void) | 144 | int __init zynq_slcr_init(void) |
89 | { | 145 | { |
146 | zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr"); | ||
147 | if (IS_ERR(zynq_slcr_regmap)) { | ||
148 | pr_err("%s: failed to find zynq-slcr\n", __func__); | ||
149 | return -ENODEV; | ||
150 | } | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * zynq_early_slcr_init - Early slcr init function | ||
157 | * | ||
158 | * Return: 0 on success, negative errno otherwise. | ||
159 | * | ||
160 | * Called very early during boot from platform code to unlock SLCR. | ||
161 | */ | ||
162 | int __init zynq_early_slcr_init(void) | ||
163 | { | ||
90 | struct device_node *np; | 164 | struct device_node *np; |
91 | 165 | ||
92 | np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); | 166 | np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); |
@@ -101,13 +175,13 @@ int __init zynq_slcr_init(void) | |||
101 | BUG(); | 175 | BUG(); |
102 | } | 176 | } |
103 | 177 | ||
178 | np->data = (__force void *)zynq_slcr_base; | ||
179 | |||
104 | /* unlock the SLCR so that registers can be changed */ | 180 | /* unlock the SLCR so that registers can be changed */ |
105 | writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET); | 181 | zynq_slcr_unlock(); |
106 | 182 | ||
107 | pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); | 183 | pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); |
108 | 184 | ||
109 | zynq_clock_init(zynq_slcr_base); | ||
110 | |||
111 | of_node_put(np); | 185 | of_node_put(np); |
112 | 186 | ||
113 | return 0; | 187 | return 0; |