MLK-16715-6 usb: chipidea: imx: add HSIC support for controllers from imx7d
authorPeter Chen <peter.chen@nxp.com>
Thu, 16 Nov 2017 09:11:51 +0000 (17:11 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:51:17 +0000 (14:51 -0500)
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>
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/ci_hdrc_imx.h
drivers/usb/chipidea/usbmisc_imx.c

index 2fe9a6d..74408d2 100644 (file)
@@ -531,6 +531,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;
index 9ae6844..8d86a9d 100644 (file)
@@ -48,6 +48,7 @@ struct imx_usbmisc_data {
        unsigned int oc_polarity:1; /* over current polarity if oc enabled */
        unsigned int pwr_polarity:1; /* polarity of enable vbus from pmic */
        unsigned int evdo:1; /* set external vbus divider option */
+       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
index 4e3b31c..b367a45 100644 (file)
@@ -94,6 +94,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)
@@ -298,41 +299,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;
@@ -545,6 +566,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);
@@ -960,12 +994,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,
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *data)