forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/clk/at91/clk-programmable.c
....@@ -1,11 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License as published by
6
- * the Free Software Foundation; either version 2 of the License, or
7
- * (at your option) any later version.
8
- *
94 */
105
116 #include <linux/clk-provider.h>
....@@ -17,23 +12,16 @@
1712
1813 #include "pmc.h"
1914
20
-#define PROG_SOURCE_MAX 5
2115 #define PROG_ID_MAX 7
2216
2317 #define PROG_STATUS_MASK(id) (1 << ((id) + 8))
24
-#define PROG_PRES_MASK 0x7
25
-#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
18
+#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & layout->pres_mask)
2619 #define PROG_MAX_RM9200_CSS 3
27
-
28
-struct clk_programmable_layout {
29
- u8 pres_shift;
30
- u8 css_mask;
31
- u8 have_slck_mck;
32
-};
3320
3421 struct clk_programmable {
3522 struct clk_hw hw;
3623 struct regmap *regmap;
24
+ u32 *mux_table;
3725 u8 id;
3826 const struct clk_programmable_layout *layout;
3927 };
....@@ -44,20 +32,29 @@
4432 unsigned long parent_rate)
4533 {
4634 struct clk_programmable *prog = to_clk_programmable(hw);
35
+ const struct clk_programmable_layout *layout = prog->layout;
4736 unsigned int pckr;
37
+ unsigned long rate;
4838
4939 regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr);
5040
51
- return parent_rate >> PROG_PRES(prog->layout, pckr);
41
+ if (layout->is_pres_direct)
42
+ rate = parent_rate / (PROG_PRES(layout, pckr) + 1);
43
+ else
44
+ rate = parent_rate >> PROG_PRES(layout, pckr);
45
+
46
+ return rate;
5247 }
5348
5449 static int clk_programmable_determine_rate(struct clk_hw *hw,
5550 struct clk_rate_request *req)
5651 {
52
+ struct clk_programmable *prog = to_clk_programmable(hw);
53
+ const struct clk_programmable_layout *layout = prog->layout;
5754 struct clk_hw *parent;
5855 long best_rate = -EINVAL;
5956 unsigned long parent_rate;
60
- unsigned long tmp_rate;
57
+ unsigned long tmp_rate = 0;
6158 int shift;
6259 int i;
6360
....@@ -67,10 +64,18 @@
6764 continue;
6865
6966 parent_rate = clk_hw_get_rate(parent);
70
- for (shift = 0; shift < PROG_PRES_MASK; shift++) {
71
- tmp_rate = parent_rate >> shift;
72
- if (tmp_rate <= req->rate)
73
- break;
67
+ if (layout->is_pres_direct) {
68
+ for (shift = 0; shift <= layout->pres_mask; shift++) {
69
+ tmp_rate = parent_rate / (shift + 1);
70
+ if (tmp_rate <= req->rate)
71
+ break;
72
+ }
73
+ } else {
74
+ for (shift = 0; shift < layout->pres_mask; shift++) {
75
+ tmp_rate = parent_rate >> shift;
76
+ if (tmp_rate <= req->rate)
77
+ break;
78
+ }
7479 }
7580
7681 if (tmp_rate > req->rate)
....@@ -104,6 +109,9 @@
104109 if (layout->have_slck_mck)
105110 mask |= AT91_PMC_CSSMCK_MCK;
106111
112
+ if (prog->mux_table)
113
+ pckr = clk_mux_index_to_val(prog->mux_table, 0, index);
114
+
107115 if (index > layout->css_mask) {
108116 if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck)
109117 return -EINVAL;
....@@ -130,6 +138,9 @@
130138 if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret)
131139 ret = PROG_MAX_RM9200_CSS + 1;
132140
141
+ if (prog->mux_table)
142
+ ret = clk_mux_val_to_index(&prog->hw, prog->mux_table, 0, ret);
143
+
133144 return ret;
134145 }
135146
....@@ -139,24 +150,28 @@
139150 struct clk_programmable *prog = to_clk_programmable(hw);
140151 const struct clk_programmable_layout *layout = prog->layout;
141152 unsigned long div = parent_rate / rate;
142
- unsigned int pckr;
143153 int shift = 0;
144
-
145
- regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr);
146154
147155 if (!div)
148156 return -EINVAL;
149157
150
- shift = fls(div) - 1;
158
+ if (layout->is_pres_direct) {
159
+ shift = div - 1;
151160
152
- if (div != (1 << shift))
153
- return -EINVAL;
161
+ if (shift > layout->pres_mask)
162
+ return -EINVAL;
163
+ } else {
164
+ shift = fls(div) - 1;
154165
155
- if (shift >= PROG_PRES_MASK)
156
- return -EINVAL;
166
+ if (div != (1 << shift))
167
+ return -EINVAL;
168
+
169
+ if (shift >= layout->pres_mask)
170
+ return -EINVAL;
171
+ }
157172
158173 regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id),
159
- PROG_PRES_MASK << layout->pres_shift,
174
+ layout->pres_mask << layout->pres_shift,
160175 shift << layout->pres_shift);
161176
162177 return 0;
....@@ -170,15 +185,16 @@
170185 .set_rate = clk_programmable_set_rate,
171186 };
172187
173
-static struct clk_hw * __init
188
+struct clk_hw * __init
174189 at91_clk_register_programmable(struct regmap *regmap,
175190 const char *name, const char **parent_names,
176191 u8 num_parents, u8 id,
177
- const struct clk_programmable_layout *layout)
192
+ const struct clk_programmable_layout *layout,
193
+ u32 *mux_table)
178194 {
179195 struct clk_programmable *prog;
180196 struct clk_hw *hw;
181
- struct clk_init_data init = {};
197
+ struct clk_init_data init;
182198 int ret;
183199
184200 if (id > PROG_ID_MAX)
....@@ -198,6 +214,7 @@
198214 prog->layout = layout;
199215 prog->hw.init = &init;
200216 prog->regmap = regmap;
217
+ prog->mux_table = mux_table;
201218
202219 hw = &prog->hw;
203220 ret = clk_hw_register(NULL, &prog->hw);
....@@ -211,86 +228,26 @@
211228 return hw;
212229 }
213230
214
-static const struct clk_programmable_layout at91rm9200_programmable_layout = {
231
+const struct clk_programmable_layout at91rm9200_programmable_layout = {
232
+ .pres_mask = 0x7,
215233 .pres_shift = 2,
216234 .css_mask = 0x3,
217235 .have_slck_mck = 0,
236
+ .is_pres_direct = 0,
218237 };
219238
220
-static const struct clk_programmable_layout at91sam9g45_programmable_layout = {
239
+const struct clk_programmable_layout at91sam9g45_programmable_layout = {
240
+ .pres_mask = 0x7,
221241 .pres_shift = 2,
222242 .css_mask = 0x3,
223243 .have_slck_mck = 1,
244
+ .is_pres_direct = 0,
224245 };
225246
226
-static const struct clk_programmable_layout at91sam9x5_programmable_layout = {
247
+const struct clk_programmable_layout at91sam9x5_programmable_layout = {
248
+ .pres_mask = 0x7,
227249 .pres_shift = 4,
228250 .css_mask = 0x7,
229251 .have_slck_mck = 0,
252
+ .is_pres_direct = 0,
230253 };
231
-
232
-static void __init
233
-of_at91_clk_prog_setup(struct device_node *np,
234
- const struct clk_programmable_layout *layout)
235
-{
236
- int num;
237
- u32 id;
238
- struct clk_hw *hw;
239
- unsigned int num_parents;
240
- const char *parent_names[PROG_SOURCE_MAX];
241
- const char *name;
242
- struct device_node *progclknp;
243
- struct regmap *regmap;
244
-
245
- num_parents = of_clk_get_parent_count(np);
246
- if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
247
- return;
248
-
249
- of_clk_parent_fill(np, parent_names, num_parents);
250
-
251
- num = of_get_child_count(np);
252
- if (!num || num > (PROG_ID_MAX + 1))
253
- return;
254
-
255
- regmap = syscon_node_to_regmap(of_get_parent(np));
256
- if (IS_ERR(regmap))
257
- return;
258
-
259
- for_each_child_of_node(np, progclknp) {
260
- if (of_property_read_u32(progclknp, "reg", &id))
261
- continue;
262
-
263
- if (of_property_read_string(np, "clock-output-names", &name))
264
- name = progclknp->name;
265
-
266
- hw = at91_clk_register_programmable(regmap, name,
267
- parent_names, num_parents,
268
- id, layout);
269
- if (IS_ERR(hw))
270
- continue;
271
-
272
- of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
273
- }
274
-}
275
-
276
-
277
-static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
278
-{
279
- of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
280
-}
281
-CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
282
- of_at91rm9200_clk_prog_setup);
283
-
284
-static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
285
-{
286
- of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
287
-}
288
-CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
289
- of_at91sam9g45_clk_prog_setup);
290
-
291
-static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
292
-{
293
- of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
294
-}
295
-CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
296
- of_at91sam9x5_clk_prog_setup);