aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-spear
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 22:03:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 22:03:06 -0400
commit16d8775700f1815076f879719ce14b33f50a3171 (patch)
tree8525e6e6f12b6acf7cf2746853cc65549f3dbf4c /arch/arm/plat-spear
parente34551339a195aa548eaf698523714a8fe7f1984 (diff)
parent05e34754518b6a90d5c392790c032575fab12d66 (diff)
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (91 commits) ARM: 6806/1: irq: introduce entry and exit functions for chained handlers ARM: 6781/1: Thumb-2: Work around buggy Thumb-2 short branch relocations in gas ARM: 6747/1: P2V: Thumb2 support ARM: 6798/1: aout-core: zero thread debug registers in a.out core dump ARM: 6796/1: Footbridge: Fix I/O mappings for NOMMU mode ARM: 6784/1: errata: no automatic Store Buffer drain on Cortex-A9 ARM: 6772/1: errata: possible fault MMU translations following an ASID switch ARM: 6776/1: mach-ux500: activate fix for errata 753970 ARM: 6794/1: SPEAr: Append UL to device address macros. ARM: 6793/1: SPEAr: Remove unused *_SIZE macros from spear*.h files ARM: 6792/1: SPEAr: Replace SIZE macro's with SZ_4K macros ARM: 6791/1: SPEAr3xx: Declare device structures after shirq code ARM: 6790/1: SPEAr: Clock Framework: Rename usbd clock and align apb_clk entry ARM: 6789/1: SPEAr3xx: Rename sdio to sdhci ARM: 6788/1: SPEAr: Include mach/hardware.h instead of mach/spear.h ARM: 6787/1: SPEAr: Reorder #includes in .h & .c files. ARM: 6681/1: SPEAr: add debugfs support to clk API ARM: 6703/1: SPEAr: update clk API support ARM: 6679/1: SPEAr: make clk API functions more generic ARM: 6737/1: SPEAr: formalized timer support ...
Diffstat (limited to 'arch/arm/plat-spear')
-rw-r--r--arch/arm/plat-spear/Makefile4
-rw-r--r--arch/arm/plat-spear/clock.c844
-rw-r--r--arch/arm/plat-spear/include/plat/clock.h166
-rw-r--r--arch/arm/plat-spear/include/plat/debug-macro.S2
-rw-r--r--arch/arm/plat-spear/include/plat/hardware.h23
-rw-r--r--arch/arm/plat-spear/include/plat/memory.h2
-rw-r--r--arch/arm/plat-spear/include/plat/system.h4
-rw-r--r--arch/arm/plat-spear/include/plat/uncompress.h2
-rw-r--r--arch/arm/plat-spear/time.c26
9 files changed, 890 insertions, 183 deletions
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index eb89540aeda9..b4f340b8f1f1 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -3,6 +3,6 @@
3# 3#
4 4
5# Common support 5# Common support
6obj-y := clock.o padmux.o time.o 6obj-y := clock.o time.o
7 7
8obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o 8obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o padmux.o
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index ee4f90e534d8..bdbd7ec9cb6b 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -12,18 +12,25 @@
12 */ 12 */
13 13
14#include <linux/bug.h> 14#include <linux/bug.h>
15#include <linux/clk.h>
16#include <linux/debugfs.h>
15#include <linux/err.h> 17#include <linux/err.h>
16#include <linux/io.h> 18#include <linux/io.h>
17#include <linux/list.h> 19#include <linux/list.h>
18#include <linux/module.h> 20#include <linux/module.h>
19#include <linux/spinlock.h> 21#include <linux/spinlock.h>
20#include <mach/misc_regs.h>
21#include <plat/clock.h> 22#include <plat/clock.h>
22 23
23static DEFINE_SPINLOCK(clocks_lock); 24static DEFINE_SPINLOCK(clocks_lock);
24static LIST_HEAD(root_clks); 25static LIST_HEAD(root_clks);
26#ifdef CONFIG_DEBUG_FS
27static LIST_HEAD(clocks);
28#endif
25 29
26static void propagate_rate(struct list_head *); 30static void propagate_rate(struct clk *, int on_init);
31#ifdef CONFIG_DEBUG_FS
32static int clk_debugfs_reparent(struct clk *);
33#endif
27 34
28static int generic_clk_enable(struct clk *clk) 35static int generic_clk_enable(struct clk *clk)
29{ 36{
@@ -65,6 +72,104 @@ static struct clkops generic_clkops = {
65 .disable = generic_clk_disable, 72 .disable = generic_clk_disable,
66}; 73};
67 74
75/* returns current programmed clocks clock info structure */
76static struct pclk_info *pclk_info_get(struct clk *clk)
77{
78 unsigned int val, i;
79 struct pclk_info *info = NULL;
80
81 val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
82 & clk->pclk_sel->pclk_sel_mask;
83
84 for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
85 if (clk->pclk_sel->pclk_info[i].pclk_val == val)
86 info = &clk->pclk_sel->pclk_info[i];
87 }
88
89 return info;
90}
91
92/*
93 * Set Update pclk, and pclk_info of clk and add clock sibling node to current
94 * parents children list
95 */
96static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info)
97{
98 unsigned long flags;
99
100 spin_lock_irqsave(&clocks_lock, flags);
101 list_del(&clk->sibling);
102 list_add(&clk->sibling, &pclk_info->pclk->children);
103
104 clk->pclk = pclk_info->pclk;
105 spin_unlock_irqrestore(&clocks_lock, flags);
106
107#ifdef CONFIG_DEBUG_FS
108 clk_debugfs_reparent(clk);
109#endif
110}
111
112static void do_clk_disable(struct clk *clk)
113{
114 if (!clk)
115 return;
116
117 if (!clk->usage_count) {
118 WARN_ON(1);
119 return;
120 }
121
122 clk->usage_count--;
123
124 if (clk->usage_count == 0) {
125 /*
126 * Surely, there are no active childrens or direct users
127 * of this clock
128 */
129 if (clk->pclk)
130 do_clk_disable(clk->pclk);
131
132 if (clk->ops && clk->ops->disable)
133 clk->ops->disable(clk);
134 }
135}
136
137static int do_clk_enable(struct clk *clk)
138{
139 int ret = 0;
140
141 if (!clk)
142 return -EFAULT;
143
144 if (clk->usage_count == 0) {
145 if (clk->pclk) {
146 ret = do_clk_enable(clk->pclk);
147 if (ret)
148 goto err;
149 }
150 if (clk->ops && clk->ops->enable) {
151 ret = clk->ops->enable(clk);
152 if (ret) {
153 if (clk->pclk)
154 do_clk_disable(clk->pclk);
155 goto err;
156 }
157 }
158 /*
159 * Since the clock is going to be used for the first
160 * time please reclac
161 */
162 if (clk->recalc) {
163 ret = clk->recalc(clk);
164 if (ret)
165 goto err;
166 }
167 }
168 clk->usage_count++;
169err:
170 return ret;
171}
172
68/* 173/*
69 * clk_enable - inform the system when the clock source should be running. 174 * clk_enable - inform the system when the clock source should be running.
70 * @clk: clock source 175 * @clk: clock source
@@ -78,17 +183,9 @@ int clk_enable(struct clk *clk)
78 unsigned long flags; 183 unsigned long flags;
79 int ret = 0; 184 int ret = 0;
80 185
81 if (!clk || IS_ERR(clk))
82 return -EFAULT;
83
84 spin_lock_irqsave(&clocks_lock, flags); 186 spin_lock_irqsave(&clocks_lock, flags);
85 if (clk->usage_count == 0) { 187 ret = do_clk_enable(clk);
86 if (clk->ops && clk->ops->enable)
87 ret = clk->ops->enable(clk);
88 }
89 clk->usage_count++;
90 spin_unlock_irqrestore(&clocks_lock, flags); 188 spin_unlock_irqrestore(&clocks_lock, flags);
91
92 return ret; 189 return ret;
93} 190}
94EXPORT_SYMBOL(clk_enable); 191EXPORT_SYMBOL(clk_enable);
@@ -109,17 +206,8 @@ void clk_disable(struct clk *clk)
109{ 206{
110 unsigned long flags; 207 unsigned long flags;
111 208
112 if (!clk || IS_ERR(clk))
113 return;
114
115 WARN_ON(clk->usage_count == 0);
116
117 spin_lock_irqsave(&clocks_lock, flags); 209 spin_lock_irqsave(&clocks_lock, flags);
118 clk->usage_count--; 210 do_clk_disable(clk);
119 if (clk->usage_count == 0) {
120 if (clk->ops && clk->ops->disable)
121 clk->ops->disable(clk);
122 }
123 spin_unlock_irqrestore(&clocks_lock, flags); 211 spin_unlock_irqrestore(&clocks_lock, flags);
124} 212}
125EXPORT_SYMBOL(clk_disable); 213EXPORT_SYMBOL(clk_disable);
@@ -153,15 +241,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
153 int i, found = 0, val = 0; 241 int i, found = 0, val = 0;
154 unsigned long flags; 242 unsigned long flags;
155 243
156 if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent)) 244 if (!clk || !parent)
157 return -EFAULT; 245 return -EFAULT;
158 if (clk->usage_count)
159 return -EBUSY;
160 if (!clk->pclk_sel)
161 return -EPERM;
162 if (clk->pclk == parent) 246 if (clk->pclk == parent)
163 return 0; 247 return 0;
248 if (!clk->pclk_sel)
249 return -EPERM;
164 250
251 /* check if requested parent is in clk parent list */
165 for (i = 0; i < clk->pclk_sel->pclk_count; i++) { 252 for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
166 if (clk->pclk_sel->pclk_info[i].pclk == parent) { 253 if (clk->pclk_sel->pclk_info[i].pclk == parent) {
167 found = 1; 254 found = 1;
@@ -176,25 +263,58 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
176 /* reflect parent change in hardware */ 263 /* reflect parent change in hardware */
177 val = readl(clk->pclk_sel->pclk_sel_reg); 264 val = readl(clk->pclk_sel->pclk_sel_reg);
178 val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift); 265 val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift);
179 val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift; 266 val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift;
180 writel(val, clk->pclk_sel->pclk_sel_reg); 267 writel(val, clk->pclk_sel->pclk_sel_reg);
181 spin_unlock_irqrestore(&clocks_lock, flags); 268 spin_unlock_irqrestore(&clocks_lock, flags);
182 269
183 /* reflect parent change in software */ 270 /* reflect parent change in software */
184 clk->recalc(clk); 271 clk_reparent(clk, &clk->pclk_sel->pclk_info[i]);
185 propagate_rate(&clk->children); 272
273 propagate_rate(clk, 0);
186 return 0; 274 return 0;
187} 275}
188EXPORT_SYMBOL(clk_set_parent); 276EXPORT_SYMBOL(clk_set_parent);
189 277
278/**
279 * clk_set_rate - set the clock rate for a clock source
280 * @clk: clock source
281 * @rate: desired clock rate in Hz
282 *
283 * Returns success (0) or negative errno.
284 */
285int clk_set_rate(struct clk *clk, unsigned long rate)
286{
287 unsigned long flags;
288 int ret = -EINVAL;
289
290 if (!clk || !rate)
291 return -EFAULT;
292
293 if (clk->set_rate) {
294 spin_lock_irqsave(&clocks_lock, flags);
295 ret = clk->set_rate(clk, rate);
296 if (!ret)
297 /* if successful -> propagate */
298 propagate_rate(clk, 0);
299 spin_unlock_irqrestore(&clocks_lock, flags);
300 } else if (clk->pclk) {
301 u32 mult = clk->div_factor ? clk->div_factor : 1;
302 ret = clk_set_rate(clk->pclk, mult * rate);
303 }
304
305 return ret;
306}
307EXPORT_SYMBOL(clk_set_rate);
308
190/* registers clock in platform clock framework */ 309/* registers clock in platform clock framework */
191void clk_register(struct clk_lookup *cl) 310void clk_register(struct clk_lookup *cl)
192{ 311{
193 struct clk *clk = cl->clk; 312 struct clk *clk;
194 unsigned long flags; 313 unsigned long flags;
195 314
196 if (!clk || IS_ERR(clk)) 315 if (!cl || !cl->clk)
197 return; 316 return;
317 clk = cl->clk;
198 318
199 spin_lock_irqsave(&clocks_lock, flags); 319 spin_lock_irqsave(&clocks_lock, flags);
200 320
@@ -207,71 +327,173 @@ void clk_register(struct clk_lookup *cl)
207 /* root clock don't have any parents */ 327 /* root clock don't have any parents */
208 if (!clk->pclk && !clk->pclk_sel) { 328 if (!clk->pclk && !clk->pclk_sel) {
209 list_add(&clk->sibling, &root_clks); 329 list_add(&clk->sibling, &root_clks);
210 /* add clocks with only one parent to parent's children list */
211 } else if (clk->pclk && !clk->pclk_sel) { 330 } else if (clk->pclk && !clk->pclk_sel) {
331 /* add clocks with only one parent to parent's children list */
212 list_add(&clk->sibling, &clk->pclk->children); 332 list_add(&clk->sibling, &clk->pclk->children);
213 } else { 333 } else {
214 /* add clocks with > 1 parent to 1st parent's children list */ 334 /* clocks with more than one parent */
215 list_add(&clk->sibling, 335 struct pclk_info *pclk_info;
216 &clk->pclk_sel->pclk_info[0].pclk->children); 336
337 pclk_info = pclk_info_get(clk);
338 if (!pclk_info) {
339 pr_err("CLKDEV: invalid pclk info of clk with"
340 " %s dev_id and %s con_id\n",
341 cl->dev_id, cl->con_id);
342 } else {
343 clk->pclk = pclk_info->pclk;
344 list_add(&clk->sibling, &pclk_info->pclk->children);
345 }
217 } 346 }
347
218 spin_unlock_irqrestore(&clocks_lock, flags); 348 spin_unlock_irqrestore(&clocks_lock, flags);
219 349
350 /* debugfs specific */
351#ifdef CONFIG_DEBUG_FS
352 list_add(&clk->node, &clocks);
353 clk->cl = cl;
354#endif
355
220 /* add clock to arm clockdev framework */ 356 /* add clock to arm clockdev framework */
221 clkdev_add(cl); 357 clkdev_add(cl);
222} 358}
223 359
224/** 360/**
225 * propagate_rate - recalculate and propagate all clocks in list head 361 * propagate_rate - recalculate and propagate all clocks to children
362 * @pclk: parent clock required to be propogated
363 * @on_init: flag for enabling clocks which are ENABLED_ON_INIT.
226 * 364 *
227 * Recalculates all root clocks in list head, which if the clock's .recalc is 365 * Recalculates all children clocks
228 * set correctly, should also propagate their rates.
229 */ 366 */
230static void propagate_rate(struct list_head *lhead) 367void propagate_rate(struct clk *pclk, int on_init)
231{ 368{
232 struct clk *clkp, *_temp; 369 struct clk *clk, *_temp;
370 int ret = 0;
233 371
234 list_for_each_entry_safe(clkp, _temp, lhead, sibling) { 372 list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
235 if (clkp->recalc) 373 if (clk->recalc) {
236 clkp->recalc(clkp); 374 ret = clk->recalc(clk);
237 propagate_rate(&clkp->children); 375 /*
376 * recalc will return error if clk out is not programmed
377 * In this case configure default rate.
378 */
379 if (ret && clk->set_rate)
380 clk->set_rate(clk, 0);
381 }
382 propagate_rate(clk, on_init);
383
384 if (!on_init)
385 continue;
386
387 /* Enable clks enabled on init, in software view */
388 if (clk->flags & ENABLED_ON_INIT)
389 do_clk_enable(clk);
238 } 390 }
239} 391}
240 392
241/* returns current programmed clocks clock info structure */ 393/**
242static struct pclk_info *pclk_info_get(struct clk *clk) 394 * round_rate_index - return closest programmable rate index in rate_config tbl
395 * @clk: ptr to clock structure
396 * @drate: desired rate
397 * @rate: final rate will be returned in this variable only.
398 *
399 * Finds index in rate_config for highest clk rate which is less than
400 * requested rate. If there is no clk rate lesser than requested rate then
401 * -EINVAL is returned. This routine assumes that rate_config is written
402 * in incrementing order of clk rates.
403 * If drate passed is zero then default rate is programmed.
404 */
405static int
406round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
243{ 407{
244 unsigned int mask, i; 408 unsigned long tmp = 0, prev_rate = 0;
245 unsigned long flags; 409 int index;
246 struct pclk_info *info = NULL;
247 410
248 spin_lock_irqsave(&clocks_lock, flags); 411 if (!clk->calc_rate)
249 mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) 412 return -EFAULT;
250 & clk->pclk_sel->pclk_sel_mask;
251 413
252 for (i = 0; i < clk->pclk_sel->pclk_count; i++) { 414 if (!drate)
253 if (clk->pclk_sel->pclk_info[i].pclk_mask == mask) 415 return -EINVAL;
254 info = &clk->pclk_sel->pclk_info[i]; 416
417 /*
418 * This loops ends on two conditions:
419 * - as soon as clk is found with rate greater than requested rate.
420 * - if all clks in rate_config are smaller than requested rate.
421 */
422 for (index = 0; index < clk->rate_config.count; index++) {
423 prev_rate = tmp;
424 tmp = clk->calc_rate(clk, index);
425 if (drate < tmp) {
426 index--;
427 break;
428 }
255 } 429 }
256 spin_unlock_irqrestore(&clocks_lock, flags); 430 /* return if can't find suitable clock */
431 if (index < 0) {
432 index = -EINVAL;
433 *rate = 0;
434 } else if (index == clk->rate_config.count) {
435 /* program with highest clk rate possible */
436 index = clk->rate_config.count - 1;
437 *rate = tmp;
438 } else
439 *rate = prev_rate;
257 440
258 return info; 441 return index;
259} 442}
260 443
261/* 444/**
262 * Set pclk as cclk's parent and add clock sibling node to current parents 445 * clk_round_rate - adjust a rate to the exact rate a clock can provide
263 * children list 446 * @clk: clock source
447 * @rate: desired clock rate in Hz
448 *
449 * Returns rounded clock rate in Hz, or negative errno.
264 */ 450 */
265static void change_parent(struct clk *cclk, struct clk *pclk) 451long clk_round_rate(struct clk *clk, unsigned long drate)
266{ 452{
267 unsigned long flags; 453 long rate = 0;
454 int index;
455
456 /*
457 * propagate call to parent who supports calc_rate. Similar approach is
458 * used in clk_set_rate.
459 */
460 if (!clk->calc_rate) {
461 u32 mult;
462 if (!clk->pclk)
463 return clk->rate;
464
465 mult = clk->div_factor ? clk->div_factor : 1;
466 return clk_round_rate(clk->pclk, mult * drate) / mult;
467 }
268 468
269 spin_lock_irqsave(&clocks_lock, flags); 469 index = round_rate_index(clk, drate, &rate);
270 list_del(&cclk->sibling); 470 if (index >= 0)
271 list_add(&cclk->sibling, &pclk->children); 471 return rate;
472 else
473 return index;
474}
475EXPORT_SYMBOL(clk_round_rate);
272 476
273 cclk->pclk = pclk; 477/*All below functions are called with lock held */
274 spin_unlock_irqrestore(&clocks_lock, flags); 478
479/*
480 * Calculates pll clk rate for specific value of mode, m, n and p
481 *
482 * In normal mode
483 * rate = (2 * M[15:8] * Fin)/(N * 2^P)
484 *
485 * In Dithered mode
486 * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
487 */
488unsigned long pll_calc_rate(struct clk *clk, int index)
489{
490 unsigned long rate = clk->pclk->rate;
491 struct pll_rate_tbl *tbls = clk->rate_config.tbls;
492 unsigned int mode;
493
494 mode = tbls[index].mode ? 256 : 1;
495 return (((2 * rate / 10000) * tbls[index].m) /
496 (mode * tbls[index].n * (1 << tbls[index].p))) * 10000;
275} 497}
276 498
277/* 499/*
@@ -283,47 +505,146 @@ static void change_parent(struct clk *cclk, struct clk *pclk)
283 * In Dithered mode 505 * In Dithered mode
284 * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) 506 * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
285 */ 507 */
286void pll1_clk_recalc(struct clk *clk) 508int pll_clk_recalc(struct clk *clk)
287{ 509{
288 struct pll_clk_config *config = clk->private_data; 510 struct pll_clk_config *config = clk->private_data;
289 unsigned int num = 2, den = 0, val, mode = 0; 511 unsigned int num = 2, den = 0, val, mode = 0;
290 unsigned long flags;
291 512
292 spin_lock_irqsave(&clocks_lock, flags); 513 mode = (readl(config->mode_reg) >> config->masks->mode_shift) &
293 mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) & 514 config->masks->mode_mask;
294 PLL_MODE_MASK;
295 515
296 val = readl(config->cfg_reg); 516 val = readl(config->cfg_reg);
297 /* calculate denominator */ 517 /* calculate denominator */
298 den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; 518 den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask;
299 den = 1 << den; 519 den = 1 << den;
300 den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; 520 den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask;
301 521
302 /* calculate numerator & denominator */ 522 /* calculate numerator & denominator */
303 if (!mode) { 523 if (!mode) {
304 /* Normal mode */ 524 /* Normal mode */
305 num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; 525 num *= (val >> config->masks->norm_fdbk_m_shift) &
526 config->masks->norm_fdbk_m_mask;
306 } else { 527 } else {
307 /* Dithered mode */ 528 /* Dithered mode */
308 num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; 529 num *= (val >> config->masks->dith_fdbk_m_shift) &
530 config->masks->dith_fdbk_m_mask;
309 den *= 256; 531 den *= 256;
310 } 532 }
311 533
534 if (!den)
535 return -EINVAL;
536
312 clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; 537 clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
313 spin_unlock_irqrestore(&clocks_lock, flags); 538 return 0;
539}
540
541/*
542 * Configures new clock rate of pll
543 */
544int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
545{
546 struct pll_rate_tbl *tbls = clk->rate_config.tbls;
547 struct pll_clk_config *config = clk->private_data;
548 unsigned long val, rate;
549 int i;
550
551 i = round_rate_index(clk, desired_rate, &rate);
552 if (i < 0)
553 return i;
554
555 val = readl(config->mode_reg) &
556 ~(config->masks->mode_mask << config->masks->mode_shift);
557 val |= (tbls[i].mode & config->masks->mode_mask) <<
558 config->masks->mode_shift;
559 writel(val, config->mode_reg);
560
561 val = readl(config->cfg_reg) &
562 ~(config->masks->div_p_mask << config->masks->div_p_shift);
563 val |= (tbls[i].p & config->masks->div_p_mask) <<
564 config->masks->div_p_shift;
565 val &= ~(config->masks->div_n_mask << config->masks->div_n_shift);
566 val |= (tbls[i].n & config->masks->div_n_mask) <<
567 config->masks->div_n_shift;
568 val &= ~(config->masks->dith_fdbk_m_mask <<
569 config->masks->dith_fdbk_m_shift);
570 if (tbls[i].mode)
571 val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) <<
572 config->masks->dith_fdbk_m_shift;
573 else
574 val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) <<
575 config->masks->norm_fdbk_m_shift;
576
577 writel(val, config->cfg_reg);
578
579 clk->rate = rate;
580
581 return 0;
582}
583
584/*
585 * Calculates ahb, apb clk rate for specific value of div
586 */
587unsigned long bus_calc_rate(struct clk *clk, int index)
588{
589 unsigned long rate = clk->pclk->rate;
590 struct bus_rate_tbl *tbls = clk->rate_config.tbls;
591
592 return rate / (tbls[index].div + 1);
314} 593}
315 594
316/* calculates current programmed rate of ahb or apb bus */ 595/* calculates current programmed rate of ahb or apb bus */
317void bus_clk_recalc(struct clk *clk) 596int bus_clk_recalc(struct clk *clk)
318{ 597{
319 struct bus_clk_config *config = clk->private_data; 598 struct bus_clk_config *config = clk->private_data;
320 unsigned int div; 599 unsigned int div;
321 unsigned long flags;
322 600
323 spin_lock_irqsave(&clocks_lock, flags); 601 div = ((readl(config->reg) >> config->masks->shift) &
324 div = ((readl(config->reg) >> config->shift) & config->mask) + 1; 602 config->masks->mask) + 1;
603
604 if (!div)
605 return -EINVAL;
606
325 clk->rate = (unsigned long)clk->pclk->rate / div; 607 clk->rate = (unsigned long)clk->pclk->rate / div;
326 spin_unlock_irqrestore(&clocks_lock, flags); 608 return 0;
609}
610
611/* Configures new clock rate of AHB OR APB bus */
612int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
613{
614 struct bus_rate_tbl *tbls = clk->rate_config.tbls;
615 struct bus_clk_config *config = clk->private_data;
616 unsigned long val, rate;
617 int i;
618
619 i = round_rate_index(clk, desired_rate, &rate);
620 if (i < 0)
621 return i;
622
623 val = readl(config->reg) &
624 ~(config->masks->mask << config->masks->shift);
625 val |= (tbls[i].div & config->masks->mask) << config->masks->shift;
626 writel(val, config->reg);
627
628 clk->rate = rate;
629
630 return 0;
631}
632
633/*
634 * gives rate for different values of eq, x and y
635 *
636 * Fout from synthesizer can be given from two equations:
637 * Fout1 = (Fin * X/Y)/2 EQ1
638 * Fout2 = Fin * X/Y EQ2
639 */
640unsigned long aux_calc_rate(struct clk *clk, int index)
641{
642 unsigned long rate = clk->pclk->rate;
643 struct aux_rate_tbl *tbls = clk->rate_config.tbls;
644 u8 eq = tbls[index].eq ? 1 : 2;
645
646 return (((rate/10000) * tbls[index].xscale) /
647 (tbls[index].yscale * eq)) * 10000;
327} 648}
328 649
329/* 650/*
@@ -336,44 +657,76 @@ void bus_clk_recalc(struct clk *clk)
336 * 657 *
337 * Selection of eqn 1 or 2 is programmed in register 658 * Selection of eqn 1 or 2 is programmed in register
338 */ 659 */
339void aux_clk_recalc(struct clk *clk) 660int aux_clk_recalc(struct clk *clk)
340{ 661{
341 struct aux_clk_config *config = clk->private_data; 662 struct aux_clk_config *config = clk->private_data;
342 struct pclk_info *pclk_info = NULL;
343 unsigned int num = 1, den = 1, val, eqn; 663 unsigned int num = 1, den = 1, val, eqn;
344 unsigned long flags;
345 664
346 /* get current programmed parent */ 665 val = readl(config->synth_reg);
347 pclk_info = pclk_info_get(clk);
348 if (!pclk_info) {
349 spin_lock_irqsave(&clocks_lock, flags);
350 clk->pclk = NULL;
351 clk->rate = 0;
352 spin_unlock_irqrestore(&clocks_lock, flags);
353 return;
354 }
355 666
356 change_parent(clk, pclk_info->pclk); 667 eqn = (val >> config->masks->eq_sel_shift) &
668 config->masks->eq_sel_mask;
669 if (eqn == config->masks->eq1_mask)
670 den *= 2;
357 671
358 spin_lock_irqsave(&clocks_lock, flags); 672 /* calculate numerator */
359 if (pclk_info->scalable) { 673 num = (val >> config->masks->xscale_sel_shift) &
360 val = readl(config->synth_reg); 674 config->masks->xscale_sel_mask;
361 675
362 eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK; 676 /* calculate denominator */
363 if (eqn == AUX_EQ1_SEL) 677 den *= (val >> config->masks->yscale_sel_shift) &
364 den *= 2; 678 config->masks->yscale_sel_mask;
365 679
366 /* calculate numerator */ 680 if (!den)
367 num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK; 681 return -EINVAL;
368 682
369 /* calculate denominator */ 683 clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
370 den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK; 684 return 0;
371 val = (((clk->pclk->rate/10000) * num) / den) * 10000; 685}
372 } else
373 val = clk->pclk->rate;
374 686
375 clk->rate = val; 687/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
376 spin_unlock_irqrestore(&clocks_lock, flags); 688int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate)
689{
690 struct aux_rate_tbl *tbls = clk->rate_config.tbls;
691 struct aux_clk_config *config = clk->private_data;
692 unsigned long val, rate;
693 int i;
694
695 i = round_rate_index(clk, desired_rate, &rate);
696 if (i < 0)
697 return i;
698
699 val = readl(config->synth_reg) &
700 ~(config->masks->eq_sel_mask << config->masks->eq_sel_shift);
701 val |= (tbls[i].eq & config->masks->eq_sel_mask) <<
702 config->masks->eq_sel_shift;
703 val &= ~(config->masks->xscale_sel_mask <<
704 config->masks->xscale_sel_shift);
705 val |= (tbls[i].xscale & config->masks->xscale_sel_mask) <<
706 config->masks->xscale_sel_shift;
707 val &= ~(config->masks->yscale_sel_mask <<
708 config->masks->yscale_sel_shift);
709 val |= (tbls[i].yscale & config->masks->yscale_sel_mask) <<
710 config->masks->yscale_sel_shift;
711 writel(val, config->synth_reg);
712
713 clk->rate = rate;
714
715 return 0;
716}
717
718/*
719 * Calculates gpt clk rate for different values of mscale and nscale
720 *
721 * Fout= Fin/((2 ^ (N+1)) * (M+1))
722 */
723unsigned long gpt_calc_rate(struct clk *clk, int index)
724{
725 unsigned long rate = clk->pclk->rate;
726 struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
727
728 return rate / ((1 << (tbls[index].nscale + 1)) *
729 (tbls[index].mscale + 1));
377} 730}
378 731
379/* 732/*
@@ -381,46 +734,142 @@ void aux_clk_recalc(struct clk *clk)
381 * Fout from synthesizer can be given from below equations: 734 * Fout from synthesizer can be given from below equations:
382 * Fout= Fin/((2 ^ (N+1)) * (M+1)) 735 * Fout= Fin/((2 ^ (N+1)) * (M+1))
383 */ 736 */
384void gpt_clk_recalc(struct clk *clk) 737int gpt_clk_recalc(struct clk *clk)
385{ 738{
386 struct aux_clk_config *config = clk->private_data; 739 struct gpt_clk_config *config = clk->private_data;
387 struct pclk_info *pclk_info = NULL;
388 unsigned int div = 1, val; 740 unsigned int div = 1, val;
389 unsigned long flags;
390 741
391 pclk_info = pclk_info_get(clk); 742 val = readl(config->synth_reg);
392 if (!pclk_info) { 743 div += (val >> config->masks->mscale_sel_shift) &
393 spin_lock_irqsave(&clocks_lock, flags); 744 config->masks->mscale_sel_mask;
394 clk->pclk = NULL; 745 div *= 1 << (((val >> config->masks->nscale_sel_shift) &
395 clk->rate = 0; 746 config->masks->nscale_sel_mask) + 1);
396 spin_unlock_irqrestore(&clocks_lock, flags);
397 return;
398 }
399
400 change_parent(clk, pclk_info->pclk);
401 747
402 spin_lock_irqsave(&clocks_lock, flags); 748 if (!div)
403 if (pclk_info->scalable) { 749 return -EINVAL;
404 val = readl(config->synth_reg);
405 div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK;
406 div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1);
407 }
408 750
409 clk->rate = (unsigned long)clk->pclk->rate / div; 751 clk->rate = (unsigned long)clk->pclk->rate / div;
410 spin_unlock_irqrestore(&clocks_lock, flags); 752 return 0;
753}
754
755/* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/
756int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate)
757{
758 struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
759 struct gpt_clk_config *config = clk->private_data;
760 unsigned long val, rate;
761 int i;
762
763 i = round_rate_index(clk, desired_rate, &rate);
764 if (i < 0)
765 return i;
766
767 val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask <<
768 config->masks->mscale_sel_shift);
769 val |= (tbls[i].mscale & config->masks->mscale_sel_mask) <<
770 config->masks->mscale_sel_shift;
771 val &= ~(config->masks->nscale_sel_mask <<
772 config->masks->nscale_sel_shift);
773 val |= (tbls[i].nscale & config->masks->nscale_sel_mask) <<
774 config->masks->nscale_sel_shift;
775 writel(val, config->synth_reg);
776
777 clk->rate = rate;
778
779 return 0;
411} 780}
412 781
413/* 782/*
414 * Used for clocks that always have same value as the parent clock divided by a 783 * Calculates clcd clk rate for different values of div
784 *
785 * Fout from synthesizer can be given from below equation:
786 * Fout= Fin/2*div (division factor)
787 * div is 17 bits:-
788 * 0-13 (fractional part)
789 * 14-16 (integer part)
790 * To calculate Fout we left shift val by 14 bits and divide Fin by
791 * complete div (including fractional part) and then right shift the
792 * result by 14 places.
793 */
794unsigned long clcd_calc_rate(struct clk *clk, int index)
795{
796 unsigned long rate = clk->pclk->rate;
797 struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
798
799 rate /= 1000;
800 rate <<= 12;
801 rate /= (2 * tbls[index].div);
802 rate >>= 12;
803 rate *= 1000;
804
805 return rate;
806}
807
808/*
809 * calculates current programmed rate of clcd synthesizer
810 * Fout from synthesizer can be given from below equation:
811 * Fout= Fin/2*div (division factor)
812 * div is 17 bits:-
813 * 0-13 (fractional part)
814 * 14-16 (integer part)
815 * To calculate Fout we left shift val by 14 bits and divide Fin by
816 * complete div (including fractional part) and then right shift the
817 * result by 14 places.
818 */
819int clcd_clk_recalc(struct clk *clk)
820{
821 struct clcd_clk_config *config = clk->private_data;
822 unsigned int div = 1;
823 unsigned long prate;
824 unsigned int val;
825
826 val = readl(config->synth_reg);
827 div = (val >> config->masks->div_factor_shift) &
828 config->masks->div_factor_mask;
829
830 if (!div)
831 return -EINVAL;
832
833 prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
834
835 clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
836 clk->rate *= 1000;
837 return 0;
838}
839
840/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
841int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
842{
843 struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
844 struct clcd_clk_config *config = clk->private_data;
845 unsigned long val, rate;
846 int i;
847
848 i = round_rate_index(clk, desired_rate, &rate);
849 if (i < 0)
850 return i;
851
852 val = readl(config->synth_reg) & ~(config->masks->div_factor_mask <<
853 config->masks->div_factor_shift);
854 val |= (tbls[i].div & config->masks->div_factor_mask) <<
855 config->masks->div_factor_shift;
856 writel(val, config->synth_reg);
857
858 clk->rate = rate;
859
860 return 0;
861}
862
863/*
864 * Used for clocks that always have value as the parent clock divided by a
415 * fixed divisor 865 * fixed divisor
416 */ 866 */
417void follow_parent(struct clk *clk) 867int follow_parent(struct clk *clk)
418{ 868{
419 unsigned long flags; 869 unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
420 870
421 spin_lock_irqsave(&clocks_lock, flags); 871 clk->rate = clk->pclk->rate/div_factor;
422 clk->rate = clk->pclk->rate; 872 return 0;
423 spin_unlock_irqrestore(&clocks_lock, flags);
424} 873}
425 874
426/** 875/**
@@ -431,5 +880,124 @@ void follow_parent(struct clk *clk)
431 */ 880 */
432void recalc_root_clocks(void) 881void recalc_root_clocks(void)
433{ 882{
434 propagate_rate(&root_clks); 883 struct clk *pclk;
884 unsigned long flags;
885 int ret = 0;
886
887 spin_lock_irqsave(&clocks_lock, flags);
888 list_for_each_entry(pclk, &root_clks, sibling) {
889 if (pclk->recalc) {
890 ret = pclk->recalc(pclk);
891 /*
892 * recalc will return error if clk out is not programmed
893 * In this case configure default clock.
894 */
895 if (ret && pclk->set_rate)
896 pclk->set_rate(pclk, 0);
897 }
898 propagate_rate(pclk, 1);
899 /* Enable clks enabled on init, in software view */
900 if (pclk->flags & ENABLED_ON_INIT)
901 do_clk_enable(pclk);
902 }
903 spin_unlock_irqrestore(&clocks_lock, flags);
904}
905
906#ifdef CONFIG_DEBUG_FS
907/*
908 * debugfs support to trace clock tree hierarchy and attributes
909 */
910static struct dentry *clk_debugfs_root;
911static int clk_debugfs_register_one(struct clk *c)
912{
913 int err;
914 struct dentry *d, *child;
915 struct clk *pa = c->pclk;
916 char s[255];
917 char *p = s;
918
919 if (c) {
920 if (c->cl->con_id)
921 p += sprintf(p, "%s", c->cl->con_id);
922 if (c->cl->dev_id)
923 p += sprintf(p, "%s", c->cl->dev_id);
924 }
925 d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
926 if (!d)
927 return -ENOMEM;
928 c->dent = d;
929
930 d = debugfs_create_u32("usage_count", S_IRUGO, c->dent,
931 (u32 *)&c->usage_count);
932 if (!d) {
933 err = -ENOMEM;
934 goto err_out;
935 }
936 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
937 if (!d) {
938 err = -ENOMEM;
939 goto err_out;
940 }
941 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
942 if (!d) {
943 err = -ENOMEM;
944 goto err_out;
945 }
946 return 0;
947
948err_out:
949 d = c->dent;
950 list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
951 debugfs_remove(child);
952 debugfs_remove(c->dent);
953 return err;
954}
955
956static int clk_debugfs_register(struct clk *c)
957{
958 int err;
959 struct clk *pa = c->pclk;
960
961 if (pa && !pa->dent) {
962 err = clk_debugfs_register(pa);
963 if (err)
964 return err;
965 }
966
967 if (!c->dent) {
968 err = clk_debugfs_register_one(c);
969 if (err)
970 return err;
971 }
972 return 0;
973}
974
975static int __init clk_debugfs_init(void)
976{
977 struct clk *c;
978 struct dentry *d;
979 int err;
980
981 d = debugfs_create_dir("clock", NULL);
982 if (!d)
983 return -ENOMEM;
984 clk_debugfs_root = d;
985
986 list_for_each_entry(c, &clocks, node) {
987 err = clk_debugfs_register(c);
988 if (err)
989 goto err_out;
990 }
991 return 0;
992err_out:
993 debugfs_remove_recursive(clk_debugfs_root);
994 return err;
995}
996late_initcall(clk_debugfs_init);
997
998static int clk_debugfs_reparent(struct clk *c)
999{
1000 debugfs_remove(c->dent);
1001 return clk_debugfs_register_one(c);
435} 1002}
1003#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 2572260f990f..2ae6606930a6 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -21,6 +21,7 @@
21/* clk structure flags */ 21/* clk structure flags */
22#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */ 22#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */
23#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */ 23#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */
24#define ENABLED_ON_INIT (1 << 2) /* clocks enabled at init */
24 25
25/** 26/**
26 * struct clkops - clock operations 27 * struct clkops - clock operations
@@ -35,13 +36,11 @@ struct clkops {
35/** 36/**
36 * struct pclk_info - parents info 37 * struct pclk_info - parents info
37 * @pclk: pointer to parent clk 38 * @pclk: pointer to parent clk
38 * @pclk_mask: value to be written for selecting this parent 39 * @pclk_val: value to be written for selecting this parent
39 * @scalable: Is parent scalable (1 - YES, 0 - NO)
40 */ 40 */
41struct pclk_info { 41struct pclk_info {
42 struct clk *pclk; 42 struct clk *pclk;
43 u8 pclk_mask; 43 u8 pclk_val;
44 u8 scalable;
45}; 44};
46 45
47/** 46/**
@@ -54,11 +53,23 @@ struct pclk_info {
54struct pclk_sel { 53struct pclk_sel {
55 struct pclk_info *pclk_info; 54 struct pclk_info *pclk_info;
56 u8 pclk_count; 55 u8 pclk_count;
57 unsigned int *pclk_sel_reg; 56 void __iomem *pclk_sel_reg;
58 unsigned int pclk_sel_mask; 57 unsigned int pclk_sel_mask;
59}; 58};
60 59
61/** 60/**
61 * struct rate_config - clk rate configurations
62 * @tbls: array of device specific clk rate tables, in ascending order of rates
63 * @count: size of tbls array
64 * @default_index: default setting when originally disabled
65 */
66struct rate_config {
67 void *tbls;
68 u8 count;
69 u8 default_index;
70};
71
72/**
62 * struct clk - clock structure 73 * struct clk - clock structure
63 * @usage_count: num of users who enabled this clock 74 * @usage_count: num of users who enabled this clock
64 * @flags: flags for clock properties 75 * @flags: flags for clock properties
@@ -67,21 +78,32 @@ struct pclk_sel {
67 * @en_reg_bit: clk enable/disable bit 78 * @en_reg_bit: clk enable/disable bit
68 * @ops: clk enable/disable ops - generic_clkops selected if NULL 79 * @ops: clk enable/disable ops - generic_clkops selected if NULL
69 * @recalc: pointer to clock rate recalculate function 80 * @recalc: pointer to clock rate recalculate function
81 * @set_rate: pointer to clock set rate function
82 * @calc_rate: pointer to clock get rate function for index
83 * @rate_config: rate configuration information, used by set_rate
84 * @div_factor: division factor to parent clock.
70 * @pclk: current parent clk 85 * @pclk: current parent clk
71 * @pclk_sel: pointer to parent selection structure 86 * @pclk_sel: pointer to parent selection structure
72 * @pclk_sel_shift: register shift for selecting parent of this clock 87 * @pclk_sel_shift: register shift for selecting parent of this clock
73 * @children: list for childrens or this clock 88 * @children: list for childrens or this clock
74 * @sibling: node for list of clocks having same parents 89 * @sibling: node for list of clocks having same parents
75 * @private_data: clock specific private data 90 * @private_data: clock specific private data
91 * @node: list to maintain clocks linearly
92 * @cl: clocklook up assoicated with this clock
93 * @dent: object for debugfs
76 */ 94 */
77struct clk { 95struct clk {
78 unsigned int usage_count; 96 unsigned int usage_count;
79 unsigned int flags; 97 unsigned int flags;
80 unsigned long rate; 98 unsigned long rate;
81 unsigned int *en_reg; 99 void __iomem *en_reg;
82 u8 en_reg_bit; 100 u8 en_reg_bit;
83 const struct clkops *ops; 101 const struct clkops *ops;
84 void (*recalc) (struct clk *); 102 int (*recalc) (struct clk *);
103 int (*set_rate) (struct clk *, unsigned long rate);
104 unsigned long (*calc_rate)(struct clk *, int index);
105 struct rate_config rate_config;
106 unsigned int div_factor;
85 107
86 struct clk *pclk; 108 struct clk *pclk;
87 struct pclk_sel *pclk_sel; 109 struct pclk_sel *pclk_sel;
@@ -90,37 +112,137 @@ struct clk {
90 struct list_head children; 112 struct list_head children;
91 struct list_head sibling; 113 struct list_head sibling;
92 void *private_data; 114 void *private_data;
115#ifdef CONFIG_DEBUG_FS
116 struct list_head node;
117 struct clk_lookup *cl;
118 struct dentry *dent;
119#endif
93}; 120};
94 121
95/* pll configuration structure */ 122/* pll configuration structure */
123struct pll_clk_masks {
124 u32 mode_mask;
125 u32 mode_shift;
126
127 u32 norm_fdbk_m_mask;
128 u32 norm_fdbk_m_shift;
129 u32 dith_fdbk_m_mask;
130 u32 dith_fdbk_m_shift;
131 u32 div_p_mask;
132 u32 div_p_shift;
133 u32 div_n_mask;
134 u32 div_n_shift;
135};
136
96struct pll_clk_config { 137struct pll_clk_config {
97 unsigned int *mode_reg; 138 void __iomem *mode_reg;
98 unsigned int *cfg_reg; 139 void __iomem *cfg_reg;
140 struct pll_clk_masks *masks;
141};
142
143/* pll clk rate config structure */
144struct pll_rate_tbl {
145 u8 mode;
146 u16 m;
147 u8 n;
148 u8 p;
99}; 149};
100 150
101/* ahb and apb bus configuration structure */ 151/* ahb and apb bus configuration structure */
152struct bus_clk_masks {
153 u32 mask;
154 u32 shift;
155};
156
102struct bus_clk_config { 157struct bus_clk_config {
103 unsigned int *reg; 158 void __iomem *reg;
104 unsigned int mask; 159 struct bus_clk_masks *masks;
105 unsigned int shift; 160};
161
162/* ahb and apb clk bus rate config structure */
163struct bus_rate_tbl {
164 u8 div;
165};
166
167/* Aux clk configuration structure: applicable to UART and FIRDA */
168struct aux_clk_masks {
169 u32 eq_sel_mask;
170 u32 eq_sel_shift;
171 u32 eq1_mask;
172 u32 eq2_mask;
173 u32 xscale_sel_mask;
174 u32 xscale_sel_shift;
175 u32 yscale_sel_mask;
176 u32 yscale_sel_shift;
106}; 177};
107 178
108/*
109 * Aux clk configuration structure: applicable to GPT, UART and FIRDA
110 */
111struct aux_clk_config { 179struct aux_clk_config {
112 unsigned int *synth_reg; 180 void __iomem *synth_reg;
181 struct aux_clk_masks *masks;
182};
183
184/* aux clk rate config structure */
185struct aux_rate_tbl {
186 u16 xscale;
187 u16 yscale;
188 u8 eq;
189};
190
191/* GPT clk configuration structure */
192struct gpt_clk_masks {
193 u32 mscale_sel_mask;
194 u32 mscale_sel_shift;
195 u32 nscale_sel_mask;
196 u32 nscale_sel_shift;
197};
198
199struct gpt_clk_config {
200 void __iomem *synth_reg;
201 struct gpt_clk_masks *masks;
202};
203
204/* gpt clk rate config structure */
205struct gpt_rate_tbl {
206 u16 mscale;
207 u16 nscale;
208};
209
210/* clcd clk configuration structure */
211struct clcd_synth_masks {
212 u32 div_factor_mask;
213 u32 div_factor_shift;
214};
215
216struct clcd_clk_config {
217 void __iomem *synth_reg;
218 struct clcd_synth_masks *masks;
219};
220
221/* clcd clk rate config structure */
222struct clcd_rate_tbl {
223 u16 div;
113}; 224};
114 225
115/* platform specific clock functions */ 226/* platform specific clock functions */
116void clk_register(struct clk_lookup *cl); 227void clk_register(struct clk_lookup *cl);
117void recalc_root_clocks(void); 228void recalc_root_clocks(void);
118 229
119/* clock recalc functions */ 230/* clock recalc & set rate functions */
120void follow_parent(struct clk *clk); 231int follow_parent(struct clk *clk);
121void pll1_clk_recalc(struct clk *clk); 232unsigned long pll_calc_rate(struct clk *clk, int index);
122void bus_clk_recalc(struct clk *clk); 233int pll_clk_recalc(struct clk *clk);
123void gpt_clk_recalc(struct clk *clk); 234int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
124void aux_clk_recalc(struct clk *clk); 235unsigned long bus_calc_rate(struct clk *clk, int index);
236int bus_clk_recalc(struct clk *clk);
237int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
238unsigned long gpt_calc_rate(struct clk *clk, int index);
239int gpt_clk_recalc(struct clk *clk);
240int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
241unsigned long aux_calc_rate(struct clk *clk, int index);
242int aux_clk_recalc(struct clk *clk);
243int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
244unsigned long clcd_calc_rate(struct clk *clk, int index);
245int clcd_clk_recalc(struct clk *clk);
246int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
125 247
126#endif /* __PLAT_CLOCK_H */ 248#endif /* __PLAT_CLOCK_H */
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
index e91270e4f640..8501bbf2c092 100644
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ b/arch/arm/plat-spear/include/plat/debug-macro.S
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include <linux/amba/serial.h> 14#include <linux/amba/serial.h>
15#include <mach/spear.h> 15#include <mach/hardware.h>
16 16
17 .macro addruart, rp, rv 17 .macro addruart, rp, rv
18 mov \rp, #SPEAR_DBG_UART_BASE @ Physical base 18 mov \rp, #SPEAR_DBG_UART_BASE @ Physical base
diff --git a/arch/arm/plat-spear/include/plat/hardware.h b/arch/arm/plat-spear/include/plat/hardware.h
new file mode 100644
index 000000000000..66d677225d15
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/hardware.h
@@ -0,0 +1,23 @@
1/*
2 * arch/arm/plat-spear/include/plat/hardware.h
3 *
4 * Hardware definitions for SPEAr
5 *
6 * Copyright (C) 2010 ST Microelectronics
7 * Viresh Kumar<viresh.kumar@st.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#ifndef __PLAT_HARDWARE_H
15#define __PLAT_HARDWARE_H
16
17#ifndef __ASSEMBLY__
18#define IOMEM(x) ((void __iomem __force *)(x))
19#else
20#define IOMEM(x) (x)
21#endif
22
23#endif /* __PLAT_HARDWARE_H */
diff --git a/arch/arm/plat-spear/include/plat/memory.h b/arch/arm/plat-spear/include/plat/memory.h
index 27a4aba77343..7e3599e1104e 100644
--- a/arch/arm/plat-spear/include/plat/memory.h
+++ b/arch/arm/plat-spear/include/plat/memory.h
@@ -15,6 +15,6 @@
15#define __PLAT_MEMORY_H 15#define __PLAT_MEMORY_H
16 16
17/* Physical DRAM offset */ 17/* Physical DRAM offset */
18#define PHYS_OFFSET UL(0x00000000) 18#define PLAT_PHYS_OFFSET UL(0x00000000)
19 19
20#endif /* __PLAT_MEMORY_H */ 20#endif /* __PLAT_MEMORY_H */
diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h
index 55a4e405d578..a235fa0ca777 100644
--- a/arch/arm/plat-spear/include/plat/system.h
+++ b/arch/arm/plat-spear/include/plat/system.h
@@ -14,9 +14,9 @@
14#ifndef __PLAT_SYSTEM_H 14#ifndef __PLAT_SYSTEM_H
15#define __PLAT_SYSTEM_H 15#define __PLAT_SYSTEM_H
16 16
17#include <asm/hardware/sp810.h>
18#include <linux/io.h> 17#include <linux/io.h>
19#include <mach/spear.h> 18#include <asm/hardware/sp810.h>
19#include <mach/hardware.h>
20 20
21static inline void arch_idle(void) 21static inline void arch_idle(void)
22{ 22{
diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h
index 6dd455bafdfd..1bf84527aee4 100644
--- a/arch/arm/plat-spear/include/plat/uncompress.h
+++ b/arch/arm/plat-spear/include/plat/uncompress.h
@@ -13,7 +13,7 @@
13 13
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/amba/serial.h> 15#include <linux/amba/serial.h>
16#include <mach/spear.h> 16#include <mach/hardware.h>
17 17
18#ifndef __PLAT_UNCOMPRESS_H 18#ifndef __PLAT_UNCOMPRESS_H
19#define __PLAT_UNCOMPRESS_H 19#define __PLAT_UNCOMPRESS_H
diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c
index 839c88df9994..dbb6e4fff79d 100644
--- a/arch/arm/plat-spear/time.c
+++ b/arch/arm/plat-spear/time.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/arm/plat-spear/time.c 2 * arch/arm/plat-spear/time.c
3 * 3 *
4 * Copyright (C) 2009 ST Microelectronics 4 * Copyright (C) 2010 ST Microelectronics
5 * Shiraz Hashim<shiraz.hashim@st.com> 5 * Shiraz Hashim<shiraz.hashim@st.com>
6 * 6 *
7 * This file is licensed under the terms of the GNU General Public 7 * This file is licensed under the terms of the GNU General Public
@@ -20,10 +20,9 @@
20#include <linux/time.h> 20#include <linux/time.h>
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <asm/mach/time.h> 22#include <asm/mach/time.h>
23#include <mach/irqs.h>
24#include <mach/hardware.h>
25#include <mach/spear.h>
26#include <mach/generic.h> 23#include <mach/generic.h>
24#include <mach/hardware.h>
25#include <mach/irqs.h>
27 26
28/* 27/*
29 * We would use TIMER0 and TIMER1 as clockevent and clocksource. 28 * We would use TIMER0 and TIMER1 as clockevent and clocksource.
@@ -211,7 +210,7 @@ static void __init spear_clockevent_init(void)
211 210
212void __init spear_setup_timer(void) 211void __init spear_setup_timer(void)
213{ 212{
214 struct clk *pll3_clk; 213 int ret;
215 214
216 if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) { 215 if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) {
217 pr_err("%s:cannot get IO addr\n", __func__); 216 pr_err("%s:cannot get IO addr\n", __func__);
@@ -230,26 +229,21 @@ void __init spear_setup_timer(void)
230 goto err_iomap; 229 goto err_iomap;
231 } 230 }
232 231
233 pll3_clk = clk_get(NULL, "pll3_48m_clk"); 232 ret = clk_enable(gpt_clk);
234 if (!pll3_clk) { 233 if (ret < 0) {
235 pr_err("%s:couldn't get PLL3 as parent for gpt\n", __func__); 234 pr_err("%s:couldn't enable gpt clock\n", __func__);
236 goto err_iomap; 235 goto err_clk;
237 } 236 }
238 237
239 clk_set_parent(gpt_clk, pll3_clk);
240
241 spear_clockevent_init(); 238 spear_clockevent_init();
242 spear_clocksource_init(); 239 spear_clocksource_init();
243 240
244 return; 241 return;
245 242
243err_clk:
244 clk_put(gpt_clk);
246err_iomap: 245err_iomap:
247 iounmap(gpt_base); 246 iounmap(gpt_base);
248
249err_mem: 247err_mem:
250 release_mem_region(SPEAR_GPT0_BASE, SZ_1K); 248 release_mem_region(SPEAR_GPT0_BASE, SZ_1K);
251} 249}
252
253struct sys_timer spear_sys_timer = {
254 .init = spear_setup_timer,
255};