Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2012 Freescale Semiconductor, Inc.
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/of_platform.h>
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/delay.h>
0011 #include <linux/usb/otg.h>
0012 
0013 #include "ci_hdrc_imx.h"
0014 
0015 #define MX25_USB_PHY_CTRL_OFFSET    0x08
0016 #define MX25_BM_EXTERNAL_VBUS_DIVIDER   BIT(23)
0017 
0018 #define MX25_EHCI_INTERFACE_SINGLE_UNI  (2 << 0)
0019 #define MX25_EHCI_INTERFACE_DIFF_UNI    (0 << 0)
0020 #define MX25_EHCI_INTERFACE_MASK    (0xf)
0021 
0022 #define MX25_OTG_SIC_SHIFT      29
0023 #define MX25_OTG_SIC_MASK       (0x3 << MX25_OTG_SIC_SHIFT)
0024 #define MX25_OTG_PM_BIT         BIT(24)
0025 #define MX25_OTG_PP_BIT         BIT(11)
0026 #define MX25_OTG_OCPOL_BIT      BIT(3)
0027 
0028 #define MX25_H1_SIC_SHIFT       21
0029 #define MX25_H1_SIC_MASK        (0x3 << MX25_H1_SIC_SHIFT)
0030 #define MX25_H1_PP_BIT          BIT(18)
0031 #define MX25_H1_PM_BIT          BIT(16)
0032 #define MX25_H1_IPPUE_UP_BIT        BIT(7)
0033 #define MX25_H1_IPPUE_DOWN_BIT      BIT(6)
0034 #define MX25_H1_TLL_BIT         BIT(5)
0035 #define MX25_H1_USBTE_BIT       BIT(4)
0036 #define MX25_H1_OCPOL_BIT       BIT(2)
0037 
0038 #define MX27_H1_PM_BIT          BIT(8)
0039 #define MX27_H2_PM_BIT          BIT(16)
0040 #define MX27_OTG_PM_BIT         BIT(24)
0041 
0042 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET  0x08
0043 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET  0x0c
0044 #define MX53_USB_CTRL_1_OFFSET          0x10
0045 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
0046 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
0047 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
0048 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
0049 #define MX53_USB_UH2_CTRL_OFFSET    0x14
0050 #define MX53_USB_UH3_CTRL_OFFSET    0x18
0051 #define MX53_USB_CLKONOFF_CTRL_OFFSET   0x24
0052 #define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
0053 #define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
0054 #define MX53_BM_OVER_CUR_DIS_H1     BIT(5)
0055 #define MX53_BM_OVER_CUR_DIS_OTG    BIT(8)
0056 #define MX53_BM_OVER_CUR_DIS_UHx    BIT(30)
0057 #define MX53_USB_CTRL_1_UH2_ULPI_EN BIT(26)
0058 #define MX53_USB_CTRL_1_UH3_ULPI_EN BIT(27)
0059 #define MX53_USB_UHx_CTRL_WAKE_UP_EN    BIT(7)
0060 #define MX53_USB_UHx_CTRL_ULPI_INT_EN   BIT(8)
0061 #define MX53_USB_PHYCTRL1_PLLDIV_MASK   0x3
0062 #define MX53_USB_PLL_DIV_24_MHZ     0x01
0063 
0064 #define MX6_BM_NON_BURST_SETTING    BIT(1)
0065 #define MX6_BM_OVER_CUR_DIS     BIT(7)
0066 #define MX6_BM_OVER_CUR_POLARITY    BIT(8)
0067 #define MX6_BM_PWR_POLARITY     BIT(9)
0068 #define MX6_BM_WAKEUP_ENABLE        BIT(10)
0069 #define MX6_BM_UTMI_ON_CLOCK        BIT(13)
0070 #define MX6_BM_ID_WAKEUP        BIT(16)
0071 #define MX6_BM_VBUS_WAKEUP      BIT(17)
0072 #define MX6SX_BM_DPDM_WAKEUP_EN     BIT(29)
0073 #define MX6_BM_WAKEUP_INTR      BIT(31)
0074 
0075 #define MX6_USB_HSIC_CTRL_OFFSET    0x10
0076 /* Send resume signal without 480Mhz PHY clock */
0077 #define MX6SX_BM_HSIC_AUTO_RESUME   BIT(23)
0078 /* set before portsc.suspendM = 1 */
0079 #define MX6_BM_HSIC_DEV_CONN        BIT(21)
0080 /* HSIC enable */
0081 #define MX6_BM_HSIC_EN          BIT(12)
0082 /* Force HSIC module 480M clock on, even when in Host is in suspend mode */
0083 #define MX6_BM_HSIC_CLK_ON      BIT(11)
0084 
0085 #define MX6_USB_OTG1_PHY_CTRL       0x18
0086 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
0087 #define MX6_USB_OTG2_PHY_CTRL       0x1c
0088 #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v) (v << 8)
0089 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS   MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
0090 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
0091 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
0092 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END   MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
0093 
0094 #define VF610_OVER_CUR_DIS      BIT(7)
0095 
0096 #define MX7D_USBNC_USB_CTRL2        0x4
0097 #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK    0x3
0098 #define MX7D_USB_VBUS_WAKEUP_SOURCE(v)      (v << 0)
0099 #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS    MX7D_USB_VBUS_WAKEUP_SOURCE(0)
0100 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID  MX7D_USB_VBUS_WAKEUP_SOURCE(1)
0101 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID  MX7D_USB_VBUS_WAKEUP_SOURCE(2)
0102 #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END    MX7D_USB_VBUS_WAKEUP_SOURCE(3)
0103 #define MX7D_USBNC_AUTO_RESUME              BIT(2)
0104 /* The default DM/DP value is pull-down */
0105 #define MX7D_USBNC_USB_CTRL2_OPMODE(v)          (v << 6)
0106 #define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1)
0107 #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK   (BIT(7) | BIT(6))
0108 #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN     BIT(8)
0109 #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_VAL        BIT(12)
0110 #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_EN     BIT(13)
0111 #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_VAL        BIT(14)
0112 #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_EN     BIT(15)
0113 #define MX7D_USBNC_USB_CTRL2_DP_DM_MASK         (BIT(12) | BIT(13) | \
0114                             BIT(14) | BIT(15))
0115 
0116 #define MX7D_USB_OTG_PHY_CFG1       0x30
0117 #define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL  BIT(0)
0118 #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0  BIT(1)
0119 #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0  BIT(2)
0120 #define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB   BIT(3)
0121 #define MX7D_USB_OTG_PHY_CFG2_DRVVBUS0      BIT(16)
0122 
0123 #define MX7D_USB_OTG_PHY_CFG2       0x34
0124 
0125 #define MX7D_USB_OTG_PHY_STATUS     0x3c
0126 #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0)
0127 #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1)
0128 #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD    BIT(3)
0129 #define MX7D_USB_OTG_PHY_STATUS_CHRGDET     BIT(29)
0130 
0131 #define MX7D_USB_OTG_PHY_CFG1       0x30
0132 #define TXPREEMPAMPTUNE0_BIT        28
0133 #define TXPREEMPAMPTUNE0_MASK       (3 << 28)
0134 #define TXVREFTUNE0_BIT         20
0135 #define TXVREFTUNE0_MASK        (0xf << 20)
0136 
0137 #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
0138                  MX6_BM_ID_WAKEUP)
0139 
0140 struct usbmisc_ops {
0141     /* It's called once when probe a usb device */
0142     int (*init)(struct imx_usbmisc_data *data);
0143     /* It's called once after adding a usb device */
0144     int (*post)(struct imx_usbmisc_data *data);
0145     /* It's called when we need to enable/disable usb wakeup */
0146     int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
0147     /* It's called before setting portsc.suspendM */
0148     int (*hsic_set_connect)(struct imx_usbmisc_data *data);
0149     /* It's called during suspend/resume */
0150     int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
0151     /* usb charger detection */
0152     int (*charger_detection)(struct imx_usbmisc_data *data);
0153 };
0154 
0155 struct imx_usbmisc {
0156     void __iomem *base;
0157     spinlock_t lock;
0158     const struct usbmisc_ops *ops;
0159 };
0160 
0161 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
0162 
0163 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
0164 {
0165     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0166     unsigned long flags;
0167     u32 val = 0;
0168 
0169     if (data->index > 1)
0170         return -EINVAL;
0171 
0172     spin_lock_irqsave(&usbmisc->lock, flags);
0173     switch (data->index) {
0174     case 0:
0175         val = readl(usbmisc->base);
0176         val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
0177         val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
0178         val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
0179 
0180         /*
0181          * If the polarity is not configured assume active high for
0182          * historical reasons.
0183          */
0184         if (data->oc_pol_configured && data->oc_pol_active_low)
0185             val &= ~MX25_OTG_OCPOL_BIT;
0186 
0187         writel(val, usbmisc->base);
0188         break;
0189     case 1:
0190         val = readl(usbmisc->base);
0191         val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
0192         val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
0193         val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
0194             MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
0195 
0196         /*
0197          * If the polarity is not configured assume active high for
0198          * historical reasons.
0199          */
0200         if (data->oc_pol_configured && data->oc_pol_active_low)
0201             val &= ~MX25_H1_OCPOL_BIT;
0202 
0203         writel(val, usbmisc->base);
0204 
0205         break;
0206     }
0207     spin_unlock_irqrestore(&usbmisc->lock, flags);
0208 
0209     return 0;
0210 }
0211 
0212 static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
0213 {
0214     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0215     void __iomem *reg;
0216     unsigned long flags;
0217     u32 val;
0218 
0219     if (data->index > 2)
0220         return -EINVAL;
0221 
0222     if (data->index)
0223         return 0;
0224 
0225     spin_lock_irqsave(&usbmisc->lock, flags);
0226     reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
0227     val = readl(reg);
0228 
0229     if (data->evdo)
0230         val |= MX25_BM_EXTERNAL_VBUS_DIVIDER;
0231     else
0232         val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER;
0233 
0234     writel(val, reg);
0235     spin_unlock_irqrestore(&usbmisc->lock, flags);
0236     usleep_range(5000, 10000); /* needed to stabilize voltage */
0237 
0238     return 0;
0239 }
0240 
0241 static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
0242 {
0243     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0244     unsigned long flags;
0245     u32 val;
0246 
0247     switch (data->index) {
0248     case 0:
0249         val = MX27_OTG_PM_BIT;
0250         break;
0251     case 1:
0252         val = MX27_H1_PM_BIT;
0253         break;
0254     case 2:
0255         val = MX27_H2_PM_BIT;
0256         break;
0257     default:
0258         return -EINVAL;
0259     }
0260 
0261     spin_lock_irqsave(&usbmisc->lock, flags);
0262     if (data->disable_oc)
0263         val = readl(usbmisc->base) | val;
0264     else
0265         val = readl(usbmisc->base) & ~val;
0266     writel(val, usbmisc->base);
0267     spin_unlock_irqrestore(&usbmisc->lock, flags);
0268 
0269     return 0;
0270 }
0271 
0272 static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
0273 {
0274     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0275     void __iomem *reg = NULL;
0276     unsigned long flags;
0277     u32 val = 0;
0278 
0279     if (data->index > 3)
0280         return -EINVAL;
0281 
0282     /* Select a 24 MHz reference clock for the PHY  */
0283     val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
0284     val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
0285     val |= MX53_USB_PLL_DIV_24_MHZ;
0286     writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
0287 
0288     spin_lock_irqsave(&usbmisc->lock, flags);
0289 
0290     switch (data->index) {
0291     case 0:
0292         if (data->disable_oc) {
0293             reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
0294             val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
0295             writel(val, reg);
0296         }
0297         break;
0298     case 1:
0299         if (data->disable_oc) {
0300             reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
0301             val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
0302             writel(val, reg);
0303         }
0304         break;
0305     case 2:
0306         if (data->ulpi) {
0307             /* set USBH2 into ULPI-mode. */
0308             reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
0309             val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
0310             /* select ULPI clock */
0311             val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
0312             val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
0313             writel(val, reg);
0314             /* Set interrupt wake up enable */
0315             reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
0316             val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
0317                 | MX53_USB_UHx_CTRL_ULPI_INT_EN;
0318             writel(val, reg);
0319             if (is_imx53_usbmisc(data)) {
0320                 /* Disable internal 60Mhz clock */
0321                 reg = usbmisc->base +
0322                     MX53_USB_CLKONOFF_CTRL_OFFSET;
0323                 val = readl(reg) |
0324                     MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
0325                 writel(val, reg);
0326             }
0327 
0328         }
0329         if (data->disable_oc) {
0330             reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
0331             val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
0332             writel(val, reg);
0333         }
0334         break;
0335     case 3:
0336         if (data->ulpi) {
0337             /* set USBH3 into ULPI-mode. */
0338             reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
0339             val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
0340             /* select ULPI clock */
0341             val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
0342             val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
0343             writel(val, reg);
0344             /* Set interrupt wake up enable */
0345             reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
0346             val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
0347                 | MX53_USB_UHx_CTRL_ULPI_INT_EN;
0348             writel(val, reg);
0349 
0350             if (is_imx53_usbmisc(data)) {
0351                 /* Disable internal 60Mhz clock */
0352                 reg = usbmisc->base +
0353                     MX53_USB_CLKONOFF_CTRL_OFFSET;
0354                 val = readl(reg) |
0355                     MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
0356                 writel(val, reg);
0357             }
0358         }
0359         if (data->disable_oc) {
0360             reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
0361             val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
0362             writel(val, reg);
0363         }
0364         break;
0365     }
0366 
0367     spin_unlock_irqrestore(&usbmisc->lock, flags);
0368 
0369     return 0;
0370 }
0371 
0372 static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
0373 {
0374     u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
0375 
0376     if (data->ext_id || data->available_role != USB_DR_MODE_OTG)
0377         wakeup_setting &= ~MX6_BM_ID_WAKEUP;
0378 
0379     if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST)
0380         wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
0381 
0382     return wakeup_setting;
0383 }
0384 
0385 static int usbmisc_imx6q_set_wakeup
0386     (struct imx_usbmisc_data *data, bool enabled)
0387 {
0388     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0389     unsigned long flags;
0390     u32 val;
0391     int ret = 0;
0392 
0393     if (data->index > 3)
0394         return -EINVAL;
0395 
0396     spin_lock_irqsave(&usbmisc->lock, flags);
0397     val = readl(usbmisc->base + data->index * 4);
0398     if (enabled) {
0399         val &= ~MX6_USB_OTG_WAKEUP_BITS;
0400         val |= usbmisc_wakeup_setting(data);
0401     } else {
0402         if (val & MX6_BM_WAKEUP_INTR)
0403             pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
0404         val &= ~MX6_USB_OTG_WAKEUP_BITS;
0405     }
0406     writel(val, usbmisc->base + data->index * 4);
0407     spin_unlock_irqrestore(&usbmisc->lock, flags);
0408 
0409     return ret;
0410 }
0411 
0412 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
0413 {
0414     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0415     unsigned long flags;
0416     u32 reg;
0417 
0418     if (data->index > 3)
0419         return -EINVAL;
0420 
0421     spin_lock_irqsave(&usbmisc->lock, flags);
0422 
0423     reg = readl(usbmisc->base + data->index * 4);
0424     if (data->disable_oc) {
0425         reg |= MX6_BM_OVER_CUR_DIS;
0426     } else {
0427         reg &= ~MX6_BM_OVER_CUR_DIS;
0428 
0429         /*
0430          * If the polarity is not configured keep it as setup by the
0431          * bootloader.
0432          */
0433         if (data->oc_pol_configured && data->oc_pol_active_low)
0434             reg |= MX6_BM_OVER_CUR_POLARITY;
0435         else if (data->oc_pol_configured)
0436             reg &= ~MX6_BM_OVER_CUR_POLARITY;
0437     }
0438     /* If the polarity is not set keep it as setup by the bootlader */
0439     if (data->pwr_pol == 1)
0440         reg |= MX6_BM_PWR_POLARITY;
0441     writel(reg, usbmisc->base + data->index * 4);
0442 
0443     /* SoC non-burst setting */
0444     reg = readl(usbmisc->base + data->index * 4);
0445     writel(reg | MX6_BM_NON_BURST_SETTING,
0446             usbmisc->base + data->index * 4);
0447 
0448     /* For HSIC controller */
0449     if (data->hsic) {
0450         reg = readl(usbmisc->base + data->index * 4);
0451         writel(reg | MX6_BM_UTMI_ON_CLOCK,
0452             usbmisc->base + data->index * 4);
0453         reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
0454             + (data->index - 2) * 4);
0455         reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
0456         writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
0457             + (data->index - 2) * 4);
0458     }
0459 
0460     spin_unlock_irqrestore(&usbmisc->lock, flags);
0461 
0462     usbmisc_imx6q_set_wakeup(data, false);
0463 
0464     return 0;
0465 }
0466 
0467 static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
0468 {
0469     int offset, ret = 0;
0470 
0471     if (data->index == 2 || data->index == 3) {
0472         offset = (data->index - 2) * 4;
0473     } else if (data->index == 0) {
0474         /*
0475          * For SoCs like i.MX7D and later, each USB controller has
0476          * its own non-core register region. For SoCs before i.MX7D,
0477          * the first two USB controllers are non-HSIC controllers.
0478          */
0479         offset = 0;
0480     } else {
0481         dev_err(data->dev, "index is error for usbmisc\n");
0482         ret = -EINVAL;
0483     }
0484 
0485     return ret ? ret : offset;
0486 }
0487 
0488 static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
0489 {
0490     unsigned long flags;
0491     u32 val;
0492     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0493     int offset;
0494 
0495     spin_lock_irqsave(&usbmisc->lock, flags);
0496     offset = usbmisc_imx6_hsic_get_reg_offset(data);
0497     if (offset < 0) {
0498         spin_unlock_irqrestore(&usbmisc->lock, flags);
0499         return offset;
0500     }
0501 
0502     val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
0503     if (!(val & MX6_BM_HSIC_DEV_CONN))
0504         writel(val | MX6_BM_HSIC_DEV_CONN,
0505             usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
0506 
0507     spin_unlock_irqrestore(&usbmisc->lock, flags);
0508 
0509     return 0;
0510 }
0511 
0512 static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
0513 {
0514     unsigned long flags;
0515     u32 val;
0516     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0517     int offset;
0518 
0519     spin_lock_irqsave(&usbmisc->lock, flags);
0520     offset = usbmisc_imx6_hsic_get_reg_offset(data);
0521     if (offset < 0) {
0522         spin_unlock_irqrestore(&usbmisc->lock, flags);
0523         return offset;
0524     }
0525 
0526     val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
0527     val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
0528     if (on)
0529         val |= MX6_BM_HSIC_CLK_ON;
0530     else
0531         val &= ~MX6_BM_HSIC_CLK_ON;
0532 
0533     writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
0534     spin_unlock_irqrestore(&usbmisc->lock, flags);
0535 
0536     return 0;
0537 }
0538 
0539 
0540 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
0541 {
0542     void __iomem *reg = NULL;
0543     unsigned long flags;
0544     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0545     u32 val;
0546 
0547     usbmisc_imx6q_init(data);
0548 
0549     if (data->index == 0 || data->index == 1) {
0550         reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
0551         spin_lock_irqsave(&usbmisc->lock, flags);
0552         /* Set vbus wakeup source as bvalid */
0553         val = readl(reg);
0554         writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
0555         /*
0556          * Disable dp/dm wakeup in device mode when vbus is
0557          * not there.
0558          */
0559         val = readl(usbmisc->base + data->index * 4);
0560         writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
0561             usbmisc->base + data->index * 4);
0562         spin_unlock_irqrestore(&usbmisc->lock, flags);
0563     }
0564 
0565     /* For HSIC controller */
0566     if (data->hsic) {
0567         val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
0568         val |= MX6SX_BM_HSIC_AUTO_RESUME;
0569         writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
0570     }
0571 
0572     return 0;
0573 }
0574 
0575 static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
0576 {
0577     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0578     u32 reg;
0579 
0580     /*
0581      * Vybrid only has one misc register set, but in two different
0582      * areas. These is reflected in two instances of this driver.
0583      */
0584     if (data->index >= 1)
0585         return -EINVAL;
0586 
0587     if (data->disable_oc) {
0588         reg = readl(usbmisc->base);
0589         writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
0590     }
0591 
0592     return 0;
0593 }
0594 
0595 static int usbmisc_imx7d_set_wakeup
0596     (struct imx_usbmisc_data *data, bool enabled)
0597 {
0598     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0599     unsigned long flags;
0600     u32 val;
0601 
0602     spin_lock_irqsave(&usbmisc->lock, flags);
0603     val = readl(usbmisc->base);
0604     if (enabled) {
0605         val &= ~MX6_USB_OTG_WAKEUP_BITS;
0606         val |= usbmisc_wakeup_setting(data);
0607         writel(val, usbmisc->base);
0608     } else {
0609         if (val & MX6_BM_WAKEUP_INTR)
0610             dev_dbg(data->dev, "wakeup int\n");
0611         writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
0612     }
0613     spin_unlock_irqrestore(&usbmisc->lock, flags);
0614 
0615     return 0;
0616 }
0617 
0618 static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
0619 {
0620     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0621     unsigned long flags;
0622     u32 reg;
0623 
0624     if (data->index >= 1)
0625         return -EINVAL;
0626 
0627     spin_lock_irqsave(&usbmisc->lock, flags);
0628     reg = readl(usbmisc->base);
0629     if (data->disable_oc) {
0630         reg |= MX6_BM_OVER_CUR_DIS;
0631     } else {
0632         reg &= ~MX6_BM_OVER_CUR_DIS;
0633 
0634         /*
0635          * If the polarity is not configured keep it as setup by the
0636          * bootloader.
0637          */
0638         if (data->oc_pol_configured && data->oc_pol_active_low)
0639             reg |= MX6_BM_OVER_CUR_POLARITY;
0640         else if (data->oc_pol_configured)
0641             reg &= ~MX6_BM_OVER_CUR_POLARITY;
0642     }
0643     /* If the polarity is not set keep it as setup by the bootlader */
0644     if (data->pwr_pol == 1)
0645         reg |= MX6_BM_PWR_POLARITY;
0646     writel(reg, usbmisc->base);
0647 
0648     /* SoC non-burst setting */
0649     reg = readl(usbmisc->base);
0650     writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
0651 
0652     if (!data->hsic) {
0653         reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0654         reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
0655         writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID
0656             | MX7D_USBNC_AUTO_RESUME,
0657             usbmisc->base + MX7D_USBNC_USB_CTRL2);
0658         /* PHY tuning for signal quality */
0659         reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
0660         if (data->emp_curr_control && data->emp_curr_control <=
0661             (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) {
0662             reg &= ~TXPREEMPAMPTUNE0_MASK;
0663             reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT);
0664         }
0665 
0666         if (data->dc_vol_level_adjust && data->dc_vol_level_adjust <=
0667             (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) {
0668             reg &= ~TXVREFTUNE0_MASK;
0669             reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT);
0670         }
0671 
0672         writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
0673     }
0674 
0675     spin_unlock_irqrestore(&usbmisc->lock, flags);
0676 
0677     usbmisc_imx7d_set_wakeup(data, false);
0678 
0679     return 0;
0680 }
0681 
0682 static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
0683 {
0684     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0685     struct usb_phy *usb_phy = data->usb_phy;
0686     int val;
0687     unsigned long flags;
0688 
0689     /* Clear VDATSRCENB0 to disable VDP_SRC and IDM_SNK required by BC 1.2 spec */
0690     spin_lock_irqsave(&usbmisc->lock, flags);
0691     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0692     val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0;
0693     writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0694     spin_unlock_irqrestore(&usbmisc->lock, flags);
0695 
0696     /* TVDMSRC_DIS */
0697     msleep(20);
0698 
0699     /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */
0700     spin_lock_irqsave(&usbmisc->lock, flags);
0701     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0702     writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
0703             MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
0704             MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL,
0705                 usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0706     spin_unlock_irqrestore(&usbmisc->lock, flags);
0707 
0708     /* TVDMSRC_ON */
0709     msleep(40);
0710 
0711     /*
0712      * Per BC 1.2, check voltage of D+:
0713      * DCP: if greater than VDAT_REF;
0714      * CDP: if less than VDAT_REF.
0715      */
0716     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
0717     if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) {
0718         dev_dbg(data->dev, "It is a dedicate charging port\n");
0719         usb_phy->chg_type = DCP_TYPE;
0720     } else {
0721         dev_dbg(data->dev, "It is a charging downstream port\n");
0722         usb_phy->chg_type = CDP_TYPE;
0723     }
0724 
0725     return 0;
0726 }
0727 
0728 static void imx7_disable_charger_detector(struct imx_usbmisc_data *data)
0729 {
0730     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0731     unsigned long flags;
0732     u32 val;
0733 
0734     spin_lock_irqsave(&usbmisc->lock, flags);
0735     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0736     val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB |
0737             MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
0738             MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
0739             MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL);
0740     writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0741 
0742     /* Set OPMODE to be 2'b00 and disable its override */
0743     val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0744     val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
0745     writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
0746 
0747     val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0748     writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
0749             usbmisc->base + MX7D_USBNC_USB_CTRL2);
0750     spin_unlock_irqrestore(&usbmisc->lock, flags);
0751 }
0752 
0753 static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data)
0754 {
0755     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0756     unsigned long flags;
0757     u32 val;
0758     int i, data_pin_contact_count = 0;
0759 
0760     /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */
0761     spin_lock_irqsave(&usbmisc->lock, flags);
0762     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0763     writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
0764             usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0765     spin_unlock_irqrestore(&usbmisc->lock, flags);
0766 
0767     for (i = 0; i < 100; i = i + 1) {
0768         val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
0769         if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) {
0770             if (data_pin_contact_count++ > 5)
0771                 /* Data pin makes contact */
0772                 break;
0773             usleep_range(5000, 10000);
0774         } else {
0775             data_pin_contact_count = 0;
0776             usleep_range(5000, 6000);
0777         }
0778     }
0779 
0780     /* Disable DCD after finished data contact check */
0781     spin_lock_irqsave(&usbmisc->lock, flags);
0782     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0783     writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
0784             usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0785     spin_unlock_irqrestore(&usbmisc->lock, flags);
0786 
0787     if (i == 100) {
0788         dev_err(data->dev,
0789             "VBUS is coming from a dedicated power supply.\n");
0790         return -ENXIO;
0791     }
0792 
0793     return 0;
0794 }
0795 
0796 static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
0797 {
0798     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0799     struct usb_phy *usb_phy = data->usb_phy;
0800     unsigned long flags;
0801     u32 val;
0802 
0803     /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */
0804     spin_lock_irqsave(&usbmisc->lock, flags);
0805     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0806     val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL;
0807     writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
0808             MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
0809                 usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
0810     spin_unlock_irqrestore(&usbmisc->lock, flags);
0811 
0812     /* TVDPSRC_ON */
0813     msleep(40);
0814 
0815     /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */
0816     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
0817     if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
0818         dev_dbg(data->dev, "It is a standard downstream port\n");
0819         usb_phy->chg_type = SDP_TYPE;
0820     }
0821 
0822     return 0;
0823 }
0824 
0825 /*
0826  * Whole charger detection process:
0827  * 1. OPMODE override to be non-driving
0828  * 2. Data contact check
0829  * 3. Primary detection
0830  * 4. Secondary detection
0831  * 5. Disable charger detection
0832  */
0833 static int imx7d_charger_detection(struct imx_usbmisc_data *data)
0834 {
0835     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0836     struct usb_phy *usb_phy = data->usb_phy;
0837     unsigned long flags;
0838     u32 val;
0839     int ret;
0840 
0841     /* Check if vbus is valid */
0842     val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
0843     if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) {
0844         dev_err(data->dev, "vbus is error\n");
0845         return -EINVAL;
0846     }
0847 
0848     /*
0849      * Keep OPMODE to be non-driving mode during the whole
0850      * charger detection process.
0851      */
0852     spin_lock_irqsave(&usbmisc->lock, flags);
0853     val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0854     val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
0855     val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING;
0856     writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
0857 
0858     val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0859     writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
0860             usbmisc->base + MX7D_USBNC_USB_CTRL2);
0861     spin_unlock_irqrestore(&usbmisc->lock, flags);
0862 
0863     ret = imx7d_charger_data_contact_detect(data);
0864     if (ret)
0865         return ret;
0866 
0867     ret = imx7d_charger_primary_detection(data);
0868     if (!ret && usb_phy->chg_type != SDP_TYPE)
0869         ret = imx7d_charger_secondary_detection(data);
0870 
0871     imx7_disable_charger_detector(data);
0872 
0873     return ret;
0874 }
0875 
0876 static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data)
0877 {
0878     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0879     unsigned long flags;
0880     u32 reg;
0881 
0882     if (data->index >= 1)
0883         return -EINVAL;
0884 
0885     spin_lock_irqsave(&usbmisc->lock, flags);
0886     reg = readl(usbmisc->base);
0887     if (data->disable_oc) {
0888         reg |= MX6_BM_OVER_CUR_DIS;
0889     } else {
0890         reg &= ~MX6_BM_OVER_CUR_DIS;
0891 
0892         /*
0893          * If the polarity is not configured keep it as setup by the
0894          * bootloader.
0895          */
0896         if (data->oc_pol_configured && data->oc_pol_active_low)
0897             reg |= MX6_BM_OVER_CUR_POLARITY;
0898         else if (data->oc_pol_configured)
0899             reg &= ~MX6_BM_OVER_CUR_POLARITY;
0900     }
0901     /* If the polarity is not set keep it as setup by the bootlader */
0902     if (data->pwr_pol == 1)
0903         reg |= MX6_BM_PWR_POLARITY;
0904 
0905     writel(reg, usbmisc->base);
0906 
0907     /* SoC non-burst setting */
0908     reg = readl(usbmisc->base);
0909     writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
0910 
0911     if (data->hsic) {
0912         reg = readl(usbmisc->base);
0913         writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base);
0914 
0915         reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
0916         reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
0917         writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
0918 
0919         /*
0920          * For non-HSIC controller, the autoresume is enabled
0921          * at MXS PHY driver (usbphy_ctrl bit18).
0922          */
0923         reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0924         writel(reg | MX7D_USBNC_AUTO_RESUME,
0925             usbmisc->base + MX7D_USBNC_USB_CTRL2);
0926     } else {
0927         reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
0928         reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
0929         writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
0930              usbmisc->base + MX7D_USBNC_USB_CTRL2);
0931     }
0932 
0933     spin_unlock_irqrestore(&usbmisc->lock, flags);
0934 
0935     usbmisc_imx7d_set_wakeup(data, false);
0936 
0937     return 0;
0938 }
0939 
0940 static const struct usbmisc_ops imx25_usbmisc_ops = {
0941     .init = usbmisc_imx25_init,
0942     .post = usbmisc_imx25_post,
0943 };
0944 
0945 static const struct usbmisc_ops imx27_usbmisc_ops = {
0946     .init = usbmisc_imx27_init,
0947 };
0948 
0949 static const struct usbmisc_ops imx51_usbmisc_ops = {
0950     .init = usbmisc_imx53_init,
0951 };
0952 
0953 static const struct usbmisc_ops imx53_usbmisc_ops = {
0954     .init = usbmisc_imx53_init,
0955 };
0956 
0957 static const struct usbmisc_ops imx6q_usbmisc_ops = {
0958     .set_wakeup = usbmisc_imx6q_set_wakeup,
0959     .init = usbmisc_imx6q_init,
0960     .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
0961     .hsic_set_clk   = usbmisc_imx6_hsic_set_clk,
0962 };
0963 
0964 static const struct usbmisc_ops vf610_usbmisc_ops = {
0965     .init = usbmisc_vf610_init,
0966 };
0967 
0968 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
0969     .set_wakeup = usbmisc_imx6q_set_wakeup,
0970     .init = usbmisc_imx6sx_init,
0971     .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
0972     .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
0973 };
0974 
0975 static const struct usbmisc_ops imx7d_usbmisc_ops = {
0976     .init = usbmisc_imx7d_init,
0977     .set_wakeup = usbmisc_imx7d_set_wakeup,
0978     .charger_detection = imx7d_charger_detection,
0979 };
0980 
0981 static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
0982     .init = usbmisc_imx7ulp_init,
0983     .set_wakeup = usbmisc_imx7d_set_wakeup,
0984     .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
0985     .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
0986 };
0987 
0988 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
0989 {
0990     struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
0991 
0992     return usbmisc->ops == &imx53_usbmisc_ops;
0993 }
0994 
0995 int imx_usbmisc_init(struct imx_usbmisc_data *data)
0996 {
0997     struct imx_usbmisc *usbmisc;
0998 
0999     if (!data)
1000         return 0;
1001 
1002     usbmisc = dev_get_drvdata(data->dev);
1003     if (!usbmisc->ops->init)
1004         return 0;
1005     return usbmisc->ops->init(data);
1006 }
1007 EXPORT_SYMBOL_GPL(imx_usbmisc_init);
1008 
1009 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
1010 {
1011     struct imx_usbmisc *usbmisc;
1012 
1013     if (!data)
1014         return 0;
1015 
1016     usbmisc = dev_get_drvdata(data->dev);
1017     if (!usbmisc->ops->post)
1018         return 0;
1019     return usbmisc->ops->post(data);
1020 }
1021 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
1022 
1023 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
1024 {
1025     struct imx_usbmisc *usbmisc;
1026 
1027     if (!data)
1028         return 0;
1029 
1030     usbmisc = dev_get_drvdata(data->dev);
1031     if (!usbmisc->ops->set_wakeup)
1032         return 0;
1033     return usbmisc->ops->set_wakeup(data, enabled);
1034 }
1035 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
1036 
1037 int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
1038 {
1039     struct imx_usbmisc *usbmisc;
1040 
1041     if (!data)
1042         return 0;
1043 
1044     usbmisc = dev_get_drvdata(data->dev);
1045     if (!usbmisc->ops->hsic_set_connect || !data->hsic)
1046         return 0;
1047     return usbmisc->ops->hsic_set_connect(data);
1048 }
1049 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
1050 
1051 int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
1052 {
1053     struct imx_usbmisc *usbmisc;
1054 
1055     if (!data)
1056         return 0;
1057 
1058     usbmisc = dev_get_drvdata(data->dev);
1059     if (!usbmisc->ops->hsic_set_clk || !data->hsic)
1060         return 0;
1061     return usbmisc->ops->hsic_set_clk(data, on);
1062 }
1063 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
1064 
1065 int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
1066 {
1067     struct imx_usbmisc *usbmisc;
1068     struct usb_phy *usb_phy;
1069     int ret = 0;
1070 
1071     if (!data)
1072         return -EINVAL;
1073 
1074     usbmisc = dev_get_drvdata(data->dev);
1075     usb_phy = data->usb_phy;
1076     if (!usbmisc->ops->charger_detection)
1077         return -ENOTSUPP;
1078 
1079     if (connect) {
1080         ret = usbmisc->ops->charger_detection(data);
1081         if (ret) {
1082             dev_err(data->dev,
1083                     "Error occurs during detection: %d\n",
1084                     ret);
1085             usb_phy->chg_state = USB_CHARGER_ABSENT;
1086         } else {
1087             usb_phy->chg_state = USB_CHARGER_PRESENT;
1088         }
1089     } else {
1090         usb_phy->chg_state = USB_CHARGER_ABSENT;
1091         usb_phy->chg_type = UNKNOWN_TYPE;
1092     }
1093     return ret;
1094 }
1095 EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);
1096 
1097 static const struct of_device_id usbmisc_imx_dt_ids[] = {
1098     {
1099         .compatible = "fsl,imx25-usbmisc",
1100         .data = &imx25_usbmisc_ops,
1101     },
1102     {
1103         .compatible = "fsl,imx35-usbmisc",
1104         .data = &imx25_usbmisc_ops,
1105     },
1106     {
1107         .compatible = "fsl,imx27-usbmisc",
1108         .data = &imx27_usbmisc_ops,
1109     },
1110     {
1111         .compatible = "fsl,imx51-usbmisc",
1112         .data = &imx51_usbmisc_ops,
1113     },
1114     {
1115         .compatible = "fsl,imx53-usbmisc",
1116         .data = &imx53_usbmisc_ops,
1117     },
1118     {
1119         .compatible = "fsl,imx6q-usbmisc",
1120         .data = &imx6q_usbmisc_ops,
1121     },
1122     {
1123         .compatible = "fsl,vf610-usbmisc",
1124         .data = &vf610_usbmisc_ops,
1125     },
1126     {
1127         .compatible = "fsl,imx6sx-usbmisc",
1128         .data = &imx6sx_usbmisc_ops,
1129     },
1130     {
1131         .compatible = "fsl,imx6ul-usbmisc",
1132         .data = &imx6sx_usbmisc_ops,
1133     },
1134     {
1135         .compatible = "fsl,imx7d-usbmisc",
1136         .data = &imx7d_usbmisc_ops,
1137     },
1138     {
1139         .compatible = "fsl,imx7ulp-usbmisc",
1140         .data = &imx7ulp_usbmisc_ops,
1141     },
1142     { /* sentinel */ }
1143 };
1144 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
1145 
1146 static int usbmisc_imx_probe(struct platform_device *pdev)
1147 {
1148     struct imx_usbmisc *data;
1149 
1150     data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
1151     if (!data)
1152         return -ENOMEM;
1153 
1154     spin_lock_init(&data->lock);
1155 
1156     data->base = devm_platform_ioremap_resource(pdev, 0);
1157     if (IS_ERR(data->base))
1158         return PTR_ERR(data->base);
1159 
1160     data->ops = of_device_get_match_data(&pdev->dev);
1161     platform_set_drvdata(pdev, data);
1162 
1163     return 0;
1164 }
1165 
1166 static int usbmisc_imx_remove(struct platform_device *pdev)
1167 {
1168     return 0;
1169 }
1170 
1171 static struct platform_driver usbmisc_imx_driver = {
1172     .probe = usbmisc_imx_probe,
1173     .remove = usbmisc_imx_remove,
1174     .driver = {
1175         .name = "usbmisc_imx",
1176         .of_match_table = usbmisc_imx_dt_ids,
1177      },
1178 };
1179 
1180 module_platform_driver(usbmisc_imx_driver);
1181 
1182 MODULE_ALIAS("platform:usbmisc-imx");
1183 MODULE_LICENSE("GPL");
1184 MODULE_DESCRIPTION("driver for imx usb non-core registers");
1185 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");