summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c8
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h2
-rw-r--r--drivers/usb/chipidea/otg_fsm.c8
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c52
-rw-r--r--include/linux/usb/chipidea.h2
5 files changed, 72 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 362eb7d4703b..e969156382d4 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -347,6 +347,14 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned event)
return ret;
}
break;
+ case CI_HDRC_IMX_TERM_SELECT_OVERRIDE_FS:
+ if (data->usbmisc_data)
+ return imx_usbmisc_term_select_override(
+ data->usbmisc_data, true, 1);
+ case CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF:
+ if (data->usbmisc_data)
+ return imx_usbmisc_term_select_override(
+ data->usbmisc_data, false, 0);
default:
dev_dbg(dev, "unknown event\n");
}
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 814f8326f58a..bdcf1b724abe 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -62,5 +62,7 @@ int imx_usbmisc_charger_secondary_detection(struct imx_usbmisc_data *data);
int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *);
int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *);
int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool);
+int imx_usbmisc_term_select_override(struct imx_usbmisc_data *data,
+ bool enable, int val);
#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 1be81b442a5a..c8d96bf5feac 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -560,6 +560,9 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
if (on) {
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF);
+
/* Enable power power */
hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP,
PORTSC_PP);
@@ -718,6 +721,9 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
PORTSC_PP, 0);
hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE);
+ /* FS termination override if needed */
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_FS);
}
if (ci->id_event)
ci->id_event = false;
@@ -854,6 +860,8 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
if (otg_int_src) {
if (otg_int_src & OTGSC_DPIS) {
hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
+ ci->platdata->notify_event(ci,
+ CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF);
ci_otg_add_timer(ci, A_DP_END);
} else if (otg_int_src & OTGSC_IDIS) {
hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 5642cd488b39..bf5b5a1503ce 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -115,6 +115,8 @@
#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3)
+#define MX7D_USB_TERMSEL_OVERRIDE BIT(4)
+#define MX7D_USB_TERMSEL_OVERRIDE_EN BIT(5)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3)
#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2)
@@ -145,6 +147,9 @@ struct usbmisc_ops {
int (*hsic_set_connect)(struct imx_usbmisc_data *data);
/* It's called during suspend/resume */
int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
+ /* override UTMI termination select */
+ int (*term_select_override)(struct imx_usbmisc_data *data,
+ bool enable, int val);
};
struct imx_usbmisc {
@@ -850,6 +855,37 @@ int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_term_select_override(struct imx_usbmisc_data *data,
+ bool enable, int val)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ if (enable) {
+ if (val)
+ writel(reg | MX7D_USB_TERMSEL_OVERRIDE,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ else
+ writel(reg & ~MX7D_USB_TERMSEL_OVERRIDE,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ writel(reg | MX7D_USB_TERMSEL_OVERRIDE_EN,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ } else {
+ writel(reg & ~MX7D_USB_TERMSEL_OVERRIDE_EN,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ }
+
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
static const struct usbmisc_ops imx25_usbmisc_ops = {
.init = usbmisc_imx25_init,
.post = usbmisc_imx25_post,
@@ -892,6 +928,7 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = {
.power_lost_check = usbmisc_imx7d_power_lost_check,
.charger_primary_detection = imx7d_charger_primary_detection,
.charger_secondary_detection = imx7d_charger_secondary_detection,
+ .term_select_override = usbmisc_term_select_override,
};
int imx_usbmisc_init(struct imx_usbmisc_data *data)
@@ -1029,6 +1066,21 @@ int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
}
EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
+int imx_usbmisc_term_select_override(struct imx_usbmisc_data *data,
+ bool enable, int val)
+{
+ struct imx_usbmisc *usbmisc;
+
+ if (!data)
+ return 0;
+
+ usbmisc = dev_get_drvdata(data->dev);
+ if (!usbmisc->ops->term_select_override)
+ return 0;
+ return usbmisc->ops->term_select_override(data, enable, val);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_term_select_override);
+
static const struct of_device_id usbmisc_imx_dt_ids[] = {
{
.compatible = "fsl,imx25-usbmisc",
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index d74c20096f16..fc9163946d75 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -46,6 +46,8 @@ struct ci_hdrc_platform_data {
#define CI_HDRC_CONTROLLER_CHARGER_POST_EVENT 4
#define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 5
#define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 6
+#define CI_HDRC_IMX_TERM_SELECT_OVERRIDE_FS 7
+#define CI_HDRC_IMX_TERM_SELECT_OVERRIDE_OFF 8
int (*notify_event)(struct ci_hdrc *ci, unsigned event);
struct regulator *reg_vbus;
struct usb_otg_caps ci_otg_caps;