aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-spear
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-spear')
-rw-r--r--arch/arm/plat-spear/clock.c1005
-rw-r--r--arch/arm/plat-spear/include/plat/clock.h249
-rw-r--r--arch/arm/plat-spear/include/plat/gpio.h24
-rw-r--r--arch/arm/plat-spear/include/plat/hardware.h23
-rw-r--r--arch/arm/plat-spear/include/plat/io.h22
-rw-r--r--arch/arm/plat-spear/include/plat/keyboard.h141
-rw-r--r--arch/arm/plat-spear/include/plat/memory.h20
-rw-r--r--arch/arm/plat-spear/include/plat/padmux.h92
-rw-r--r--arch/arm/plat-spear/include/plat/shirq.h73
-rw-r--r--arch/arm/plat-spear/include/plat/system.h41
-rw-r--r--arch/arm/plat-spear/include/plat/vmalloc.h19
-rw-r--r--arch/arm/plat-spear/padmux.c164
-rw-r--r--arch/arm/plat-spear/shirq.c118
13 files changed, 1991 insertions, 0 deletions
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
new file mode 100644
index 00000000000..67dd00381ea
--- /dev/null
+++ b/arch/arm/plat-spear/clock.c
@@ -0,0 +1,1005 @@
1/*
2 * arch/arm/plat-spear/clock.c
3 *
4 * Clock framework for SPEAr platform
5 *
6 * Copyright (C) 2009 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#include <linux/bug.h>
15#include <linux/clk.h>
16#include <linux/debugfs.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/list.h>
20#include <linux/module.h>
21#include <linux/spinlock.h>
22#include <plat/clock.h>
23
24static DEFINE_SPINLOCK(clocks_lock);
25static LIST_HEAD(root_clks);
26#ifdef CONFIG_DEBUG_FS
27static LIST_HEAD(clocks);
28#endif
29
30static void propagate_rate(struct clk *, int on_init);
31#ifdef CONFIG_DEBUG_FS
32static int clk_debugfs_reparent(struct clk *);
33#endif
34
35static int generic_clk_enable(struct clk *clk)
36{
37 unsigned int val;
38
39 if (!clk->en_reg)
40 return -EFAULT;
41
42 val = readl(clk->en_reg);
43 if (unlikely(clk->flags & RESET_TO_ENABLE))
44 val &= ~(1 << clk->en_reg_bit);
45 else
46 val |= 1 << clk->en_reg_bit;
47
48 writel(val, clk->en_reg);
49
50 return 0;
51}
52
53static void generic_clk_disable(struct clk *clk)
54{
55 unsigned int val;
56
57 if (!clk->en_reg)
58 return;
59
60 val = readl(clk->en_reg);
61 if (unlikely(clk->flags & RESET_TO_ENABLE))
62 val |= 1 << clk->en_reg_bit;
63 else
64 val &= ~(1 << clk->en_reg_bit);
65
66 writel(val, clk->en_reg);
67}
68
69/* generic clk ops */
70static struct clkops generic_clkops = {
71 .enable = generic_clk_enable,
72 .disable = generic_clk_disable,
73};
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
173/*
174 * clk_enable - inform the system when the clock source should be running.
175 * @clk: clock source
176 *
177 * If the clock can not be enabled/disabled, this should return success.
178 *
179 * Returns success (0) or negative errno.
180 */
181int clk_enable(struct clk *clk)
182{
183 unsigned long flags;
184 int ret = 0;
185
186 spin_lock_irqsave(&clocks_lock, flags);
187 ret = do_clk_enable(clk);
188 spin_unlock_irqrestore(&clocks_lock, flags);
189 return ret;
190}
191EXPORT_SYMBOL(clk_enable);
192
193/*
194 * clk_disable - inform the system when the clock source is no longer required.
195 * @clk: clock source
196 *
197 * Inform the system that a clock source is no longer required by
198 * a driver and may be shut down.
199 *
200 * Implementation detail: if the clock source is shared between
201 * multiple drivers, clk_enable() calls must be balanced by the
202 * same number of clk_disable() calls for the clock source to be
203 * disabled.
204 */
205void clk_disable(struct clk *clk)
206{
207 unsigned long flags;
208
209 spin_lock_irqsave(&clocks_lock, flags);
210 do_clk_disable(clk);
211 spin_unlock_irqrestore(&clocks_lock, flags);
212}
213EXPORT_SYMBOL(clk_disable);
214
215/**
216 * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
217 * This is only valid once the clock source has been enabled.
218 * @clk: clock source
219 */
220unsigned long clk_get_rate(struct clk *clk)
221{
222 unsigned long flags, rate;
223
224 spin_lock_irqsave(&clocks_lock, flags);
225 rate = clk->rate;
226 spin_unlock_irqrestore(&clocks_lock, flags);
227
228 return rate;
229}
230EXPORT_SYMBOL(clk_get_rate);
231
232/**
233 * clk_set_parent - set the parent clock source for this clock
234 * @clk: clock source
235 * @parent: parent clock source
236 *
237 * Returns success (0) or negative errno.
238 */
239int clk_set_parent(struct clk *clk, struct clk *parent)
240{
241 int i, found = 0, val = 0;
242 unsigned long flags;
243
244 if (!clk || !parent)
245 return -EFAULT;
246 if (clk->pclk == parent)
247 return 0;
248 if (!clk->pclk_sel)
249 return -EPERM;
250
251 /* check if requested parent is in clk parent list */
252 for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
253 if (clk->pclk_sel->pclk_info[i].pclk == parent) {
254 found = 1;
255 break;
256 }
257 }
258
259 if (!found)
260 return -EINVAL;
261
262 spin_lock_irqsave(&clocks_lock, flags);
263 /* reflect parent change in hardware */
264 val = readl(clk->pclk_sel->pclk_sel_reg);
265 val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift);
266 val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift;
267 writel(val, clk->pclk_sel->pclk_sel_reg);
268 spin_unlock_irqrestore(&clocks_lock, flags);
269
270 /* reflect parent change in software */
271 clk_reparent(clk, &clk->pclk_sel->pclk_info[i]);
272
273 propagate_rate(clk, 0);
274 return 0;
275}
276EXPORT_SYMBOL(clk_set_parent);
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
309/* registers clock in platform clock framework */
310void clk_register(struct clk_lookup *cl)
311{
312 struct clk *clk;
313 unsigned long flags;
314
315 if (!cl || !cl->clk)
316 return;
317 clk = cl->clk;
318
319 spin_lock_irqsave(&clocks_lock, flags);
320
321 INIT_LIST_HEAD(&clk->children);
322 if (clk->flags & ALWAYS_ENABLED)
323 clk->ops = NULL;
324 else if (!clk->ops)
325 clk->ops = &generic_clkops;
326
327 /* root clock don't have any parents */
328 if (!clk->pclk && !clk->pclk_sel) {
329 list_add(&clk->sibling, &root_clks);
330 } else if (clk->pclk && !clk->pclk_sel) {
331 /* add clocks with only one parent to parent's children list */
332 list_add(&clk->sibling, &clk->pclk->children);
333 } else {
334 /* clocks with more than one parent */
335 struct pclk_info *pclk_info;
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 }
346 }
347
348 spin_unlock_irqrestore(&clocks_lock, flags);
349
350 /* debugfs specific */
351#ifdef CONFIG_DEBUG_FS
352 list_add(&clk->node, &clocks);
353 clk->cl = cl;
354#endif
355
356 /* add clock to arm clockdev framework */
357 clkdev_add(cl);
358}
359
360/**
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.
364 *
365 * Recalculates all children clocks
366 */
367void propagate_rate(struct clk *pclk, int on_init)
368{
369 struct clk *clk, *_temp;
370 int ret = 0;
371
372 list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
373 if (clk->recalc) {
374 ret = clk->recalc(clk);
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);
390 }
391}
392
393/**
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)
407{
408 unsigned long tmp = 0, prev_rate = 0;
409 int index;
410
411 if (!clk->calc_rate)
412 return -EFAULT;
413
414 if (!drate)
415 return -EINVAL;
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 }
429 }
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;
440
441 return index;
442}
443
444/**
445 * clk_round_rate - adjust a rate to the exact rate a clock can provide
446 * @clk: clock source
447 * @rate: desired clock rate in Hz
448 *
449 * Returns rounded clock rate in Hz, or negative errno.
450 */
451long clk_round_rate(struct clk *clk, unsigned long drate)
452{
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 }
468
469 index = round_rate_index(clk, drate, &rate);
470 if (index >= 0)
471 return rate;
472 else
473 return index;
474}
475EXPORT_SYMBOL(clk_round_rate);
476
477/*All below functions are called with lock held */
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;
497}
498
499/*
500 * calculates current programmed rate of pll1
501 *
502 * In normal mode
503 * rate = (2 * M[15:8] * Fin)/(N * 2^P)
504 *
505 * In Dithered mode
506 * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
507 */
508int pll_clk_recalc(struct clk *clk)
509{
510 struct pll_clk_config *config = clk->private_data;
511 unsigned int num = 2, den = 0, val, mode = 0;
512
513 mode = (readl(config->mode_reg) >> config->masks->mode_shift) &
514 config->masks->mode_mask;
515
516 val = readl(config->cfg_reg);
517 /* calculate denominator */
518 den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask;
519 den = 1 << den;
520 den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask;
521
522 /* calculate numerator & denominator */
523 if (!mode) {
524 /* Normal mode */
525 num *= (val >> config->masks->norm_fdbk_m_shift) &
526 config->masks->norm_fdbk_m_mask;
527 } else {
528 /* Dithered mode */
529 num *= (val >> config->masks->dith_fdbk_m_shift) &
530 config->masks->dith_fdbk_m_mask;
531 den *= 256;
532 }
533
534 if (!den)
535 return -EINVAL;
536
537 clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
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);
593}
594
595/* calculates current programmed rate of ahb or apb bus */
596int bus_clk_recalc(struct clk *clk)
597{
598 struct bus_clk_config *config = clk->private_data;
599 unsigned int div;
600
601 div = ((readl(config->reg) >> config->masks->shift) &
602 config->masks->mask) + 1;
603
604 if (!div)
605 return -EINVAL;
606
607 clk->rate = (unsigned long)clk->pclk->rate / div;
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;
648}
649
650/*
651 * calculates current programmed rate of auxiliary synthesizers
652 * used by: UART, FIRDA
653 *
654 * Fout from synthesizer can be given from two equations:
655 * Fout1 = (Fin * X/Y)/2
656 * Fout2 = Fin * X/Y
657 *
658 * Selection of eqn 1 or 2 is programmed in register
659 */
660int aux_clk_recalc(struct clk *clk)
661{
662 struct aux_clk_config *config = clk->private_data;
663 unsigned int num = 1, den = 1, val, eqn;
664
665 val = readl(config->synth_reg);
666
667 eqn = (val >> config->masks->eq_sel_shift) &
668 config->masks->eq_sel_mask;
669 if (eqn == config->masks->eq1_mask)
670 den *= 2;
671
672 /* calculate numerator */
673 num = (val >> config->masks->xscale_sel_shift) &
674 config->masks->xscale_sel_mask;
675
676 /* calculate denominator */
677 den *= (val >> config->masks->yscale_sel_shift) &
678 config->masks->yscale_sel_mask;
679
680 if (!den)
681 return -EINVAL;
682
683 clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
684 return 0;
685}
686
687/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
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));
730}
731
732/*
733 * calculates current programmed rate of gpt synthesizers
734 * Fout from synthesizer can be given from below equations:
735 * Fout= Fin/((2 ^ (N+1)) * (M+1))
736 */
737int gpt_clk_recalc(struct clk *clk)
738{
739 struct gpt_clk_config *config = clk->private_data;
740 unsigned int div = 1, val;
741
742 val = readl(config->synth_reg);
743 div += (val >> config->masks->mscale_sel_shift) &
744 config->masks->mscale_sel_mask;
745 div *= 1 << (((val >> config->masks->nscale_sel_shift) &
746 config->masks->nscale_sel_mask) + 1);
747
748 if (!div)
749 return -EINVAL;
750
751 clk->rate = (unsigned long)clk->pclk->rate / div;
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;
780}
781
782/*
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
865 * fixed divisor
866 */
867int follow_parent(struct clk *clk)
868{
869 unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
870
871 clk->rate = clk->pclk->rate/div_factor;
872 return 0;
873}
874
875/**
876 * recalc_root_clocks - recalculate and propagate all root clocks
877 *
878 * Recalculates all root clocks (clocks with no parent), which if the
879 * clock's .recalc is set correctly, should also propagate their rates.
880 */
881void recalc_root_clocks(void)
882{
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
906void __init clk_init(void)
907{
908 recalc_root_clocks();
909}
910
911#ifdef CONFIG_DEBUG_FS
912/*
913 * debugfs support to trace clock tree hierarchy and attributes
914 */
915static struct dentry *clk_debugfs_root;
916static int clk_debugfs_register_one(struct clk *c)
917{
918 int err;
919 struct dentry *d;
920 struct clk *pa = c->pclk;
921 char s[255];
922 char *p = s;
923
924 if (c) {
925 if (c->cl->con_id)
926 p += sprintf(p, "%s", c->cl->con_id);
927 if (c->cl->dev_id)
928 p += sprintf(p, "%s", c->cl->dev_id);
929 }
930 d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
931 if (!d)
932 return -ENOMEM;
933 c->dent = d;
934
935 d = debugfs_create_u32("usage_count", S_IRUGO, c->dent,
936 (u32 *)&c->usage_count);
937 if (!d) {
938 err = -ENOMEM;
939 goto err_out;
940 }
941 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
942 if (!d) {
943 err = -ENOMEM;
944 goto err_out;
945 }
946 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
947 if (!d) {
948 err = -ENOMEM;
949 goto err_out;
950 }
951 return 0;
952
953err_out:
954 debugfs_remove_recursive(c->dent);
955 return err;
956}
957
958static int clk_debugfs_register(struct clk *c)
959{
960 int err;
961 struct clk *pa = c->pclk;
962
963 if (pa && !pa->dent) {
964 err = clk_debugfs_register(pa);
965 if (err)
966 return err;
967 }
968
969 if (!c->dent) {
970 err = clk_debugfs_register_one(c);
971 if (err)
972 return err;
973 }
974 return 0;
975}
976
977static int __init clk_debugfs_init(void)
978{
979 struct clk *c;
980 struct dentry *d;
981 int err;
982
983 d = debugfs_create_dir("clock", NULL);
984 if (!d)
985 return -ENOMEM;
986 clk_debugfs_root = d;
987
988 list_for_each_entry(c, &clocks, node) {
989 err = clk_debugfs_register(c);
990 if (err)
991 goto err_out;
992 }
993 return 0;
994err_out:
995 debugfs_remove_recursive(clk_debugfs_root);
996 return err;
997}
998late_initcall(clk_debugfs_init);
999
1000static int clk_debugfs_reparent(struct clk *c)
1001{
1002 debugfs_remove(c->dent);
1003 return clk_debugfs_register_one(c);
1004}
1005#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
new file mode 100644
index 00000000000..0062bafef12
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -0,0 +1,249 @@
1/*
2 * arch/arm/plat-spear/include/plat/clock.h
3 *
4 * Clock framework definitions for SPEAr platform
5 *
6 * Copyright (C) 2009 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_CLOCK_H
15#define __PLAT_CLOCK_H
16
17#include <linux/list.h>
18#include <linux/clkdev.h>
19#include <linux/types.h>
20
21/* clk structure flags */
22#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */
23#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */
24#define ENABLED_ON_INIT (1 << 2) /* clocks enabled at init */
25
26/**
27 * struct clkops - clock operations
28 * @enable: pointer to clock enable function
29 * @disable: pointer to clock disable function
30 */
31struct clkops {
32 int (*enable) (struct clk *);
33 void (*disable) (struct clk *);
34};
35
36/**
37 * struct pclk_info - parents info
38 * @pclk: pointer to parent clk
39 * @pclk_val: value to be written for selecting this parent
40 */
41struct pclk_info {
42 struct clk *pclk;
43 u8 pclk_val;
44};
45
46/**
47 * struct pclk_sel - parents selection configuration
48 * @pclk_info: pointer to array of parent clock info
49 * @pclk_count: number of parents
50 * @pclk_sel_reg: register for selecting a parent
51 * @pclk_sel_mask: mask for selecting parent (can be used to clear bits also)
52 */
53struct pclk_sel {
54 struct pclk_info *pclk_info;
55 u8 pclk_count;
56 void __iomem *pclk_sel_reg;
57 unsigned int pclk_sel_mask;
58};
59
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/**
73 * struct clk - clock structure
74 * @usage_count: num of users who enabled this clock
75 * @flags: flags for clock properties
76 * @rate: programmed clock rate in Hz
77 * @en_reg: clk enable/disable reg
78 * @en_reg_bit: clk enable/disable bit
79 * @ops: clk enable/disable ops - generic_clkops selected if NULL
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.
85 * @pclk: current parent clk
86 * @pclk_sel: pointer to parent selection structure
87 * @pclk_sel_shift: register shift for selecting parent of this clock
88 * @children: list for childrens or this clock
89 * @sibling: node for list of clocks having same parents
90 * @private_data: clock specific private data
91 * @node: list to maintain clocks linearly
92 * @cl: clocklook up associated with this clock
93 * @dent: object for debugfs
94 */
95struct clk {
96 unsigned int usage_count;
97 unsigned int flags;
98 unsigned long rate;
99 void __iomem *en_reg;
100 u8 en_reg_bit;
101 const struct clkops *ops;
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;
107
108 struct clk *pclk;
109 struct pclk_sel *pclk_sel;
110 unsigned int pclk_sel_shift;
111
112 struct list_head children;
113 struct list_head sibling;
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
120};
121
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
137struct pll_clk_config {
138 void __iomem *mode_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;
149};
150
151/* ahb and apb bus configuration structure */
152struct bus_clk_masks {
153 u32 mask;
154 u32 shift;
155};
156
157struct bus_clk_config {
158 void __iomem *reg;
159 struct bus_clk_masks *masks;
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;
177};
178
179struct aux_clk_config {
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;
224};
225
226/* platform specific clock functions */
227void __init clk_init(void);
228void clk_register(struct clk_lookup *cl);
229void recalc_root_clocks(void);
230
231/* clock recalc & set rate functions */
232int follow_parent(struct clk *clk);
233unsigned long pll_calc_rate(struct clk *clk, int index);
234int pll_clk_recalc(struct clk *clk);
235int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
236unsigned long bus_calc_rate(struct clk *clk, int index);
237int bus_clk_recalc(struct clk *clk);
238int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
239unsigned long gpt_calc_rate(struct clk *clk, int index);
240int gpt_clk_recalc(struct clk *clk);
241int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
242unsigned long aux_calc_rate(struct clk *clk, int index);
243int aux_clk_recalc(struct clk *clk);
244int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
245unsigned long clcd_calc_rate(struct clk *clk, int index);
246int clcd_clk_recalc(struct clk *clk);
247int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
248
249#endif /* __PLAT_CLOCK_H */
diff --git a/arch/arm/plat-spear/include/plat/gpio.h b/arch/arm/plat-spear/include/plat/gpio.h
new file mode 100644
index 00000000000..b857c91257d
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/gpio.h
@@ -0,0 +1,24 @@
1/*
2 * arch/arm/plat-spear/include/plat/gpio.h
3 *
4 * GPIO macros for SPEAr platform
5 *
6 * Copyright (C) 2009 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_GPIO_H
15#define __PLAT_GPIO_H
16
17#include <asm-generic/gpio.h>
18
19#define gpio_get_value __gpio_get_value
20#define gpio_set_value __gpio_set_value
21#define gpio_cansleep __gpio_cansleep
22#define gpio_to_irq __gpio_to_irq
23
24#endif /* __PLAT_GPIO_H */
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 00000000000..66d677225d1
--- /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/io.h b/arch/arm/plat-spear/include/plat/io.h
new file mode 100644
index 00000000000..4d4ba822b3e
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/io.h
@@ -0,0 +1,22 @@
1/*
2 * arch/arm/plat-spear/include/plat/io.h
3 *
4 * IO definitions for SPEAr platform
5 *
6 * Copyright (C) 2009 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_IO_H
15#define __PLAT_IO_H
16
17#define IO_SPACE_LIMIT 0xFFFFFFFF
18
19#define __io(a) __typesafe_io(a)
20#define __mem_pci(a) (a)
21
22#endif /* __PLAT_IO_H */
diff --git a/arch/arm/plat-spear/include/plat/keyboard.h b/arch/arm/plat-spear/include/plat/keyboard.h
new file mode 100644
index 00000000000..68b5394fc58
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/keyboard.h
@@ -0,0 +1,141 @@
1/*
2 * Copyright (C) 2010 ST Microelectronics
3 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
4 *
5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any
7 * warranty of any kind, whether express or implied.
8 */
9
10#ifndef __PLAT_KEYBOARD_H
11#define __PLAT_KEYBOARD_H
12
13#include <linux/bitops.h>
14#include <linux/input.h>
15#include <linux/input/matrix_keypad.h>
16#include <linux/types.h>
17
18#define DECLARE_KEYMAP(_name) \
19int _name[] = { \
20 KEY(0, 0, KEY_ESC), \
21 KEY(0, 1, KEY_1), \
22 KEY(0, 2, KEY_2), \
23 KEY(0, 3, KEY_3), \
24 KEY(0, 4, KEY_4), \
25 KEY(0, 5, KEY_5), \
26 KEY(0, 6, KEY_6), \
27 KEY(0, 7, KEY_7), \
28 KEY(0, 8, KEY_8), \
29 KEY(1, 0, KEY_9), \
30 KEY(1, 1, KEY_MINUS), \
31 KEY(1, 2, KEY_EQUAL), \
32 KEY(1, 3, KEY_BACKSPACE), \
33 KEY(1, 4, KEY_TAB), \
34 KEY(1, 5, KEY_Q), \
35 KEY(1, 6, KEY_W), \
36 KEY(1, 7, KEY_E), \
37 KEY(1, 8, KEY_R), \
38 KEY(2, 0, KEY_T), \
39 KEY(2, 1, KEY_Y), \
40 KEY(2, 2, KEY_U), \
41 KEY(2, 3, KEY_I), \
42 KEY(2, 4, KEY_O), \
43 KEY(2, 5, KEY_P), \
44 KEY(2, 6, KEY_LEFTBRACE), \
45 KEY(2, 7, KEY_RIGHTBRACE), \
46 KEY(2, 8, KEY_ENTER), \
47 KEY(3, 0, KEY_LEFTCTRL), \
48 KEY(3, 1, KEY_A), \
49 KEY(3, 2, KEY_S), \
50 KEY(3, 3, KEY_D), \
51 KEY(3, 4, KEY_F), \
52 KEY(3, 5, KEY_G), \
53 KEY(3, 6, KEY_H), \
54 KEY(3, 7, KEY_J), \
55 KEY(3, 8, KEY_K), \
56 KEY(4, 0, KEY_L), \
57 KEY(4, 1, KEY_SEMICOLON), \
58 KEY(4, 2, KEY_APOSTROPHE), \
59 KEY(4, 3, KEY_GRAVE), \
60 KEY(4, 4, KEY_LEFTSHIFT), \
61 KEY(4, 5, KEY_BACKSLASH), \
62 KEY(4, 6, KEY_Z), \
63 KEY(4, 7, KEY_X), \
64 KEY(4, 8, KEY_C), \
65 KEY(4, 0, KEY_L), \
66 KEY(4, 1, KEY_SEMICOLON), \
67 KEY(4, 2, KEY_APOSTROPHE), \
68 KEY(4, 3, KEY_GRAVE), \
69 KEY(4, 4, KEY_LEFTSHIFT), \
70 KEY(4, 5, KEY_BACKSLASH), \
71 KEY(4, 6, KEY_Z), \
72 KEY(4, 7, KEY_X), \
73 KEY(4, 8, KEY_C), \
74 KEY(4, 0, KEY_L), \
75 KEY(4, 1, KEY_SEMICOLON), \
76 KEY(4, 2, KEY_APOSTROPHE), \
77 KEY(4, 3, KEY_GRAVE), \
78 KEY(4, 4, KEY_LEFTSHIFT), \
79 KEY(4, 5, KEY_BACKSLASH), \
80 KEY(4, 6, KEY_Z), \
81 KEY(4, 7, KEY_X), \
82 KEY(4, 8, KEY_C), \
83 KEY(5, 0, KEY_V), \
84 KEY(5, 1, KEY_B), \
85 KEY(5, 2, KEY_N), \
86 KEY(5, 3, KEY_M), \
87 KEY(5, 4, KEY_COMMA), \
88 KEY(5, 5, KEY_DOT), \
89 KEY(5, 6, KEY_SLASH), \
90 KEY(5, 7, KEY_RIGHTSHIFT), \
91 KEY(5, 8, KEY_KPASTERISK), \
92 KEY(6, 0, KEY_LEFTALT), \
93 KEY(6, 1, KEY_SPACE), \
94 KEY(6, 2, KEY_CAPSLOCK), \
95 KEY(6, 3, KEY_F1), \
96 KEY(6, 4, KEY_F2), \
97 KEY(6, 5, KEY_F3), \
98 KEY(6, 6, KEY_F4), \
99 KEY(6, 7, KEY_F5), \
100 KEY(6, 8, KEY_F6), \
101 KEY(7, 0, KEY_F7), \
102 KEY(7, 1, KEY_F8), \
103 KEY(7, 2, KEY_F9), \
104 KEY(7, 3, KEY_F10), \
105 KEY(7, 4, KEY_NUMLOCK), \
106 KEY(7, 5, KEY_SCROLLLOCK), \
107 KEY(7, 6, KEY_KP7), \
108 KEY(7, 7, KEY_KP8), \
109 KEY(7, 8, KEY_KP9), \
110 KEY(8, 0, KEY_KPMINUS), \
111 KEY(8, 1, KEY_KP4), \
112 KEY(8, 2, KEY_KP5), \
113 KEY(8, 3, KEY_KP6), \
114 KEY(8, 4, KEY_KPPLUS), \
115 KEY(8, 5, KEY_KP1), \
116 KEY(8, 6, KEY_KP2), \
117 KEY(8, 7, KEY_KP3), \
118 KEY(8, 8, KEY_KP0), \
119}
120
121/**
122 * struct kbd_platform_data - spear keyboard platform data
123 * keymap: pointer to keymap data (table and size)
124 * rep: enables key autorepeat
125 *
126 * This structure is supposed to be used by platform code to supply
127 * keymaps to drivers that implement keyboards.
128 */
129struct kbd_platform_data {
130 const struct matrix_keymap_data *keymap;
131 bool rep;
132};
133
134/* This function is used to set platform data field of pdev->dev */
135static inline void
136kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data)
137{
138 pdev->dev.platform_data = data;
139}
140
141#endif /* __PLAT_KEYBOARD_H */
diff --git a/arch/arm/plat-spear/include/plat/memory.h b/arch/arm/plat-spear/include/plat/memory.h
new file mode 100644
index 00000000000..7e3599e1104
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/memory.h
@@ -0,0 +1,20 @@
1/*
2 * arch/arm/plat-spear/include/plat/memory.h
3 *
4 * Memory map for SPEAr platform
5 *
6 * Copyright (C) 2009 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_MEMORY_H
15#define __PLAT_MEMORY_H
16
17/* Physical DRAM offset */
18#define PLAT_PHYS_OFFSET UL(0x00000000)
19
20#endif /* __PLAT_MEMORY_H */
diff --git a/arch/arm/plat-spear/include/plat/padmux.h b/arch/arm/plat-spear/include/plat/padmux.h
new file mode 100644
index 00000000000..877f3adcf61
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/padmux.h
@@ -0,0 +1,92 @@
1/*
2 * arch/arm/plat-spear/include/plat/padmux.h
3 *
4 * SPEAr platform specific gpio pads muxing file
5 *
6 * Copyright (C) 2009 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_PADMUX_H
15#define __PLAT_PADMUX_H
16
17#include <linux/types.h>
18
19/*
20 * struct pmx_reg: configuration structure for mode reg and mux reg
21 *
22 * offset: offset of mode reg
23 * mask: mask of mode reg
24 */
25struct pmx_reg {
26 u32 offset;
27 u32 mask;
28};
29
30/*
31 * struct pmx_dev_mode: configuration structure every group of modes of a device
32 *
33 * ids: all modes for this configuration
34 * mask: mask for supported mode
35 */
36struct pmx_dev_mode {
37 u32 ids;
38 u32 mask;
39};
40
41/*
42 * struct pmx_mode: mode definition structure
43 *
44 * name: mode name
45 * mask: mode mask
46 */
47struct pmx_mode {
48 char *name;
49 u32 id;
50 u32 mask;
51};
52
53/*
54 * struct pmx_dev: device definition structure
55 *
56 * name: device name
57 * modes: device configuration array for different modes supported
58 * mode_count: size of modes array
59 * is_active: is peripheral active/enabled
60 * enb_on_reset: if 1, mask bits to be cleared in reg otherwise to be set in reg
61 */
62struct pmx_dev {
63 char *name;
64 struct pmx_dev_mode *modes;
65 u8 mode_count;
66 bool is_active;
67 bool enb_on_reset;
68};
69
70/*
71 * struct pmx_driver: driver definition structure
72 *
73 * mode: mode to be set
74 * devs: array of pointer to pmx devices
75 * devs_count: ARRAY_SIZE of devs
76 * base: base address of soc config registers
77 * mode_reg: structure of mode config register
78 * mux_reg: structure of device mux config register
79 */
80struct pmx_driver {
81 struct pmx_mode *mode;
82 struct pmx_dev **devs;
83 u8 devs_count;
84 u32 *base;
85 struct pmx_reg mode_reg;
86 struct pmx_reg mux_reg;
87};
88
89/* pmx functions */
90int pmx_register(struct pmx_driver *driver);
91
92#endif /* __PLAT_PADMUX_H */
diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h
new file mode 100644
index 00000000000..03ed8b585dc
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/shirq.h
@@ -0,0 +1,73 @@
1/*
2 * arch/arm/plat-spear/include/plat/shirq.h
3 *
4 * SPEAr platform shared irq layer header file
5 *
6 * Copyright (C) 2009 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_SHIRQ_H
15#define __PLAT_SHIRQ_H
16
17#include <linux/irq.h>
18#include <linux/types.h>
19
20/*
21 * struct shirq_dev_config: shared irq device configuration
22 *
23 * virq: virtual irq number of device
24 * enb_mask: enable mask of device
25 * status_mask: status mask of device
26 * clear_mask: clear mask of device
27 */
28struct shirq_dev_config {
29 u32 virq;
30 u32 enb_mask;
31 u32 status_mask;
32 u32 clear_mask;
33};
34
35/*
36 * struct shirq_regs: shared irq register configuration
37 *
38 * base: base address of shared irq register
39 * enb_reg: enable register offset
40 * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
41 * status_reg: status register offset
42 * status_reg_mask: status register valid mask
43 * clear_reg: clear register offset
44 * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
45 */
46struct shirq_regs {
47 void __iomem *base;
48 u32 enb_reg;
49 u32 reset_to_enb;
50 u32 status_reg;
51 u32 status_reg_mask;
52 u32 clear_reg;
53 u32 reset_to_clear;
54};
55
56/*
57 * struct spear_shirq: shared irq structure
58 *
59 * irq: hardware irq number
60 * dev_config: array of device config structures which are using "irq" line
61 * dev_count: size of dev_config array
62 * regs: register configuration for shared irq block
63 */
64struct spear_shirq {
65 u32 irq;
66 struct shirq_dev_config *dev_config;
67 u32 dev_count;
68 struct shirq_regs regs;
69};
70
71int spear_shirq_register(struct spear_shirq *shirq);
72
73#endif /* __PLAT_SHIRQ_H */
diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h
new file mode 100644
index 00000000000..a235fa0ca77
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/system.h
@@ -0,0 +1,41 @@
1/*
2 * arch/arm/plat-spear/include/plat/system.h
3 *
4 * SPEAr platform specific architecture functions
5 *
6 * Copyright (C) 2009 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_SYSTEM_H
15#define __PLAT_SYSTEM_H
16
17#include <linux/io.h>
18#include <asm/hardware/sp810.h>
19#include <mach/hardware.h>
20
21static inline void arch_idle(void)
22{
23 /*
24 * This should do all the clock switching
25 * and wait for interrupt tricks
26 */
27 cpu_do_idle();
28}
29
30static inline void arch_reset(char mode, const char *cmd)
31{
32 if (mode == 's') {
33 /* software reset, Jump into ROM at address 0 */
34 cpu_reset(0);
35 } else {
36 /* hardware reset, Use on-chip reset capability */
37 sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE);
38 }
39}
40
41#endif /* __PLAT_SYSTEM_H */
diff --git a/arch/arm/plat-spear/include/plat/vmalloc.h b/arch/arm/plat-spear/include/plat/vmalloc.h
new file mode 100644
index 00000000000..8c8b24d0704
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/vmalloc.h
@@ -0,0 +1,19 @@
1/*
2 * arch/arm/plat-spear/include/plat/vmalloc.h
3 *
4 * Defining Vmalloc area for SPEAr platform
5 *
6 * Copyright (C) 2009 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_VMALLOC_H
15#define __PLAT_VMALLOC_H
16
17#define VMALLOC_END 0xF0000000UL
18
19#endif /* __PLAT_VMALLOC_H */
diff --git a/arch/arm/plat-spear/padmux.c b/arch/arm/plat-spear/padmux.c
new file mode 100644
index 00000000000..555eec6dc1c
--- /dev/null
+++ b/arch/arm/plat-spear/padmux.c
@@ -0,0 +1,164 @@
1/*
2 * arch/arm/plat-spear/include/plat/padmux.c
3 *
4 * SPEAr platform specific gpio pads muxing source file
5 *
6 * Copyright (C) 2009 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#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/slab.h>
17#include <plat/padmux.h>
18
19/*
20 * struct pmx: pmx definition structure
21 *
22 * base: base address of configuration registers
23 * mode_reg: mode configurations
24 * mux_reg: muxing configurations
25 * active_mode: pointer to current active mode
26 */
27struct pmx {
28 u32 base;
29 struct pmx_reg mode_reg;
30 struct pmx_reg mux_reg;
31 struct pmx_mode *active_mode;
32};
33
34static struct pmx *pmx;
35
36/**
37 * pmx_mode_set - Enables an multiplexing mode
38 * @mode - pointer to pmx mode
39 *
40 * It will set mode of operation in hardware.
41 * Returns -ve on Err otherwise 0
42 */
43static int pmx_mode_set(struct pmx_mode *mode)
44{
45 u32 val;
46
47 if (!mode->name)
48 return -EFAULT;
49
50 pmx->active_mode = mode;
51
52 val = readl(pmx->base + pmx->mode_reg.offset);
53 val &= ~pmx->mode_reg.mask;
54 val |= mode->mask & pmx->mode_reg.mask;
55 writel(val, pmx->base + pmx->mode_reg.offset);
56
57 return 0;
58}
59
60/**
61 * pmx_devs_enable - Enables list of devices
62 * @devs - pointer to pmx device array
63 * @count - number of devices to enable
64 *
65 * It will enable pads for all required peripherals once and only once.
66 * If peripheral is not supported by current mode then request is rejected.
67 * Conflicts between peripherals are not handled and peripherals will be
68 * enabled in the order they are present in pmx_dev array.
69 * In case of conflicts last peripheral enabled will be present.
70 * Returns -ve on Err otherwise 0
71 */
72static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
73{
74 u32 val, i, mask;
75
76 if (!count)
77 return -EINVAL;
78
79 val = readl(pmx->base + pmx->mux_reg.offset);
80 for (i = 0; i < count; i++) {
81 u8 j = 0;
82
83 if (!devs[i]->name || !devs[i]->modes) {
84 printk(KERN_ERR "padmux: dev name or modes is null\n");
85 continue;
86 }
87 /* check if peripheral exists in active mode */
88 if (pmx->active_mode) {
89 bool found = false;
90 for (j = 0; j < devs[i]->mode_count; j++) {
91 if (devs[i]->modes[j].ids &
92 pmx->active_mode->id) {
93 found = true;
94 break;
95 }
96 }
97 if (found == false) {
98 printk(KERN_ERR "%s device not available in %s"\
99 "mode\n", devs[i]->name,
100 pmx->active_mode->name);
101 continue;
102 }
103 }
104
105 /* enable peripheral */
106 mask = devs[i]->modes[j].mask & pmx->mux_reg.mask;
107 if (devs[i]->enb_on_reset)
108 val &= ~mask;
109 else
110 val |= mask;
111
112 devs[i]->is_active = true;
113 }
114 writel(val, pmx->base + pmx->mux_reg.offset);
115 kfree(pmx);
116
117 /* this will ensure that multiplexing can't be changed now */
118 pmx = (struct pmx *)-1;
119
120 return 0;
121}
122
123/**
124 * pmx_register - registers a platform requesting pad mux feature
125 * @driver - pointer to driver structure containing driver specific parameters
126 *
127 * Also this must be called only once. This will allocate memory for pmx
128 * structure, will call pmx_mode_set, will call pmx_devs_enable.
129 * Returns -ve on Err otherwise 0
130 */
131int pmx_register(struct pmx_driver *driver)
132{
133 int ret = 0;
134
135 if (pmx)
136 return -EPERM;
137 if (!driver->base || !driver->devs)
138 return -EFAULT;
139
140 pmx = kzalloc(sizeof(*pmx), GFP_KERNEL);
141 if (!pmx)
142 return -ENOMEM;
143
144 pmx->base = (u32)driver->base;
145 pmx->mode_reg.offset = driver->mode_reg.offset;
146 pmx->mode_reg.mask = driver->mode_reg.mask;
147 pmx->mux_reg.offset = driver->mux_reg.offset;
148 pmx->mux_reg.mask = driver->mux_reg.mask;
149
150 /* choose mode to enable */
151 if (driver->mode) {
152 ret = pmx_mode_set(driver->mode);
153 if (ret)
154 goto pmx_fail;
155 }
156 ret = pmx_devs_enable(driver->devs, driver->devs_count);
157 if (ret)
158 goto pmx_fail;
159
160 return 0;
161
162pmx_fail:
163 return ret;
164}
diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c
new file mode 100644
index 00000000000..961fb726124
--- /dev/null
+++ b/arch/arm/plat-spear/shirq.c
@@ -0,0 +1,118 @@
1/*
2 * arch/arm/plat-spear/shirq.c
3 *
4 * SPEAr platform shared irq layer source file
5 *
6 * Copyright (C) 2009 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#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/irq.h>
17#include <linux/spinlock.h>
18#include <plat/shirq.h>
19
20struct spear_shirq *shirq;
21static DEFINE_SPINLOCK(lock);
22
23static void shirq_irq_mask(struct irq_data *d)
24{
25 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
26 u32 val, id = d->irq - shirq->dev_config[0].virq;
27 unsigned long flags;
28
29 if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
30 return;
31
32 spin_lock_irqsave(&lock, flags);
33 val = readl(shirq->regs.base + shirq->regs.enb_reg);
34 if (shirq->regs.reset_to_enb)
35 val |= shirq->dev_config[id].enb_mask;
36 else
37 val &= ~(shirq->dev_config[id].enb_mask);
38 writel(val, shirq->regs.base + shirq->regs.enb_reg);
39 spin_unlock_irqrestore(&lock, flags);
40}
41
42static void shirq_irq_unmask(struct irq_data *d)
43{
44 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
45 u32 val, id = d->irq - shirq->dev_config[0].virq;
46 unsigned long flags;
47
48 if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
49 return;
50
51 spin_lock_irqsave(&lock, flags);
52 val = readl(shirq->regs.base + shirq->regs.enb_reg);
53 if (shirq->regs.reset_to_enb)
54 val &= ~(shirq->dev_config[id].enb_mask);
55 else
56 val |= shirq->dev_config[id].enb_mask;
57 writel(val, shirq->regs.base + shirq->regs.enb_reg);
58 spin_unlock_irqrestore(&lock, flags);
59}
60
61static struct irq_chip shirq_chip = {
62 .name = "spear_shirq",
63 .irq_ack = shirq_irq_mask,
64 .irq_mask = shirq_irq_mask,
65 .irq_unmask = shirq_irq_unmask,
66};
67
68static void shirq_handler(unsigned irq, struct irq_desc *desc)
69{
70 u32 i, val, mask;
71 struct spear_shirq *shirq = irq_get_handler_data(irq);
72
73 desc->irq_data.chip->irq_ack(&desc->irq_data);
74 while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
75 shirq->regs.status_reg_mask)) {
76 for (i = 0; (i < shirq->dev_count) && val; i++) {
77 if (!(shirq->dev_config[i].status_mask & val))
78 continue;
79
80 generic_handle_irq(shirq->dev_config[i].virq);
81
82 /* clear interrupt */
83 val &= ~shirq->dev_config[i].status_mask;
84 if ((shirq->regs.clear_reg == -1) ||
85 shirq->dev_config[i].clear_mask == -1)
86 continue;
87 mask = readl(shirq->regs.base + shirq->regs.clear_reg);
88 if (shirq->regs.reset_to_clear)
89 mask &= ~shirq->dev_config[i].clear_mask;
90 else
91 mask |= shirq->dev_config[i].clear_mask;
92 writel(mask, shirq->regs.base + shirq->regs.clear_reg);
93 }
94 }
95 desc->irq_data.chip->irq_unmask(&desc->irq_data);
96}
97
98int spear_shirq_register(struct spear_shirq *shirq)
99{
100 int i;
101
102 if (!shirq || !shirq->dev_config || !shirq->regs.base)
103 return -EFAULT;
104
105 if (!shirq->dev_count)
106 return -EINVAL;
107
108 irq_set_chained_handler(shirq->irq, shirq_handler);
109 for (i = 0; i < shirq->dev_count; i++) {
110 irq_set_chip_and_handler(shirq->dev_config[i].virq,
111 &shirq_chip, handle_simple_irq);
112 set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
113 irq_set_chip_data(shirq->dev_config[i].virq, shirq);
114 }
115
116 irq_set_handler_data(shirq->irq, shirq);
117 return 0;
118}