diff mbox

[v2,2/2] USB: ehci-tegra: add probing through device tree

Message ID 1320433960-18173-2-git-send-email-olof@lixom.net
State Accepted, archived
Headers show

Commit Message

Olof Johansson Nov. 4, 2011, 7:12 p.m. UTC
Rely on platform_data being passed through auxdata for now; more elaborate
bindings for phy config and tunings to be added.

v2: moved vbus-gpio check to the helper function, added check for !of_node,
    added usb2 clock to board-dt table.

Signed-off-by: Olof Johansson <olof@lixom.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
---
 arch/arm/mach-tegra/board-dt.c |    9 +++++
 drivers/usb/host/ehci-tegra.c  |   71 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 0 deletions(-)

Comments

Grant Likely Nov. 4, 2011, 7:23 p.m. UTC | #1
On Fri, Nov 4, 2011 at 3:12 PM, Olof Johansson <olof@lixom.net> wrote:
> Rely on platform_data being passed through auxdata for now; more elaborate
> bindings for phy config and tunings to be added.
>
> v2: moved vbus-gpio check to the helper function, added check for !of_node,
>    added usb2 clock to board-dt table.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
> Cc: Greg Kroah-Hartman <gregkh@suse.de>

Acked-by: Grant Likely <grant.likely@secretlab.ca>

> ---
>  arch/arm/mach-tegra/board-dt.c |    9 +++++
>  drivers/usb/host/ehci-tegra.c  |   71 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 80 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
> index 74743ad..7f287a8 100644
> --- a/arch/arm/mach-tegra/board-dt.c
> +++ b/arch/arm/mach-tegra/board-dt.c
> @@ -61,12 +61,21 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
>        OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
>        OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
>        OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
> +       OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
> +                      &tegra_ehci1_device.dev.platform_data),
> +       OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
> +                      &tegra_ehci2_device.dev.platform_data),
> +       OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
> +                      &tegra_ehci3_device.dev.platform_data),
>        {}
>  };
>
>  static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
>        /* name         parent          rate            enabled */
>        { "uartd",      "pll_p",        216000000,      true },
> +       { "usbd",       "clk_m",        12000000,       false },
> +       { "usb2",       "clk_m",        12000000,       false },
> +       { "usb3",       "clk_m",        12000000,       false },
>        { NULL,         NULL,           0,              0},
>  };
>
> diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
> index db9d1b4..dbc7fe8 100644
> --- a/drivers/usb/host/ehci-tegra.c
> +++ b/drivers/usb/host/ehci-tegra.c
> @@ -21,7 +21,12 @@
>  #include <linux/platform_data/tegra_usb.h>
>  #include <linux/irq.h>
>  #include <linux/usb/otg.h>
> +#include <linux/gpio.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +
>  #include <mach/usb_phy.h>
> +#include <mach/iomap.h>
>
>  #define TEGRA_USB_DMA_ALIGN 32
>
> @@ -574,6 +579,35 @@ static const struct hc_driver tegra_ehci_hc_driver = {
>        .port_handed_over       = ehci_port_handed_over,
>  };
>
> +static int setup_vbus_gpio(struct platform_device *pdev)
> +{
> +       int err = 0;
> +       int gpio;
> +
> +       if (!pdev->dev.of_node)
> +               return 0;
> +
> +       gpio = of_get_named_gpio(pdev->dev.of_node, "nvidia,vbus-gpio", 0);
> +       if (!gpio_is_valid(gpio))
> +               return 0;
> +
> +       err = gpio_request(gpio, "vbus_gpio");
> +       if (err) {
> +               dev_err(&pdev->dev, "can't request vbus gpio %d", gpio);
> +               return err;
> +       }
> +       err = gpio_direction_output(gpio, 1);
> +       if (err) {
> +               dev_err(&pdev->dev, "can't enable vbus\n");
> +               return err;
> +       }
> +       gpio_set_value(gpio, 1);
> +
> +       return err;
> +}
> +
> +static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
> +
>  static int tegra_ehci_probe(struct platform_device *pdev)
>  {
>        struct resource *res;
> @@ -590,6 +624,15 @@ static int tegra_ehci_probe(struct platform_device *pdev)
>                return -EINVAL;
>        }
>
> +       /* Right now device-tree probed devices don't get dma_mask set.
> +        * Since shared usb code relies on it, set it here for now.
> +        * Once we have dma capability bindings this can go away.
> +        */
> +       if (!pdev->dev.dma_mask)
> +               pdev->dev.dma_mask = &tegra_ehci_dma_mask;
> +
> +       setup_vbus_gpio(pdev);
> +
>        tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
>        if (!tegra)
>                return -ENOMEM;
> @@ -640,6 +683,28 @@ static int tegra_ehci_probe(struct platform_device *pdev)
>                goto fail_io;
>        }
>
> +       /* This is pretty ugly and needs to be fixed when we do only
> +        * device-tree probing. Old code relies on the platform_device
> +        * numbering that we lack for device-tree-instantiated devices.
> +        */
> +       if (instance < 0) {
> +               switch (res->start) {
> +               case TEGRA_USB_BASE:
> +                       instance = 0;
> +                       break;
> +               case TEGRA_USB2_BASE:
> +                       instance = 1;
> +                       break;
> +               case TEGRA_USB3_BASE:
> +                       instance = 2;
> +                       break;
> +               default:
> +                       err = -ENODEV;
> +                       dev_err(&pdev->dev, "unknown usb instance\n");
> +                       goto fail_phy;
> +               }
> +       }
> +
>        tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
>                                                TEGRA_USB_PHY_MODE_HOST);
>        if (IS_ERR(tegra->phy)) {
> @@ -773,6 +838,11 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
>                hcd->driver->shutdown(hcd);
>  }
>
> +static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
> +       { .compatible = "nvidia,tegra20-ehci", },
> +       { },
> +};
> +
>  static struct platform_driver tegra_ehci_driver = {
>        .probe          = tegra_ehci_probe,
>        .remove         = tegra_ehci_remove,
> @@ -783,5 +853,6 @@ static struct platform_driver tegra_ehci_driver = {
>        .shutdown       = tegra_ehci_hcd_shutdown,
>        .driver         = {
>                .name   = "tegra-ehci",
> +               .of_match_table = tegra_ehci_of_match,
>        }
>  };
> --
> 1.7.4.1
>
>
Greg KH Nov. 14, 2011, 7:21 p.m. UTC | #2
On Fri, Nov 04, 2011 at 12:12:40PM -0700, Olof Johansson wrote:
> Rely on platform_data being passed through auxdata for now; more elaborate
> bindings for phy config and tunings to be added.
> 
> v2: moved vbus-gpio check to the helper function, added check for !of_node,
>     added usb2 clock to board-dt table.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>
> Cc: Greg Kroah-Hartman <gregkh@suse.de>

Acked-by: Greg Kroah-Hartman <gregkh@suse.de>

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

Patch

diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
index 74743ad..7f287a8 100644
--- a/arch/arm/mach-tegra/board-dt.c
+++ b/arch/arm/mach-tegra/board-dt.c
@@ -61,12 +61,21 @@  struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
+		       &tegra_ehci1_device.dev.platform_data),
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
+		       &tegra_ehci2_device.dev.platform_data),
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
+		       &tegra_ehci3_device.dev.platform_data),
 	{}
 };
 
 static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "uartd",	"pll_p",	216000000,	true },
+	{ "usbd",	"clk_m",	12000000,	false },
+	{ "usb2",	"clk_m",	12000000,	false },
+	{ "usb3",	"clk_m",	12000000,	false },
 	{ NULL,		NULL,		0,		0},
 };
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index db9d1b4..dbc7fe8 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -21,7 +21,12 @@ 
 #include <linux/platform_data/tegra_usb.h>
 #include <linux/irq.h>
 #include <linux/usb/otg.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
 #include <mach/usb_phy.h>
+#include <mach/iomap.h>
 
 #define TEGRA_USB_DMA_ALIGN 32
 
@@ -574,6 +579,35 @@  static const struct hc_driver tegra_ehci_hc_driver = {
 	.port_handed_over	= ehci_port_handed_over,
 };
 
+static int setup_vbus_gpio(struct platform_device *pdev)
+{
+	int err = 0;
+	int gpio;
+
+	if (!pdev->dev.of_node)
+		return 0;
+
+	gpio = of_get_named_gpio(pdev->dev.of_node, "nvidia,vbus-gpio", 0);
+	if (!gpio_is_valid(gpio))
+		return 0;
+
+	err = gpio_request(gpio, "vbus_gpio");
+	if (err) {
+		dev_err(&pdev->dev, "can't request vbus gpio %d", gpio);
+		return err;
+	}
+	err = gpio_direction_output(gpio, 1);
+	if (err) {
+		dev_err(&pdev->dev, "can't enable vbus\n");
+		return err;
+	}
+	gpio_set_value(gpio, 1);
+
+	return err;
+}
+
+static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
+
 static int tegra_ehci_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -590,6 +624,15 @@  static int tegra_ehci_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	/* Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we have dma capability bindings this can go away.
+	 */
+	if (!pdev->dev.dma_mask)
+		pdev->dev.dma_mask = &tegra_ehci_dma_mask;
+
+	setup_vbus_gpio(pdev);
+
 	tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
 	if (!tegra)
 		return -ENOMEM;
@@ -640,6 +683,28 @@  static int tegra_ehci_probe(struct platform_device *pdev)
 		goto fail_io;
 	}
 
+	/* This is pretty ugly and needs to be fixed when we do only
+	 * device-tree probing. Old code relies on the platform_device
+	 * numbering that we lack for device-tree-instantiated devices.
+	 */
+	if (instance < 0) {
+		switch (res->start) {
+		case TEGRA_USB_BASE:
+			instance = 0;
+			break;
+		case TEGRA_USB2_BASE:
+			instance = 1;
+			break;
+		case TEGRA_USB3_BASE:
+			instance = 2;
+			break;
+		default:
+			err = -ENODEV;
+			dev_err(&pdev->dev, "unknown usb instance\n");
+			goto fail_phy;
+		}
+	}
+
 	tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
 						TEGRA_USB_PHY_MODE_HOST);
 	if (IS_ERR(tegra->phy)) {
@@ -773,6 +838,11 @@  static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
+static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-ehci", },
+	{ },
+};
+
 static struct platform_driver tegra_ehci_driver = {
 	.probe		= tegra_ehci_probe,
 	.remove		= tegra_ehci_remove,
@@ -783,5 +853,6 @@  static struct platform_driver tegra_ehci_driver = {
 	.shutdown	= tegra_ehci_hcd_shutdown,
 	.driver		= {
 		.name	= "tegra-ehci",
+		.of_match_table = tegra_ehci_of_match,
 	}
 };