1
2
3
4
5
6
7
8
9
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/errno.h>
14#include <linux/bug.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17
18#include "cm2xxx.h"
19#include "cm3xxx.h"
20#include "cm33xx.h"
21#include "cm44xx.h"
22#include "clock.h"
23
24
25
26
27
28static struct cm_ll_data null_cm_ll_data;
29static const struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
30
31
32struct omap_domain_base cm_base;
33
34
35struct omap_domain_base cm2_base;
36
37#define CM_NO_CLOCKS 0x1
38#define CM_SINGLE_INSTANCE 0x2
39
40
41
42
43
44
45
46
47
48
49
50
51
52int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
53 u8 *idlest_reg_id)
54{
55 int ret;
56 if (!cm_ll_data->split_idlest_reg) {
57 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
58 __func__);
59 return -EINVAL;
60 }
61
62 ret = cm_ll_data->split_idlest_reg(idlest_reg, prcm_inst,
63 idlest_reg_id);
64 *prcm_inst -= cm_base.offset;
65 return ret;
66}
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
82 u8 idlest_shift)
83{
84 if (!cm_ll_data->wait_module_ready) {
85 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
86 __func__);
87 return -EINVAL;
88 }
89
90 return cm_ll_data->wait_module_ready(part, prcm_mod, idlest_reg,
91 idlest_shift);
92}
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
108 u8 idlest_shift)
109{
110 if (!cm_ll_data->wait_module_idle) {
111 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
112 __func__);
113 return -EINVAL;
114 }
115
116 return cm_ll_data->wait_module_idle(part, prcm_mod, idlest_reg,
117 idlest_shift);
118}
119
120
121
122
123
124
125
126
127
128
129
130
131int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs)
132{
133 if (!cm_ll_data->module_enable) {
134 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
135 __func__);
136 return -EINVAL;
137 }
138
139 cm_ll_data->module_enable(mode, part, inst, clkctrl_offs);
140 return 0;
141}
142
143
144
145
146
147
148
149
150
151
152
153int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
154{
155 if (!cm_ll_data->module_disable) {
156 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
157 __func__);
158 return -EINVAL;
159 }
160
161 cm_ll_data->module_disable(part, inst, clkctrl_offs);
162 return 0;
163}
164
165u32 omap_cm_xlate_clkctrl(u8 part, u16 inst, u16 clkctrl_offs)
166{
167 if (!cm_ll_data->xlate_clkctrl) {
168 WARN_ONCE(1, "cm: %s: no low-level function defined\n",
169 __func__);
170 return 0;
171 }
172 return cm_ll_data->xlate_clkctrl(part, inst, clkctrl_offs);
173}
174
175
176
177
178
179
180
181
182
183
184
185
186int cm_register(const struct cm_ll_data *cld)
187{
188 if (!cld)
189 return -EINVAL;
190
191 if (cm_ll_data != &null_cm_ll_data)
192 return -EEXIST;
193
194 cm_ll_data = cld;
195
196 return 0;
197}
198
199
200
201
202
203
204
205
206
207
208
209
210int cm_unregister(const struct cm_ll_data *cld)
211{
212 if (!cld || cm_ll_data != cld)
213 return -EINVAL;
214
215 cm_ll_data = &null_cm_ll_data;
216
217 return 0;
218}
219
220#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
221 defined(CONFIG_SOC_DRA7XX)
222static struct omap_prcm_init_data cm_data __initdata = {
223 .index = TI_CLKM_CM,
224 .init = omap4_cm_init,
225};
226
227static struct omap_prcm_init_data cm2_data __initdata = {
228 .index = TI_CLKM_CM2,
229 .init = omap4_cm_init,
230};
231#endif
232
233#ifdef CONFIG_ARCH_OMAP2
234static struct omap_prcm_init_data omap2_prcm_data __initdata = {
235 .index = TI_CLKM_CM,
236 .init = omap2xxx_cm_init,
237 .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
238};
239#endif
240
241#ifdef CONFIG_ARCH_OMAP3
242static struct omap_prcm_init_data omap3_cm_data __initdata = {
243 .index = TI_CLKM_CM,
244 .init = omap3xxx_cm_init,
245 .flags = CM_SINGLE_INSTANCE,
246
247
248
249
250
251 .offset = -OMAP3430_IVA2_MOD,
252};
253#endif
254
255#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_TI81XX)
256static struct omap_prcm_init_data am3_prcm_data __initdata = {
257 .index = TI_CLKM_CM,
258 .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
259 .init = am33xx_cm_init,
260};
261#endif
262
263#ifdef CONFIG_SOC_AM43XX
264static struct omap_prcm_init_data am4_prcm_data __initdata = {
265 .index = TI_CLKM_CM,
266 .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
267 .init = omap4_cm_init,
268};
269#endif
270
271static const struct of_device_id omap_cm_dt_match_table[] __initconst = {
272#ifdef CONFIG_ARCH_OMAP2
273 { .compatible = "ti,omap2-prcm", .data = &omap2_prcm_data },
274#endif
275#ifdef CONFIG_ARCH_OMAP3
276 { .compatible = "ti,omap3-cm", .data = &omap3_cm_data },
277#endif
278#ifdef CONFIG_ARCH_OMAP4
279 { .compatible = "ti,omap4-cm1", .data = &cm_data },
280 { .compatible = "ti,omap4-cm2", .data = &cm2_data },
281#endif
282#ifdef CONFIG_SOC_OMAP5
283 { .compatible = "ti,omap5-cm-core-aon", .data = &cm_data },
284 { .compatible = "ti,omap5-cm-core", .data = &cm2_data },
285#endif
286#ifdef CONFIG_SOC_DRA7XX
287 { .compatible = "ti,dra7-cm-core-aon", .data = &cm_data },
288 { .compatible = "ti,dra7-cm-core", .data = &cm2_data },
289#endif
290#ifdef CONFIG_SOC_AM33XX
291 { .compatible = "ti,am3-prcm", .data = &am3_prcm_data },
292#endif
293#ifdef CONFIG_SOC_AM43XX
294 { .compatible = "ti,am4-prcm", .data = &am4_prcm_data },
295#endif
296#ifdef CONFIG_SOC_TI81XX
297 { .compatible = "ti,dm814-prcm", .data = &am3_prcm_data },
298 { .compatible = "ti,dm816-prcm", .data = &am3_prcm_data },
299#endif
300 { }
301};
302
303
304
305
306
307
308
309
310int __init omap2_cm_base_init(void)
311{
312 struct device_node *np;
313 const struct of_device_id *match;
314 struct omap_prcm_init_data *data;
315 struct resource res;
316 int ret;
317 struct omap_domain_base *mem = NULL;
318
319 for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
320 data = (struct omap_prcm_init_data *)match->data;
321
322 ret = of_address_to_resource(np, 0, &res);
323 if (ret)
324 return ret;
325
326 if (data->index == TI_CLKM_CM)
327 mem = &cm_base;
328
329 if (data->index == TI_CLKM_CM2)
330 mem = &cm2_base;
331
332 data->mem = ioremap(res.start, resource_size(&res));
333
334 if (mem) {
335 mem->pa = res.start + data->offset;
336 mem->va = data->mem + data->offset;
337 mem->offset = data->offset;
338 }
339
340 data->np = np;
341
342 if (data->init && (data->flags & CM_SINGLE_INSTANCE ||
343 (cm_base.va && cm2_base.va)))
344 data->init(data);
345 }
346
347 return 0;
348}
349
350
351
352
353
354
355
356int __init omap_cm_init(void)
357{
358 struct device_node *np;
359 const struct of_device_id *match;
360 const struct omap_prcm_init_data *data;
361 int ret;
362
363 for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
364 data = match->data;
365
366 if (data->flags & CM_NO_CLOCKS)
367 continue;
368
369 ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
370 if (ret)
371 return ret;
372 }
373
374 return 0;
375}
376