1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/clk-provider.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/of_address.h>
21#include <linux/of_device.h>
22#include <linux/platform_device.h>
23#include <linux/slab.h>
24#include <linux/soc/ti/ti_sci_protocol.h>
25#include <linux/bsearch.h>
26
27#define SCI_CLK_SSC_ENABLE BIT(0)
28#define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
29#define SCI_CLK_INPUT_TERMINATION BIT(2)
30
31
32
33
34
35
36struct sci_clk_data {
37 u16 dev;
38 u16 num_clks;
39};
40
41
42
43
44
45
46
47
48
49
50struct sci_clk_provider {
51 const struct ti_sci_handle *sci;
52 const struct ti_sci_clk_ops *ops;
53 struct device *dev;
54 const struct sci_clk_data *clk_data;
55 struct clk_hw **clocks;
56 int num_clocks;
57};
58
59
60
61
62
63
64
65
66
67struct sci_clk {
68 struct clk_hw hw;
69 u16 dev_id;
70 u8 clk_id;
71 struct sci_clk_provider *provider;
72 u8 flags;
73};
74
75#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
76
77
78
79
80
81
82
83static int sci_clk_prepare(struct clk_hw *hw)
84{
85 struct sci_clk *clk = to_sci_clk(hw);
86 bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
87 bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
88 bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
89
90 return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
91 clk->clk_id, enable_ssc,
92 allow_freq_change,
93 input_termination);
94}
95
96
97
98
99
100
101
102static void sci_clk_unprepare(struct clk_hw *hw)
103{
104 struct sci_clk *clk = to_sci_clk(hw);
105 int ret;
106
107 ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
108 clk->clk_id);
109 if (ret)
110 dev_err(clk->provider->dev,
111 "unprepare failed for dev=%d, clk=%d, ret=%d\n",
112 clk->dev_id, clk->clk_id, ret);
113}
114
115
116
117
118
119
120
121
122static int sci_clk_is_prepared(struct clk_hw *hw)
123{
124 struct sci_clk *clk = to_sci_clk(hw);
125 bool req_state, current_state;
126 int ret;
127
128 ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
129 clk->clk_id, &req_state,
130 ¤t_state);
131 if (ret) {
132 dev_err(clk->provider->dev,
133 "is_prepared failed for dev=%d, clk=%d, ret=%d\n",
134 clk->dev_id, clk->clk_id, ret);
135 return 0;
136 }
137
138 return req_state;
139}
140
141
142
143
144
145
146
147
148
149static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
150 unsigned long parent_rate)
151{
152 struct sci_clk *clk = to_sci_clk(hw);
153 u64 freq;
154 int ret;
155
156 ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
157 clk->clk_id, &freq);
158 if (ret) {
159 dev_err(clk->provider->dev,
160 "recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
161 clk->dev_id, clk->clk_id, ret);
162 return 0;
163 }
164
165 return freq;
166}
167
168
169
170
171
172
173
174
175
176
177
178static int sci_clk_determine_rate(struct clk_hw *hw,
179 struct clk_rate_request *req)
180{
181 struct sci_clk *clk = to_sci_clk(hw);
182 int ret;
183 u64 new_rate;
184
185 ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
186 clk->dev_id,
187 clk->clk_id,
188 req->min_rate,
189 req->rate,
190 req->max_rate,
191 &new_rate);
192 if (ret) {
193 dev_err(clk->provider->dev,
194 "determine-rate failed for dev=%d, clk=%d, ret=%d\n",
195 clk->dev_id, clk->clk_id, ret);
196 return ret;
197 }
198
199 req->rate = new_rate;
200
201 return 0;
202}
203
204
205
206
207
208
209
210
211
212
213static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
214 unsigned long parent_rate)
215{
216 struct sci_clk *clk = to_sci_clk(hw);
217
218 return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
219 clk->clk_id, rate, rate, rate);
220}
221
222
223
224
225
226
227
228static u8 sci_clk_get_parent(struct clk_hw *hw)
229{
230 struct sci_clk *clk = to_sci_clk(hw);
231 u8 parent_id;
232 int ret;
233
234 ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
235 clk->clk_id, &parent_id);
236 if (ret) {
237 dev_err(clk->provider->dev,
238 "get-parent failed for dev=%d, clk=%d, ret=%d\n",
239 clk->dev_id, clk->clk_id, ret);
240 return 0;
241 }
242
243 return parent_id - clk->clk_id - 1;
244}
245
246
247
248
249
250
251
252
253static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
254{
255 struct sci_clk *clk = to_sci_clk(hw);
256
257 return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
258 clk->clk_id,
259 index + 1 + clk->clk_id);
260}
261
262static const struct clk_ops sci_clk_ops = {
263 .prepare = sci_clk_prepare,
264 .unprepare = sci_clk_unprepare,
265 .is_prepared = sci_clk_is_prepared,
266 .recalc_rate = sci_clk_recalc_rate,
267 .determine_rate = sci_clk_determine_rate,
268 .set_rate = sci_clk_set_rate,
269 .get_parent = sci_clk_get_parent,
270 .set_parent = sci_clk_set_parent,
271};
272
273
274
275
276
277
278
279
280
281
282
283
284
285static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
286 u16 dev_id, u8 clk_id)
287{
288 struct clk_init_data init = { NULL };
289 struct sci_clk *sci_clk = NULL;
290 char *name = NULL;
291 char **parent_names = NULL;
292 int i;
293 int ret;
294
295 sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
296 if (!sci_clk)
297 return ERR_PTR(-ENOMEM);
298
299 sci_clk->dev_id = dev_id;
300 sci_clk->clk_id = clk_id;
301 sci_clk->provider = provider;
302
303 ret = provider->ops->get_num_parents(provider->sci, dev_id,
304 clk_id,
305 &init.num_parents);
306 if (ret)
307 goto err;
308
309 name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
310 sci_clk->dev_id, sci_clk->clk_id);
311
312 init.name = name;
313
314
315
316
317
318
319
320 if (init.num_parents < 2)
321 init.num_parents = 0;
322
323 if (init.num_parents) {
324 parent_names = kcalloc(init.num_parents, sizeof(char *),
325 GFP_KERNEL);
326
327 if (!parent_names) {
328 ret = -ENOMEM;
329 goto err;
330 }
331
332 for (i = 0; i < init.num_parents; i++) {
333 char *parent_name;
334
335 parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
336 dev_name(provider->dev),
337 sci_clk->dev_id,
338 sci_clk->clk_id + 1 + i);
339 if (!parent_name) {
340 ret = -ENOMEM;
341 goto err;
342 }
343 parent_names[i] = parent_name;
344 }
345 init.parent_names = (void *)parent_names;
346 }
347
348 init.ops = &sci_clk_ops;
349 sci_clk->hw.init = &init;
350
351 ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
352 if (ret)
353 dev_err(provider->dev, "failed clk register with %d\n", ret);
354
355err:
356 if (parent_names) {
357 for (i = 0; i < init.num_parents; i++)
358 kfree(parent_names[i]);
359
360 kfree(parent_names);
361 }
362
363 kfree(name);
364
365 if (ret)
366 return ERR_PTR(ret);
367
368 return &sci_clk->hw;
369}
370
371static int _cmp_sci_clk(const void *a, const void *b)
372{
373 const struct sci_clk *ca = a;
374 const struct sci_clk *cb = *(struct sci_clk **)b;
375
376 if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id)
377 return 0;
378 if (ca->dev_id > cb->dev_id ||
379 (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id))
380 return 1;
381 return -1;
382}
383
384
385
386
387
388
389
390
391
392
393
394static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
395{
396 struct sci_clk_provider *provider = data;
397 struct sci_clk **clk;
398 struct sci_clk key;
399
400 if (clkspec->args_count != 2)
401 return ERR_PTR(-EINVAL);
402
403 key.dev_id = clkspec->args[0];
404 key.clk_id = clkspec->args[1];
405
406 clk = bsearch(&key, provider->clocks, provider->num_clocks,
407 sizeof(clk), _cmp_sci_clk);
408
409 if (!clk)
410 return ERR_PTR(-ENODEV);
411
412 return &(*clk)->hw;
413}
414
415static int ti_sci_init_clocks(struct sci_clk_provider *p)
416{
417 const struct sci_clk_data *data = p->clk_data;
418 struct clk_hw *hw;
419 int i;
420 int num_clks = 0;
421
422 while (data->num_clks) {
423 num_clks += data->num_clks;
424 data++;
425 }
426
427 p->num_clocks = num_clks;
428
429 p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk),
430 GFP_KERNEL);
431 if (!p->clocks)
432 return -ENOMEM;
433
434 num_clks = 0;
435
436 data = p->clk_data;
437
438 while (data->num_clks) {
439 for (i = 0; i < data->num_clks; i++) {
440 hw = _sci_clk_build(p, data->dev, i);
441 if (!IS_ERR(hw)) {
442 p->clocks[num_clks++] = hw;
443 continue;
444 }
445
446
447 if (PTR_ERR(hw) == -ENODEV)
448 continue;
449
450 return PTR_ERR(hw);
451 }
452 data++;
453 }
454
455 return 0;
456}
457
458static const struct sci_clk_data k2g_clk_data[] = {
459
460 { .dev = 0x0, .num_clks = 4 },
461
462
463 { .dev = 0x1, .num_clks = 5 },
464
465
466 { .dev = 0x2, .num_clks = 2 },
467
468
469 { .dev = 0x3, .num_clks = 8 },
470
471
472 { .dev = 0x4, .num_clks = 8 },
473
474
475 { .dev = 0x5, .num_clks = 8 },
476
477
478 { .dev = 0x6, .num_clks = 8 },
479
480
481 { .dev = 0x8, .num_clks = 2 },
482
483
484 { .dev = 0x9, .num_clks = 2 },
485
486
487 { .dev = 0xa, .num_clks = 6 },
488
489
490 { .dev = 0xb, .num_clks = 3 },
491
492
493 { .dev = 0xc, .num_clks = 3 },
494
495
496 { .dev = 0xd, .num_clks = 1 },
497
498
499 { .dev = 0xe, .num_clks = 1 },
500
501
502 { .dev = 0x10, .num_clks = 1 },
503
504
505 { .dev = 0x11, .num_clks = 1 },
506
507
508 { .dev = 0x12, .num_clks = 1 },
509
510
511 { .dev = 0x13, .num_clks = 1 },
512
513
514 { .dev = 0x14, .num_clks = 6 },
515
516
517 { .dev = 0x15, .num_clks = 6 },
518
519
520 { .dev = 0x16, .num_clks = 7 },
521
522
523 { .dev = 0x17, .num_clks = 7 },
524
525
526 { .dev = 0x18, .num_clks = 14 },
527
528
529 { .dev = 0x19, .num_clks = 1 },
530
531
532 { .dev = 0x1b, .num_clks = 1 },
533
534
535 { .dev = 0x1c, .num_clks = 1 },
536
537
538 { .dev = 0x1d, .num_clks = 9 },
539
540
541 { .dev = 0x1e, .num_clks = 9 },
542
543
544 { .dev = 0x1f, .num_clks = 9 },
545
546
547 { .dev = 0x20, .num_clks = 9 },
548
549
550 { .dev = 0x21, .num_clks = 9 },
551
552
553 { .dev = 0x22, .num_clks = 9 },
554
555
556 { .dev = 0x23, .num_clks = 9 },
557
558
559 { .dev = 0x25, .num_clks = 1 },
560
561
562 { .dev = 0x26, .num_clks = 1 },
563
564
565 { .dev = 0x27, .num_clks = 1 },
566
567
568 { .dev = 0x29, .num_clks = 1 },
569
570
571 { .dev = 0x2b, .num_clks = 8 },
572
573
574 { .dev = 0x2c, .num_clks = 1 },
575
576
577 { .dev = 0x2d, .num_clks = 1 },
578
579
580 { .dev = 0x2e, .num_clks = 1 },
581
582
583 { .dev = 0x2f, .num_clks = 1 },
584
585
586 { .dev = 0x30, .num_clks = 1 },
587
588
589 { .dev = 0x31, .num_clks = 1 },
590
591
592 { .dev = 0x32, .num_clks = 1 },
593
594
595 { .dev = 0x33, .num_clks = 1 },
596
597
598 { .dev = 0x34, .num_clks = 1 },
599
600
601 { .dev = 0x35, .num_clks = 1 },
602
603
604 { .dev = 0x36, .num_clks = 1 },
605
606
607 { .dev = 0x37, .num_clks = 1 },
608
609
610 { .dev = 0x38, .num_clks = 1 },
611
612
613 { .dev = 0x39, .num_clks = 1 },
614
615
616 { .dev = 0x3a, .num_clks = 1 },
617
618
619 { .dev = 0x3b, .num_clks = 1 },
620
621
622 { .dev = 0x3c, .num_clks = 1 },
623
624
625 { .dev = 0x3f, .num_clks = 2 },
626
627
628 { .dev = 0x40, .num_clks = 1 },
629
630
631 { .dev = 0x41, .num_clks = 1 },
632
633
634 { .dev = 0x42, .num_clks = 1 },
635
636
637 { .dev = 0x43, .num_clks = 5 },
638
639
640 { .dev = 0x44, .num_clks = 2 },
641
642
643 { .dev = 0x45, .num_clks = 2 },
644
645
646 { .dev = 0x46, .num_clks = 2 },
647
648
649 { .dev = 0x47, .num_clks = 1 },
650
651
652 { .dev = 0x49, .num_clks = 1 },
653
654
655 { .dev = 0x4c, .num_clks = 36 },
656
657
658 { .dev = 0x4f, .num_clks = 2 },
659 { .num_clks = 0 },
660};
661
662static const struct of_device_id ti_sci_clk_of_match[] = {
663 { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
664 { },
665};
666MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
667
668
669
670
671
672
673
674
675
676
677
678static int ti_sci_clk_probe(struct platform_device *pdev)
679{
680 struct device *dev = &pdev->dev;
681 struct device_node *np = dev->of_node;
682 struct sci_clk_provider *provider;
683 const struct ti_sci_handle *handle;
684 const struct sci_clk_data *data;
685 int ret;
686
687 data = of_device_get_match_data(dev);
688 if (!data)
689 return -EINVAL;
690
691 handle = devm_ti_sci_get_handle(dev);
692 if (IS_ERR(handle))
693 return PTR_ERR(handle);
694
695 provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
696 if (!provider)
697 return -ENOMEM;
698
699 provider->clk_data = data;
700
701 provider->sci = handle;
702 provider->ops = &handle->ops.clk_ops;
703 provider->dev = dev;
704
705 ret = ti_sci_init_clocks(provider);
706 if (ret) {
707 pr_err("ti-sci-init-clocks failed.\n");
708 return ret;
709 }
710
711 return of_clk_add_hw_provider(np, sci_clk_get, provider);
712}
713
714
715
716
717
718
719
720
721
722static int ti_sci_clk_remove(struct platform_device *pdev)
723{
724 of_clk_del_provider(pdev->dev.of_node);
725
726 return 0;
727}
728
729static struct platform_driver ti_sci_clk_driver = {
730 .probe = ti_sci_clk_probe,
731 .remove = ti_sci_clk_remove,
732 .driver = {
733 .name = "ti-sci-clk",
734 .of_match_table = of_match_ptr(ti_sci_clk_of_match),
735 },
736};
737module_platform_driver(ti_sci_clk_driver);
738
739MODULE_LICENSE("GPL v2");
740MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
741MODULE_AUTHOR("Tero Kristo");
742MODULE_ALIAS("platform:ti-sci-clk");
743