diff options
Diffstat (limited to 'drivers/usb/host/ehci-omap.c')
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 74d07f4..f0282d6 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -26,10 +26,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * TODO (last updated Feb 23rd, 2009): + * TODO (last updated Feb 12, 2010): * - add kernel-doc * - enable AUTOIDLE - * - move DPLL5 programming to clock fw * - add suspend/resume * - move workarounds to board-files */ @@ -37,6 +36,7 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/gpio.h> +#include <linux/regulator/consumer.h> #include <plat/usb.h> /* @@ -178,6 +178,11 @@ struct ehci_hcd_omap { void __iomem *uhh_base; void __iomem *tll_base; void __iomem *ehci_base; + + /* Regulators for USB PHYs. + * Each PHY can have a seperate regulator. + */ + struct regulator *regulator[OMAP3_HS_USB_PORTS]; }; /*-------------------------------------------------------------------------*/ @@ -546,6 +551,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) int irq = platform_get_irq(pdev, 0); int ret = -ENODEV; + int i; + char supply[7]; if (!pdata) { dev_dbg(&pdev->dev, "missing platform_data\n"); @@ -613,6 +620,21 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) goto err_tll_ioremap; } + /* get ehci regulator and enable */ + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) { + omap->regulator[i] = NULL; + continue; + } + snprintf(supply, sizeof(supply), "hsusb%d", i); + omap->regulator[i] = regulator_get(omap->dev, supply); + if (IS_ERR(omap->regulator[i])) + dev_dbg(&pdev->dev, + "failed to get ehci port%d regulator\n", i); + else + regulator_enable(omap->regulator[i]); + } + ret = omap_start_ehc(omap, hcd); if (ret) { dev_dbg(&pdev->dev, "failed to start ehci\n"); @@ -622,13 +644,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) omap->ehci->regs = hcd->regs + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase)); + dbg_hcs_params(omap->ehci, "reset"); + dbg_hcc_params(omap->ehci, "reset"); + /* cache this readonly data; minimize chip reads */ omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params); - /* SET 1 micro-frame Interrupt interval */ - writel(readl(&omap->ehci->regs->command) | (1 << 16), - &omap->ehci->regs->command); - ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (ret) { dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); @@ -641,6 +662,12 @@ err_add_hcd: omap_stop_ehc(omap, hcd); err_start: + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + if (omap->regulator[i]) { + regulator_disable(omap->regulator[i]); + regulator_put(omap->regulator[i]); + } + } iounmap(omap->tll_base); err_tll_ioremap: @@ -674,13 +701,21 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) { struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); + int i; usb_remove_hcd(hcd); omap_stop_ehc(omap, hcd); iounmap(hcd->regs); + for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + if (omap->regulator[i]) { + regulator_disable(omap->regulator[i]); + regulator_put(omap->regulator[i]); + } + } iounmap(omap->tll_base); iounmap(omap->uhh_base); usb_put_hcd(hcd); + kfree(omap); return 0; } |