summaryrefslogtreecommitdiff
path: root/drivers/usb/core/message.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2017-11-09 18:07:21 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-11-28 15:12:38 +0100
commit1a7e3948cb9f5bb9241112706267b8fbc7812c7a (patch)
tree71cf2ea665a76fdd6c9e87dbf5c6581be21e952e /drivers/usb/core/message.c
parente96bd3970894758087f934860aa1c7c076a1e76c (diff)
USB: add device-tree support for interfaces
Add OF device-tree support for USB interfaces. USB "interface nodes" are children of USB "device nodes" and are identified by an interface number and a configuration value: &usb1 { /* host controller */ dev1: device@1 { /* device at port 1 */ compatible = "usb1234,5678"; reg = <1>; #address-cells = <2>; #size-cells = <0>; interface@0,2 { /* interface 0 of configuration 2 */ compatible = "usbif1234,5678.config2.0"; reg = <0 2>; }; }; }; The configuration component is not included in the textual representation of an interface-node unit address for configuration 1: &dev1 { interface@0 { /* interface 0 of configuration 1 */ compatible = "usbif1234,5678.config1.0"; reg = <0 1>; }; }; When a USB device of class 0 or 9 (hub) has only a single configuration with a single interface, a special case "combined node" is used instead of a device node with an interface node: &usb1 { device@2 { compatible = "usb1234,abcd"; reg = <2>; }; }; Combined nodes are shared by the two device structures representing the USB device and its interface in the kernel's device model. Note that, as for device nodes, the compatible strings for interface nodes are currently not used. For more details see "Open Firmware Recommended Practice: Universal Serial Bus Version 1" and the binding documentation. Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r--drivers/usb/core/message.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 5a8ab77bc367..f836bae1e485 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -18,6 +18,7 @@
#include <linux/usb/cdc.h>
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h> /* for usbcore internals */
+#include <linux/usb/of.h>
#include <asm/byteorder.h>
#include "usb.h"
@@ -1583,6 +1584,7 @@ static void usb_release_interface(struct device *dev)
kref_put(&intfc->ref, usb_release_interface_cache);
usb_put_dev(interface_to_usbdev(intf));
+ of_node_put(dev->of_node);
kfree(intf);
}
@@ -1868,6 +1870,7 @@ free_interfaces:
struct usb_interface_cache *intfc;
struct usb_interface *intf;
struct usb_host_interface *alt;
+ u8 ifnum;
cp->interface[i] = intf = new_interfaces[i];
intfc = cp->intf_cache[i];
@@ -1886,11 +1889,17 @@ free_interfaces:
if (!alt)
alt = &intf->altsetting[0];
- intf->intf_assoc =
- find_iad(dev, cp, alt->desc.bInterfaceNumber);
+ ifnum = alt->desc.bInterfaceNumber;
+ intf->intf_assoc = find_iad(dev, cp, ifnum);
intf->cur_altsetting = alt;
usb_enable_interface(dev, intf, true);
intf->dev.parent = &dev->dev;
+ if (usb_of_has_combined_node(dev)) {
+ device_set_of_node_from_dev(&intf->dev, &dev->dev);
+ } else {
+ intf->dev.of_node = usb_of_get_interface_node(dev,
+ configuration, ifnum);
+ }
intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
@@ -1905,9 +1914,8 @@ free_interfaces:
intf->minor = -1;
device_initialize(&intf->dev);
pm_runtime_no_callbacks(&intf->dev);
- dev_set_name(&intf->dev, "%d-%s:%d.%d",
- dev->bus->busnum, dev->devpath,
- configuration, alt->desc.bInterfaceNumber);
+ dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum,
+ dev->devpath, configuration, ifnum);
usb_get_dev(dev);
}
kfree(new_interfaces);