diff options
Diffstat (limited to 'drivers/bus/omap-ocp2scp.c')
-rw-r--r-- | drivers/bus/omap-ocp2scp.c | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c index ff63560b8467..0c48b0e05ed6 100644 --- a/drivers/bus/omap-ocp2scp.c +++ b/drivers/bus/omap-ocp2scp.c | |||
@@ -22,6 +22,26 @@ | |||
22 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/of_platform.h> | 24 | #include <linux/of_platform.h> |
25 | #include <linux/platform_data/omap_ocp2scp.h> | ||
26 | |||
27 | /** | ||
28 | * _count_resources - count for the number of resources | ||
29 | * @res: struct resource * | ||
30 | * | ||
31 | * Count and return the number of resources populated for the device that is | ||
32 | * connected to ocp2scp. | ||
33 | */ | ||
34 | static unsigned _count_resources(struct resource *res) | ||
35 | { | ||
36 | int cnt = 0; | ||
37 | |||
38 | while (res->start != res->end) { | ||
39 | cnt++; | ||
40 | res++; | ||
41 | } | ||
42 | |||
43 | return cnt; | ||
44 | } | ||
25 | 45 | ||
26 | static int ocp2scp_remove_devices(struct device *dev, void *c) | 46 | static int ocp2scp_remove_devices(struct device *dev, void *c) |
27 | { | 47 | { |
@@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c) | |||
34 | 54 | ||
35 | static int __devinit omap_ocp2scp_probe(struct platform_device *pdev) | 55 | static int __devinit omap_ocp2scp_probe(struct platform_device *pdev) |
36 | { | 56 | { |
37 | int ret; | 57 | int ret; |
38 | struct device_node *np = pdev->dev.of_node; | 58 | unsigned res_cnt, i; |
59 | struct device_node *np = pdev->dev.of_node; | ||
60 | struct platform_device *pdev_child; | ||
61 | struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data; | ||
62 | struct omap_ocp2scp_dev *dev; | ||
39 | 63 | ||
40 | if (np) { | 64 | if (np) { |
41 | ret = of_platform_populate(np, NULL, NULL, &pdev->dev); | 65 | ret = of_platform_populate(np, NULL, NULL, &pdev->dev); |
42 | if (ret) { | 66 | if (ret) { |
43 | dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n"); | 67 | dev_err(&pdev->dev, |
68 | "failed to add resources for ocp2scp child\n"); | ||
44 | goto err0; | 69 | goto err0; |
45 | } | 70 | } |
71 | } else if (pdata) { | ||
72 | for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++, | ||
73 | dev++) { | ||
74 | res_cnt = _count_resources(dev->res); | ||
75 | |||
76 | pdev_child = platform_device_alloc(dev->drv_name, | ||
77 | PLATFORM_DEVID_AUTO); | ||
78 | if (!pdev_child) { | ||
79 | dev_err(&pdev->dev, | ||
80 | "failed to allocate mem for ocp2scp child\n"); | ||
81 | goto err0; | ||
82 | } | ||
83 | |||
84 | ret = platform_device_add_resources(pdev_child, | ||
85 | dev->res, res_cnt); | ||
86 | if (ret) { | ||
87 | dev_err(&pdev->dev, | ||
88 | "failed to add resources for ocp2scp child\n"); | ||
89 | goto err1; | ||
90 | } | ||
91 | |||
92 | pdev_child->dev.parent = &pdev->dev; | ||
93 | |||
94 | ret = platform_device_add(pdev_child); | ||
95 | if (ret) { | ||
96 | dev_err(&pdev->dev, | ||
97 | "failed to register ocp2scp child device\n"); | ||
98 | goto err1; | ||
99 | } | ||
100 | } | ||
101 | } else { | ||
102 | dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n"); | ||
103 | return -EINVAL; | ||
46 | } | 104 | } |
105 | |||
47 | pm_runtime_enable(&pdev->dev); | 106 | pm_runtime_enable(&pdev->dev); |
48 | 107 | ||
49 | return 0; | 108 | return 0; |
50 | 109 | ||
110 | err1: | ||
111 | platform_device_put(pdev_child); | ||
112 | |||
51 | err0: | 113 | err0: |
52 | device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices); | 114 | device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices); |
53 | 115 | ||