[PATCH v2 2/2] USB: ehci-tegra: add probing through device tree
Grant Likely
grant.likely at secretlab.ca
Sat Nov 5 06:23:33 EST 2011
On Fri, Nov 4, 2011 at 3:12 PM, Olof Johansson <olof at 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 at lixom.net>
> Cc: Greg Kroah-Hartman <gregkh at suse.de>
Acked-by: Grant Likely <grant.likely at 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
>
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
More information about the devicetree-discuss
mailing list