[PATCH] USB: isp1362: Add devicetree support
Grant Likely
grant.likely at secretlab.ca
Tue Aug 9 04:37:49 EST 2011
On Tue, Aug 2, 2011 at 7:49 AM, Tobias Klauser <tklauser at distanz.ch> wrote:
> Signed-off-by: Tobias Klauser <tklauser at distanz.ch>
> ---
No commit text?
> .../devicetree/bindings/usb/isp1362-hcd.txt | 23 +++++
> drivers/usb/host/isp1362-hcd.c | 93 +++++++++++++++++++-
> 2 files changed, 113 insertions(+), 3 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/usb/isp1362-hcd.txt
>
> diff --git a/Documentation/devicetree/bindings/usb/isp1362-hcd.txt b/Documentation/devicetree/bindings/usb/isp1362-hcd.txt
> new file mode 100644
> index 0000000..9641a82
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/isp1362-hcd.txt
Woo! Documentation!
> @@ -0,0 +1,23 @@
> +NXP ISP1362 USB host controller
> +
> +Required properties :
> + - compatible : should be "nxp,usb-isp1362"
> + - reg : offset and length of the register set for the device
> + - interrupts : interrupt number
> +
> +Optional properties :
> + - nxp,sel15Kres: boolean; Enable internal pulldown resistors on downstream
> + ports.
> + - nxp,clknotstop: boolean; Clock cannot be stopped
> + - nxp,oc_enable: boolean; Enable on-chip overcurrent protection
'-' is preferred to '_' on property names.
> + - nxp,int_act_high: boolean; INT output polarity high
> + - nxp,int_edge_triggered: boolean; INT edge triggered
Typically interupt polarity/sense is encoded in the flags of the
interrupt specifier.
> + - nxp,dreq_act_high: boolean; DREQ output polarity high
> + - nxp,dack_act_high: boolean; DACK input polarity high
> + - nxp,remote_wakeup_connected: boolean; chip can be resumed via H_WAKEUP pin
> + - nxp,no_power_switching: boolean; Switch or not to switch (keep always
> + powered)
> + - nxp,power_switching_mode: boolean; Ganged port power switching (0) or
> + individual port power switching (1)
> + - nxp,potpg: Power on to power good time (duration the host controller has to
> + wait before accessing a power-on-port of the root hub) in units of 2 msecs.
The documentation is a little unclear. I assume you mean that each of
the boolean options defaults to false, and becomes true if the named
property is present. Is that correct? You may want to do some
wordsmithing here. The nxp,power_switching_mode property appears to
expect an integer instead of being a boolean based on the presense of
a property
> diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
> index 9c37dad..dbf6f16 100644
> --- a/drivers/usb/host/isp1362-hcd.c
> +++ b/drivers/usb/host/isp1362-hcd.c
> @@ -78,6 +78,7 @@
> #include <linux/usb/isp1362.h>
> #include <linux/usb/hcd.h>
> #include <linux/platform_device.h>
> +#include <linux/of.h>
> #include <linux/pm.h>
> #include <linux/io.h>
> #include <linux/bitmap.h>
> @@ -2678,13 +2679,62 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
> usb_put_hcd(hcd);
> DBG(0, "%s: Done\n", __func__);
>
> + /*
> + * If we had no platform_data, we allocated the board struct
> + * dynamically and filled it from device tree.
> + */
> + if (!pdev->dev.platform_data)
> + kfree(isp1362_hcd->board);
If the driver used devm_kzalloc(), it wouldn't have to free the data on exit.
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_OF
> +
> +/*
> + * Translate device tree nodes to platform data.
> + */
> +static int isp1362_get_devtree_pdata(struct platform_device *pdev,
> + struct isp1362_platform_data *pdata)
> +{
> + struct device_node *node = pdev->dev.of_node;
> + const __be32 *reg;
> + int len;
> +
> + if (!node)
> + return -ENODEV;
> +
> + pdata->sel15Kres = !!of_get_property(node, "nxp,sel15Kres", NULL);
> + pdata->clknotstop = !!of_get_property(node, "nxp,clknotstop", NULL);
> + pdata->oc_enable = !!of_get_property(node, "nxp,oc_enable", NULL);
> + pdata->int_act_high = !!of_get_property(node, "nxp,int_act_high", NULL);
> + pdata->int_edge_triggered =
> + !!of_get_property(node, "nxp,int_edge_triggered", NULL);
> + pdata->remote_wakeup_connected =
> + !!of_get_property(node, "nxp,remote_wakeup_connected", NULL);
> + pdata->no_power_switching =
> + !!of_get_property(node, "nxp,no_power_switching", NULL);
> + pdata->power_switching_mode =
> + !!of_get_property(node, "nxp,power_switching_mode", NULL);
> + reg = of_get_property(node, "nxp,potpg", &len);
> + if (reg && len == sizeof(__be32))
> + pdata->potpg = be32_to_cpup(reg);
of_property_read_u32() will help here.
> +
> return 0;
> }
> +#else
> +static int isp1362_get_devtree_pdata(struct platform_device *pdev,
> + struct isp1362_platform_data *pdata)
> +{
> + return -ENODEV;
> +}
> +#endif /* CONFIG_OF */
>
> static int __devinit isp1362_probe(struct platform_device *pdev)
> {
> struct usb_hcd *hcd;
> struct isp1362_hcd *isp1362_hcd;
> + struct isp1362_platform_data *pdata;
> struct resource *addr, *data;
> void __iomem *addr_reg;
> void __iomem *data_reg;
> @@ -2755,12 +2805,31 @@ static int __devinit isp1362_probe(struct platform_device *pdev)
> INIT_LIST_HEAD(&isp1362_hcd->periodic);
> INIT_LIST_HEAD(&isp1362_hcd->isoc);
> INIT_LIST_HEAD(&isp1362_hcd->remove_list);
> - isp1362_hcd->board = pdev->dev.platform_data;
> +
> + pdata = pdev->dev.platform_data;
> +
> + /* If no platform data is available, try to get it from device tree */
> + if (!pdata) {
> + pdata = kzalloc(sizeof(struct isp1362_platform_data), GFP_KERNEL);
> + if (!pdata) {
> + retval = -ENOMEM;
> + goto err6;
> + }
> +
> + retval = isp1362_get_devtree_pdata(pdev, pdata);
> + if (retval) {
> + kfree(pdata);
> + goto err6;
> + }
> + }
The kzalloc could be rolled into isp1362_get_devtree_pdata() to
simplify the impact on the probe hook.
> +
> + isp1362_hcd->board = pdata;
> +
> #if USE_PLATFORM_DELAY
> if (!isp1362_hcd->board->delay) {
> dev_err(hcd->self.controller, "No platform delay function given\n");
> retval = -ENODEV;
> - goto err6;
> + goto err7;
> }
> #endif
>
> @@ -2775,13 +2844,20 @@ static int __devinit isp1362_probe(struct platform_device *pdev)
>
> retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_DISABLED | IRQF_SHARED);
> if (retval != 0)
> - goto err6;
> + goto err7;
> pr_info("%s, irq %d\n", hcd->product_desc, irq);
>
> create_debug_file(isp1362_hcd);
>
> return 0;
>
> +err7:
> + /*
> + * If we have no platform_data, we allocated the board struct
> + * dynamically.
> + */
> + if (!pdev->dev.platform_data)
> + kfree(isp1362_hcd->board);
This also would disappear when using devm_kzalloc()
> err6:
> DBG(0, "%s: Freeing dev %p\n", __func__, isp1362_hcd);
> usb_put_hcd(hcd);
> @@ -2852,6 +2928,16 @@ static int isp1362_resume(struct platform_device *pdev)
> #define isp1362_resume NULL
> #endif
>
> +#ifdef CONFIG_OF
> +static struct of_device_id isp1362_match[] = {
> + { .compatible = "nxp,usb-isp1362", },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, isp1362_match);
> +#else
> +#define isp1362_match NULL
> +#endif /* CONFIG_OF */
> +
> static struct platform_driver isp1362_driver = {
> .probe = isp1362_probe,
> .remove = __devexit_p(isp1362_remove),
> @@ -2861,6 +2947,7 @@ static struct platform_driver isp1362_driver = {
> .driver = {
> .name = (char *)hcd_name,
> .owner = THIS_MODULE,
> + .of_match_table = isp1362_match,
> },
> };
>
> --
> 1.7.5.4
>
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
More information about the devicetree-discuss
mailing list