USB: ehci-tegra: add probing through device tree
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>
This commit is contained in:
parent
c27317c0ed
commit
4a53f4e692
2 changed files with 80 additions and 0 deletions
|
@ -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.0", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", 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-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[] = {
|
static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
|
||||||
/* name parent rate enabled */
|
/* name parent rate enabled */
|
||||||
{ "uartd", "pll_p", 216000000, true },
|
{ "uartd", "pll_p", 216000000, true },
|
||||||
|
{ "usbd", "clk_m", 12000000, false },
|
||||||
|
{ "usb2", "clk_m", 12000000, false },
|
||||||
|
{ "usb3", "clk_m", 12000000, false },
|
||||||
{ NULL, NULL, 0, 0},
|
{ NULL, NULL, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,12 @@
|
||||||
#include <linux/platform_data/tegra_usb.h>
|
#include <linux/platform_data/tegra_usb.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/usb/otg.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/usb_phy.h>
|
||||||
|
#include <mach/iomap.h>
|
||||||
|
|
||||||
#define TEGRA_USB_DMA_ALIGN 32
|
#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,
|
.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)
|
static int tegra_ehci_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
@ -590,6 +624,15 @@ static int tegra_ehci_probe(struct platform_device *pdev)
|
||||||
return -EINVAL;
|
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);
|
tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
|
||||||
if (!tegra)
|
if (!tegra)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -640,6 +683,28 @@ static int tegra_ehci_probe(struct platform_device *pdev)
|
||||||
goto fail_io;
|
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->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
|
||||||
TEGRA_USB_PHY_MODE_HOST);
|
TEGRA_USB_PHY_MODE_HOST);
|
||||||
if (IS_ERR(tegra->phy)) {
|
if (IS_ERR(tegra->phy)) {
|
||||||
|
@ -773,6 +838,11 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
|
||||||
hcd->driver->shutdown(hcd);
|
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 = {
|
static struct platform_driver tegra_ehci_driver = {
|
||||||
.probe = tegra_ehci_probe,
|
.probe = tegra_ehci_probe,
|
||||||
.remove = tegra_ehci_remove,
|
.remove = tegra_ehci_remove,
|
||||||
|
@ -783,5 +853,6 @@ static struct platform_driver tegra_ehci_driver = {
|
||||||
.shutdown = tegra_ehci_hcd_shutdown,
|
.shutdown = tegra_ehci_hcd_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tegra-ehci",
|
.name = "tegra-ehci",
|
||||||
|
.of_match_table = tegra_ehci_of_match,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue