From: Peter Chen <peter.chen@nxp.com>
To: Matthias Kaehlcke <mka@chromium.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh+dt@kernel.org>,
Frank Rowand <frowand.list@gmail.com>,
Alan Stern <stern@rowland.harvard.edu>,
Krzysztof Kozlowski <krzk@kernel.org>,
Bastien Nocera <hadess@hadess.net>,
Ravi Chandra Sadineni <ravisadineni@chromium.org>,
"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
Stephen Boyd <swboyd@chromium.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
Douglas Anderson <dianders@chromium.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"Alexander A. Klimov" <grandmaster@al2klimov.de>,
Masahiro Yamada <masahiroy@kernel.org>
Subject: Re: [PATCH 2/2] USB: misc: Add onboard_usb_hub driver
Date: Tue, 15 Sep 2020 02:55:06 +0000 [thread overview]
Message-ID: <20200915025426.GA17450@b29397-desktop> (raw)
In-Reply-To: <20200914112716.2.I7c9a1f1d6ced41dd8310e8a03da666a32364e790@changeid>
On 20-09-14 11:27:49, Matthias Kaehlcke wrote:
> The main issue this driver addresses is that a USB hub needs to be
> powered before it can be discovered. For onboard hubs this is often
> solved by supplying the hub with an 'always-on' regulator, which is
> kind of a hack. Some onboard hubs may require further initialization
> steps, like changing the state of a GPIO or enabling a clock, which
> requires further hacks. This driver creates a platform device
> representing the hub which performs the necessary initialization.
> Currently it only supports switching on a single regulator, support
> for multiple regulators or other actions can be added as needed.
> Different initialization sequences can be supported based on the
> compatible string.
>
> Besides performing the initialization the driver can be configured
> to power the hub off during system suspend. This can help to extend
> battery life on battery powered devices, which have no requirements
> to keep the hub powered during suspend. The driver can also be
> configured to leave the hub powered when a wakeup capable USB device
> is connected when suspending, and keeping it powered otherwise.
>
> Technically the driver consists of two drivers, the platform driver
> described above and a very thin USB driver that subclasses the
> generic hub driver. The purpose of this driver is to provide the
> platform driver with the USB devices corresponding to the hub(s)
> (a hub controller may provide multiple 'logical' hubs, e.g. one
> to support USB 2.0 and another for USB 3.x).
I agree with Alan, you may change this driver to apply for generic
onboard USB devices.
> +static int onboard_hub_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct onboard_hub *hub;
> +
> + hub = devm_kzalloc(dev, sizeof(*hub), GFP_KERNEL);
> + if (!hub)
> + return -ENOMEM;
> +
> + hub->vdd = devm_regulator_get(dev, "vdd");
> + if (IS_ERR(hub->vdd))
> + return PTR_ERR(hub->vdd);
> +
> + hub->dev = dev;
> + mutex_init(&hub->lock);
> + INIT_LIST_HEAD(&hub->udev_list);
> +
> + hub->cfg.power_off_in_suspend = of_property_read_bool(dev->of_node, "power-off-in-suspend");
> + hub->cfg.wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source");
Do you really need these two properties? If the device (and its children
if existed) has wakeup enabled, you keep power in suspend, otherwise,
you could close it, any exceptions?
Peter
> +
> + dev_set_drvdata(dev, hub);
> +
> + return onboard_hub_power_on(hub);
> +}
> +
> +static int onboard_hub_remove(struct platform_device *pdev)
> +{
> + struct onboard_hub *hub = dev_get_drvdata(&pdev->dev);
> +
> + return onboard_hub_power_off(hub);
> +}
> +
> +static const struct of_device_id onboard_hub_match[] = {
> + { .compatible = "onboard-usb-hub" },
> + { .compatible = "realtek,rts5411" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, onboard_hub_match);
> +
> +static struct platform_driver onboard_hub_driver = {
> + .probe = onboard_hub_probe,
> + .remove = onboard_hub_remove,
> +#ifdef CONFIG_PM
> + .suspend = onboard_hub_suspend,
> + .resume = onboard_hub_resume,
> +#endif
> + .driver = {
> + .name = "onboard-usb-hub",
> + .of_match_table = onboard_hub_match,
> + },
> +};
> +
> +/************************** USB driver **************************/
> +
> +#define VENDOR_ID_REALTEK 0x0bda
> +
> +static struct onboard_hub *_find_onboard_hub(struct device *dev)
> +{
> + const phandle *ph;
> + struct device_node *np;
> + struct platform_device *pdev;
> +
> + ph = of_get_property(dev->of_node, "hub", NULL);
> + if (!ph) {
> + dev_err(dev, "failed to read 'hub' property\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + np = of_find_node_by_phandle(be32_to_cpu(*ph));
> + if (!np) {
> + dev_err(dev, "failed find device node for onboard hub\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + pdev = of_find_device_by_node(np);
> + of_node_put(np);
> + if (!pdev)
> + return ERR_PTR(-EPROBE_DEFER);
> +
> + return dev_get_drvdata(&pdev->dev);
> +}
> +
> +static int onboard_hub_usbdev_probe(struct usb_device *udev)
> +{
> + struct device *dev = &udev->dev;
> + struct onboard_hub *hub;
> +
> + /* ignore supported hubs without device tree node */
> + if (!dev->of_node)
> + return -ENODEV;
> +
> + hub = _find_onboard_hub(dev);
> + if (IS_ERR(hub))
> + return PTR_ERR(dev);
> +
> + dev_set_drvdata(dev, hub);
> +
> + onboard_hub_add_usbdev(hub, udev);
> +
> + return 0;
> +}
> +
> +static void onboard_hub_usbdev_disconnect(struct usb_device *udev)
> +{
> + struct onboard_hub *hub = dev_get_drvdata(&udev->dev);
> +
> + onboard_hub_remove_usbdev(hub, udev);
> +
> + put_device(hub->dev);
> +}
> +
> +static const struct usb_device_id onboard_hub_id_table[] = {
> + { .idVendor = VENDOR_ID_REALTEK,
> + .idProduct = 0x0411, /* RTS5411 USB 3.0 */
> + .match_flags = USB_DEVICE_ID_MATCH_DEVICE },
> + { .idVendor = VENDOR_ID_REALTEK,
> + .idProduct = 0x5411, /* RTS5411 USB 2.0 */
> + .match_flags = USB_DEVICE_ID_MATCH_DEVICE },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(usb, onboard_hub_id_table);
> +
> +static struct usb_device_driver onboard_hub_usbdev_driver = {
> +
> + .name = "onboard-usb-hub",
> + .probe = onboard_hub_usbdev_probe,
> + .disconnect = onboard_hub_usbdev_disconnect,
> + .generic_subclass = 1,
> + .supports_autosuspend = 1,
> + .id_table = onboard_hub_id_table,
> +};
> +
> +/************************** Driver (de)registration **************************/
> +
> +static int __init onboard_hub_init(void)
> +{
> + int rc;
> +
> + rc = platform_driver_register(&onboard_hub_driver);
> + if (rc)
> + return rc;
> +
> + return usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE);
> +}
> +device_initcall(onboard_hub_init);
> +
> +static void __exit onboard_hub_exit(void)
> +{
> + usb_deregister_device_driver(&onboard_hub_usbdev_driver);
> + platform_driver_unregister(&onboard_hub_driver);
> +}
> +module_exit(onboard_hub_exit);
> +
> +MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
> +MODULE_DESCRIPTION("Onboard USB Hub driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.28.0.618.gf4bc123cb7-goog
>
--
Thanks,
Peter Chen
next prev parent reply other threads:[~2020-09-15 2:55 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-14 18:27 [PATCH 1/2] dt-bindings: usb: Add binding for onboard USB hubs Matthias Kaehlcke
2020-09-14 18:27 ` [PATCH 2/2] USB: misc: Add onboard_usb_hub driver Matthias Kaehlcke
2020-09-14 19:52 ` Matthias Kaehlcke
2020-09-14 20:14 ` Alan Stern
2020-09-14 21:14 ` Matthias Kaehlcke
2020-09-15 2:32 ` kernel test robot
2020-09-15 2:55 ` Peter Chen [this message]
2020-09-15 5:02 ` Matthias Kaehlcke
2020-09-15 7:05 ` Peter Chen
2020-09-15 23:03 ` Matthias Kaehlcke
2020-09-16 2:14 ` Alan Stern
2020-09-16 19:27 ` Matthias Kaehlcke
2020-09-16 8:19 ` Peter Chen
2020-09-16 19:16 ` Matthias Kaehlcke
2020-09-17 0:27 ` Peter Chen
2020-09-17 0:47 ` Matthias Kaehlcke
2020-09-17 1:24 ` Peter Chen
2020-09-17 15:54 ` Matthias Kaehlcke
2020-09-15 14:21 ` [PATCH 1/2] dt-bindings: usb: Add binding for onboard USB hubs Rob Herring
2020-09-16 0:00 ` Matthias Kaehlcke
2020-09-18 16:05 ` Rob Herring
2020-09-22 23:39 ` Matthias Kaehlcke
2020-09-15 14:21 ` Rob Herring
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200915025426.GA17450@b29397-desktop \
--to=peter.chen@nxp.com \
--cc=devicetree@vger.kernel.org \
--cc=dianders@chromium.org \
--cc=frowand.list@gmail.com \
--cc=grandmaster@al2klimov.de \
--cc=gregkh@linuxfoundation.org \
--cc=hadess@hadess.net \
--cc=krzk@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=mka@chromium.org \
--cc=ravisadineni@chromium.org \
--cc=robh+dt@kernel.org \
--cc=stern@rowland.harvard.edu \
--cc=swboyd@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.