1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#undef DEBUG
27
28#include <linux/kernel.h>
29#include <linux/platform_device.h>
30#include <linux/slab.h>
31#include <linux/err.h>
32#include <linux/io.h>
33#include <linux/clk.h>
34#include <linux/clkdev.h>
35#include <linux/pm_domain.h>
36#include <linux/pm_runtime.h>
37#include <linux/of.h>
38#include <linux/notifier.h>
39
40#include "common.h"
41#include "soc.h"
42#include "omap_device.h"
43#include "omap_hwmod.h"
44
45
46
47static void _add_clkdev(struct omap_device *od, const char *clk_alias,
48 const char *clk_name)
49{
50 struct clk *r;
51 int rc;
52
53 if (!clk_alias || !clk_name)
54 return;
55
56 dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
57
58 r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
59 if (!IS_ERR(r)) {
60 dev_dbg(&od->pdev->dev,
61 "alias %s already exists\n", clk_alias);
62 clk_put(r);
63 return;
64 }
65
66 rc = clk_add_alias(clk_alias, dev_name(&od->pdev->dev), clk_name, NULL);
67 if (rc) {
68 if (rc == -ENODEV || rc == -ENOMEM)
69 dev_err(&od->pdev->dev,
70 "clkdev_alloc for %s failed\n", clk_alias);
71 else
72 dev_err(&od->pdev->dev,
73 "clk_get for %s failed\n", clk_name);
74 }
75}
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96static void _add_hwmod_clocks_clkdev(struct omap_device *od,
97 struct omap_hwmod *oh)
98{
99 int i;
100
101 _add_clkdev(od, "fck", oh->main_clk);
102
103 for (i = 0; i < oh->opt_clks_cnt; i++)
104 _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
105}
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120static int omap_device_build_from_dt(struct platform_device *pdev)
121{
122 struct omap_hwmod **hwmods;
123 struct omap_device *od;
124 struct omap_hwmod *oh;
125 struct device_node *node = pdev->dev.of_node;
126 const char *oh_name;
127 int oh_cnt, i, ret = 0;
128 bool device_active = false;
129
130 oh_cnt = of_property_count_strings(node, "ti,hwmods");
131 if (oh_cnt <= 0) {
132 dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
133 return -ENODEV;
134 }
135
136 hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
137 if (!hwmods) {
138 ret = -ENOMEM;
139 goto odbfd_exit;
140 }
141
142 for (i = 0; i < oh_cnt; i++) {
143 of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
144 oh = omap_hwmod_lookup(oh_name);
145 if (!oh) {
146 dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
147 oh_name);
148 ret = -EINVAL;
149 goto odbfd_exit1;
150 }
151 hwmods[i] = oh;
152 if (oh->flags & HWMOD_INIT_NO_IDLE)
153 device_active = true;
154 }
155
156 od = omap_device_alloc(pdev, hwmods, oh_cnt);
157 if (IS_ERR(od)) {
158 dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
159 oh_name);
160 ret = PTR_ERR(od);
161 goto odbfd_exit1;
162 }
163
164
165 for (i = 0; i < pdev->num_resources; i++) {
166 struct resource *r = &pdev->resource[i];
167
168 if (r->name == NULL)
169 r->name = dev_name(&pdev->dev);
170 }
171
172 dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
173
174 if (device_active) {
175 omap_device_enable(pdev);
176 pm_runtime_set_active(&pdev->dev);
177 }
178
179odbfd_exit1:
180 kfree(hwmods);
181odbfd_exit:
182
183 if (ret)
184 dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain);
185
186 return ret;
187}
188
189static int _omap_device_notifier_call(struct notifier_block *nb,
190 unsigned long event, void *dev)
191{
192 struct platform_device *pdev = to_platform_device(dev);
193 struct omap_device *od;
194 int err;
195
196 switch (event) {
197 case BUS_NOTIFY_DEL_DEVICE:
198 if (pdev->archdata.od)
199 omap_device_delete(pdev->archdata.od);
200 break;
201 case BUS_NOTIFY_UNBOUND_DRIVER:
202 od = to_omap_device(pdev);
203 if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) {
204 dev_info(dev, "enabled after unload, idling\n");
205 err = omap_device_idle(pdev);
206 if (err)
207 dev_err(dev, "failed to idle\n");
208 }
209 break;
210 case BUS_NOTIFY_ADD_DEVICE:
211 if (pdev->dev.of_node)
212 omap_device_build_from_dt(pdev);
213 omap_auxdata_legacy_init(dev);
214
215 default:
216 od = to_omap_device(pdev);
217 if (od)
218 od->_driver_status = event;
219 }
220
221 return NOTIFY_DONE;
222}
223
224
225
226
227
228
229
230static int _omap_device_enable_hwmods(struct omap_device *od)
231{
232 int ret = 0;
233 int i;
234
235 for (i = 0; i < od->hwmods_cnt; i++)
236 ret |= omap_hwmod_enable(od->hwmods[i]);
237
238 return ret;
239}
240
241
242
243
244
245
246
247static int _omap_device_idle_hwmods(struct omap_device *od)
248{
249 int ret = 0;
250 int i;
251
252 for (i = 0; i < od->hwmods_cnt; i++)
253 ret |= omap_hwmod_idle(od->hwmods[i]);
254
255 return ret;
256}
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275int omap_device_get_context_loss_count(struct platform_device *pdev)
276{
277 struct omap_device *od;
278 u32 ret = 0;
279
280 od = to_omap_device(pdev);
281
282 if (od->hwmods_cnt)
283 ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
284
285 return ret;
286}
287
288
289
290
291
292
293
294
295
296
297
298static int omap_device_count_resources(struct omap_device *od,
299 unsigned long flags)
300{
301 int c = 0;
302 int i;
303
304 for (i = 0; i < od->hwmods_cnt; i++)
305 c += omap_hwmod_count_resources(od->hwmods[i], flags);
306
307 pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
308 od->pdev->name, c, od->hwmods_cnt);
309
310 return c;
311}
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330static int omap_device_fill_resources(struct omap_device *od,
331 struct resource *res)
332{
333 int i, r;
334
335 for (i = 0; i < od->hwmods_cnt; i++) {
336 r = omap_hwmod_fill_resources(od->hwmods[i], res);
337 res += r;
338 }
339
340 return 0;
341}
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357static int _od_fill_dma_resources(struct omap_device *od,
358 struct resource *res)
359{
360 int i, r;
361
362 for (i = 0; i < od->hwmods_cnt; i++) {
363 r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
364 res += r;
365 }
366
367 return 0;
368}
369
370
371
372
373
374
375
376
377
378
379
380
381
382struct omap_device *omap_device_alloc(struct platform_device *pdev,
383 struct omap_hwmod **ohs, int oh_cnt)
384{
385 int ret = -ENOMEM;
386 struct omap_device *od;
387 struct resource *res = NULL;
388 int i, res_count;
389 struct omap_hwmod **hwmods;
390
391 od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
392 if (!od) {
393 ret = -ENOMEM;
394 goto oda_exit1;
395 }
396 od->hwmods_cnt = oh_cnt;
397
398 hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
399 if (!hwmods)
400 goto oda_exit2;
401
402 od->hwmods = hwmods;
403 od->pdev = pdev;
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424 if (!pdev->num_resources) {
425
426 res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
427 IORESOURCE_DMA |
428 IORESOURCE_MEM);
429 } else {
430
431 for (i = 0; i < pdev->num_resources; i++) {
432 struct resource *r = &pdev->resource[i];
433
434
435 if (r->flags == IORESOURCE_DMA)
436 goto have_everything;
437 }
438
439 res_count = omap_device_count_resources(od, IORESOURCE_DMA);
440
441 if (!res_count)
442 goto have_everything;
443
444 res_count += pdev->num_resources;
445 }
446
447
448 res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
449 if (!res)
450 goto oda_exit3;
451
452 if (!pdev->num_resources) {
453 dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
454 __func__, res_count);
455 omap_device_fill_resources(od, res);
456 } else {
457 dev_dbg(&pdev->dev,
458 "%s: appending %d DMA resources from hwmod\n",
459 __func__, res_count - pdev->num_resources);
460 memcpy(res, pdev->resource,
461 sizeof(struct resource) * pdev->num_resources);
462 _od_fill_dma_resources(od, &res[pdev->num_resources]);
463 }
464
465 ret = platform_device_add_resources(pdev, res, res_count);
466 kfree(res);
467
468 if (ret)
469 goto oda_exit3;
470
471have_everything:
472 pdev->archdata.od = od;
473
474 for (i = 0; i < oh_cnt; i++) {
475 hwmods[i]->od = od;
476 _add_hwmod_clocks_clkdev(od, hwmods[i]);
477 }
478
479 return od;
480
481oda_exit3:
482 kfree(hwmods);
483oda_exit2:
484 kfree(od);
485oda_exit1:
486 dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
487
488 return ERR_PTR(ret);
489}
490
491void omap_device_delete(struct omap_device *od)
492{
493 if (!od)
494 return;
495
496 od->pdev->archdata.od = NULL;
497 kfree(od->hwmods);
498 kfree(od);
499}
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515struct platform_device __init *omap_device_build(const char *pdev_name,
516 int pdev_id,
517 struct omap_hwmod *oh,
518 void *pdata, int pdata_len)
519{
520 struct omap_hwmod *ohs[] = { oh };
521
522 if (!oh)
523 return ERR_PTR(-EINVAL);
524
525 return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
526 pdata_len);
527}
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543struct platform_device __init *omap_device_build_ss(const char *pdev_name,
544 int pdev_id,
545 struct omap_hwmod **ohs,
546 int oh_cnt, void *pdata,
547 int pdata_len)
548{
549 int ret = -ENOMEM;
550 struct platform_device *pdev;
551 struct omap_device *od;
552
553 if (!ohs || oh_cnt == 0 || !pdev_name)
554 return ERR_PTR(-EINVAL);
555
556 if (!pdata && pdata_len > 0)
557 return ERR_PTR(-EINVAL);
558
559 pdev = platform_device_alloc(pdev_name, pdev_id);
560 if (!pdev) {
561 ret = -ENOMEM;
562 goto odbs_exit;
563 }
564
565
566 if (pdev->id != -1)
567 dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
568 else
569 dev_set_name(&pdev->dev, "%s", pdev->name);
570
571 od = omap_device_alloc(pdev, ohs, oh_cnt);
572 if (IS_ERR(od))
573 goto odbs_exit1;
574
575 ret = platform_device_add_data(pdev, pdata, pdata_len);
576 if (ret)
577 goto odbs_exit2;
578
579 ret = omap_device_register(pdev);
580 if (ret)
581 goto odbs_exit2;
582
583 return pdev;
584
585odbs_exit2:
586 omap_device_delete(od);
587odbs_exit1:
588 platform_device_put(pdev);
589odbs_exit:
590
591 pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
592
593 return ERR_PTR(ret);
594}
595
596#ifdef CONFIG_PM
597static int _od_runtime_suspend(struct device *dev)
598{
599 struct platform_device *pdev = to_platform_device(dev);
600 int ret;
601
602 ret = pm_generic_runtime_suspend(dev);
603 if (ret)
604 return ret;
605
606 return omap_device_idle(pdev);
607}
608
609static int _od_runtime_resume(struct device *dev)
610{
611 struct platform_device *pdev = to_platform_device(dev);
612 int ret;
613
614 ret = omap_device_enable(pdev);
615 if (ret) {
616 dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n");
617 return ret;
618 }
619
620 return pm_generic_runtime_resume(dev);
621}
622
623static int _od_fail_runtime_suspend(struct device *dev)
624{
625 dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
626 return -ENODEV;
627}
628
629static int _od_fail_runtime_resume(struct device *dev)
630{
631 dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
632 return -ENODEV;
633}
634
635#endif
636
637#ifdef CONFIG_SUSPEND
638static int _od_suspend_noirq(struct device *dev)
639{
640 struct platform_device *pdev = to_platform_device(dev);
641 struct omap_device *od = to_omap_device(pdev);
642 int ret;
643
644
645 if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
646 return 0;
647
648 ret = pm_generic_suspend_noirq(dev);
649
650 if (!ret && !pm_runtime_status_suspended(dev)) {
651 if (pm_generic_runtime_suspend(dev) == 0) {
652 pm_runtime_set_suspended(dev);
653 omap_device_idle(pdev);
654 od->flags |= OMAP_DEVICE_SUSPENDED;
655 }
656 }
657
658 return ret;
659}
660
661static int _od_resume_noirq(struct device *dev)
662{
663 struct platform_device *pdev = to_platform_device(dev);
664 struct omap_device *od = to_omap_device(pdev);
665
666 if (od->flags & OMAP_DEVICE_SUSPENDED) {
667 od->flags &= ~OMAP_DEVICE_SUSPENDED;
668 omap_device_enable(pdev);
669
670
671
672
673
674
675
676 WARN(pm_runtime_set_active(dev),
677 "Could not set %s runtime state active\n", dev_name(dev));
678 pm_generic_runtime_resume(dev);
679 }
680
681 return pm_generic_resume_noirq(dev);
682}
683#else
684#define _od_suspend_noirq NULL
685#define _od_resume_noirq NULL
686#endif
687
688struct dev_pm_domain omap_device_fail_pm_domain = {
689 .ops = {
690 SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
691 _od_fail_runtime_resume, NULL)
692 }
693};
694
695struct dev_pm_domain omap_device_pm_domain = {
696 .ops = {
697 SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
698 NULL)
699 USE_PLATFORM_PM_SLEEP_OPS
700 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq,
701 _od_resume_noirq)
702 }
703};
704
705
706
707
708
709
710
711
712
713int omap_device_register(struct platform_device *pdev)
714{
715 pr_debug("omap_device: %s: registering\n", pdev->name);
716
717 dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
718 return platform_device_add(pdev);
719}
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736int omap_device_enable(struct platform_device *pdev)
737{
738 int ret;
739 struct omap_device *od;
740
741 od = to_omap_device(pdev);
742
743 if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
744 dev_warn(&pdev->dev,
745 "omap_device: %s() called from invalid state %d\n",
746 __func__, od->_state);
747 return -EINVAL;
748 }
749
750 ret = _omap_device_enable_hwmods(od);
751
752 if (ret == 0)
753 od->_state = OMAP_DEVICE_STATE_ENABLED;
754
755 return ret;
756}
757
758
759
760
761
762
763
764
765
766
767int omap_device_idle(struct platform_device *pdev)
768{
769 int ret;
770 struct omap_device *od;
771
772 od = to_omap_device(pdev);
773
774 if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
775 dev_warn(&pdev->dev,
776 "omap_device: %s() called from invalid state %d\n",
777 __func__, od->_state);
778 return -EINVAL;
779 }
780
781 ret = _omap_device_idle_hwmods(od);
782
783 if (ret == 0)
784 od->_state = OMAP_DEVICE_STATE_IDLE;
785
786 return ret;
787}
788
789
790
791
792
793
794
795
796
797
798
799
800
801int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
802{
803 struct omap_device *od = to_omap_device(pdev);
804 int ret = 0;
805 int i;
806
807 for (i = 0; i < od->hwmods_cnt; i++) {
808 ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
809 if (ret)
810 break;
811 }
812
813 return ret;
814}
815
816
817
818
819
820
821
822
823
824
825
826
827
828int omap_device_deassert_hardreset(struct platform_device *pdev,
829 const char *name)
830{
831 struct omap_device *od = to_omap_device(pdev);
832 int ret = 0;
833 int i;
834
835 for (i = 0; i < od->hwmods_cnt; i++) {
836 ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
837 if (ret)
838 break;
839 }
840
841 return ret;
842}
843
844
845
846
847
848
849
850
851
852struct device *omap_device_get_by_hwmod_name(const char *oh_name)
853{
854 struct omap_hwmod *oh;
855
856 if (!oh_name) {
857 WARN(1, "%s: no hwmod name!\n", __func__);
858 return ERR_PTR(-EINVAL);
859 }
860
861 oh = omap_hwmod_lookup(oh_name);
862 if (!oh) {
863 WARN(1, "%s: no hwmod for %s\n", __func__,
864 oh_name);
865 return ERR_PTR(-ENODEV);
866 }
867 if (!oh->od) {
868 WARN(1, "%s: no omap_device for %s\n", __func__,
869 oh_name);
870 return ERR_PTR(-ENODEV);
871 }
872
873 return &oh->od->pdev->dev;
874}
875
876static struct notifier_block platform_nb = {
877 .notifier_call = _omap_device_notifier_call,
878};
879
880static int __init omap_device_init(void)
881{
882 bus_register_notifier(&platform_bus_type, &platform_nb);
883 return 0;
884}
885omap_postcore_initcall(omap_device_init);
886
887
888
889
890
891
892
893
894
895static int __init omap_device_late_idle(struct device *dev, void *data)
896{
897 struct platform_device *pdev = to_platform_device(dev);
898 struct omap_device *od = to_omap_device(pdev);
899 int i;
900
901 if (!od)
902 return 0;
903
904
905
906
907
908
909
910
911
912
913 for (i = 0; i < od->hwmods_cnt; i++)
914 if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE)
915 return 0;
916
917 if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER &&
918 od->_driver_status != BUS_NOTIFY_BIND_DRIVER) {
919 if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
920 dev_warn(dev, "%s: enabled but no driver. Idling\n",
921 __func__);
922 omap_device_idle(pdev);
923 }
924 }
925
926 return 0;
927}
928
929static int __init omap_device_late_init(void)
930{
931 bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
932
933 WARN(!of_have_populated_dt(),
934 "legacy booting deprecated, please update to boot with .dts\n");
935
936 return 0;
937}
938omap_late_initcall_sync(omap_device_late_init);
939