• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include <linux/clk.h>
12 #include <linux/delay.h>
13 #include <linux/io.h>
14 #include <linux/of.h>
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. */
get_core_freq_default(void)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 
39 static struct clk *clk_core;
40 
41 /* Clk based get_core_freq callback. */
get_core_freq_clk(void)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  */
init_metag_core_clock(void)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  */
init_metag_clocks(void)87 void __init init_metag_clocks(void)
88 {
89 	init_metag_core_clock();
90 
91 	pr_info("Core clock frequency: %lu Hz\n", get_coreclock());
92 }
93 
94 /**
95  * setup_meta_clocks() - Early set up of the Meta clock.
96  * @desc:	Clock descriptor usually provided by machine description
97  *
98  * Ensures all callbacks are valid.
99  */
setup_meta_clocks(struct meta_clock_desc * desc)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 
111