Branch data Line data Source code
1 : : /*
2 : : * This program is free software; you can redistribute it and/or modify
3 : : * it under the terms of the GNU General Public License version 2 as
4 : : * published by the Free Software Foundation.
5 : : *
6 : : * This program is distributed in the hope that it will be useful,
7 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 : : * GNU General Public License for more details.
10 : : *
11 : : * Copyright (C) 2012 ARM Limited
12 : : */
13 : :
14 : : #include <linux/amba/sp810.h>
15 : : #include <linux/clkdev.h>
16 : : #include <linux/clk-provider.h>
17 : : #include <linux/err.h>
18 : : #include <linux/vexpress.h>
19 : :
20 : : static struct clk *vexpress_sp810_timerclken[4];
21 : : static DEFINE_SPINLOCK(vexpress_sp810_lock);
22 : :
23 : 0 : static void __init vexpress_sp810_init(void __iomem *base)
24 : : {
25 : : int i;
26 : :
27 [ # # ][ # # ]: 0 : if (WARN_ON(!base))
28 : 0 : return;
29 : :
30 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
31 : : char name[12];
32 : 0 : const char *parents[] = {
33 : : "v2m:refclk32khz", /* REFCLK */
34 : : "v2m:refclk1mhz" /* TIMCLK */
35 : : };
36 : :
37 : 0 : snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
38 : :
39 : 0 : vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
40 : : parents, 2, CLK_SET_RATE_NO_REPARENT,
41 : : base + SCCTRL, SCCTRL_TIMERENnSEL_SHIFT(i), 1,
42 : : 0, &vexpress_sp810_lock);
43 : :
44 [ # # ][ # # ]: 0 : if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
45 : : break;
46 : : }
47 : : }
48 : :
49 : :
50 : : static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
51 : : "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
52 : : "mb:mmci", "mb:kmi0", "mb:kmi1"
53 : : };
54 : :
55 : 0 : void __init vexpress_clk_init(void __iomem *sp810_base)
56 : : {
57 : : struct clk *clk;
58 : : int i;
59 : :
60 : 0 : clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
61 : : CLK_IS_ROOT, 0);
62 [ # # ]: 0 : WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
63 : :
64 : 0 : clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
65 : : CLK_IS_ROOT, 24000000);
66 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
67 [ # # ]: 0 : WARN_ON(clk_register_clkdev(clk, NULL,
68 : : vexpress_clk_24mhz_periphs[i]));
69 : :
70 : 0 : clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
71 : : CLK_IS_ROOT, 32768);
72 [ # # ]: 0 : WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
73 : :
74 : 0 : clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
75 : : CLK_IS_ROOT, 1000000);
76 : :
77 : 0 : vexpress_sp810_init(sp810_base);
78 : :
79 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
80 [ # # ]: 0 : WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
81 : :
82 [ # # ]: 0 : WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
83 : : "v2m-timer0", "sp804"));
84 [ # # ]: 0 : WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
85 : : "v2m-timer1", "sp804"));
86 : 0 : }
|