Linux 4.16-rc2
[linux-2.6-block.git] / arch / metag / kernel / clock.c
CommitLineData
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
19struct meta_clock_desc _meta_clock;
20
21/* Default machine get_core_freq callback. */
22static 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
39static struct clk *clk_core;
40
41/* Clk based get_core_freq callback. */
42static 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 */
53static 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 */
87void __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 */
100void __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