diff options
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.c | 8 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.h | 2 | ||||
-rw-r--r-- | drivers/usb/chipidea/otg_fsm.c | 8 | ||||
-rw-r--r-- | drivers/usb/chipidea/usbmisc_imx.c | 52 | ||||
-rw-r--r-- | include/linux/usb/chipidea.h | 2 |
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; |