Commit | Line | Data |
---|---|---|
a2c5d4ed JH |
1 | /* |
2 | * arch/metag/kernel/clock.c | |
3 | * | |
4 | * Copyright (C) 2012 Imagination Technologies Ltd. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | */ | |
10 | ||
caa279dd | 11 | #include <linux/clk.h> |
a2c5d4ed JH |
12 | #include <linux/delay.h> |
13 | #include <linux/io.h> | |
caa279dd | 14 | #include <linux/of.h> |
a2c5d4ed JH |
15 | |
16 | #include <asm/param.h> | |
17 | #include <asm/clock.h> | |
18 | ||
19 | struct meta_clock_desc _meta_clock; | |
20 | ||
21 | /* Default machine get_core_freq callback. */ | |
22 | static unsigned long get_core_freq_default(void) | |
23 | { | |
24 | #ifdef CONFIG_METAG_META21 | |
25 | /* | |
26 | * Meta 2 cores divide down the core clock for the Meta timers, so we | |
27 | * can estimate the core clock from the divider. | |
28 | */ | |
29 | return (metag_in32(EXPAND_TIMER_DIV) + 1) * 1000000; | |
30 | #else | |
31 | /* | |
32 | * On Meta 1 we don't know the core clock, but assuming the Meta timer | |
33 | * is correct it can be estimated based on loops_per_jiffy. | |
34 | */ | |
35 | return (loops_per_jiffy * HZ * 5) >> 1; | |
36 | #endif | |
37 | } | |
38 | ||
caa279dd JH |
39 | static struct clk *clk_core; |
40 | ||
41 | /* Clk based get_core_freq callback. */ | |
42 | static unsigned long get_core_freq_clk(void) | |
43 | { | |
44 | return clk_get_rate(clk_core); | |
45 | } | |
46 | ||
47 | /** | |
48 | * init_metag_core_clock() - Set up core clock from devicetree. | |
49 | * | |
50 | * Checks to see if a "core" clock is provided in the device tree, and overrides | |
51 | * the get_core_freq callback to use it. | |
52 | */ | |
53 | static void __init init_metag_core_clock(void) | |
54 | { | |
55 | /* | |
56 | * See if a core clock is provided by the devicetree (and | |
57 | * registered by the init callback above). | |
58 | */ | |
59 | struct device_node *node; | |
60 | node = of_find_compatible_node(NULL, NULL, "img,meta"); | |
61 | if (!node) { | |
62 | pr_warn("%s: no compatible img,meta DT node found\n", | |
63 | __func__); | |
64 | return; | |
65 | } | |
66 | ||
67 | clk_core = of_clk_get_by_name(node, "core"); | |
68 | if (IS_ERR(clk_core)) { | |
69 | pr_warn("%s: no core clock found in DT\n", | |
70 | __func__); | |
71 | return; | |
72 | } | |
73 | ||
74 | /* | |
75 | * Override the core frequency callback to use | |
76 | * this clk. | |
77 | */ | |
78 | _meta_clock.get_core_freq = get_core_freq_clk; | |
79 | } | |
80 | ||
81 | /** | |
82 | * init_metag_clocks() - Set up clocks from devicetree. | |
83 | * | |
84 | * Set up important clocks from device tree. In particular any needed for clock | |
85 | * sources. | |
86 | */ | |
87 | void __init init_metag_clocks(void) | |
88 | { | |
89 | init_metag_core_clock(); | |
cf070532 JH |
90 | |
91 | pr_info("Core clock frequency: %lu Hz\n", get_coreclock()); | |
caa279dd JH |
92 | } |
93 | ||
a2c5d4ed | 94 | /** |
caa279dd | 95 | * setup_meta_clocks() - Early set up of the Meta clock. |
a2c5d4ed JH |
96 | * @desc: Clock descriptor usually provided by machine description |
97 | * | |
98 | * Ensures all callbacks are valid. | |
99 | */ | |
100 | void __init setup_meta_clocks(struct meta_clock_desc *desc) | |
101 | { | |
102 | /* copy callbacks */ | |
103 | if (desc) | |
104 | _meta_clock = *desc; | |
105 | ||
106 | /* set fallback functions */ | |
107 | if (!_meta_clock.get_core_freq) | |
108 | _meta_clock.get_core_freq = get_core_freq_default; | |
109 | } | |
110 |