summaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@nxp.com>2017-11-16 17:11:51 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:29:53 +0800
commit0c735e6213b4295ffc34364ea518824e0302de99 (patch)
tree1a45548a47213788aa3bb732b6b336c4f6bfa5d2 /drivers/usb/chipidea
parent37285910ed8a4282553dfcf4532d44ff517344ee (diff)
MLK-16715-6 usb: chipidea: imx: add HSIC support for controllers from imx7d
From imx7d, there is a dedicate non-core register region for each controller, and HSIC configurations are almost at non-core register, this commit adds HSIC support for controllers from imx7d, and the non-core confugrations are different with imx6's. Acked-by: Jun Li <jun.li@nxp.com> Signed-off-by: Peter Chen <peter.chen@nxp.com>
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c1
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h1
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c74
3 files changed, 58 insertions, 18 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index e3bdb26f0196..c1f269fe6a8e 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -535,6 +535,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) {
pdata.flags |= CI_HDRC_IMX_IS_HSIC;
+ data->usbmisc_data->hsic = 1;
data->hsic_pad_regulator = devm_regulator_get(dev, "pad");
if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 4db372932751..9284f4b99971 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -49,6 +49,7 @@ struct imx_usbmisc_data {
unsigned int pwr_polarity:1; /* polarity of enable vbus from pmic */
unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
+ unsigned int hsic:1; /* HSIC controlller */
/*
* Specifies the delay between powering up the xtal 24MHz clock
* and release the clock to the digital logic inside the analog block
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index c6645c1b84ff..37e2fb5b3e49 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -106,6 +106,7 @@
#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK (BIT(7) | BIT(6))
#define MX7D_USBNC_USB_CTRL2_OPMODE(v) (v << 6)
#define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1)
+#define MX7D_USBNC_HSIC_AUTO_RESUME BIT(2)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3
#define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0)
@@ -368,41 +369,61 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
{
unsigned long flags;
- u32 val;
+ u32 val, offset;
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ int ret = 0;
spin_lock_irqsave(&usbmisc->lock, flags);
if (data->index == 2 || data->index == 3) {
- val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
- + (data->index - 2) * 4);
- if (!(val & MX6_BM_HSIC_DEV_CONN))
- writel(val | MX6_BM_HSIC_DEV_CONN,
- usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
- + (data->index - 2) * 4);
+ offset = (data->index - 2) * 4;
+ } else if (data->index == 0) {
+ /*
+ * For controllers later than imx7d (imx7d is included),
+ * each controller has its own non core register region.
+ * And the controllers before than imx7d, the 1st controller
+ * is not HSIC controller.
+ */
+ offset = 0;
+ } else {
+ dev_err(data->dev, "index is error for usbmisc\n");
+ offset = 0;
+ ret = -EINVAL;
}
+
+ val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
+ if (!(val & MX6_BM_HSIC_DEV_CONN))
+ writel(val | MX6_BM_HSIC_DEV_CONN,
+ usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
spin_unlock_irqrestore(&usbmisc->lock, flags);
- return 0;
+ return ret;
}
static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
{
unsigned long flags;
- u32 val;
+ u32 val, offset;
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ int ret = 0;
spin_lock_irqsave(&usbmisc->lock, flags);
if (data->index == 2 || data->index == 3) {
- val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
- + (data->index - 2) * 4);
- val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
- if (on)
- val |= MX6_BM_HSIC_CLK_ON;
- else
- val &= ~MX6_BM_HSIC_CLK_ON;
- writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
- + (data->index - 2) * 4);
+ offset = (data->index - 2) * 4;
+ } else if (data->index == 0) {
+ offset = 0;
+ } else {
+ dev_err(data->dev, "index is error for usbmisc\n");
+ offset = 0;
+ ret = -EINVAL;
}
+
+ val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
+ val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
+ if (on)
+ val |= MX6_BM_HSIC_CLK_ON;
+ else
+ val &= ~MX6_BM_HSIC_CLK_ON;
+ writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
spin_unlock_irqrestore(&usbmisc->lock, flags);
return 0;
@@ -615,6 +636,19 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
usbmisc->base + MX7D_USBNC_USB_CTRL2);
+
+ if (data->hsic) {
+ reg = readl(usbmisc->base);
+ writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base);
+
+ reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
+ reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
+ writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
+
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ writel(reg | MX7D_USBNC_HSIC_AUTO_RESUME,
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
+ }
spin_unlock_irqrestore(&usbmisc->lock, flags);
usbmisc_imx7d_set_wakeup(data, false);
@@ -1034,12 +1068,16 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = {
.charger_primary_detection = imx7d_charger_primary_detection,
.charger_secondary_detection = imx7d_charger_secondary_detection,
.term_select_override = usbmisc_term_select_override,
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
};
static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
.init = usbmisc_imx7d_init,
.set_wakeup = usbmisc_imx7d_set_wakeup,
.power_lost_check = usbmisc_imx7d_power_lost_check,
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
};
static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)