1 /*
2  * Copyright 2014 Chen-Yu Tsai
3  *
4  * Chen-Yu Tsai <wens@csie.org>
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 as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <linux/clk-provider.h>
18 #include <linux/clkdev.h>
19 #include <linux/of.h>
20 #include <linux/of_address.h>
21 #include <linux/log2.h>
22 
23 #include "clk-factors.h"
24 
25 
26 /**
27  * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
28  * PLL4 rate is calculated as follows
29  * rate = (parent_rate * n >> p) / (m + 1);
30  * parent_rate is always 24Mhz
31  *
32  * p and m are named div1 and div2 in Allwinner's SDK
33  */
34 
35 static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
36 				       u8 *n, u8 *k, u8 *m, u8 *p)
37 {
38 	int div;
39 
40 	/* Normalize value to a 6M multiple */
41 	div = DIV_ROUND_UP(*freq, 6000000);
42 
43 	/* divs above 256 cannot be odd */
44 	if (div > 256)
45 		div = round_up(div, 2);
46 
47 	/* divs above 512 must be a multiple of 4 */
48 	if (div > 512)
49 		div = round_up(div, 4);
50 
51 	*freq = 6000000 * div;
52 
53 	/* we were called to round the frequency, we can now return */
54 	if (n == NULL)
55 		return;
56 
57 	/* p will be 1 for divs under 512 */
58 	if (div < 512)
59 		*p = 1;
60 	else
61 		*p = 0;
62 
63 	/* m will be 1 if div is odd */
64 	if (div & 1)
65 		*m = 1;
66 	else
67 		*m = 0;
68 
69 	/* calculate a suitable n based on m and p */
70 	*n = div / (*p + 1) / (*m + 1);
71 }
72 
73 static struct clk_factors_config sun9i_a80_pll4_config = {
74 	.mshift = 18,
75 	.mwidth = 1,
76 	.nshift = 8,
77 	.nwidth = 8,
78 	.pshift = 16,
79 	.pwidth = 1,
80 };
81 
82 static const struct factors_data sun9i_a80_pll4_data __initconst = {
83 	.enable = 31,
84 	.table = &sun9i_a80_pll4_config,
85 	.getter = sun9i_a80_get_pll4_factors,
86 };
87 
88 static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
89 
90 static void __init sun9i_a80_pll4_setup(struct device_node *node)
91 {
92 	sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
93 }
94 CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
95 
96 
97 /**
98  * sun9i_a80_get_gt_factors() - calculates m factor for GT
99  * GT rate is calculated as follows
100  * rate = parent_rate / (m + 1);
101  */
102 
103 static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate,
104 				     u8 *n, u8 *k, u8 *m, u8 *p)
105 {
106 	u32 div;
107 
108 	if (parent_rate < *freq)
109 		*freq = parent_rate;
110 
111 	div = DIV_ROUND_UP(parent_rate, *freq);
112 
113 	/* maximum divider is 4 */
114 	if (div > 4)
115 		div = 4;
116 
117 	*freq = parent_rate / div;
118 
119 	/* we were called to round the frequency, we can now return */
120 	if (!m)
121 		return;
122 
123 	*m = div;
124 }
125 
126 static struct clk_factors_config sun9i_a80_gt_config = {
127 	.mshift = 0,
128 	.mwidth = 2,
129 };
130 
131 static const struct factors_data sun9i_a80_gt_data __initconst = {
132 	.mux = 24,
133 	.muxmask = BIT(1) | BIT(0),
134 	.table = &sun9i_a80_gt_config,
135 	.getter = sun9i_a80_get_gt_factors,
136 };
137 
138 static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
139 
140 static void __init sun9i_a80_gt_setup(struct device_node *node)
141 {
142 	struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
143 						&sun9i_a80_gt_lock);
144 
145 	/* The GT bus clock needs to be always enabled */
146 	__clk_get(gt);
147 	clk_prepare_enable(gt);
148 }
149 CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup);
150 
151 
152 /**
153  * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2
154  * AHB rate is calculated as follows
155  * rate = parent_rate >> p;
156  */
157 
158 static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate,
159 				      u8 *n, u8 *k, u8 *m, u8 *p)
160 {
161 	u32 _p;
162 
163 	if (parent_rate < *freq)
164 		*freq = parent_rate;
165 
166 	_p = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
167 
168 	/* maximum p is 3 */
169 	if (_p > 3)
170 		_p = 3;
171 
172 	*freq = parent_rate >> _p;
173 
174 	/* we were called to round the frequency, we can now return */
175 	if (!p)
176 		return;
177 
178 	*p = _p;
179 }
180 
181 static struct clk_factors_config sun9i_a80_ahb_config = {
182 	.pshift = 0,
183 	.pwidth = 2,
184 };
185 
186 static const struct factors_data sun9i_a80_ahb_data __initconst = {
187 	.mux = 24,
188 	.muxmask = BIT(1) | BIT(0),
189 	.table = &sun9i_a80_ahb_config,
190 	.getter = sun9i_a80_get_ahb_factors,
191 };
192 
193 static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
194 
195 static void __init sun9i_a80_ahb_setup(struct device_node *node)
196 {
197 	sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
198 }
199 CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
200 
201 
202 static const struct factors_data sun9i_a80_apb0_data __initconst = {
203 	.mux = 24,
204 	.muxmask = BIT(0),
205 	.table = &sun9i_a80_ahb_config,
206 	.getter = sun9i_a80_get_ahb_factors,
207 };
208 
209 static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
210 
211 static void __init sun9i_a80_apb0_setup(struct device_node *node)
212 {
213 	sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
214 }
215 CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
216 
217 
218 /**
219  * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1
220  * APB1 rate is calculated as follows
221  * rate = (parent_rate >> p) / (m + 1);
222  */
223 
224 static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate,
225 				       u8 *n, u8 *k, u8 *m, u8 *p)
226 {
227 	u32 div;
228 	u8 calcm, calcp;
229 
230 	if (parent_rate < *freq)
231 		*freq = parent_rate;
232 
233 	div = DIV_ROUND_UP(parent_rate, *freq);
234 
235 	/* Highest possible divider is 256 (p = 3, m = 31) */
236 	if (div > 256)
237 		div = 256;
238 
239 	calcp = order_base_2(div);
240 	calcm = (parent_rate >> calcp) - 1;
241 	*freq = (parent_rate >> calcp) / (calcm + 1);
242 
243 	/* we were called to round the frequency, we can now return */
244 	if (n == NULL)
245 		return;
246 
247 	*m = calcm;
248 	*p = calcp;
249 }
250 
251 static struct clk_factors_config sun9i_a80_apb1_config = {
252 	.mshift = 0,
253 	.mwidth = 5,
254 	.pshift = 16,
255 	.pwidth = 2,
256 };
257 
258 static const struct factors_data sun9i_a80_apb1_data __initconst = {
259 	.mux = 24,
260 	.muxmask = BIT(0),
261 	.table = &sun9i_a80_apb1_config,
262 	.getter = sun9i_a80_get_apb1_factors,
263 };
264 
265 static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
266 
267 static void __init sun9i_a80_apb1_setup(struct device_node *node)
268 {
269 	sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
270 }
271 CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
272