Message ID | 1539869054-13395-2-git-send-email-paolo.pisati@canonical.com |
---|---|
State | New |
Headers | show |
Series | USB: core: let USB device know device node | expand |
On 18/10/2018 14:24, Paolo Pisati wrote: > From: Peter Chen <peter.chen@freescale.com> > > BugLink: http://bugs.launchpad.net/bugs/1798578 > > Although most of USB devices are hot-plug's, there are still some devices > are hard wired on the board, eg, for HSIC and SSIC interface USB devices. > If these kinds of USB devices are multiple functions, and they can supply > other interfaces like i2c, gpios for other devices, we may need to > describe these at device tree. > > In this commit, it uses "reg" in dts as physical port number to match > the phyiscal port number decided by USB core, if they are the same, > then the device node is for the device we are creating for USB core. > > Signed-off-by: Peter Chen <peter.chen@freescale.com> > Acked-by: Philipp Zabel <p.zabel@pengutronix.de> > Acked-by: Alan Stern <stern@rowland.harvard.edu> > Acked-by: Rob Herring <robh@kernel.org> > Acked-by: Arnd Bergmann <arnd@arndb.de> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > (cherry picked from commit 69bec725985324e79b1c47ea287815ac4ddb0521) > Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com> > --- > .../devicetree/bindings/usb/usb-device.txt | 28 +++++++++++++ > drivers/usb/core/Makefile | 2 +- > drivers/usb/core/of.c | 47 ++++++++++++++++++++++ > drivers/usb/core/usb.c | 10 +++++ > include/linux/usb/of.h | 7 ++++ > 5 files changed, 93 insertions(+), 1 deletion(-) > create mode 100644 Documentation/devicetree/bindings/usb/usb-device.txt > create mode 100644 drivers/usb/core/of.c > > diff --git a/Documentation/devicetree/bindings/usb/usb-device.txt b/Documentation/devicetree/bindings/usb/usb-device.txt > new file mode 100644 > index 0000000..1c35e7b > --- /dev/null > +++ b/Documentation/devicetree/bindings/usb/usb-device.txt > @@ -0,0 +1,28 @@ > +Generic USB Device Properties > + > +Usually, we only use device tree for hard wired USB device. > +The reference binding doc is from: > +http://www.firmware.org/1275/bindings/usb/usb-1_0.ps > + > +Required properties: > +- compatible: usbVID,PID. The textual representation of VID, PID shall > + be in lower case hexadecimal with leading zeroes suppressed. The > + other compatible strings from the above standard binding could also > + be used, but a device adhering to this binding may leave out all except > + for usbVID,PID. > +- reg: the port number which this device is connecting to, the range > + is 1-31. > + > +Example: > + > +&usb1 { > + status = "okay"; > + > + #address-cells = <1>; > + #size-cells = <0>; > + > + hub: genesys@1 { > + compatible = "usb5e3,608"; > + reg = <1>; > + }; > +} > diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile > index 2f6f932..9780877 100644 > --- a/drivers/usb/core/Makefile > +++ b/drivers/usb/core/Makefile > @@ -5,7 +5,7 @@ > usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o > usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o > usbcore-y += devio.o notify.o generic.o quirks.o devices.o > -usbcore-y += port.o > +usbcore-y += port.o of.o > > usbcore-$(CONFIG_PCI) += hcd-pci.o > usbcore-$(CONFIG_ACPI) += usb-acpi.o > diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c > new file mode 100644 > index 0000000..2289700 > --- /dev/null > +++ b/drivers/usb/core/of.c > @@ -0,0 +1,47 @@ > +/* > + * of.c The helpers for hcd device tree support > + * > + * Copyright (C) 2016 Freescale Semiconductor, Inc. > + * Author: Peter Chen <peter.chen@freescale.com> > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 of > + * the License as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <linux/of.h> > + > +/** > + * usb_of_get_child_node - Find the device node match port number > + * @parent: the parent device node > + * @portnum: the port number which device is connecting > + * > + * Find the node from device tree according to its port number. > + * > + * Return: On success, a pointer to the device node, %NULL on failure. > + */ > +struct device_node *usb_of_get_child_node(struct device_node *parent, > + int portnum) > +{ > + struct device_node *node; > + u32 port; > + > + for_each_child_of_node(parent, node) { > + if (!of_property_read_u32(node, "reg", &port)) { > + if (port == portnum) > + return node; > + } > + } > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL(usb_of_get_child_node); > + > diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c > index f8bbd0b..3fdb2f8 100644 > --- a/drivers/usb/core/usb.c > +++ b/drivers/usb/core/usb.c > @@ -36,6 +36,7 @@ > #include <linux/mutex.h> > #include <linux/workqueue.h> > #include <linux/debugfs.h> > +#include <linux/usb/of.h> > > #include <asm/io.h> > #include <linux/scatterlist.h> > @@ -469,6 +470,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, > dev->route = 0; > > dev->dev.parent = bus->controller; > + dev->dev.of_node = bus->controller->of_node; > dev_set_name(&dev->dev, "usb%d", bus->busnum); > root_hub = 1; > } else { > @@ -493,6 +495,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, > dev->dev.parent = &parent->dev; > dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); > > + if (!parent->parent) { > + /* device under root hub's port */ > + port1 = usb_hcd_find_raw_port_number(usb_hcd, > + port1); > + } > + dev->dev.of_node = usb_of_get_child_node(parent->dev.of_node, > + port1); > + > /* hub driver sets up TT records */ > } > > diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h > index c3fe9e4..bc7644b 100644 > --- a/include/linux/usb/of.h > +++ b/include/linux/usb/of.h > @@ -15,6 +15,8 @@ > bool of_usb_host_tpl_support(struct device_node *np); > int of_usb_update_otg_caps(struct device_node *np, > struct usb_otg_caps *otg_caps); > +struct device_node *usb_of_get_child_node(struct device_node *parent, > + int portnum); > #else > static inline bool of_usb_host_tpl_support(struct device_node *np) > { > @@ -25,6 +27,11 @@ static inline int of_usb_update_otg_caps(struct device_node *np, > { > return 0; > } > +static inline struct device_node *usb_of_get_child_node > + (struct device_node *parent, int portnum) > +{ > + return NULL; > +} > #endif > > #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT) > Clean cherry pick, fixes the issue, limited regression potential and has been tested, so.. Acked-by: Colin Ian King <colin.king@canonical.com>
diff --git a/Documentation/devicetree/bindings/usb/usb-device.txt b/Documentation/devicetree/bindings/usb/usb-device.txt new file mode 100644 index 0000000..1c35e7b --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usb-device.txt @@ -0,0 +1,28 @@ +Generic USB Device Properties + +Usually, we only use device tree for hard wired USB device. +The reference binding doc is from: +http://www.firmware.org/1275/bindings/usb/usb-1_0.ps + +Required properties: +- compatible: usbVID,PID. The textual representation of VID, PID shall + be in lower case hexadecimal with leading zeroes suppressed. The + other compatible strings from the above standard binding could also + be used, but a device adhering to this binding may leave out all except + for usbVID,PID. +- reg: the port number which this device is connecting to, the range + is 1-31. + +Example: + +&usb1 { + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + hub: genesys@1 { + compatible = "usb5e3,608"; + reg = <1>; + }; +} diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 2f6f932..9780877 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -5,7 +5,7 @@ usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o usbcore-y += devio.o notify.o generic.o quirks.o devices.o -usbcore-y += port.o +usbcore-y += port.o of.o usbcore-$(CONFIG_PCI) += hcd-pci.o usbcore-$(CONFIG_ACPI) += usb-acpi.o diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c new file mode 100644 index 0000000..2289700 --- /dev/null +++ b/drivers/usb/core/of.c @@ -0,0 +1,47 @@ +/* + * of.c The helpers for hcd device tree support + * + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Author: Peter Chen <peter.chen@freescale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/of.h> + +/** + * usb_of_get_child_node - Find the device node match port number + * @parent: the parent device node + * @portnum: the port number which device is connecting + * + * Find the node from device tree according to its port number. + * + * Return: On success, a pointer to the device node, %NULL on failure. + */ +struct device_node *usb_of_get_child_node(struct device_node *parent, + int portnum) +{ + struct device_node *node; + u32 port; + + for_each_child_of_node(parent, node) { + if (!of_property_read_u32(node, "reg", &port)) { + if (port == portnum) + return node; + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(usb_of_get_child_node); + diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index f8bbd0b..3fdb2f8 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -36,6 +36,7 @@ #include <linux/mutex.h> #include <linux/workqueue.h> #include <linux/debugfs.h> +#include <linux/usb/of.h> #include <asm/io.h> #include <linux/scatterlist.h> @@ -469,6 +470,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev->route = 0; dev->dev.parent = bus->controller; + dev->dev.of_node = bus->controller->of_node; dev_set_name(&dev->dev, "usb%d", bus->busnum); root_hub = 1; } else { @@ -493,6 +495,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev->dev.parent = &parent->dev; dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); + if (!parent->parent) { + /* device under root hub's port */ + port1 = usb_hcd_find_raw_port_number(usb_hcd, + port1); + } + dev->dev.of_node = usb_of_get_child_node(parent->dev.of_node, + port1); + /* hub driver sets up TT records */ } diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index c3fe9e4..bc7644b 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -15,6 +15,8 @@ bool of_usb_host_tpl_support(struct device_node *np); int of_usb_update_otg_caps(struct device_node *np, struct usb_otg_caps *otg_caps); +struct device_node *usb_of_get_child_node(struct device_node *parent, + int portnum); #else static inline bool of_usb_host_tpl_support(struct device_node *np) { @@ -25,6 +27,11 @@ static inline int of_usb_update_otg_caps(struct device_node *np, { return 0; } +static inline struct device_node *usb_of_get_child_node + (struct device_node *parent, int portnum) +{ + return NULL; +} #endif #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)