0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/export.h>
0010 #include <linux/kernel.h>
0011 #include <linux/list.h>
0012 #include <linux/of.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/usb.h>
0016 #include <linux/usb/hcd.h>
0017 #include <linux/usb/of.h>
0018 #include <linux/usb/onboard_hub.h>
0019
0020 #include "onboard_usb_hub.h"
0021
0022 struct pdev_list_entry {
0023 struct platform_device *pdev;
0024 struct list_head node;
0025 };
0026
0027 static bool of_is_onboard_usb_hub(const struct device_node *np)
0028 {
0029 return !!of_match_node(onboard_hub_match, np);
0030 }
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 void onboard_hub_create_pdevs(struct usb_device *parent_hub, struct list_head *pdev_list)
0067 {
0068 int i;
0069 struct usb_hcd *hcd = bus_to_hcd(parent_hub->bus);
0070 struct device_node *np, *npc;
0071 struct platform_device *pdev;
0072 struct pdev_list_entry *pdle;
0073
0074 if (!parent_hub->dev.of_node)
0075 return;
0076
0077 if (!parent_hub->parent && !usb_hcd_is_primary_hcd(hcd))
0078 return;
0079
0080 for (i = 1; i <= parent_hub->maxchild; i++) {
0081 np = usb_of_get_device_node(parent_hub, i);
0082 if (!np)
0083 continue;
0084
0085 if (!of_is_onboard_usb_hub(np))
0086 goto node_put;
0087
0088 npc = of_parse_phandle(np, "peer-hub", 0);
0089 if (npc) {
0090 if (!usb_hcd_is_primary_hcd(hcd)) {
0091 of_node_put(npc);
0092 goto node_put;
0093 }
0094
0095 pdev = of_find_device_by_node(npc);
0096 of_node_put(npc);
0097
0098 if (pdev) {
0099 put_device(&pdev->dev);
0100 goto node_put;
0101 }
0102 }
0103
0104 pdev = of_platform_device_create(np, NULL, &parent_hub->dev);
0105 if (!pdev) {
0106 dev_err(&parent_hub->dev,
0107 "failed to create platform device for onboard hub '%pOF'\n", np);
0108 goto node_put;
0109 }
0110
0111 pdle = kzalloc(sizeof(*pdle), GFP_KERNEL);
0112 if (!pdle) {
0113 of_platform_device_destroy(&pdev->dev, NULL);
0114 goto node_put;
0115 }
0116
0117 pdle->pdev = pdev;
0118 list_add(&pdle->node, pdev_list);
0119
0120 node_put:
0121 of_node_put(np);
0122 }
0123 }
0124 EXPORT_SYMBOL_GPL(onboard_hub_create_pdevs);
0125
0126
0127
0128
0129
0130
0131
0132
0133 void onboard_hub_destroy_pdevs(struct list_head *pdev_list)
0134 {
0135 struct pdev_list_entry *pdle, *tmp;
0136
0137 list_for_each_entry_safe(pdle, tmp, pdev_list, node) {
0138 list_del(&pdle->node);
0139 of_platform_device_destroy(&pdle->pdev->dev, NULL);
0140 kfree(pdle);
0141 }
0142 }
0143 EXPORT_SYMBOL_GPL(onboard_hub_destroy_pdevs);