Skip to contentSkip to conversation

USB: add generic onboard USB HUB driver

PATCH Superseded Peter Chen 11 participants 35 messages Dec 8, 2015 – Dec 16, 2015

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Peter Chen

author
#0 lore raw

cover USB: add generic onboard USB HUB driver

Hi all,

There is a known issue that the USB code can't handle USB HUB's external pins well, in that case, it may cause some onboard USB HUBs can't work since their PHY's clock or reset pin needs to operate.

The user reported this issue at below:
http://www.spinics.net/lists/linux-usb/msg131502.html

In this patch set, I add a generic onboard USB HUB driver to handle this problem, the external signals will be configured before usb controller's initialization, it much likes we did it at board code before.

The user needs to add this generic hub node at dts or add releted platform data to support it.

The udoo users, help to test please.

Peter Chen (3):
usb: misc: generic_onboard_hub: add generic onboard USB HUB driver
doc: dt-binding: generic onboard USB HUB
ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB property

 .../bindings/usb/generic-onboard-hub.txt           |  28 ++++
 MAINTAINERS                                        |   7 +
 arch/arm/boot/dts/imx6qdl-udoo.dtsi                |  25 +---
 drivers/usb/misc/Kconfig                           |   9 ++
 drivers/usb/misc/Makefile                          |   1 +
 drivers/usb/misc/generic_onboard_hub.c             | 162 +++++++++++++++++++++
 include/linux/usb/generic_onboard_hub.h            |  11 ++
 7 files changed, 224 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
 create mode 100644 drivers/usb/misc/generic_onboard_hub.c
 create mode 100644 include/linux/usb/generic_onboard_hub.h
Signature · 1 line
1.9.1
author
#1 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Current USB HUB driver lacks of platform interfaces to configure external signal on HUB chip, eg, the PHY input clock and gpio reset pin for HUB, these kinds of HUBs are usually soldered at the board, and they are not hot-plug USB devices.

With this patch, the user can configure the HUB's pins at platform part (through dts or platform), and these configuration will be effective before the USB bus can be used, we use subsys_initcall for this driver.

---
 MAINTAINERS                             |   7 ++
 drivers/usb/misc/Kconfig                |   9 ++
 drivers/usb/misc/Makefile               |   1 +
 drivers/usb/misc/generic_onboard_hub.c  | 162 ++++++++++++++++++++++++++++++++
 include/linux/usb/generic_onboard_hub.h |  11 +++
 5 files changed, 190 insertions(+)
 create mode 100644 drivers/usb/misc/generic_onboard_hub.c
 create mode 100644 include/linux/usb/generic_onboard_hub.h
MAINTAINERS +7 -0
index e9caa4b..cc1981e 100644
@@ -11121,6 +11121,13 @@ S:	Maintained
 F:	Documentation/usb/ohci.txt
 F:	drivers/usb/host/ohci*
 
+USB Generic Onboard HUB Driver
+M:	Peter Chen <[email protected]>
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
+L:	linux-usb at vger.kernel.org
+S:	Maintained
+F:	drivers/usb/misc/generic_onboard_hub.c
+
 USB OTG FSM (Finite State Machine)
 M:	Peter Chen <[email protected]>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
drivers/usb/misc/Kconfig +9 -0
index f7a7fc2..8921cae 100644
@@ -268,3 +268,12 @@ config USB_CHAOSKEY
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called chaoskey.
+
+config USB_ONBOARD_HUB
+	tristate "Generic USB Onboard HUB"
+	help
+	  Say Y here if your board has an onboard HUB, and this hub needs
+	  to control its PHY clock and reset pin through external signals.
+	  If you are not sure, say N.
+
+	  To compile this driver as a module, choose M here.
drivers/usb/misc/Makefile +1 -0
index 45fd4ac..da52e9a 100644
@@ -29,3 +29,4 @@ obj-$(CONFIG_USB_CHAOSKEY)		+= chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
+obj-$(CONFIG_USB_ONBOARD_HUB)		+= generic_onboard_hub.o
drivers/usb/misc/generic_onboard_hub.c new file +162 -0

162 lines not on this page · raw message

include/linux/usb/generic_onboard_hub.h new file +11 -0
new file mode 100644
index 0000000..1b70ccc
@@ -0,0 +1,11 @@
+#ifndef __LINUX_USB_GENERIC_HUB_H
+#define __LINUX_USB_GENERIC_HUB_H
+
+struct usb_hub_generic_platform_data {
+	int gpio_reset;
+	int gpio_reset_polarity;
+	int gpio_reset_duration_us;
+	struct clk *ext_clk;
+};
+
+#endif /* __LINUX_USB_GENERIC_HUB_H */
Signature · 1 line
1.9.1
#2 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Hi,

Quoted 31 lines · Peter Chen
drivers/usb/misc/Makefile +1 -0
index 45fd4ac..da52e9a 100644
@@ -29,3 +29,4 @@ obj-$(CONFIG_USB_CHAOSKEY)		+= chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
+obj-$(CONFIG_USB_ONBOARD_HUB)		+= generic_onboard_hub.o
drivers/usb/misc/generic_onboard_hub.c new file +16 -0
new file mode 100644
index 0000000..df722a0
@@ -0,0 +1,162 @@
+/*
+ * usb_hub_generic.c	The generic onboard USB HUB driver
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Author: Peter Chen <[email protected]>
+ *
+ * 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

drivers/usb/misc/generic_onboard_hub.c line 26

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver is only for the USB HUB devices which need to control
+ * their external pins(clock, reset, etc), and these USB HUB devices
+ * are soldered at the board.
+ */
+
+#define DEBUG

nope

drivers/usb/misc/generic_onboard_hub.c line 36

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/generic_onboard_hub.h>

<linux/platform_data/generic_onboard_hub.h> ?

drivers/usb/misc/generic_onboard_hub.c line 39

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+struct usb_hub_generic_data {
+	struct clk *clk;

seriously ? Is this really all ? What about that reset line below ?

In fact, that reset line should be using a generic reset-gpio.c instead of a raw gpio.

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);

drivers/usb/misc/generic_onboard_hub.c line 60

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));

how about setting clock to NULL to here ? then you don't need IS_ERR() checks anywhere else.

drivers/usb/misc/generic_onboard_hub.c line 58

Quoted 1 line
drivers/usb/misc/generic_onboard_hub.c new file +1 -0
+		}

braces shouldn't be used here, if you add NULL trick above, however... then you can keep them.

drivers/usb/misc/generic_onboard_hub.c line 71

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;

you see, this is definitely *not* generic. You should write a generic reset-gpio.c reset controller and describe the polarity on the gpio binding. This driver *always* uses reset_assert(); reset_deassert(); and reset-gpio implements though by gpiod_set_value() correctly.

Polarity _must_ be described elsewhere in DT.

drivers/usb/misc/generic_onboard_hub.c line 74

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);

likewise, this should be described as a debounce time for the GPIO.

Quoted 27 lines
drivers/usb/misc/generic_onboard_hub.c new file +27 -0
+		gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+			reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+		ret = PTR_ERR_OR_ZERO(gpiod_reset);
+		if (ret) {
+			dev_err(dev, "Failed to get reset gpio, err = %d\n",
+				ret);
+			return ret;
+		}
+	} else if (pdata) {
+		hub_data->clk = pdata->ext_clk;
+		duration_us = pdata->gpio_reset_duration_us;
+		reset_pol = pdata->gpio_reset_polarity;
+
+		if (gpio_is_valid(pdata->gpio_reset)) {
+			ret = devm_gpio_request_one(
+				dev, pdata->gpio_reset, reset_pol
+				? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				dev_name(dev));
+			if (!ret)
+				gpiod_reset = gpio_to_desc(pdata->gpio_reset);
+		}
+	}
+
+	if (!IS_ERR(hub_data->clk)) {
+		ret = clk_prepare_enable(hub_data->clk);
+		if (ret) {
+			dev_err(dev,

drivers/usb/misc/generic_onboard_hub.c line 112

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+				"Can't enable external clock: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	if (gpiod_reset) {
+		/* Sanity check */
+		if (duration_us > 1000000)
+			duration_us = 50;

this check makes no sense whatsoever. What I *really* need over 1s of debounce ?

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		usleep_range(duration_us, duration_us + 100);
+		gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

wrong. You should _not_ have polarity checks here. You should have already initialized the gpio as ACTIVE_HIGH or ACTIVE_LOW and gpiolib will handle the polarity for you.

Quoted 34 lines
drivers/usb/misc/generic_onboard_hub.c new file +34 -0
+	}
+
+	dev_set_drvdata(dev, hub_data);
+	return ret;
+}
+
+static int usb_hub_generic_remove(struct platform_device *pdev)
+{
+	struct usb_hub_generic_data *hub_data = platform_get_drvdata(pdev);
+
+	if (!IS_ERR(hub_data->clk))
+		clk_disable_unprepare(hub_data->clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id usb_hub_generic_dt_ids[] = {
+	{.compatible = "generic-onboard-hub"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, usb_hub_generic_dt_ids);
+#endif
+
+static struct platform_driver usb_hub_generic_driver = {
+	.probe = usb_hub_generic_probe,
+	.remove = usb_hub_generic_remove,
+	.driver = {
+		.name = "usb_hub_generic_onboard",
+		.of_match_table = usb_hub_generic_dt_ids,
+	 },
+};
+
+static int __init usb_hub_generic_init(void)

drivers/usb/misc/generic_onboard_hub.c line 158

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+{
+	return platform_driver_register(&usb_hub_generic_driver);
+}
+subsys_initcall(usb_hub_generic_init);
+
+static void __exit usb_hub_generic_exit(void)
+{
+	platform_driver_unregister(&usb_hub_generic_driver);
+}
+module_exit(usb_hub_generic_exit);

module_platform_driver();

drivers/usb/misc/generic_onboard_hub.c line 162

Quoted 3 lines
drivers/usb/misc/generic_onboard_hub.c new file +3 -0
+MODULE_AUTHOR("Peter Chen <[email protected]>");
+MODULE_DESCRIPTION("Generic Onboard USB HUB driver");
+MODULE_LICENSE("GPL");

comment header says GPL v2 only, this is GPL v2+. Which is correct ?

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151207/f2e29aad/attachment.sig>
author
#3 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 39 lines · Felipe Balbi

Hi,

Quoted 35 lines · Peter Chen
drivers/usb/misc/Makefile +1 -0
index 45fd4ac..da52e9a 100644
@@ -29,3 +29,4 @@ obj-$(CONFIG_USB_CHAOSKEY)		+= chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
+obj-$(CONFIG_USB_ONBOARD_HUB)		+= generic_onboard_hub.o
drivers/usb/misc/generic_onboard_hub.c new file +20 -0
new file mode 100644
index 0000000..df722a0
@@ -0,0 +1,162 @@
+/*
+ * usb_hub_generic.c	The generic onboard USB HUB driver
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Author: Peter Chen <[email protected]>
+ *
+ * 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/>.
+ */
+
+/*
Quoted 9 lines

drivers/usb/misc/generic_onboard_hub.c line 26

Quoted 6 lines
drivers/usb/misc/generic_onboard_hub.c new file +6 -0
+ * This driver is only for the USB HUB devices which need to control
+ * their external pins(clock, reset, etc), and these USB HUB devices
+ * are soldered at the board.
+ */
+
+#define DEBUG

nope

Will change.

Quoted 4 lines
Quoted 4 lines
drivers/usb/misc/generic_onboard_hub.c new file +4 -0
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
Quoted 9 lines

drivers/usb/misc/generic_onboard_hub.c line 36

Quoted 6 lines
drivers/usb/misc/generic_onboard_hub.c new file +6 -0
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/generic_onboard_hub.h>

<linux/platform_data/generic_onboard_hub.h> ?

Yes, you are right, I did not know it

Quoted 4 lines

drivers/usb/misc/generic_onboard_hub.c line 39

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+struct usb_hub_generic_data {
+	struct clk *clk;

seriously ? Is this really all ? What about that reset line below ?

The clock is PHY input clock on the HUB, this clock may from SoC's PLL.

Quoted 4 lines

In fact, that reset line should be using a generic reset-gpio.c instead of a raw gpio.

This reset gpio is not at mainline, I don't know what's reason

http://lists.infradead.org/pipermail/linux-arm-kernel/2013-July/186693.html

Philipp, do you know the reason?

Quoted 23 lines
Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);

drivers/usb/misc/generic_onboard_hub.c line 60

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));

how about setting clock to NULL to here ? then you don't need IS_ERR() checks anywhere else.

Quoted 5 lines

drivers/usb/misc/generic_onboard_hub.c line 58

Quoted 1 line
drivers/usb/misc/generic_onboard_hub.c new file +1 -0
+		}

braces shouldn't be used here, if you add NULL trick above, however... then you can keep them.

Braces aren't needed, it may not too much useful to using NULL as a indicator for error pointer.

Quoted 15 lines

drivers/usb/misc/generic_onboard_hub.c line 71

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;

you see, this is definitely *not* generic. You should write a generic reset-gpio.c reset controller and describe the polarity on the gpio binding. This driver *always* uses reset_assert(); reset_deassert(); and reset-gpio implements though by gpiod_set_value() correctly.

Quoted 7 lines

Polarity _must_ be described elsewhere in DT.

drivers/usb/misc/generic_onboard_hub.c line 74

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);

likewise, this should be described as a debounce time for the GPIO.

Yes, if we are a reset gpio driver.

Quoted 32 lines
Quoted 32 lines
drivers/usb/misc/generic_onboard_hub.c new file +32 -0
+		gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+			reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+		ret = PTR_ERR_OR_ZERO(gpiod_reset);
+		if (ret) {
+			dev_err(dev, "Failed to get reset gpio, err = %d\n",
+				ret);
+			return ret;
+		}
+	} else if (pdata) {
+		hub_data->clk = pdata->ext_clk;
+		duration_us = pdata->gpio_reset_duration_us;
+		reset_pol = pdata->gpio_reset_polarity;
+
+		if (gpio_is_valid(pdata->gpio_reset)) {
+			ret = devm_gpio_request_one(
+				dev, pdata->gpio_reset, reset_pol
+				? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				dev_name(dev));
+			if (!ret)
+				gpiod_reset = gpio_to_desc(pdata->gpio_reset);
+		}
+	}
+
+	if (!IS_ERR(hub_data->clk)) {
+		ret = clk_prepare_enable(hub_data->clk);
+		if (ret) {
+			dev_err(dev,
+				"Can't enable external clock: %d\n",
+				ret);
+			return ret;
+		}
+	}
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 112

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+
+	if (gpiod_reset) {
+		/* Sanity check */
+		if (duration_us > 1000000)
+			duration_us = 50;

this check makes no sense whatsoever. What I *really* need over 1s of debounce ?

Ok, I will delete this check.

Quoted 7 lines

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 3 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		usleep_range(duration_us, duration_us + 100);
+		gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

wrong. You should _not_ have polarity checks here. You should have already initialized the gpio as ACTIVE_HIGH or ACTIVE_LOW and gpiolib will handle the polarity for you.

Yes, you are right. I did not understand ACTIVE_LOW for gpio flag before.

Quoted 39 lines
Quoted 39 lines
drivers/usb/misc/generic_onboard_hub.c new file +38 -0
+	}
+
+	dev_set_drvdata(dev, hub_data);
+	return ret;
+}
+
+static int usb_hub_generic_remove(struct platform_device *pdev)
+{
+	struct usb_hub_generic_data *hub_data = platform_get_drvdata(pdev);
+
+	if (!IS_ERR(hub_data->clk))
+		clk_disable_unprepare(hub_data->clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id usb_hub_generic_dt_ids[] = {
+	{.compatible = "generic-onboard-hub"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, usb_hub_generic_dt_ids);
+#endif
+
+static struct platform_driver usb_hub_generic_driver = {
+	.probe = usb_hub_generic_probe,
+	.remove = usb_hub_generic_remove,
+	.driver = {
+		.name = "usb_hub_generic_onboard",
+		.of_match_table = usb_hub_generic_dt_ids,
+	 },
+};
+
+static int __init usb_hub_generic_init(void)
+{
+	return platform_driver_register(&usb_hub_generic_driver);
+}
+subsys_initcall(usb_hub_generic_init);
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 158

Quoted 6 lines
drivers/usb/misc/generic_onboard_hub.c new file +6 -0
+
+static void __exit usb_hub_generic_exit(void)
+{
+	platform_driver_unregister(&usb_hub_generic_driver);
+}
+module_exit(usb_hub_generic_exit);

module_platform_driver();

I want this driver to be called before module init's.

Quoted 7 lines

drivers/usb/misc/generic_onboard_hub.c line 162

Quoted 4 lines
drivers/usb/misc/generic_onboard_hub.c new file +3 -0
+MODULE_AUTHOR("Peter Chen <[email protected]>");
+MODULE_DESCRIPTION("Generic Onboard USB HUB driver");
+MODULE_LICENSE("GPL");

comment header says GPL v2 only, this is GPL v2+. Which is correct ?

I will change it to GPL v2, thanks.

Signature · 2 lines
Best Regards,
Peter Chen
#4 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Hi,

Quoted 4 lines · Peter Chen
Quoted 1 line

seriously ? Is this really all ? What about that reset line below ?

The clock is PHY input clock on the HUB, this clock may from SoC's PLL.

oh, you might have misunderstood my comment. I'm saying that there is more than one thing you could cache in your private structure. That's all.

Quoted 23 lines
Quoted 23 lines
Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);

drivers/usb/misc/generic_onboard_hub.c line 60

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));

how about setting clock to NULL to here ? then you don't need IS_ERR() checks anywhere else.

Quoted 8 lines
Quoted 5 lines

Review

Quoted 1 line
(quoted diff) +1 -0
+		}

braces shouldn't be used here, if you add NULL trick above, however... then you can keep them.

Braces aren't needed, it may not too much useful to using NULL as a indicator for error pointer.

heh, it's not about using it as an error pointer. I'm merely trying to make clk optional. NULL is a valid clk, meaning you won't get NULL pointer dereferences when passing it along clk_*() calls (if you find any, it's likely a bug in CCF), so NULL can be used to cope with optional clocks:

         clk = clk_get(dev, "foo");
         if (IS_ERR(clk)) {
         	if (PTR_ERR(clk) == -EPROBE_DEFER)
                	return -EPROBE_DEFER;
                else
                	clk = NULL;
         }
Quoted 17 lines
Quoted 17 lines

drivers/usb/misc/generic_onboard_hub.c line 71

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;

you see, this is definitely *not* generic. You should write a generic reset-gpio.c reset controller and describe the polarity on the gpio binding. This driver *always* uses reset_assert(); reset_deassert(); and reset-gpio implements though by gpiod_set_value() correctly.

Polarity _must_ be described elsewhere in DT.

Quoted 7 lines
Quoted 5 lines

drivers/usb/misc/generic_onboard_hub.c line 74

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);

likewise, this should be described as a debounce time for the GPIO.

Yes, if we are a reset gpio driver.

even if you use a raw GPIO, polarity and duration must come through DT.

Quoted 9 lines
Quoted 6 lines

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		usleep_range(duration_us, duration_us + 100);
+		gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

wrong. You should _not_ have polarity checks here. You should have already initialized the gpio as ACTIVE_HIGH or ACTIVE_LOW and gpiolib will handle the polarity for you.

Yes, you are right. I did not understand ACTIVE_LOW for gpio flag before.

with open source code, that's a rather poor excuse, Peter.

Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+static int __init usb_hub_generic_init(void)
+{
+	return platform_driver_register(&usb_hub_generic_driver);
+}
+subsys_initcall(usb_hub_generic_init);
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 158

Quoted 6 lines
drivers/usb/misc/generic_onboard_hub.c new file +6 -0
+
+static void __exit usb_hub_generic_exit(void)
+{
+	platform_driver_unregister(&usb_hub_generic_driver);
+}
+module_exit(usb_hub_generic_exit);

module_platform_driver();

Quoted 1 line

I want this driver to be called before module init's.

why ?

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151208/46d4f17b/attachment.sig>
author
#5 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 4 lines · Felipe Balbi

Hi,

Peter Chen <[email protected]> writes:

Quoted 9 lines
Quoted 4 lines
Quoted 1 line

seriously ? Is this really all ? What about that reset line below ?

The clock is PHY input clock on the HUB, this clock may from SoC's PLL.

oh, you might have misunderstood my comment. I'm saying that there is more than one thing you could cache in your private structure. That's all.

How? I need to handle clock at both ->probe and ->remove.

Quoted 38 lines
Quoted 23 lines
Quoted 23 lines
Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);

drivers/usb/misc/generic_onboard_hub.c line 60

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));

how about setting clock to NULL to here ? then you don't need IS_ERR() checks anywhere else.

Quoted 8 lines
Quoted 5 lines

Review

Quoted 1 line
(quoted diff) +1 -0
+		}

braces shouldn't be used here, if you add NULL trick above, however... then you can keep them.

Braces aren't needed, it may not too much useful to using NULL as a indicator for error pointer.

heh, it's not about using it as an error pointer. I'm merely trying to make clk optional. NULL is a valid clk, meaning you won't get NULL pointer dereferences when passing it along clk_*() calls (if you find any, it's likely a bug in CCF), so NULL can be used to cope with optional clocks:

Quoted 8 lines
         clk = clk_get(dev, "foo");
         if (IS_ERR(clk)) {
         	if (PTR_ERR(clk) == -EPROBE_DEFER)
                	return -EPROBE_DEFER;
                else
                	clk = NULL;
         }

Get your point, so at coming code, we don't need to add condition to enable optional clock.

Quoted 34 lines
Quoted 17 lines
Quoted 17 lines

drivers/usb/misc/generic_onboard_hub.c line 71

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;

you see, this is definitely *not* generic. You should write a generic reset-gpio.c reset controller and describe the polarity on the gpio binding. This driver *always* uses reset_assert(); reset_deassert(); and reset-gpio implements though by gpiod_set_value() correctly.

Polarity _must_ be described elsewhere in DT.

Quoted 7 lines
Quoted 5 lines

drivers/usb/misc/generic_onboard_hub.c line 74

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);

likewise, this should be described as a debounce time for the GPIO.

Yes, if we are a reset gpio driver.

even if you use a raw GPIO, polarity and duration must come through DT.

Quoted 7 lines
Quoted 6 lines

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 2 lines
drivers/usb/misc/generic_onboard_hub.c new file +2 -0
+		usleep_range(duration_us, duration_us + 100);
+		gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

wrong. You should _not_ have polarity checks here. You should have already initialized the gpio as ACTIVE_HIGH or ACTIVE_LOW and gpiolib will handle the polarity for you.

Quoted 4 lines
Quoted 2 lines

Yes, you are right. I did not understand ACTIVE_LOW for gpio flag before.

with open source code, that's a rather poor excuse, Peter.

I will pay attention to it, thanks.
At my dts example, it is like below, I just treat it at raw gpio handling.

	usb_hub1 {
		compatible = "generic-onboard-hub";
		clocks = <&clks IMX6QDL_CLK_CKO>;
		clock-names = "external_clk";
		hub-reset-active-high;
		hub-reset-gpios = <&gpio7 12 0>;
		hub-reset-duration-us = <2>;
	};

I will change it like below:

	usb_hub1 {
		compatible = "generic-onboard-hub";
		clocks = <&clks IMX6QDL_CLK_CKO>;
		clock-names = "clk";
		reset-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>;
		reset-duration-us = <2>;
	};
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines

drivers/usb/misc/generic_onboard_hub.c line 158

Quoted 12 lines
drivers/usb/misc/generic_onboard_hub.c new file +11 -0
+static int __init usb_hub_generic_init(void)
+{
+	return platform_driver_register(&usb_hub_generic_driver);
+}
+subsys_initcall(usb_hub_generic_init);
+
+static void __exit usb_hub_generic_exit(void)
+{
+	platform_driver_unregister(&usb_hub_generic_driver);
+}
+module_exit(usb_hub_generic_exit);

module_platform_driver();

Quoted 3 lines
Quoted 1 line

I want this driver to be called before module init's.

why ?

The USB HUB should be in ready state before controller tries to talk with it, otherwise, it may has noise at the bus during the HUB reset/power on process.

Signature · 2 lines
Best Regards,
Peter Chen
#6 lore raw

[PATCH 1/3] usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

In reply to Peter Chen
reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree…

Hi Peter,

[auto build test ERROR on usb/usb-testing]
[also build test ERROR on v4.4-rc4 next-20151207]

url:    https://github.com/0day-ci/linux/commits/Peter-Chen/USB-add-generic-onboard-USB-HUB-driver/20151208-094428
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
config: tile-allmodconfig (attached as .config)

reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=tile

All error/warnings (new ones prefixed by >>):

drivers/usb/misc/generic_onboard_hub.c: In function 'usb_hub_generic_probe':

>> drivers/usb/misc/generic_onboard_hub.c:76:3: error: implicit declaration of function 'devm_gpiod_get_optional'
>> drivers/usb/misc/generic_onboard_hub.c:77:16: error: 'GPIOD_OUT_HIGH' undeclared (first use in this function)
   drivers/usb/misc/generic_onboard_hub.c:77:16: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/usb/misc/generic_onboard_hub.c:77:33: error: 'GPIOD_OUT_LOW' undeclared (first use in this function)
>> drivers/usb/misc/generic_onboard_hub.c:95:5: error: implicit declaration of function 'gpio_to_desc'
>> drivers/usb/misc/generic_onboard_hub.c:95:17: warning: assignment makes pointer from integer without a cast [enabled by default]
>> drivers/usb/misc/generic_onboard_hub.c:114:3: error: implicit declaration of function 'gpiod_set_value'

cc1: some warnings being treated as errors

vim +/devm_gpiod_get_optional +76 drivers/usb/misc/generic_onboard_hub.c

    70			if (of_find_property(node, "hub-reset-active-high", NULL))
    71				reset_pol = 1;
    72	
    73			of_property_read_u32(node, "hub-reset-duration-us",
    74				&duration_us);
    75	
  > 76			gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
  > 77				reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
    78			ret = PTR_ERR_OR_ZERO(gpiod_reset);
    79			if (ret) {
    80				dev_err(dev, "Failed to get reset gpio, err = %d\n",
    81					ret);
    82				return ret;
    83			}
    84		} else if (pdata) {
    85			hub_data->clk = pdata->ext_clk;
    86			duration_us = pdata->gpio_reset_duration_us;
    87			reset_pol = pdata->gpio_reset_polarity;
    88	
    89			if (gpio_is_valid(pdata->gpio_reset)) {
    90				ret = devm_gpio_request_one(
    91					dev, pdata->gpio_reset, reset_pol
    92					? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
    93					dev_name(dev));
    94				if (!ret)
  > 95					gpiod_reset = gpio_to_desc(pdata->gpio_reset);
    96			}
    97		}
    98	
    99		if (!IS_ERR(hub_data->clk)) {
   100			ret = clk_prepare_enable(hub_data->clk);
   101			if (ret) {
   102				dev_err(dev,
   103					"Can't enable external clock: %d\n",
   104					ret);
   105				return ret;
   106			}
   107		}
   108	
   109		if (gpiod_reset) {
   110			/* Sanity check */
   111			if (duration_us > 1000000)
   112				duration_us = 50;
   113			usleep_range(duration_us, duration_us + 100);
 > 114			gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

115 }
116
117 dev_set_drvdata(dev, hub_data);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 42151 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151208/1811f234/attachment-0001.obj>

author
#7 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 72 lines · kbuild test robot

Hi Peter,

[auto build test ERROR on usb/usb-testing]
[also build test ERROR on v4.4-rc4 next-20151207]

url:    https://github.com/0day-ci/linux/commits/Peter-Chen/USB-add-generic-onboard-USB-HUB-driver/20151208-094428
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
config: tile-allmodconfig (attached as .config)

reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=tile

All error/warnings (new ones prefixed by >>):

drivers/usb/misc/generic_onboard_hub.c: In function 'usb_hub_generic_probe':

Quoted 2 lines
Quoted 2 lines

drivers/usb/misc/generic_onboard_hub.c:76:3: error: implicit declaration of function 'devm_gpiod_get_optional' drivers/usb/misc/generic_onboard_hub.c:77:16: error: 'GPIOD_OUT_HIGH' undeclared (first use in this function)

drivers/usb/misc/generic_onboard_hub.c:77:16: note: each undeclared identifier is reported only once for each function it appears in

Quoted 4 lines
Quoted 4 lines

drivers/usb/misc/generic_onboard_hub.c:77:33: error: 'GPIOD_OUT_LOW' undeclared (first use in this function) drivers/usb/misc/generic_onboard_hub.c:95:5: error: implicit declaration of function 'gpio_to_desc' drivers/usb/misc/generic_onboard_hub.c:95:17: warning: assignment makes pointer from integer without a cast [enabled by default] drivers/usb/misc/generic_onboard_hub.c:114:3: error: implicit declaration of function 'gpiod_set_value'

cc1: some warnings being treated as errors

vim +/devm_gpiod_get_optional +76 drivers/usb/misc/generic_onboard_hub.c

    70			if (of_find_property(node, "hub-reset-active-high", NULL))
    71				reset_pol = 1;
    72	
    73			of_property_read_u32(node, "hub-reset-duration-us",
    74				&duration_us);
    75	
Quoted 2 lines

76 gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
77 reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);

    78			ret = PTR_ERR_OR_ZERO(gpiod_reset);
    79			if (ret) {
    80				dev_err(dev, "Failed to get reset gpio, err = %d\n",
    81					ret);
    82				return ret;
    83			}
    84		} else if (pdata) {
    85			hub_data->clk = pdata->ext_clk;
    86			duration_us = pdata->gpio_reset_duration_us;
    87			reset_pol = pdata->gpio_reset_polarity;
    88	
    89			if (gpio_is_valid(pdata->gpio_reset)) {
    90				ret = devm_gpio_request_one(
    91					dev, pdata->gpio_reset, reset_pol
    92					? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
    93					dev_name(dev));
    94				if (!ret)
Quoted 1 line

95 gpiod_reset = gpio_to_desc(pdata->gpio_reset);

    96			}
    97		}
    98	
    99		if (!IS_ERR(hub_data->clk)) {
   100			ret = clk_prepare_enable(hub_data->clk);
   101			if (ret) {
   102				dev_err(dev,
   103					"Can't enable external clock: %d\n",
   104					ret);
   105				return ret;
   106			}
   107		}
   108	
   109		if (gpiod_reset) {
   110			/* Sanity check */
   111			if (duration_us > 1000000)
   112				duration_us = 50;
   113			usleep_range(duration_us, duration_us + 100);
Quoted 8 lines
Quoted 1 line

114 gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

115 }
116
117 dev_set_drvdata(dev, hub_data);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

I will add <linux/gpio/consumer.h> at header file list.

Signature · 2 lines
Best Regards,
Peter Chen
maintainer
#8 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

In reply to Peter Chen
Quoted 118 lines · Peter Chen

Current USB HUB driver lacks of platform interfaces to configure external signal on HUB chip, eg, the PHY input clock and gpio reset pin for HUB, these kinds of HUBs are usually soldered at the board, and they are not hot-plug USB devices.

With this patch, the user can configure the HUB's pins at platform part (through dts or platform), and these configuration will be effective before the USB bus can be used, we use subsys_initcall for this driver.

---
 MAINTAINERS                             |   7 ++
 drivers/usb/misc/Kconfig                |   9 ++
 drivers/usb/misc/Makefile               |   1 +
 drivers/usb/misc/generic_onboard_hub.c  | 162 ++++++++++++++++++++++++++++++++
 include/linux/usb/generic_onboard_hub.h |  11 +++
 5 files changed, 190 insertions(+)
 create mode 100644 drivers/usb/misc/generic_onboard_hub.c
 create mode 100644 include/linux/usb/generic_onboard_hub.h
MAINTAINERS +7 -0
index e9caa4b..cc1981e 100644
@@ -11121,6 +11121,13 @@ S:	Maintained
 F:	Documentation/usb/ohci.txt
 F:	drivers/usb/host/ohci*
 
+USB Generic Onboard HUB Driver
+M:	Peter Chen <[email protected]>
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
+L:	linux-usb at vger.kernel.org
+S:	Maintained
+F:	drivers/usb/misc/generic_onboard_hub.c
+
 USB OTG FSM (Finite State Machine)
 M:	Peter Chen <[email protected]>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
drivers/usb/misc/Kconfig +9 -0
index f7a7fc2..8921cae 100644
@@ -268,3 +268,12 @@ config USB_CHAOSKEY
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called chaoskey.
+
+config USB_ONBOARD_HUB
+	tristate "Generic USB Onboard HUB"
+	help
+	  Say Y here if your board has an onboard HUB, and this hub needs
+	  to control its PHY clock and reset pin through external signals.
+	  If you are not sure, say N.
+
+	  To compile this driver as a module, choose M here.
drivers/usb/misc/Makefile +1 -0
index 45fd4ac..da52e9a 100644
@@ -29,3 +29,4 @@ obj-$(CONFIG_USB_CHAOSKEY)		+= chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
+obj-$(CONFIG_USB_ONBOARD_HUB)		+= generic_onboard_hub.o
drivers/usb/misc/generic_onboard_hub.c new file +47 -0
new file mode 100644
index 0000000..df722a0
@@ -0,0 +1,162 @@
+/*
+ * usb_hub_generic.c	The generic onboard USB HUB driver
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Author: Peter Chen <[email protected]>
+ *
+ * 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/>.
+ */
+
+/*
+ * This driver is only for the USB HUB devices which need to control
+ * their external pins(clock, reset, etc), and these USB HUB devices
+ * are soldered at the board.
+ */
+
+#define DEBUG
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/generic_onboard_hub.h>
+
+struct usb_hub_generic_data {
+	struct clk *clk;
+};
+
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;

drivers/usb/misc/generic_onboard_hub.c line 57

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");

Please drop such _clk suffixes. The context already makes it clear that it's a clock.

Quoted 18 lines
drivers/usb/misc/generic_onboard_hub.c new file +18 -0
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));
+		}
+
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;
+
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);
+

drivers/usb/misc/generic_onboard_hub.c line 85

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+		gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+			reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+		ret = PTR_ERR_OR_ZERO(gpiod_reset);
+		if (ret) {
+			dev_err(dev, "Failed to get reset gpio, err = %d\n",
+				ret);
+			return ret;
+		}
+	} else if (pdata) {
+		hub_data->clk = pdata->ext_clk;

Passing clocks in platform_data is a no go. clocks must always be retrieved with clk_get.

drivers/usb/misc/generic_onboard_hub.c line 95

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+		duration_us = pdata->gpio_reset_duration_us;
+		reset_pol = pdata->gpio_reset_polarity;
+
+		if (gpio_is_valid(pdata->gpio_reset)) {
+			ret = devm_gpio_request_one(
+				dev, pdata->gpio_reset, reset_pol
+				? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				dev_name(dev));
+			if (!ret)
+				gpiod_reset = gpio_to_desc(pdata->gpio_reset);

If the gpio is valid then being unable to get it is an error.

Do you need this platform_data stuff at all?

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author
#9 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 12 lines · Sascha Hauer

drivers/usb/misc/generic_onboard_hub.c line 57

Quoted 8 lines
drivers/usb/misc/generic_onboard_hub.c new file +8 -0
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");

Please drop such _clk suffixes. The context already makes it clear that it's a clock.

Will change.

Quoted 23 lines
Quoted 23 lines
drivers/usb/misc/generic_onboard_hub.c new file +23 -0
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));
+		}
+
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;
+
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);
+
+		gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+			reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+		ret = PTR_ERR_OR_ZERO(gpiod_reset);
+		if (ret) {
+			dev_err(dev, "Failed to get reset gpio, err = %d\n",
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 85

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+				ret);
+			return ret;
+		}
+	} else if (pdata) {
+		hub_data->clk = pdata->ext_clk;

Passing clocks in platform_data is a no go. clocks must always be retrieved with clk_get.

Yes, you are right.

Quoted 13 lines

drivers/usb/misc/generic_onboard_hub.c line 95

Quoted 11 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+		duration_us = pdata->gpio_reset_duration_us;
+		reset_pol = pdata->gpio_reset_polarity;
+
+		if (gpio_is_valid(pdata->gpio_reset)) {
+			ret = devm_gpio_request_one(
+				dev, pdata->gpio_reset, reset_pol
+				? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				dev_name(dev));
+			if (!ret)
+				gpiod_reset = gpio_to_desc(pdata->gpio_reset);

If the gpio is valid then being unable to get it is an error.

I can't catch you, if the gpio is invalid, its descriptor will be NULL, then, the code will not do any gpio operation.

Quoted 3 lines

Do you need this platform_data stuff at all?

If not, how can I cover the platform which does not use dts, but still uses these kinds of HUBs?

Signature · 2 lines
Best Regards,
Peter Chen
maintainer
#10 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 64 lines · Peter Chen
Quoted 12 lines · Sascha Hauer

drivers/usb/misc/generic_onboard_hub.c line 57

Quoted 8 lines
drivers/usb/misc/generic_onboard_hub.c new file +8 -0
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");

Please drop such _clk suffixes. The context already makes it clear that it's a clock.

Will change.

Quoted 23 lines
Quoted 23 lines
drivers/usb/misc/generic_onboard_hub.c new file +23 -0
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));
+		}
+
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;
+
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);
+
+		gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+			reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+		ret = PTR_ERR_OR_ZERO(gpiod_reset);
+		if (ret) {
+			dev_err(dev, "Failed to get reset gpio, err = %d\n",
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 85

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+				ret);
+			return ret;
+		}
+	} else if (pdata) {
+		hub_data->clk = pdata->ext_clk;

Passing clocks in platform_data is a no go. clocks must always be retrieved with clk_get.

Yes, you are right.

Quoted 13 lines

drivers/usb/misc/generic_onboard_hub.c line 95

Quoted 11 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+		duration_us = pdata->gpio_reset_duration_us;
+		reset_pol = pdata->gpio_reset_polarity;
+
+		if (gpio_is_valid(pdata->gpio_reset)) {
+			ret = devm_gpio_request_one(
+				dev, pdata->gpio_reset, reset_pol
+				? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				dev_name(dev));
+			if (!ret)
+				gpiod_reset = gpio_to_desc(pdata->gpio_reset);

If the gpio is valid then being unable to get it is an error.

Quoted 2 lines

I can't catch you, if the gpio is invalid, its descriptor will be NULL, then, the code will not do any gpio operation.

When the platform_data provides a gpio (gpio_is_valid() is true) then you must use the gpio. If then devm_gpio_request_one() fails you must bail out.

Quoted 7 lines
Quoted 4 lines

Do you need this platform_data stuff at all?

If not, how can I cover the platform which does not use dts, but still uses these kinds of HUBs?

You can't, but are there any non device tree platforms which want to use this driver?

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author
#11 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 65 lines · Sascha Hauer
Quoted 64 lines · Peter Chen
Quoted 12 lines · Sascha Hauer

drivers/usb/misc/generic_onboard_hub.c line 57

Quoted 8 lines
drivers/usb/misc/generic_onboard_hub.c new file +8 -0
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+
+		hub_data->clk = devm_clk_get(dev, "external_clk");

Please drop such _clk suffixes. The context already makes it clear that it's a clock.

Will change.

Quoted 23 lines
Quoted 23 lines
drivers/usb/misc/generic_onboard_hub.c new file +23 -0
+		if (IS_ERR(hub_data->clk)) {
+			dev_dbg(dev, "Can't get external clock: %ld\n",
+					PTR_ERR(hub_data->clk));
+		}
+
+		/*
+		 * Try to get the information for HUB reset, the
+		 * default setting like below:
+		 *
+		 * - Reset state is low
+		 * - The duration is 50us
+		 */
+		if (of_find_property(node, "hub-reset-active-high", NULL))
+			reset_pol = 1;
+
+		of_property_read_u32(node, "hub-reset-duration-us",
+			&duration_us);
+
+		gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+			reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+		ret = PTR_ERR_OR_ZERO(gpiod_reset);
+		if (ret) {
+			dev_err(dev, "Failed to get reset gpio, err = %d\n",
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 85

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+				ret);
+			return ret;
+		}
+	} else if (pdata) {
+		hub_data->clk = pdata->ext_clk;

Passing clocks in platform_data is a no go. clocks must always be retrieved with clk_get.

Yes, you are right.

Quoted 13 lines

drivers/usb/misc/generic_onboard_hub.c line 95

Quoted 11 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+		duration_us = pdata->gpio_reset_duration_us;
+		reset_pol = pdata->gpio_reset_polarity;
+
+		if (gpio_is_valid(pdata->gpio_reset)) {
+			ret = devm_gpio_request_one(
+				dev, pdata->gpio_reset, reset_pol
+				? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				dev_name(dev));
+			if (!ret)
+				gpiod_reset = gpio_to_desc(pdata->gpio_reset);

If the gpio is valid then being unable to get it is an error.

Quoted 6 lines
Quoted 2 lines

I can't catch you, if the gpio is invalid, its descriptor will be NULL, then, the code will not do any gpio operation.

When the platform_data provides a gpio (gpio_is_valid() is true) then you must use the gpio. If then devm_gpio_request_one() fails you must bail out.

I see.

Quoted 12 lines
Quoted 8 lines
Quoted 5 lines

Do you need this platform_data stuff at all?

If not, how can I cover the platform which does not use dts, but still uses these kinds of HUBs?

You can't, but are there any non device tree platforms which want to use this driver?

I thought there are i386 embedded devices, it may use the HUB, like this driver tries to handle. I agree that we only handle dt in this driver first until the non-dt user appears.

Signature · 2 lines
Best Regards,
Peter Chen
#12 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

In reply to Peter Chen
Quoted 7 lines · On Tuesday 08 December 2015 09:37:48 Peter Chen wrote:
drivers/usb/misc/generic_onboard_hub.c new file +7 -0
+struct usb_hub_generic_data {
+	struct clk *clk;
+};
+
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;

drivers/usb/misc/generic_onboard_hub.c line 54

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {

Let's not worry about the !DT case until someone adds a board file that needs it. Just remove the if() here along and the whole else block.

Quoted 6 lines
drivers/usb/misc/generic_onboard_hub.c new file +6 -0
+#ifdef CONFIG_OF
+static const struct of_device_id usb_hub_generic_dt_ids[] = {
+	{.compatible = "generic-onboard-hub"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, usb_hub_generic_dt_ids);

drivers/usb/misc/generic_onboard_hub.c line 146

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+#endif
+
+static struct platform_driver usb_hub_generic_driver = {
+	.probe = usb_hub_generic_probe,
+	.remove = usb_hub_generic_remove,
+	.driver = {
+		.name = "usb_hub_generic_onboard",
+		.of_match_table = usb_hub_generic_dt_ids,
+	 },
+};

Build error when CONFIG_OF is disabled: Please remove the #ifdef around the device table.

Quoted 6 lines
include/linux/usb/generic_onboard_hub.h new file +0 -0
new file mode 100644
index 0000000..1b70ccc

include/linux/usb/generic_onboard_hub.h line 9

Quoted 9 lines
include/linux/usb/generic_onboard_hub.h new file +9 -0
@@ -0,0 +1,11 @@
+#ifndef __LINUX_USB_GENERIC_HUB_H
+#define __LINUX_USB_GENERIC_HUB_H
+
+struct usb_hub_generic_platform_data {
+	int gpio_reset;
+	int gpio_reset_polarity;
+	int gpio_reset_duration_us;
+	struct clk *ext_clk;
+};

Merge this structure into struct usb_hub_generic_data and remove the header.

ARnd

author
#13 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 62 lines · Arnd Bergmann
Quoted 7 lines · On Tuesday 08 December 2015 09:37:48 Peter Chen wrote:
drivers/usb/misc/generic_onboard_hub.c new file +7 -0
+struct usb_hub_generic_data {
+	struct clk *clk;
+};
+
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;

drivers/usb/misc/generic_onboard_hub.c line 54

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+	struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+	struct usb_hub_generic_data *hub_data;
+	int reset_pol = 0, duration_us = 50, ret = 0;
+	struct gpio_desc *gpiod_reset = NULL;
+
+	hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+	if (!hub_data)
+		return -ENOMEM;
+
+	if (dev->of_node) {

Let's not worry about the !DT case until someone adds a board file that needs it. Just remove the if() here along and the whole else block.

Quoted 6 lines
drivers/usb/misc/generic_onboard_hub.c new file +6 -0
+#ifdef CONFIG_OF
+static const struct of_device_id usb_hub_generic_dt_ids[] = {
+	{.compatible = "generic-onboard-hub"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, usb_hub_generic_dt_ids);

drivers/usb/misc/generic_onboard_hub.c line 146

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+#endif
+
+static struct platform_driver usb_hub_generic_driver = {
+	.probe = usb_hub_generic_probe,
+	.remove = usb_hub_generic_remove,
+	.driver = {
+		.name = "usb_hub_generic_onboard",
+		.of_match_table = usb_hub_generic_dt_ids,
+	 },
+};

Build error when CONFIG_OF is disabled: Please remove the #ifdef around the device table.

Quoted 6 lines
include/linux/usb/generic_onboard_hub.h new file +0 -0
new file mode 100644
index 0000000..1b70ccc

include/linux/usb/generic_onboard_hub.h line 9

Quoted 9 lines
include/linux/usb/generic_onboard_hub.h new file +9 -0
@@ -0,0 +1,11 @@
+#ifndef __LINUX_USB_GENERIC_HUB_H
+#define __LINUX_USB_GENERIC_HUB_H
+
+struct usb_hub_generic_platform_data {
+	int gpio_reset;
+	int gpio_reset_polarity;
+	int gpio_reset_duration_us;
+	struct clk *ext_clk;
+};

Merge this structure into struct usb_hub_generic_data and remove the header.

Quoted 1 line

ARnd

Agree.

Signature · 2 lines
Best Regards,
Peter Chen
#14 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

In reply to Peter Chen
Quoted 122 lines · Peter Chen

Current USB HUB driver lacks of platform interfaces to configure external signal on HUB chip, eg, the PHY input clock and gpio reset pin for HUB, these kinds of HUBs are usually soldered at the board, and they are not hot-plug USB devices.

With this patch, the user can configure the HUB's pins at platform part (through dts or platform), and these configuration will be effective before the USB bus can be used, we use subsys_initcall for this driver.

---
 MAINTAINERS                             |   7 ++
 drivers/usb/misc/Kconfig                |   9 ++
 drivers/usb/misc/Makefile               |   1 +
 drivers/usb/misc/generic_onboard_hub.c  | 162 ++++++++++++++++++++++++++++++++
 include/linux/usb/generic_onboard_hub.h |  11 +++
 5 files changed, 190 insertions(+)
 create mode 100644 drivers/usb/misc/generic_onboard_hub.c
 create mode 100644 include/linux/usb/generic_onboard_hub.h
MAINTAINERS +7 -0
index e9caa4b..cc1981e 100644
@@ -11121,6 +11121,13 @@ S:     Maintained
 F:     Documentation/usb/ohci.txt
 F:     drivers/usb/host/ohci*
 
+USB Generic Onboard HUB Driver
+M:     Peter Chen <[email protected]>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
+L:     linux-usb at vger.kernel.org
+S:     Maintained
+F:     drivers/usb/misc/generic_onboard_hub.c
+
 USB OTG FSM (Finite State Machine)
 M:     Peter Chen <[email protected]>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
drivers/usb/misc/Kconfig +9 -0
index f7a7fc2..8921cae 100644
@@ -268,3 +268,12 @@ config USB_CHAOSKEY
 
          To compile this driver as a module, choose M here: the
          module will be called chaoskey.
+
+config USB_ONBOARD_HUB
+       tristate "Generic USB Onboard HUB"
+       help
+         Say Y here if your board has an onboard HUB, and this hub needs
+         to control its PHY clock and reset pin through external signals.
+         If you are not sure, say N.
+
+         To compile this driver as a module, choose M here.
drivers/usb/misc/Makefile +1 -0
index 45fd4ac..da52e9a 100644
@@ -29,3 +29,4 @@ obj-$(CONFIG_USB_CHAOSKEY)            += chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)            += sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)      += lvstest.o
+obj-$(CONFIG_USB_ONBOARD_HUB)          += generic_onboard_hub.o
drivers/usb/misc/generic_onboard_hub.c new file +51 -0
new file mode 100644
index 0000000..df722a0
@@ -0,0 +1,162 @@
+/*
+ * usb_hub_generic.c   The generic onboard USB HUB driver
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Author: Peter Chen <[email protected]>
+ *
+ * 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/>.
+ */
+
+/*
+ * This driver is only for the USB HUB devices which need to control
+ * their external pins(clock, reset, etc), and these USB HUB devices
+ * are soldered at the board.
+ */
+
+#define DEBUG
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/generic_onboard_hub.h>
+
+struct usb_hub_generic_data {
+       struct clk *clk;
+};
+
+static int usb_hub_generic_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct usb_hub_generic_platform_data *pdata = dev->platform_data;
+       struct usb_hub_generic_data *hub_data;
+       int reset_pol = 0, duration_us = 50, ret = 0;
+       struct gpio_desc *gpiod_reset = NULL;
+
+       hub_data = devm_kzalloc(dev, sizeof(*hub_data), GFP_KERNEL);
+       if (!hub_data)

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+               return -ENOMEM;
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Quoted 43 lines
drivers/usb/misc/generic_onboard_hub.c new file +43 -0
+
+               /*
+                * Try to get the information for HUB reset, the
+                * default setting like below:
+                *
+                * - Reset state is low
+                * - The duration is 50us
+                */
+               if (of_find_property(node, "hub-reset-active-high", NULL))
+                       reset_pol = 1;
+
+               of_property_read_u32(node, "hub-reset-duration-us",
+                       &duration_us);
+
+               gpiod_reset = devm_gpiod_get_optional(dev, "hub-reset",
+                       reset_pol ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
+               ret = PTR_ERR_OR_ZERO(gpiod_reset);
+               if (ret) {
+                       dev_err(dev, "Failed to get reset gpio, err = %d\n",
+                               ret);
+                       return ret;
+               }
+       } else if (pdata) {
+               hub_data->clk = pdata->ext_clk;
+               duration_us = pdata->gpio_reset_duration_us;
+               reset_pol = pdata->gpio_reset_polarity;
+
+               if (gpio_is_valid(pdata->gpio_reset)) {
+                       ret = devm_gpio_request_one(
+                               dev, pdata->gpio_reset, reset_pol
+                               ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+                               dev_name(dev));
+                       if (!ret)
+                               gpiod_reset = gpio_to_desc(pdata->gpio_reset);
+               }
+       }
+
+       if (!IS_ERR(hub_data->clk)) {
+               ret = clk_prepare_enable(hub_data->clk);
+               if (ret) {
+                       dev_err(dev,
+                               "Can't enable external clock: %d\n",
+                               ret);

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 10 lines
drivers/usb/misc/generic_onboard_hub.c new file +10 -0
+                       return ret;
+               }
+       }
+
+       if (gpiod_reset) {
+               /* Sanity check */
+               if (duration_us > 1000000)
+                       duration_us = 50;
+               usleep_range(duration_us, duration_us + 100);
+               gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);

What are these hard-coded values? Shouldn't this be taken from the DT? If not then some comments explaining the values would be appreciated.

Quoted 54 lines
drivers/usb/misc/generic_onboard_hub.c new file +48 -0
+       }
+
+       dev_set_drvdata(dev, hub_data);
+       return ret;
+}
+
+static int usb_hub_generic_remove(struct platform_device *pdev)
+{
+       struct usb_hub_generic_data *hub_data = platform_get_drvdata(pdev);
+
+       if (!IS_ERR(hub_data->clk))
+               clk_disable_unprepare(hub_data->clk);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id usb_hub_generic_dt_ids[] = {
+       {.compatible = "generic-onboard-hub"},
+       { },
+};
+MODULE_DEVICE_TABLE(of, usb_hub_generic_dt_ids);
+#endif
+
+static struct platform_driver usb_hub_generic_driver = {
+       .probe = usb_hub_generic_probe,
+       .remove = usb_hub_generic_remove,
+       .driver = {
+               .name = "usb_hub_generic_onboard",
+               .of_match_table = usb_hub_generic_dt_ids,
+        },
+};
+
+static int __init usb_hub_generic_init(void)
+{
+       return platform_driver_register(&usb_hub_generic_driver);
+}
+subsys_initcall(usb_hub_generic_init);
+
+static void __exit usb_hub_generic_exit(void)
+{
+       platform_driver_unregister(&usb_hub_generic_driver);
+}
+module_exit(usb_hub_generic_exit);
+
+MODULE_AUTHOR("Peter Chen <[email protected]>");
+MODULE_DESCRIPTION("Generic Onboard USB HUB driver");
+MODULE_LICENSE("GPL");
include/linux/usb/generic_onboard_hub.h new file +0 -0
new file mode 100644
index 0000000..1b70ccc

include/linux/usb/generic_onboard_hub.h line 9

Quoted 9 lines
include/linux/usb/generic_onboard_hub.h new file +9 -0
@@ -0,0 +1,11 @@
+#ifndef __LINUX_USB_GENERIC_HUB_H
+#define __LINUX_USB_GENERIC_HUB_H
+
+struct usb_hub_generic_platform_data {
+       int gpio_reset;
+       int gpio_reset_polarity;
+       int gpio_reset_duration_us;
+       struct clk *ext_clk;
+};

Please document this structure in accordance with kernel documentation standards.

Quoted 9 lines
include/linux/usb/generic_onboard_hub.h new file +2 -1
+
+#endif /* __LINUX_USB_GENERIC_HUB_H */
--

1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

author
#15 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 13 lines · Mathieu Poirier

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 9 lines · Peter Chen
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

Quoted 9 lines

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 8 lines
drivers/usb/misc/generic_onboard_hub.c new file +8 -0
+       }
+
+       if (gpiod_reset) {
+               /* Sanity check */
+               if (duration_us > 1000000)
+                       duration_us = 50;
+               usleep_range(duration_us, duration_us + 100);
+               gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);
Quoted 3 lines

What are these hard-coded values? Shouldn't this be taken from the DT? If not then some comments explaining the values would be appreciated.

Yes, I did it wrongly, thanks.

Quoted 10 lines
Quoted 10 lines
include/linux/usb/generic_onboard_hub.h new file +4 -0
new file mode 100644
index 0000000..1b70ccc
@@ -0,0 +1,11 @@
+#ifndef __LINUX_USB_GENERIC_HUB_H
+#define __LINUX_USB_GENERIC_HUB_H
+
+struct usb_hub_generic_platform_data {
Quoted 9 lines

include/linux/usb/generic_onboard_hub.h line 9

Quoted 5 lines
include/linux/usb/generic_onboard_hub.h new file +5 -0
+       int gpio_reset;
+       int gpio_reset_polarity;
+       int gpio_reset_duration_us;
+       struct clk *ext_clk;
+};

Please document this structure in accordance with kernel documentation standards.

Thanks, it should be.

Signature · 2 lines
Best Regards,
Peter Chen
#16 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Am Mittwoch, den 09.12.2015, 16:50 +0800 schrieb Peter Chen:

Quoted 15 lines · Mathieu Poirier
Quoted 5 lines · Peter Chen
Quoted 4 lines
drivers/usb/misc/generic_onboard_hub.c new file +4 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Quoted 4 lines

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

If the hub always requires a clock it must not be optional. If you have a fixed 24MHz clock on board add this to the DT as a fixed-clock and use it as an input to the hub.

Quoted 37 lines
Quoted 9 lines

drivers/usb/misc/generic_onboard_hub.c line 114

Quoted 8 lines
drivers/usb/misc/generic_onboard_hub.c new file +8 -0
+       }
+
+       if (gpiod_reset) {
+               /* Sanity check */
+               if (duration_us > 1000000)
+                       duration_us = 50;
+               usleep_range(duration_us, duration_us + 100);
+               gpiod_set_value(gpiod_reset, reset_pol ? 0 : 1);
Quoted 3 lines

What are these hard-coded values? Shouldn't this be taken from the DT? If not then some comments explaining the values would be appreciated.

Yes, I did it wrongly, thanks.

Quoted 10 lines
Quoted 10 lines
include/linux/usb/generic_onboard_hub.h new file +4 -0
new file mode 100644
index 0000000..1b70ccc
@@ -0,0 +1,11 @@
+#ifndef __LINUX_USB_GENERIC_HUB_H
+#define __LINUX_USB_GENERIC_HUB_H
+
+struct usb_hub_generic_platform_data {
Quoted 9 lines

include/linux/usb/generic_onboard_hub.h line 9

Quoted 5 lines
include/linux/usb/generic_onboard_hub.h new file +5 -0
+       int gpio_reset;
+       int gpio_reset_polarity;
+       int gpio_reset_duration_us;
+       struct clk *ext_clk;
+};

Please document this structure in accordance with kernel documentation standards.

Thanks, it should be.

Signature · 2 lines
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |
author
#17 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 16 lines · Lucas Stach

Am Mittwoch, den 09.12.2015, 16:50 +0800 schrieb Peter Chen:

Quoted 15 lines · Mathieu Poirier
Quoted 13 lines · Peter Chen

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Quoted 8 lines
Quoted 4 lines

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

If the hub always requires a clock it must not be optional. If you have a fixed 24MHz clock on board add this to the DT as a fixed-clock and use it as an input to the hub.

This fixed 24MHz clock may from a fixed crystal on board, it is always on, no software need to control it, imx51-bbg board is an example.

Signature · 2 lines
Best Regards,
Peter Chen
#18 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Am Mittwoch, den 09.12.2015, 17:00 +0800 schrieb Peter Chen:

Quoted 21 lines · Lucas Stach
Quoted 20 lines

Am Mittwoch, den 09.12.2015, 16:50 +0800 schrieb Peter Chen:

Quoted 19 lines · Mathieu Poirier
Quoted 5 lines · Peter Chen
Quoted 4 lines
drivers/usb/misc/generic_onboard_hub.c new file +4 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

Quoted 8 lines
Quoted 4 lines

If the hub always requires a clock it must not be optional. If you have a fixed 24MHz clock on board add this to the DT as a fixed-clock and use it as an input to the hub.

This fixed 24MHz clock may from a fixed crystal on board, it is always on, no software need to control it, imx51-bbg board is an example.

And that's wh it is a fixed-clock. Please look it up in the DT binding documentation.

Signature · 2 lines
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |
author
#19 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Best regards,
Peter Chen

Quoted 42 lines

-----Original Message-----
From: Lucas Stach [mailto:l.stach at pengutronix.de]
Sent: Wednesday, December 09, 2015 5:13 PM
To: Chen Peter-B29397 <[email protected]>
Cc: Mathieu Poirier <[email protected]>; Mark Rutland <[email protected]>; devicetree at vger.kernel.org; festevam at gmail.com; Philipp Zabel <[email protected]>; Pawe? Moll <[email protected]>; Greg KH <[email protected]>; linux-usb at vger.kernel.org; patryk at kowalczyk.ws; Rob Herring <[email protected]>;
stern at rowland.harvard.edu; kernel at pengutronix.de; Shawn Guo <[email protected]>; linux-arm-kernel at lists.infradead.org
Subject: Re: [PATCH 1/3] usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Am Mittwoch, den 09.12.2015, 17:00 +0800 schrieb Peter Chen:

Quoted 4 lines · Lucas Stach
Quoted 3 lines

Am Mittwoch, den 09.12.2015, 16:50 +0800 schrieb Peter Chen:

Quoted 2 lines · Mathieu Poirier
Quoted 1 line

On 7 December 2015 at 18:37, Peter Chen <[email protected]>

Quoted 22 lines · wrote:
Quoted 21 lines
Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
drivers/usb/misc/generic_onboard_hub.c new file +4 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
Quoted 8 lines

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 5 lines
drivers/usb/misc/generic_onboard_hub.c new file +5 -0
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Quoted 4 lines

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

If the hub always requires a clock it must not be optional. If you have a fixed 24MHz clock on board add this to the DT as a fixed-clock and use it as an input to the hub.

Quoted 5 lines
Quoted 3 lines

This fixed 24MHz clock may from a fixed crystal on board, it is always on, no software need to control it, imx51-bbg board is an example.

And that's wh it is a fixed-clock. Please look it up in the DT binding documentation.

Yes, I see similar things are described at [1], but why we need this additional entry at dts for this case, it is always on, no software is needed.

[1] Documentation/devicetree/bindings/clock/clock-bindings.txt

Peter

#20 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

In reply to Lucas Stach
Quoted 16 lines · On Wednesday 09 December 2015 09:57:40 Lucas Stach wrote:

Am Mittwoch, den 09.12.2015, 16:50 +0800 schrieb Peter Chen:

Quoted 15 lines · Mathieu Poirier
Quoted 13 lines · Peter Chen

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Quoted 7 lines
Quoted 4 lines

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

If the hub always requires a clock it must not be optional. If you have a fixed 24MHz clock on board add this to the DT as a fixed-clock and use it as an input to the hub.

I think it's fine to make the clock optional in the sense that you only need to list non-fixed clocks that have to be enabled and or controlled.

Which reminds me, should the driver call clk_set_rate()? It currently doesn't, but other machines might need that.

Arnd

author
#21 lore raw

PATCH 1/3 usb: misc: generic_onboard_hub: add generic onboard USB HUB driver

Quoted 25 lines · Arnd Bergmann
Quoted 16 lines · On Wednesday 09 December 2015 09:57:40 Lucas Stach wrote:

Am Mittwoch, den 09.12.2015, 16:50 +0800 schrieb Peter Chen:

Quoted 15 lines · Mathieu Poirier
Quoted 13 lines · Peter Chen

drivers/usb/misc/generic_onboard_hub.c line 61

Quoted 9 lines
drivers/usb/misc/generic_onboard_hub.c new file +9 -0
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               hub_data->clk = devm_clk_get(dev, "external_clk");
+               if (IS_ERR(hub_data->clk)) {
+                       dev_dbg(dev, "Can't get external clock: %ld\n",
+                                       PTR_ERR(hub_data->clk));
+               }

Is the intended behaviour to keep going here event when there is an error? Can the "hub_data" really work without a clock?

Quoted 7 lines
Quoted 4 lines

Yes, some HUB may work with fixed 24M OSC at the board, but they need to reset through external IO, so the clock is not need at this case, but reset pin is mandatory.

If the hub always requires a clock it must not be optional. If you have a fixed 24MHz clock on board add this to the DT as a fixed-clock and use it as an input to the hub.

Quoted 6 lines

I think it's fine to make the clock optional in the sense that you only need to list non-fixed clocks that have to be enabled and or controlled.

Which reminds me, should the driver call clk_set_rate()? It currently doesn't, but other machines might need that.

Yes, you are right, I will add it at v2.

Signature · 2 lines
Best Regards,
Peter Chen
author
#22 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

In reply to Peter Chen

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +28 -0
new file mode 100644
index 0000000..ea92205
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"
+
+Optional properties:
+- clocks: the input clock for HUB.
+
+- clock-names: Should be "external_clk"
+
+- hub-reset-gpios: Should specify the GPIO for reset.
+
+- hub-reset-active-high: the active reset signal is high, if this property is
+  not set, the active reset signal is low.
+
+- hub-reset-duration-us: the duration for assert reset signal, the time unit
+  is microsecond.
+
+Example:
+
+	usb_hub1 {
+		compatible = "generic-onboard-hub";
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		clock-names = "external_clk";
+		hub-reset-gpios = <&gpio7 12 0>;
+		hub-reset-active-high;
+		hub-reset-duration-us = <2>;
+	};
Signature · 1 line
1.9.1
reviewer
#23 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 30 lines · Peter Chen

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +16 -0
new file mode 100644
index 0000000..ea92205
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"
+
+Optional properties:
+- clocks: the input clock for HUB.
+
+- clock-names: Should be "external_clk"
+
+- hub-reset-gpios: Should specify the GPIO for reset.
+
+- hub-reset-active-high: the active reset signal is high, if this property is
+  not set, the active reset signal is low.
+
+- hub-reset-duration-us: the duration for assert reset signal, the time unit

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 26

Quoted 10 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +10 -0
+  is microsecond.
+
+Example:
+
+       usb_hub1 {
+               compatible = "generic-onboard-hub";
+               clocks = <&clks IMX6QDL_CLK_CKO>;
+               clock-names = "external_clk";
+               hub-reset-gpios = <&gpio7 12 0>;
+               hub-reset-active-high;

I think you could drop the 'hub-reset-active-high' property and do like this instead:

hub-reset-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>;

or

hub-reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;

author
#24 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 45 lines · Fabio Estevam
Quoted 30 lines · Peter Chen

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +16 -0
new file mode 100644
index 0000000..ea92205
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"
+
+Optional properties:
+- clocks: the input clock for HUB.
+
+- clock-names: Should be "external_clk"
+
+- hub-reset-gpios: Should specify the GPIO for reset.
+
+- hub-reset-active-high: the active reset signal is high, if this property is
+  not set, the active reset signal is low.
+
+- hub-reset-duration-us: the duration for assert reset signal, the time unit

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 26

Quoted 10 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +10 -0
+  is microsecond.
+
+Example:
+
+       usb_hub1 {
+               compatible = "generic-onboard-hub";
+               clocks = <&clks IMX6QDL_CLK_CKO>;
+               clock-names = "external_clk";
+               hub-reset-gpios = <&gpio7 12 0>;
+               hub-reset-active-high;

I think you could drop the 'hub-reset-active-high' property and do like this instead:

Quoted 5 lines

hub-reset-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>;

or

hub-reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;

Yes, you are right, would you have a test to see if can work for udoo board?

Signature · 2 lines
Best Regards,
Peter Chen
#25 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 10 lines · On Tuesday 08 December 2015 17:20:46 Peter Chen wrote:
Quoted 9 lines · Fabio Estevam
Quoted 8 lines · Peter Chen

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Quoted 15 lines
Quoted 7 lines
Quoted 7 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +1 -0
new file mode 100644
index 0000000..ea92205
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
Quoted 8 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 9

Quoted 8 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +8 -0
+
+Required properties:
+- compatible: should be "generic-onboard-hub"
+
+Optional properties:
+- clocks: the input clock for HUB.
+
+- clock-names: Should be "external_clk"

Make this just "external", or remove the name and use it as an anonymous clock.

Quoted 7 lines
Quoted 7 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 17

Quoted 7 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +7 -0
+- hub-reset-gpios: Should specify the GPIO for reset.
+
+- hub-reset-active-high: the active reset signal is high, if this property is
+  not set, the active reset signal is low.
+
+- hub-reset-duration-us: the duration for assert reset signal, the time unit
+  is microsecond.

Remove the "hub-" prefix here.

Quoted 12 lines
Quoted 12 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 26

Quoted 8 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +8 -0
+Example:
+
+       usb_hub1 {
+               compatible = "generic-onboard-hub";
+               clocks = <&clks IMX6QDL_CLK_CKO>;
+               clock-names = "external_clk";
+               hub-reset-gpios = <&gpio7 12 0>;
+               hub-reset-active-high;

I think you could drop the 'hub-reset-active-high' property and do like this instead:

Quoted 8 lines
Quoted 5 lines

hub-reset-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>;

or

hub-reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;

Yes, you are right, would you have a test to see if can work for udoo board?

Yes, it should be done like this.

Arnd

#26 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

In reply to Peter Chen

Hi Peter,

Am Dienstag, den 08.12.2015, 09:37 +0800 schrieb Peter Chen:

Quoted 14 lines

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +0 -0
new file mode 100644
index 0000000..ea92205

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 4

Quoted 4 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 9

Quoted 4 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
+Optional properties:
+- clocks: the input clock for HUB.
+
+- clock-names: Should be "external_clk"

Is clock-names necessary for a single clock?

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 11

Quoted 1 line
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +1 -0
+- hub-reset-gpios: Should specify the GPIO for reset.

I'd prefer that to be just "reset-gpios", it is the only reset property in the hub node after all. And use the GPIO_ACTIVE_HIGH/LOW flags to indicate polarity.

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 14

Quoted 2 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +2 -0
+- hub-reset-active-high: the active reset signal is high, if this property is
+  not set, the active reset signal is low.

Then this could be dropped.

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 17

Quoted 2 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +2 -0
+- hub-reset-duration-us: the duration for assert reset signal, the time unit
+  is microsecond.

And consequently, this could just be called "reset-duration-us". It might make sense to define the same for other reset GPIOs, too. The Freescale FEC, for example, has "phy-reset-duration" (in ms) already.

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 28

Quoted 11 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +11 -0
+
+Example:
+
+	usb_hub1 {
+		compatible = "generic-onboard-hub";
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		clock-names = "external_clk";
+		hub-reset-gpios = <&gpio7 12 0>;
+		hub-reset-active-high;
+		hub-reset-duration-us = <2>;
+	};

best regards
Philipp

#27 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 26 lines · On Tuesday 08 December 2015 10:50:49 Philipp Zabel wrote:

Am Dienstag, den 08.12.2015, 09:37 +0800 schrieb Peter Chen:

Quoted 14 lines

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +0 -0
new file mode 100644
index 0000000..ea92205

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 4

Quoted 4 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Quoted 5 lines

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Good point, I had not thought of that when I looked at the patches.

Yes, let's do this way. I don't know if we ever implemented the simple patch to associate a USB device with a device_node, but if not, then let's do it now for this driver. A lot of people have asked for it in the past.

Arnd

maintainer
#28 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 33 lines · Arnd Bergmann
Quoted 26 lines · On Tuesday 08 December 2015 10:50:49 Philipp Zabel wrote:

Am Dienstag, den 08.12.2015, 09:37 +0800 schrieb Peter Chen:

Quoted 14 lines

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +0 -0
new file mode 100644
index 0000000..ea92205

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 4

Quoted 4 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Quoted 5 lines

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Quoted 6 lines

Good point, I had not thought of that when I looked at the patches.

Yes, let's do this way. I don't know if we ever implemented the simple patch to associate a USB device with a device_node, but if not, then let's do it now for this driver. A lot of people have asked for it in the past.

Agreed. Also, some hubs have I2C buses as well, but I still think under the USB bus is the right place.

However, one complication here is often (probably this case) these addtional signals need to be controlled before the device enumerates.

Rob

author
#29 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 41 lines · Rob Herring
Quoted 33 lines · Arnd Bergmann
Quoted 26 lines · On Tuesday 08 December 2015 10:50:49 Philipp Zabel wrote:

Am Dienstag, den 08.12.2015, 09:37 +0800 schrieb Peter Chen:

Quoted 14 lines

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +0 -0
new file mode 100644
index 0000000..ea92205

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 4

Quoted 4 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Quoted 5 lines

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Quoted 6 lines

Good point, I had not thought of that when I looked at the patches.

Yes, let's do this way. I don't know if we ever implemented the simple patch to associate a USB device with a device_node, but if not, then let's do it now for this driver. A lot of people have asked for it in the past.

Quoted 6 lines

Agreed. Also, some hubs have I2C buses as well, but I still think under the USB bus is the right place.

However, one complication here is often (probably this case) these addtional signals need to be controlled before the device enumerates.

Yes, I did not find a way to let the USB bus code handle it, so I had to write a platform driver to do it

Signature · 2 lines
Best Regards,
Peter Chen
#30 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 25 lines · On Wednesday 09 December 2015 16:12:24 Peter Chen wrote:
Quoted 24 lines · Rob Herring
Quoted 13 lines · Arnd Bergmann
Quoted 11 lines · On Tuesday 08 December 2015 10:50:49 Philipp Zabel wrote:

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Quoted 6 lines

Good point, I had not thought of that when I looked at the patches.

Yes, let's do this way. I don't know if we ever implemented the simple patch to associate a USB device with a device_node, but if not, then let's do it now for this driver. A lot of people have asked for it in the past.

Agreed. Also, some hubs have I2C buses as well, but I still think under the USB bus is the right place.

Quoted 6 lines
Quoted 3 lines

However, one complication here is often (probably this case) these addtional signals need to be controlled before the device enumerates.

Yes, I did not find a way to let the USB bus code handle it, so I had to write a platform driver to do it

Looping in Ulf, he solved the same problem for SDIO devices recently, and probably remembers the details best.

Arnd

#31 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 30 lines · Arnd Bergmann
Quoted 29 lines · On Wednesday 09 December 2015 16:12:24 Peter Chen wrote:
Quoted 27 lines · Rob Herring
Quoted 13 lines · Arnd Bergmann
Quoted 11 lines · On Tuesday 08 December 2015 10:50:49 Philipp Zabel wrote:

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Quoted 6 lines

Good point, I had not thought of that when I looked at the patches.

Yes, let's do this way. I don't know if we ever implemented the simple patch to associate a USB device with a device_node, but if not, then let's do it now for this driver. A lot of people have asked for it in the past.

Agreed. Also, some hubs have I2C buses as well, but I still think under the USB bus is the right place.

However, one complication here is often (probably this case) these addtional signals need to be controlled before the device enumerates.

Quoted 6 lines
Quoted 2 lines

Yes, I did not find a way to let the USB bus code handle it, so I had to write a platform driver to do it

Looping in Ulf, he solved the same problem for SDIO devices recently, and probably remembers the details best.

Thanks Arnd!

Yes, that was a kind of a long outstanding issue we have had for SDIO devices.

Several generic attempts was made to have a framework/library available to support so called "power sequences" for exactly the same reasons as above.
Others and myself failed to get those attempts accepted.

Instead, I invented a mmc subsystem specific DT based solution, the "mmc-pwrseq".

DT documentation:
Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt Documentation/devicetree/bindings/mmc/mmc.txt

Long story short: The mmc host device may contain a phandle to a mmc-pwrseq, which will describe the resources needed to power on/off the SDIO card.

The code is available at:
drivers/mmc/core/pwrseq*

We didn't implement this as platform driver, but that was mostly because I initially wanted things to be simple. Although, nothing prevents us from converting to this as a follow up, which would make the solution a bit less "hacky".

Kind regards
Uffe

author
#32 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

Quoted 58 lines · Ulf Hansson
Quoted 30 lines · Arnd Bergmann
Quoted 29 lines · On Wednesday 09 December 2015 16:12:24 Peter Chen wrote:
Quoted 27 lines · Rob Herring
Quoted 13 lines · Arnd Bergmann
Quoted 11 lines · On Tuesday 08 December 2015 10:50:49 Philipp Zabel wrote:

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Quoted 6 lines

Good point, I had not thought of that when I looked at the patches.

Yes, let's do this way. I don't know if we ever implemented the simple patch to associate a USB device with a device_node, but if not, then let's do it now for this driver. A lot of people have asked for it in the past.

Agreed. Also, some hubs have I2C buses as well, but I still think under the USB bus is the right place.

However, one complication here is often (probably this case) these addtional signals need to be controlled before the device enumerates.

Quoted 6 lines
Quoted 2 lines

Yes, I did not find a way to let the USB bus code handle it, so I had to write a platform driver to do it

Looping in Ulf, he solved the same problem for SDIO devices recently, and probably remembers the details best.

Thanks Arnd!

Yes, that was a kind of a long outstanding issue we have had for SDIO devices.

Several generic attempts was made to have a framework/library available to support so called "power sequences" for exactly the same reasons as above.
Others and myself failed to get those attempts accepted.

Instead, I invented a mmc subsystem specific DT based solution, the "mmc-pwrseq".

DT documentation:
Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt Documentation/devicetree/bindings/mmc/mmc.txt

Long story short: The mmc host device may contain a phandle to a mmc-pwrseq, which will describe the resources needed to power on/off the SDIO card.

Quoted 8 lines

The code is available at:
drivers/mmc/core/pwrseq*

We didn't implement this as platform driver, but that was mostly because I initially wanted things to be simple. Although, nothing prevents us from converting to this as a follow up, which would make the solution a bit less "hacky".

Thanks for your information, Ulf.

Signature · 2 lines
Best Regards,
Peter Chen
author
#33 lore raw

PATCH 2/3 doc: dt-binding: generic onboard USB HUB

In reply to Philipp Zabel
Quoted 28 lines · Philipp Zabel

Hi Peter,

Am Dienstag, den 08.12.2015, 09:37 +0800 schrieb Peter Chen:

Quoted 14 lines

Add dt-binding documentation for generic onboard USB HUB.

---
 .../bindings/usb/generic-onboard-hub.txt           | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/generic-onboard-hub.txt
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +0 -0
new file mode 100644
index 0000000..ea92205

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 4

Quoted 4 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
@@ -0,0 +1,28 @@
+Generic Onboard USB HUB
+
+Required properties:
+- compatible: should be "generic-onboard-hub"

This something we don't have to define ad-hoc. The hub hangs off an USB controller, right? The "Open Firmware recommended practice: USB" document already describes how to represent USB devices in a generic manner:
http://www.firmware.org/1275/bindings/usb/usb-1_0.ps

Quoted 6 lines

Is there a reason not to reuse this?

The usb hub node would be a child of the usb controller node, and it could use
compatible = "usb,class9"; /* bDeviceClass 9 (Hub) */

Before writing this driver, I did consider how to let the USB core handle device tree, but without good solution.

The controller (platform) driver should not handle specific USB device described at device tree, since we want this handling to be generic. And the USB device may not be recognized by controller without handling its properties, like clock, reset pins.

With your suggestion, the dts likes below

usbh1: usb at 02184000 {
	compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
	reg = <0x02184000 0x200>;
	interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clks IMX6QDL_CLK_USBOH3>;
	usb_hub at 1 {
		compatible = "usb,class9"
		clocks = <&clks USB_HUB_CLK>;
		....
	};
};

I don't know how to handle above at USB bus, if you have any suggestions, give me some tips please.

Quoted 8 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 9

Quoted 5 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +4 -0
+Optional properties:
+- clocks: the input clock for HUB.
+
+- clock-names: Should be "external_clk"

Is clock-names necessary for a single clock?

Quoted 5 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 11

Quoted 1 line
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +1 -0
+- hub-reset-gpios: Should specify the GPIO for reset.

I'd prefer that to be just "reset-gpios", it is the only reset property in the hub node after all. And use the GPIO_ACTIVE_HIGH/LOW flags to indicate polarity.

I will change to "clk" and "reset-gpios".

Quoted 6 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 14

Quoted 3 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +2 -0
+- hub-reset-active-high: the active reset signal is high, if this property is
+  not set, the active reset signal is low.

Then this could be dropped.

Quoted 8 lines

Documentation/devicetree/bindings/usb/generic-onboard-hub.txt line 17

Quoted 2 lines
Documentation/devicetree/bindings/usb/generic-onboard-hub.txt new file +2 -0
+- hub-reset-duration-us: the duration for assert reset signal, the time unit
+  is microsecond.

And consequently, this could just be called "reset-duration-us". It might make sense to define the same for other reset GPIOs, too. The Freescale FEC, for example, has "phy-reset-duration" (in ms) already.

Agree.

By the way: Felipe suggest using generic reset gpio driver to handle above, I find you have written similar things before [1], why it can't be accepted?

[1]http://comments.gmane.org/gmane.linux.ports.arm.kernel/255129

Signature · 2 lines
Best Regards,
Peter Chen
author
#34 lore raw

PATCH 3/3 ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB property

In reply to Peter Chen

The current dts describes USB HUB's property at USB controller's entry, it is improper. Fix it by using a generic USB HUB entry.

---
 arch/arm/boot/dts/imx6qdl-udoo.dtsi | 25 ++++++-------------------
 1 file changed, 6 insertions(+), 19 deletions(-)
arch/arm/boot/dts/imx6qdl-udoo.dtsi +6 -19
index 1211da8..9416d75 100644
@@ -18,21 +18,12 @@
 		reg = <0x10000000 0x40000000>;
 	};
 
-	regulators {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		reg_usb_h1_vbus: regulator at 0 {
-			compatible = "regulator-fixed";
-			reg = <0>;
-			regulator-name = "usb_h1_vbus";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			enable-active-high;
-			startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */
-			gpio = <&gpio7 12 0>;
-		};
+	usb_hub1 {
+		compatible = "generic-onboard-hub";
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		clock-names = "external_clk";
+		hub-reset-gpios = <&gpio7 12 0>;
+		hub-reset-duration-us = <2>;
 	};
 };
 
@@ -119,10 +110,6 @@
 };
 
 &usbh1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbh>;
-	vbus-supply = <&reg_usb_h1_vbus>;
-	clocks = <&clks 201>;
 	status = "okay";
 };
 
Signature · 1 line
1.9.1