35
35
#include <linux/pm_domain.h>
36
36
#include <linux/pm_runtime.h>
37
37
#include <linux/of.h>
38
+ #include <linux/of_address.h>
39
+ #include <linux/of_irq.h>
38
40
#include <linux/notifier.h>
39
41
40
42
#include "common.h"
@@ -521,6 +523,91 @@ void omap_device_delete(struct omap_device *od)
521
523
kfree (od );
522
524
}
523
525
526
+ /**
527
+ * omap_device_copy_resources - Add legacy IO and IRQ resources
528
+ * @oh: interconnect target module
529
+ * @pdev: platform device to copy resources to
530
+ *
531
+ * We still have legacy DMA and smartreflex needing resources.
532
+ * Let's populate what they need until we can eventually just
533
+ * remove this function. Note that there should be no need to
534
+ * call this from omap_device_build_from_dt(), nor should there
535
+ * be any need to call it for other devices.
536
+ */
537
+ static int
538
+ omap_device_copy_resources (struct omap_hwmod * oh ,
539
+ struct platform_device * pdev )
540
+ {
541
+ struct device_node * np , * child ;
542
+ struct property * prop ;
543
+ struct resource * res ;
544
+ const char * name ;
545
+ int error , irq = 0 ;
546
+
547
+ if (!oh || !oh -> od || !oh -> od -> pdev ) {
548
+ error = - EINVAL ;
549
+ goto error ;
550
+ }
551
+
552
+ np = oh -> od -> pdev -> dev .of_node ;
553
+ if (!np ) {
554
+ error = - ENODEV ;
555
+ goto error ;
556
+ }
557
+
558
+ res = kzalloc (sizeof (* res ) * 2 , GFP_KERNEL );
559
+ if (!res )
560
+ return - ENOMEM ;
561
+
562
+ /* Do we have a dts range for the interconnect target module? */
563
+ error = omap_hwmod_parse_module_range (oh , np , res );
564
+
565
+ /* No ranges, rely on device reg entry */
566
+ if (error )
567
+ error = of_address_to_resource (np , 0 , res );
568
+ if (error )
569
+ goto free ;
570
+
571
+ /* SmartReflex needs first IO resource name to be "mpu" */
572
+ res [0 ].name = "mpu" ;
573
+
574
+ /*
575
+ * We may have a configured "ti,sysc" interconnect target with a
576
+ * dts child with the interrupt. If so use the first child's
577
+ * first interrupt for "ti-hwmods" legacy support.
578
+ */
579
+ of_property_for_each_string (np , "compatible" , prop , name )
580
+ if (!strncmp ("ti,sysc-" , name , 8 ))
581
+ break ;
582
+
583
+ child = of_get_next_available_child (np , NULL );
584
+
585
+ if (name )
586
+ irq = irq_of_parse_and_map (child , 0 );
587
+ if (!irq )
588
+ irq = irq_of_parse_and_map (np , 0 );
589
+ if (!irq )
590
+ goto free ;
591
+
592
+ /* Legacy DMA code needs interrupt name to be "0" */
593
+ res [1 ].start = irq ;
594
+ res [1 ].end = irq ;
595
+ res [1 ].flags = IORESOURCE_IRQ ;
596
+ res [1 ].name = "0" ;
597
+
598
+ error = platform_device_add_resources (pdev , res , 2 );
599
+
600
+ free :
601
+ kfree (res );
602
+
603
+ error :
604
+ WARN (error , "%s: %s device %s failed: %i\n" ,
605
+ __func__ , oh -> name , dev_name (& pdev -> dev ),
606
+ error );
607
+
608
+ return error ;
609
+ }
610
+
524
611
/**
525
612
* omap_device_build - build and register an omap_device with one omap_hwmod
526
613
* @pdev_name: name of the platform_device driver to use
@@ -539,46 +626,25 @@ struct platform_device __init *omap_device_build(const char *pdev_name,
539
626
int pdev_id ,
540
627
struct omap_hwmod * oh ,
541
628
void * pdata , int pdata_len )
542
- {
543
- struct omap_hwmod * ohs [] = { oh };
544
-
545
- if (!oh )
546
- return ERR_PTR (- EINVAL );
547
-
548
- return omap_device_build_ss (pdev_name , pdev_id , ohs , 1 , pdata ,
549
- pdata_len );
550
- }
551
-
552
- /**
553
- * omap_device_build_ss - build and register an omap_device with multiple hwmods
554
- * @pdev_name: name of the platform_device driver to use
555
- * @pdev_id: this platform_device's connection ID
556
- * @oh: ptr to the single omap_hwmod that backs this omap_device
557
- * @pdata: platform_data ptr to associate with the platform_device
558
- * @pdata_len: amount of memory pointed to by @pdata
559
- *
560
- * Convenience function for building and registering an omap_device
561
- * subsystem record. Subsystem records consist of multiple
562
- * omap_hwmods. This function in turn builds and registers a
563
- * platform_device record. Returns an ERR_PTR() on error, or passes
564
- * along the return value of omap_device_register().
565
- */
566
- struct platform_device __init * omap_device_build_ss (const char * pdev_name ,
567
- int pdev_id ,
568
- struct omap_hwmod * * ohs ,
569
- int oh_cnt , void * pdata ,
570
- int pdata_len )
571
629
{
572
630
int ret = - ENOMEM ;
573
631
struct platform_device * pdev ;
574
632
struct omap_device * od ;
575
633
576
- if (!ohs || oh_cnt == 0 || !pdev_name )
634
+ if (!oh || !pdev_name )
577
635
return ERR_PTR (- EINVAL );
578
636
579
637
if (!pdata && pdata_len > 0 )
580
638
return ERR_PTR (- EINVAL );
581
639
640
+ if (strncmp (oh -> name , "smartreflex" , 11 ) &&
641
+ strncmp (oh -> name , "dma" , 3 )) {
642
+ pr_warn ("%s need to update %s to probe with dt\na" ,
643
+ __func__ , pdev_name );
644
+ ret = - ENODEV ;
645
+ goto odbs_exit ;
646
+ }
647
+
582
648
pdev = platform_device_alloc (pdev_name , pdev_id );
583
649
if (!pdev ) {
584
650
ret = - ENOMEM ;
@@ -591,7 +657,16 @@ struct platform_device __init *omap_device_build_ss(const char *pdev_name,
591
657
else
592
658
dev_set_name (& pdev -> dev , "%s" , pdev -> name );
593
659
594
- od = omap_device_alloc (pdev , ohs , oh_cnt );
660
+ /*
661
+ * Must be called before omap_device_alloc() as oh->od
662
+ * only contains the currently registered omap_device
663
+ * and will get overwritten by omap_device_alloc().
664
+ */
665
+ ret = omap_device_copy_resources (oh , pdev );
666
+ if (ret )
667
+ goto odbs_exit1 ;
668
+
669
+ od = omap_device_alloc (pdev , & oh , 1 );
595
670
if (IS_ERR (od ))
596
671
goto odbs_exit1 ;
597
672
0 commit comments