aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ux500
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500')
-rw-r--r--arch/arm/mach-ux500/Makefile3
-rw-r--r--arch/arm/mach-ux500/clock.c104
-rw-r--r--arch/arm/mach-ux500/clock.h22
-rw-r--r--arch/arm/mach-ux500/cpu.c6
4 files changed, 128 insertions, 7 deletions
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index c7bc4199e3a8..4556aea9c3c5 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o
7obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o 7obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
8obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o 8obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o
9obj-$(CONFIG_MACH_U5500) += board-u5500.o 9obj-$(CONFIG_MACH_U5500) += board-u5500.o
10obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o 10obj-$(CONFIG_SMP) += platsmp.o headsmp.o
11obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 6544855af2f1..fe84b9021c7a 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -16,6 +16,7 @@
16 16
17#include <asm/clkdev.h> 17#include <asm/clkdev.h>
18 18
19#include <plat/mtu.h>
19#include <mach/hardware.h> 20#include <mach/hardware.h>
20#include "clock.h" 21#include "clock.h"
21 22
@@ -59,6 +60,9 @@
59#define PRCM_DMACLK_MGT 0x074 60#define PRCM_DMACLK_MGT 0x074
60#define PRCM_B2R2CLK_MGT 0x078 61#define PRCM_B2R2CLK_MGT 0x078
61#define PRCM_TVCLK_MGT 0x07C 62#define PRCM_TVCLK_MGT 0x07C
63#define PRCM_TCR 0x1C8
64#define PRCM_TCR_STOPPED (1 << 16)
65#define PRCM_TCR_DOZE_MODE (1 << 17)
62#define PRCM_UNIPROCLK_MGT 0x278 66#define PRCM_UNIPROCLK_MGT 0x278
63#define PRCM_SSPCLK_MGT 0x280 67#define PRCM_SSPCLK_MGT 0x280
64#define PRCM_RNGCLK_MGT 0x284 68#define PRCM_RNGCLK_MGT 0x284
@@ -120,10 +124,95 @@ void clk_disable(struct clk *clk)
120} 124}
121EXPORT_SYMBOL(clk_disable); 125EXPORT_SYMBOL(clk_disable);
122 126
127/*
128 * The MTU has a separate, rather complex muxing setup
129 * with alternative parents (peripheral cluster or
130 * ULP or fixed 32768 Hz) depending on settings
131 */
132static unsigned long clk_mtu_get_rate(struct clk *clk)
133{
134 void __iomem *addr = __io_address(U8500_PRCMU_BASE)
135 + PRCM_TCR;
136 u32 tcr = readl(addr);
137 int mtu = (int) clk->data;
138 /*
139 * One of these is selected eventually
140 * TODO: Replace the constant with a reference
141 * to the ULP source once this is modeled.
142 */
143 unsigned long clk32k = 32768;
144 unsigned long mturate;
145 unsigned long retclk;
146
147 /* Get the rate from the parent as a default */
148 if (clk->parent_periph)
149 mturate = clk_get_rate(clk->parent_periph);
150 else if (clk->parent_cluster)
151 mturate = clk_get_rate(clk->parent_cluster);
152 else
153 /* We need to be connected SOMEWHERE */
154 BUG();
155
156 /*
157 * Are we in doze mode?
158 * In this mode the parent peripheral or the fixed 32768 Hz
159 * clock is fed into the block.
160 */
161 if (!(tcr & PRCM_TCR_DOZE_MODE)) {
162 /*
163 * Here we're using the clock input from the APE ULP
164 * clock domain. But first: are the timers stopped?
165 */
166 if (tcr & PRCM_TCR_STOPPED) {
167 clk32k = 0;
168 mturate = 0;
169 } else {
170 /* Else default mode: 0 and 2.4 MHz */
171 clk32k = 0;
172 if (cpu_is_u5500())
173 /* DB5500 divides by 8 */
174 mturate /= 8;
175 else if (cpu_is_u8500ed()) {
176 /*
177 * This clocking setting must not be used
178 * in the ED chip, it is simply not
179 * connected anywhere!
180 */
181 mturate = 0;
182 BUG();
183 } else
184 /*
185 * In this mode the ulp38m4 clock is divided
186 * by a factor 16, on the DB8500 typically
187 * 38400000 / 16 ~ 2.4 MHz.
188 * TODO: Replace the constant with a reference
189 * to the ULP source once this is modeled.
190 */
191 mturate = 38400000 / 16;
192 }
193 }
194
195 /* Return the clock selected for this MTU */
196 if (tcr & (1 << mtu))
197 retclk = clk32k;
198 else
199 retclk = mturate;
200
201 pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
202 return retclk;
203}
204
123unsigned long clk_get_rate(struct clk *clk) 205unsigned long clk_get_rate(struct clk *clk)
124{ 206{
125 unsigned long rate; 207 unsigned long rate;
126 208
209 /*
210 * If there is a custom getrate callback for this clock,
211 * it will take precedence.
212 */
213 if (clk->get_rate)
214 return clk->get_rate(clk);
215
127 if (clk->ops && clk->ops->get_rate) 216 if (clk->ops && clk->ops->get_rate)
128 return clk->ops->get_rate(clk); 217 return clk->ops->get_rate(clk);
129 218
@@ -341,8 +430,9 @@ static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL);
341 430
342/* Peripheral Cluster #6 */ 431/* Peripheral Cluster #6 */
343 432
344static DEFINE_PRCC_CLK(6, mtu1_v1, 8, -1, NULL); 433/* MTU ID in data */
345static DEFINE_PRCC_CLK(6, mtu0_v1, 7, -1, NULL); 434static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
435static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
346static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); 436static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL);
347static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); 437static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL);
348static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); 438static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
@@ -357,8 +447,9 @@ static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk);
357/* Peripheral Cluster #7 */ 447/* Peripheral Cluster #7 */
358 448
359static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); 449static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL);
360static DEFINE_PRCC_CLK(7, mtu1_ed, 3, -1, NULL); 450/* MTU ID in data */
361static DEFINE_PRCC_CLK(7, mtu0_ed, 2, -1, NULL); 451static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
452static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
362static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); 453static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
363static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); 454static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
364 455
@@ -503,15 +594,17 @@ static struct clk_lookup u8500_v1_clks[] = {
503 CLK(uiccclk, "uicc", NULL), 594 CLK(uiccclk, "uicc", NULL),
504}; 595};
505 596
506static int __init clk_init(void) 597int __init clk_init(void)
507{ 598{
508 if (cpu_is_u8500ed()) { 599 if (cpu_is_u8500ed()) {
509 clk_prcmu_ops.enable = clk_prcmu_ed_enable; 600 clk_prcmu_ops.enable = clk_prcmu_ed_enable;
510 clk_prcmu_ops.disable = clk_prcmu_ed_disable; 601 clk_prcmu_ops.disable = clk_prcmu_ed_disable;
602 clk_per6clk.rate = 100000000;
511 } else if (cpu_is_u5500()) { 603 } else if (cpu_is_u5500()) {
512 /* Clock tree for U5500 not implemented yet */ 604 /* Clock tree for U5500 not implemented yet */
513 clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; 605 clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
514 clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; 606 clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
607 clk_per6clk.rate = 26000000;
515 } 608 }
516 609
517 clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); 610 clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
@@ -522,4 +615,3 @@ static int __init clk_init(void)
522 615
523 return 0; 616 return 0;
524} 617}
525arch_initcall(clk_init);
diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h
index e4f99b65026f..a05802501527 100644
--- a/arch/arm/mach-ux500/clock.h
+++ b/arch/arm/mach-ux500/clock.h
@@ -28,6 +28,9 @@ struct clkops {
28 * @ops: pointer to clkops struct used to control this clock 28 * @ops: pointer to clkops struct used to control this clock
29 * @name: name, for debugging 29 * @name: name, for debugging
30 * @enabled: refcount. positive if enabled, zero if disabled 30 * @enabled: refcount. positive if enabled, zero if disabled
31 * @get_rate: custom callback for getting the clock rate
32 * @data: custom per-clock data for example for the get_rate
33 * callback
31 * @rate: fixed rate for clocks which don't implement 34 * @rate: fixed rate for clocks which don't implement
32 * ops->getrate 35 * ops->getrate
33 * @prcmu_cg_off: address offset of the combined enable/disable register 36 * @prcmu_cg_off: address offset of the combined enable/disable register
@@ -67,6 +70,8 @@ struct clk {
67 const struct clkops *ops; 70 const struct clkops *ops;
68 const char *name; 71 const char *name;
69 unsigned int enabled; 72 unsigned int enabled;
73 unsigned long (*get_rate)(struct clk *);
74 void *data;
70 75
71 unsigned long rate; 76 unsigned long rate;
72 struct list_head list; 77 struct list_head list;
@@ -117,9 +122,26 @@ struct clk clk_##_name = { \
117 .parent_periph = _kernclk \ 122 .parent_periph = _kernclk \
118 } 123 }
119 124
125#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \
126struct clk clk_##_name = { \
127 .name = #_name, \
128 .ops = &clk_prcc_ops, \
129 .cluster = _pclust, \
130 .prcc_bus = _bus_en, \
131 .prcc_kernel = _kernel_en, \
132 .parent_cluster = &clk_per##_pclust##clk, \
133 .parent_periph = _kernclk, \
134 .get_rate = _callback, \
135 .data = (void *) _data \
136 }
137
138
120#define CLK(_clk, _devname, _conname) \ 139#define CLK(_clk, _devname, _conname) \
121 { \ 140 { \
122 .clk = &clk_##_clk, \ 141 .clk = &clk_##_clk, \
123 .dev_id = _devname, \ 142 .dev_id = _devname, \
124 .con_id = _conname, \ 143 .con_id = _conname, \
125 } 144 }
145
146int __init clk_db8500_ed_fixup(void);
147int __init clk_init(void);
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index d81ad023963c..e0fd747e447a 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -62,6 +62,12 @@ void __init ux500_init_irq(void)
62{ 62{
63 gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); 63 gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
64 gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); 64 gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
65
66 /*
67 * Init clocks here so that they are available for system timer
68 * initialization.
69 */
70 clk_init();
65} 71}
66 72
67#ifdef CONFIG_CACHE_L2X0 73#ifdef CONFIG_CACHE_L2X0