|
@@ -37,6 +37,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 +179,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 +552,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 +621,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");
|
|
@@ -641,6 +664,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,10 +703,17 @@ 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);
|