Merge branches 'acpi-ec', 'acpi-soc', 'acpi-video' and 'acpi-resources'
[firefly-linux-kernel-4.4.55.git] / drivers / clk / sunxi / clk-sun9i-core.c
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);