1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * of.c The helpers for hcd device tree support 4 * 5 * Copyright (C) 2016 Freescale Semiconductor, Inc. 6 * Author: Peter Chen <peter.chen@freescale.com> 7 * Copyright (C) 2017 Johan Hovold <johan@kernel.org> 8 */ 9 10 #include <linux/of.h> 11 #include <linux/of_platform.h> 12 #include <linux/usb/of.h> 13 14 /** 15 * usb_of_get_device_node() - get a USB device node 16 * @hub: hub to which device is connected 17 * @port1: one-based index of port 18 * 19 * Look up the node of a USB device given its parent hub device and one-based 20 * port number. 21 * 22 * Return: A pointer to the node with incremented refcount if found, or 23 * %NULL otherwise. 24 */ 25 struct device_node *usb_of_get_device_node(struct usb_device *hub, int port1) 26 { 27 struct device_node *node; 28 u32 reg; 29 30 for_each_child_of_node(hub->dev.of_node, node) { 31 if (of_property_read_u32(node, "reg", ®)) 32 continue; 33 34 if (reg == port1) 35 return node; 36 } 37 38 return NULL; 39 } 40 EXPORT_SYMBOL_GPL(usb_of_get_device_node); 41 42 /** 43 * usb_of_has_combined_node() - determine whether a device has a combined node 44 * @udev: USB device 45 * 46 * Determine whether a USB device has a so called combined node which is 47 * shared with its sole interface. This is the case if and only if the device 48 * has a node and its decriptors report the following: 49 * 50 * 1) bDeviceClass is 0 or 9, and 51 * 2) bNumConfigurations is 1, and 52 * 3) bNumInterfaces is 1. 53 * 54 * Return: True iff the device has a device node and its descriptors match the 55 * criteria for a combined node. 56 */ 57 bool usb_of_has_combined_node(struct usb_device *udev) 58 { 59 struct usb_device_descriptor *ddesc = &udev->descriptor; 60 struct usb_config_descriptor *cdesc; 61 62 if (!udev->dev.of_node) 63 return false; 64 65 switch (ddesc->bDeviceClass) { 66 case USB_CLASS_PER_INTERFACE: 67 case USB_CLASS_HUB: 68 if (ddesc->bNumConfigurations == 1) { 69 cdesc = &udev->config->desc; 70 if (cdesc->bNumInterfaces == 1) 71 return true; 72 } 73 } 74 75 return false; 76 } 77 EXPORT_SYMBOL_GPL(usb_of_has_combined_node); 78 79 /** 80 * usb_of_get_interface_node() - get a USB interface node 81 * @udev: USB device of interface 82 * @config: configuration value 83 * @ifnum: interface number 84 * 85 * Look up the node of a USB interface given its USB device, configuration 86 * value and interface number. 87 * 88 * Return: A pointer to the node with incremented refcount if found, or 89 * %NULL otherwise. 90 */ 91 struct device_node * 92 usb_of_get_interface_node(struct usb_device *udev, u8 config, u8 ifnum) 93 { 94 struct device_node *node; 95 u32 reg[2]; 96 97 for_each_child_of_node(udev->dev.of_node, node) { 98 if (of_property_read_u32_array(node, "reg", reg, 2)) 99 continue; 100 101 if (reg[0] == ifnum && reg[1] == config) 102 return node; 103 } 104 105 return NULL; 106 } 107 EXPORT_SYMBOL_GPL(usb_of_get_interface_node); 108 109 /** 110 * usb_of_get_companion_dev - Find the companion device 111 * @dev: the device pointer to find a companion 112 * 113 * Find the companion device from platform bus. 114 * 115 * Takes a reference to the returned struct device which needs to be dropped 116 * after use. 117 * 118 * Return: On success, a pointer to the companion device, %NULL on failure. 119 */ 120 struct device *usb_of_get_companion_dev(struct device *dev) 121 { 122 struct device_node *node; 123 struct platform_device *pdev = NULL; 124 125 node = of_parse_phandle(dev->of_node, "companion", 0); 126 if (node) 127 pdev = of_find_device_by_node(node); 128 129 of_node_put(node); 130 131 return pdev ? &pdev->dev : NULL; 132 } 133 EXPORT_SYMBOL_GPL(usb_of_get_companion_dev); 134