Documentation: embargoed-hardware-issues.rst: Add myself for Power
[sfrench/cifs-2.6.git] / drivers / clk / mediatek / clk-mtk.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 MediaTek Inc.
4  * Author: James Liao <jamesjj.liao@mediatek.com>
5  */
6
7 #include <linux/bitops.h>
8 #include <linux/clk-provider.h>
9 #include <linux/err.h>
10 #include <linux/io.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_address.h>
15 #include <linux/platform_device.h>
16 #include <linux/slab.h>
17
18 #include "clk-mtk.h"
19 #include "clk-gate.h"
20 #include "clk-mux.h"
21
22 const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 };
23 EXPORT_SYMBOL_GPL(cg_regs_dummy);
24
25 static int mtk_clk_dummy_enable(struct clk_hw *hw)
26 {
27         return 0;
28 }
29
30 static void mtk_clk_dummy_disable(struct clk_hw *hw) { }
31
32 const struct clk_ops mtk_clk_dummy_ops = {
33         .enable         = mtk_clk_dummy_enable,
34         .disable        = mtk_clk_dummy_disable,
35 };
36 EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops);
37
38 static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data,
39                               unsigned int clk_num)
40 {
41         int i;
42
43         clk_data->num = clk_num;
44
45         for (i = 0; i < clk_num; i++)
46                 clk_data->hws[i] = ERR_PTR(-ENOENT);
47 }
48
49 struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev,
50                                                     unsigned int clk_num)
51 {
52         struct clk_hw_onecell_data *clk_data;
53
54         clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, clk_num),
55                                 GFP_KERNEL);
56         if (!clk_data)
57                 return NULL;
58
59         mtk_init_clk_data(clk_data, clk_num);
60
61         return clk_data;
62 }
63 EXPORT_SYMBOL_GPL(mtk_devm_alloc_clk_data);
64
65 struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
66 {
67         struct clk_hw_onecell_data *clk_data;
68
69         clk_data = kzalloc(struct_size(clk_data, hws, clk_num), GFP_KERNEL);
70         if (!clk_data)
71                 return NULL;
72
73         mtk_init_clk_data(clk_data, clk_num);
74
75         return clk_data;
76 }
77 EXPORT_SYMBOL_GPL(mtk_alloc_clk_data);
78
79 void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data)
80 {
81         kfree(clk_data);
82 }
83 EXPORT_SYMBOL_GPL(mtk_free_clk_data);
84
85 int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num,
86                                 struct clk_hw_onecell_data *clk_data)
87 {
88         int i;
89         struct clk_hw *hw;
90
91         if (!clk_data)
92                 return -ENOMEM;
93
94         for (i = 0; i < num; i++) {
95                 const struct mtk_fixed_clk *rc = &clks[i];
96
97                 if (!IS_ERR_OR_NULL(clk_data->hws[rc->id])) {
98                         pr_warn("Trying to register duplicate clock ID: %d\n", rc->id);
99                         continue;
100                 }
101
102                 hw = clk_hw_register_fixed_rate(NULL, rc->name, rc->parent, 0,
103                                               rc->rate);
104
105                 if (IS_ERR(hw)) {
106                         pr_err("Failed to register clk %s: %pe\n", rc->name,
107                                hw);
108                         goto err;
109                 }
110
111                 clk_data->hws[rc->id] = hw;
112         }
113
114         return 0;
115
116 err:
117         while (--i >= 0) {
118                 const struct mtk_fixed_clk *rc = &clks[i];
119
120                 if (IS_ERR_OR_NULL(clk_data->hws[rc->id]))
121                         continue;
122
123                 clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]);
124                 clk_data->hws[rc->id] = ERR_PTR(-ENOENT);
125         }
126
127         return PTR_ERR(hw);
128 }
129 EXPORT_SYMBOL_GPL(mtk_clk_register_fixed_clks);
130
131 void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num,
132                                    struct clk_hw_onecell_data *clk_data)
133 {
134         int i;
135
136         if (!clk_data)
137                 return;
138
139         for (i = num; i > 0; i--) {
140                 const struct mtk_fixed_clk *rc = &clks[i - 1];
141
142                 if (IS_ERR_OR_NULL(clk_data->hws[rc->id]))
143                         continue;
144
145                 clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]);
146                 clk_data->hws[rc->id] = ERR_PTR(-ENOENT);
147         }
148 }
149 EXPORT_SYMBOL_GPL(mtk_clk_unregister_fixed_clks);
150
151 int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
152                              struct clk_hw_onecell_data *clk_data)
153 {
154         int i;
155         struct clk_hw *hw;
156
157         if (!clk_data)
158                 return -ENOMEM;
159
160         for (i = 0; i < num; i++) {
161                 const struct mtk_fixed_factor *ff = &clks[i];
162
163                 if (!IS_ERR_OR_NULL(clk_data->hws[ff->id])) {
164                         pr_warn("Trying to register duplicate clock ID: %d\n", ff->id);
165                         continue;
166                 }
167
168                 hw = clk_hw_register_fixed_factor(NULL, ff->name, ff->parent_name,
169                                 ff->flags, ff->mult, ff->div);
170
171                 if (IS_ERR(hw)) {
172                         pr_err("Failed to register clk %s: %pe\n", ff->name,
173                                hw);
174                         goto err;
175                 }
176
177                 clk_data->hws[ff->id] = hw;
178         }
179
180         return 0;
181
182 err:
183         while (--i >= 0) {
184                 const struct mtk_fixed_factor *ff = &clks[i];
185
186                 if (IS_ERR_OR_NULL(clk_data->hws[ff->id]))
187                         continue;
188
189                 clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]);
190                 clk_data->hws[ff->id] = ERR_PTR(-ENOENT);
191         }
192
193         return PTR_ERR(hw);
194 }
195 EXPORT_SYMBOL_GPL(mtk_clk_register_factors);
196
197 void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num,
198                                 struct clk_hw_onecell_data *clk_data)
199 {
200         int i;
201
202         if (!clk_data)
203                 return;
204
205         for (i = num; i > 0; i--) {
206                 const struct mtk_fixed_factor *ff = &clks[i - 1];
207
208                 if (IS_ERR_OR_NULL(clk_data->hws[ff->id]))
209                         continue;
210
211                 clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]);
212                 clk_data->hws[ff->id] = ERR_PTR(-ENOENT);
213         }
214 }
215 EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors);
216
217 static struct clk_hw *mtk_clk_register_composite(struct device *dev,
218                 const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock)
219 {
220         struct clk_hw *hw;
221         struct clk_mux *mux = NULL;
222         struct clk_gate *gate = NULL;
223         struct clk_divider *div = NULL;
224         struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
225         const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
226         const char * const *parent_names;
227         const char *parent;
228         int num_parents;
229         int ret;
230
231         if (mc->mux_shift >= 0) {
232                 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
233                 if (!mux)
234                         return ERR_PTR(-ENOMEM);
235
236                 mux->reg = base + mc->mux_reg;
237                 mux->mask = BIT(mc->mux_width) - 1;
238                 mux->shift = mc->mux_shift;
239                 mux->lock = lock;
240                 mux->flags = mc->mux_flags;
241                 mux_hw = &mux->hw;
242                 mux_ops = &clk_mux_ops;
243
244                 parent_names = mc->parent_names;
245                 num_parents = mc->num_parents;
246         } else {
247                 parent = mc->parent;
248                 parent_names = &parent;
249                 num_parents = 1;
250         }
251
252         if (mc->gate_shift >= 0) {
253                 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
254                 if (!gate) {
255                         ret = -ENOMEM;
256                         goto err_out;
257                 }
258
259                 gate->reg = base + mc->gate_reg;
260                 gate->bit_idx = mc->gate_shift;
261                 gate->flags = CLK_GATE_SET_TO_DISABLE;
262                 gate->lock = lock;
263
264                 gate_hw = &gate->hw;
265                 gate_ops = &clk_gate_ops;
266         }
267
268         if (mc->divider_shift >= 0) {
269                 div = kzalloc(sizeof(*div), GFP_KERNEL);
270                 if (!div) {
271                         ret = -ENOMEM;
272                         goto err_out;
273                 }
274
275                 div->reg = base + mc->divider_reg;
276                 div->shift = mc->divider_shift;
277                 div->width = mc->divider_width;
278                 div->lock = lock;
279
280                 div_hw = &div->hw;
281                 div_ops = &clk_divider_ops;
282         }
283
284         hw = clk_hw_register_composite(dev, mc->name, parent_names, num_parents,
285                 mux_hw, mux_ops,
286                 div_hw, div_ops,
287                 gate_hw, gate_ops,
288                 mc->flags);
289
290         if (IS_ERR(hw)) {
291                 ret = PTR_ERR(hw);
292                 goto err_out;
293         }
294
295         return hw;
296 err_out:
297         kfree(div);
298         kfree(gate);
299         kfree(mux);
300
301         return ERR_PTR(ret);
302 }
303
304 static void mtk_clk_unregister_composite(struct clk_hw *hw)
305 {
306         struct clk_composite *composite;
307         struct clk_mux *mux = NULL;
308         struct clk_gate *gate = NULL;
309         struct clk_divider *div = NULL;
310
311         if (!hw)
312                 return;
313
314         composite = to_clk_composite(hw);
315         if (composite->mux_hw)
316                 mux = to_clk_mux(composite->mux_hw);
317         if (composite->gate_hw)
318                 gate = to_clk_gate(composite->gate_hw);
319         if (composite->rate_hw)
320                 div = to_clk_divider(composite->rate_hw);
321
322         clk_hw_unregister_composite(hw);
323         kfree(div);
324         kfree(gate);
325         kfree(mux);
326 }
327
328 int mtk_clk_register_composites(struct device *dev,
329                                 const struct mtk_composite *mcs, int num,
330                                 void __iomem *base, spinlock_t *lock,
331                                 struct clk_hw_onecell_data *clk_data)
332 {
333         struct clk_hw *hw;
334         int i;
335
336         if (!clk_data)
337                 return -ENOMEM;
338
339         for (i = 0; i < num; i++) {
340                 const struct mtk_composite *mc = &mcs[i];
341
342                 if (!IS_ERR_OR_NULL(clk_data->hws[mc->id])) {
343                         pr_warn("Trying to register duplicate clock ID: %d\n",
344                                 mc->id);
345                         continue;
346                 }
347
348                 hw = mtk_clk_register_composite(dev, mc, base, lock);
349
350                 if (IS_ERR(hw)) {
351                         pr_err("Failed to register clk %s: %pe\n", mc->name,
352                                hw);
353                         goto err;
354                 }
355
356                 clk_data->hws[mc->id] = hw;
357         }
358
359         return 0;
360
361 err:
362         while (--i >= 0) {
363                 const struct mtk_composite *mc = &mcs[i];
364
365                 if (IS_ERR_OR_NULL(clk_data->hws[mcs->id]))
366                         continue;
367
368                 mtk_clk_unregister_composite(clk_data->hws[mc->id]);
369                 clk_data->hws[mc->id] = ERR_PTR(-ENOENT);
370         }
371
372         return PTR_ERR(hw);
373 }
374 EXPORT_SYMBOL_GPL(mtk_clk_register_composites);
375
376 void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num,
377                                    struct clk_hw_onecell_data *clk_data)
378 {
379         int i;
380
381         if (!clk_data)
382                 return;
383
384         for (i = num; i > 0; i--) {
385                 const struct mtk_composite *mc = &mcs[i - 1];
386
387                 if (IS_ERR_OR_NULL(clk_data->hws[mc->id]))
388                         continue;
389
390                 mtk_clk_unregister_composite(clk_data->hws[mc->id]);
391                 clk_data->hws[mc->id] = ERR_PTR(-ENOENT);
392         }
393 }
394 EXPORT_SYMBOL_GPL(mtk_clk_unregister_composites);
395
396 int mtk_clk_register_dividers(struct device *dev,
397                               const struct mtk_clk_divider *mcds, int num,
398                               void __iomem *base, spinlock_t *lock,
399                               struct clk_hw_onecell_data *clk_data)
400 {
401         struct clk_hw *hw;
402         int i;
403
404         if (!clk_data)
405                 return -ENOMEM;
406
407         for (i = 0; i <  num; i++) {
408                 const struct mtk_clk_divider *mcd = &mcds[i];
409
410                 if (!IS_ERR_OR_NULL(clk_data->hws[mcd->id])) {
411                         pr_warn("Trying to register duplicate clock ID: %d\n",
412                                 mcd->id);
413                         continue;
414                 }
415
416                 hw = clk_hw_register_divider(dev, mcd->name, mcd->parent_name,
417                         mcd->flags, base +  mcd->div_reg, mcd->div_shift,
418                         mcd->div_width, mcd->clk_divider_flags, lock);
419
420                 if (IS_ERR(hw)) {
421                         pr_err("Failed to register clk %s: %pe\n", mcd->name,
422                                hw);
423                         goto err;
424                 }
425
426                 clk_data->hws[mcd->id] = hw;
427         }
428
429         return 0;
430
431 err:
432         while (--i >= 0) {
433                 const struct mtk_clk_divider *mcd = &mcds[i];
434
435                 if (IS_ERR_OR_NULL(clk_data->hws[mcd->id]))
436                         continue;
437
438                 clk_hw_unregister_divider(clk_data->hws[mcd->id]);
439                 clk_data->hws[mcd->id] = ERR_PTR(-ENOENT);
440         }
441
442         return PTR_ERR(hw);
443 }
444 EXPORT_SYMBOL_GPL(mtk_clk_register_dividers);
445
446 void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num,
447                                  struct clk_hw_onecell_data *clk_data)
448 {
449         int i;
450
451         if (!clk_data)
452                 return;
453
454         for (i = num; i > 0; i--) {
455                 const struct mtk_clk_divider *mcd = &mcds[i - 1];
456
457                 if (IS_ERR_OR_NULL(clk_data->hws[mcd->id]))
458                         continue;
459
460                 clk_hw_unregister_divider(clk_data->hws[mcd->id]);
461                 clk_data->hws[mcd->id] = ERR_PTR(-ENOENT);
462         }
463 }
464 EXPORT_SYMBOL_GPL(mtk_clk_unregister_dividers);
465
466 static int __mtk_clk_simple_probe(struct platform_device *pdev,
467                                   struct device_node *node)
468 {
469         const struct platform_device_id *id;
470         const struct mtk_clk_desc *mcd;
471         struct clk_hw_onecell_data *clk_data;
472         void __iomem *base = NULL;
473         int num_clks, r;
474
475         mcd = device_get_match_data(&pdev->dev);
476         if (!mcd) {
477                 /* Clock driver wasn't registered from devicetree */
478                 id = platform_get_device_id(pdev);
479                 if (id)
480                         mcd = (const struct mtk_clk_desc *)id->driver_data;
481
482                 if (!mcd)
483                         return -EINVAL;
484         }
485
486         /* Composite and divider clocks needs us to pass iomem pointer */
487         if (mcd->composite_clks || mcd->divider_clks) {
488                 if (!mcd->shared_io)
489                         base = devm_platform_ioremap_resource(pdev, 0);
490                 else
491                         base = of_iomap(node, 0);
492
493                 if (IS_ERR_OR_NULL(base))
494                         return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM;
495         }
496
497         /* Calculate how many clk_hw_onecell_data entries to allocate */
498         num_clks = mcd->num_clks + mcd->num_composite_clks;
499         num_clks += mcd->num_fixed_clks + mcd->num_factor_clks;
500         num_clks += mcd->num_mux_clks + mcd->num_divider_clks;
501
502         clk_data = mtk_alloc_clk_data(num_clks);
503         if (!clk_data) {
504                 r = -ENOMEM;
505                 goto free_base;
506         }
507
508         if (mcd->fixed_clks) {
509                 r = mtk_clk_register_fixed_clks(mcd->fixed_clks,
510                                                 mcd->num_fixed_clks, clk_data);
511                 if (r)
512                         goto free_data;
513         }
514
515         if (mcd->factor_clks) {
516                 r = mtk_clk_register_factors(mcd->factor_clks,
517                                              mcd->num_factor_clks, clk_data);
518                 if (r)
519                         goto unregister_fixed_clks;
520         }
521
522         if (mcd->mux_clks) {
523                 r = mtk_clk_register_muxes(&pdev->dev, mcd->mux_clks,
524                                            mcd->num_mux_clks, node,
525                                            mcd->clk_lock, clk_data);
526                 if (r)
527                         goto unregister_factors;
528         }
529
530         if (mcd->composite_clks) {
531                 /* We don't check composite_lock because it's optional */
532                 r = mtk_clk_register_composites(&pdev->dev,
533                                                 mcd->composite_clks,
534                                                 mcd->num_composite_clks,
535                                                 base, mcd->clk_lock, clk_data);
536                 if (r)
537                         goto unregister_muxes;
538         }
539
540         if (mcd->divider_clks) {
541                 r = mtk_clk_register_dividers(&pdev->dev,
542                                               mcd->divider_clks,
543                                               mcd->num_divider_clks,
544                                               base, mcd->clk_lock, clk_data);
545                 if (r)
546                         goto unregister_composites;
547         }
548
549         if (mcd->clks) {
550                 r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks,
551                                            mcd->num_clks, clk_data);
552                 if (r)
553                         goto unregister_dividers;
554         }
555
556         if (mcd->clk_notifier_func) {
557                 struct clk *mfg_mux = clk_data->hws[mcd->mfg_clk_idx]->clk;
558
559                 r = mcd->clk_notifier_func(&pdev->dev, mfg_mux);
560                 if (r)
561                         goto unregister_clks;
562         }
563
564         r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
565         if (r)
566                 goto unregister_clks;
567
568         platform_set_drvdata(pdev, clk_data);
569
570         if (mcd->rst_desc) {
571                 r = mtk_register_reset_controller_with_dev(&pdev->dev,
572                                                            mcd->rst_desc);
573                 if (r)
574                         goto unregister_clks;
575         }
576
577         return r;
578
579 unregister_clks:
580         if (mcd->clks)
581                 mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data);
582 unregister_dividers:
583         if (mcd->divider_clks)
584                 mtk_clk_unregister_dividers(mcd->divider_clks,
585                                             mcd->num_divider_clks, clk_data);
586 unregister_composites:
587         if (mcd->composite_clks)
588                 mtk_clk_unregister_composites(mcd->composite_clks,
589                                               mcd->num_composite_clks, clk_data);
590 unregister_muxes:
591         if (mcd->mux_clks)
592                 mtk_clk_unregister_muxes(mcd->mux_clks,
593                                          mcd->num_mux_clks, clk_data);
594 unregister_factors:
595         if (mcd->factor_clks)
596                 mtk_clk_unregister_factors(mcd->factor_clks,
597                                            mcd->num_factor_clks, clk_data);
598 unregister_fixed_clks:
599         if (mcd->fixed_clks)
600                 mtk_clk_unregister_fixed_clks(mcd->fixed_clks,
601                                               mcd->num_fixed_clks, clk_data);
602 free_data:
603         mtk_free_clk_data(clk_data);
604 free_base:
605         if (mcd->shared_io && base)
606                 iounmap(base);
607         return r;
608 }
609
610 static void __mtk_clk_simple_remove(struct platform_device *pdev,
611                                    struct device_node *node)
612 {
613         struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
614         const struct mtk_clk_desc *mcd = device_get_match_data(&pdev->dev);
615
616         of_clk_del_provider(node);
617         if (mcd->clks)
618                 mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data);
619         if (mcd->divider_clks)
620                 mtk_clk_unregister_dividers(mcd->divider_clks,
621                                             mcd->num_divider_clks, clk_data);
622         if (mcd->composite_clks)
623                 mtk_clk_unregister_composites(mcd->composite_clks,
624                                               mcd->num_composite_clks, clk_data);
625         if (mcd->mux_clks)
626                 mtk_clk_unregister_muxes(mcd->mux_clks,
627                                          mcd->num_mux_clks, clk_data);
628         if (mcd->factor_clks)
629                 mtk_clk_unregister_factors(mcd->factor_clks,
630                                            mcd->num_factor_clks, clk_data);
631         if (mcd->fixed_clks)
632                 mtk_clk_unregister_fixed_clks(mcd->fixed_clks,
633                                               mcd->num_fixed_clks, clk_data);
634         mtk_free_clk_data(clk_data);
635 }
636
637 int mtk_clk_pdev_probe(struct platform_device *pdev)
638 {
639         struct device *dev = &pdev->dev;
640         struct device_node *node = dev->parent->of_node;
641
642         return __mtk_clk_simple_probe(pdev, node);
643 }
644 EXPORT_SYMBOL_GPL(mtk_clk_pdev_probe);
645
646 int mtk_clk_simple_probe(struct platform_device *pdev)
647 {
648         struct device_node *node = pdev->dev.of_node;
649
650         return __mtk_clk_simple_probe(pdev, node);
651 }
652 EXPORT_SYMBOL_GPL(mtk_clk_simple_probe);
653
654 void mtk_clk_pdev_remove(struct platform_device *pdev)
655 {
656         struct device *dev = &pdev->dev;
657         struct device_node *node = dev->parent->of_node;
658
659         __mtk_clk_simple_remove(pdev, node);
660 }
661 EXPORT_SYMBOL_GPL(mtk_clk_pdev_remove);
662
663 void mtk_clk_simple_remove(struct platform_device *pdev)
664 {
665         __mtk_clk_simple_remove(pdev, pdev->dev.of_node);
666 }
667 EXPORT_SYMBOL_GPL(mtk_clk_simple_remove);
668
669 MODULE_LICENSE("GPL");