summaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/host.c67
-rw-r--r--drivers/usb/chipidea/otg_fsm.c5
2 files changed, 47 insertions, 25 deletions
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 4f8eb40ad93a..48731d0bab35 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -34,6 +34,44 @@
static struct hc_driver __read_mostly ci_ehci_hc_driver;
+struct ehci_ci_priv {
+ struct regulator *reg_vbus;
+};
+
+static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
+ struct device *dev = hcd->self.controller;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+ int ret = 0;
+ int port = HCS_N_PORTS(ehci->hcs_params);
+
+ if (priv->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
+ if (port > 1) {
+ dev_warn(dev,
+ "Not support multi-port regulator control\n");
+ return 0;
+ }
+ if (enable)
+ ret = regulator_enable(priv->reg_vbus);
+ else
+ ret = regulator_disable(priv->reg_vbus);
+ if (ret) {
+ dev_err(dev,
+ "Failed to %s vbus regulator, ret=%d\n",
+ enable ? "enable" : "disable", ret);
+ return ret;
+ }
+ }
+ return 0;
+};
+
+static const struct ehci_driver_overrides ehci_ci_overrides = {
+ .extra_priv_size = sizeof(struct ehci_ci_priv),
+ .port_power = ehci_ci_portpower,
+};
+
static irqreturn_t host_irq(struct ci_hdrc *ci)
{
return usb_hcd_irq(ci->irq, ci->hcd);
@@ -43,6 +81,7 @@ static int host_start(struct ci_hdrc *ci)
{
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
+ struct ehci_ci_priv *priv;
int ret;
if (usb_disabled())
@@ -71,23 +110,15 @@ static int host_start(struct ci_hdrc *ci)
ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
ehci->imx28_write_fix = ci->imx28_write_fix;
- /*
- * vbus is always on if host is not in OTG FSM mode,
- * otherwise should be controlled by OTG FSM
- */
- if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
- ret = regulator_enable(ci->platdata->reg_vbus);
- if (ret) {
- dev_err(ci->dev,
- "Failed to enable vbus regulator, ret=%d\n",
- ret);
- goto put_hcd;
- }
- }
+ priv = (struct ehci_ci_priv *)ehci->priv;
+ priv->reg_vbus = NULL;
+
+ if (ci->platdata->reg_vbus)
+ priv->reg_vbus = ci->platdata->reg_vbus;
ret = usb_add_hcd(hcd, 0, 0);
if (ret) {
- goto disable_reg;
+ goto put_hcd;
} else {
struct usb_otg *otg = &ci->otg;
@@ -104,10 +135,6 @@ static int host_start(struct ci_hdrc *ci)
return ret;
-disable_reg:
- if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci))
- regulator_disable(ci->platdata->reg_vbus);
-
put_hcd:
usb_put_hcd(hcd);
@@ -121,8 +148,6 @@ static void host_stop(struct ci_hdrc *ci)
if (hcd) {
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
- if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci))
- regulator_disable(ci->platdata->reg_vbus);
}
}
@@ -150,7 +175,7 @@ int ci_hdrc_host_init(struct ci_hdrc *ci)
rdrv->name = "host";
ci->roles[CI_ROLE_HOST] = rdrv;
- ehci_init_driver(&ci_ehci_hc_driver, NULL);
+ ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
return 0;
}
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 3c2ab1ae00fc..368cc8e94fd6 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -795,11 +795,8 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
ci->fsm_timer = devm_kzalloc(ci->dev,
sizeof(struct ci_otg_fsm_timer_list), GFP_KERNEL);
- if (!ci->fsm_timer) {
- dev_err(ci->dev,
- "Failed to allocate timer structure for ci hdrc otg!\n");
+ if (!ci->fsm_timer)
return -ENOMEM;
- }
INIT_LIST_HEAD(&ci->fsm_timer->active_timers);
retval = ci_otg_init_timers(ci);