aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_device.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2017-10-10 17:23:35 -0400
committerTony Lindgren <tony@atomide.com>2017-10-10 17:23:35 -0400
commitd85a2d61432aed6a4c2e5f90109a37562f9a8092 (patch)
treeff5e96ee1dc5d26438c0eeb24035fe045d1f9911 /arch/arm/mach-omap2/omap_device.c
parent6c72b35506728b2669835cfa8c245ac3f1c15659 (diff)
ARM: OMAP2+: Populate legacy resources for dma and smartreflex
We can populate the legacy resources needed by dma and smartreflex from device tree in omap_device_build(). There should be no need to do this for other devices, and eventually these two remaining users will be gone too. The legacy dma will be dropped when the remaining users have been converted to use the dmaengine driver, and smartreflex can now become just a regular device driver with a few pdata callbacks. This is needed in order to remove remaining device dma, irq and io resources from the interconnect code. And while at it, let's simplify things by removing otherwise unused omap_device_build_ss() as we will never call it for more than one hwmod. Cc: "BenoƮt Cousson" <bcousson@baylibre.com> Cc: Lokesh Vutla <lokeshvutla@ti.com> Cc: Nishanth Menon <nm@ti.com> Cc: Paul Walmsley <paul@pwsan.com> Cc: Tero Kristo <t-kristo@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_device.c')
-rw-r--r--arch/arm/mach-omap2/omap_device.c137
1 files changed, 106 insertions, 31 deletions
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index acbede082b5b..50f81b2d22b7 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -35,6 +35,8 @@
35#include <linux/pm_domain.h> 35#include <linux/pm_domain.h>
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37#include <linux/of.h> 37#include <linux/of.h>
38#include <linux/of_address.h>
39#include <linux/of_irq.h>
38#include <linux/notifier.h> 40#include <linux/notifier.h>
39 41
40#include "common.h" 42#include "common.h"
@@ -522,6 +524,91 @@ void omap_device_delete(struct omap_device *od)
522} 524}
523 525
524/** 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 */
537static int
538omap_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
600free:
601 kfree(res);
602
603error:
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
611/**
525 * omap_device_build - build and register an omap_device with one omap_hwmod 612 * omap_device_build - build and register an omap_device with one omap_hwmod
526 * @pdev_name: name of the platform_device driver to use 613 * @pdev_name: name of the platform_device driver to use
527 * @pdev_id: this platform_device's connection ID 614 * @pdev_id: this platform_device's connection ID
@@ -540,45 +627,24 @@ struct platform_device __init *omap_device_build(const char *pdev_name,
540 struct omap_hwmod *oh, 627 struct omap_hwmod *oh,
541 void *pdata, int pdata_len) 628 void *pdata, int pdata_len)
542{ 629{
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 */
566struct 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{
572 int ret = -ENOMEM; 630 int ret = -ENOMEM;
573 struct platform_device *pdev; 631 struct platform_device *pdev;
574 struct omap_device *od; 632 struct omap_device *od;
575 633
576 if (!ohs || oh_cnt == 0 || !pdev_name) 634 if (!oh || !pdev_name)
577 return ERR_PTR(-EINVAL); 635 return ERR_PTR(-EINVAL);
578 636
579 if (!pdata && pdata_len > 0) 637 if (!pdata && pdata_len > 0)
580 return ERR_PTR(-EINVAL); 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 pdev = platform_device_alloc(pdev_name, pdev_id); 648 pdev = platform_device_alloc(pdev_name, pdev_id);
583 if (!pdev) { 649 if (!pdev) {
584 ret = -ENOMEM; 650 ret = -ENOMEM;
@@ -591,7 +657,16 @@ struct platform_device __init *omap_device_build_ss(const char *pdev_name,
591 else 657 else
592 dev_set_name(&pdev->dev, "%s", pdev->name); 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 if (IS_ERR(od)) 670 if (IS_ERR(od))
596 goto odbs_exit1; 671 goto odbs_exit1;
597 672