linux/drivers/usb/chipidea/usbmisc_imx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2012 Freescale Semiconductor, Inc.
   4 */
   5
   6#include <linux/module.h>
   7#include <linux/of_platform.h>
   8#include <linux/err.h>
   9#include <linux/io.h>
  10#include <linux/delay.h>
  11#include <linux/usb/otg.h>
  12
  13#include "ci_hdrc_imx.h"
  14
  15#define MX25_USB_PHY_CTRL_OFFSET        0x08
  16#define MX25_BM_EXTERNAL_VBUS_DIVIDER   BIT(23)
  17
  18#define MX25_EHCI_INTERFACE_SINGLE_UNI  (2 << 0)
  19#define MX25_EHCI_INTERFACE_DIFF_UNI    (0 << 0)
  20#define MX25_EHCI_INTERFACE_MASK        (0xf)
  21
  22#define MX25_OTG_SIC_SHIFT              29
  23#define MX25_OTG_SIC_MASK               (0x3 << MX25_OTG_SIC_SHIFT)
  24#define MX25_OTG_PM_BIT                 BIT(24)
  25#define MX25_OTG_PP_BIT                 BIT(11)
  26#define MX25_OTG_OCPOL_BIT              BIT(3)
  27
  28#define MX25_H1_SIC_SHIFT               21
  29#define MX25_H1_SIC_MASK                (0x3 << MX25_H1_SIC_SHIFT)
  30#define MX25_H1_PP_BIT                  BIT(18)
  31#define MX25_H1_PM_BIT                  BIT(16)
  32#define MX25_H1_IPPUE_UP_BIT            BIT(7)
  33#define MX25_H1_IPPUE_DOWN_BIT          BIT(6)
  34#define MX25_H1_TLL_BIT                 BIT(5)
  35#define MX25_H1_USBTE_BIT               BIT(4)
  36#define MX25_H1_OCPOL_BIT               BIT(2)
  37
  38#define MX27_H1_PM_BIT                  BIT(8)
  39#define MX27_H2_PM_BIT                  BIT(16)
  40#define MX27_OTG_PM_BIT                 BIT(24)
  41
  42#define MX53_USB_OTG_PHY_CTRL_0_OFFSET  0x08
  43#define MX53_USB_OTG_PHY_CTRL_1_OFFSET  0x0c
  44#define MX53_USB_CTRL_1_OFFSET          0x10
  45#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
  46#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
  47#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
  48#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
  49#define MX53_USB_UH2_CTRL_OFFSET        0x14
  50#define MX53_USB_UH3_CTRL_OFFSET        0x18
  51#define MX53_USB_CLKONOFF_CTRL_OFFSET   0x24
  52#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
  53#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
  54#define MX53_BM_OVER_CUR_DIS_H1         BIT(5)
  55#define MX53_BM_OVER_CUR_DIS_OTG        BIT(8)
  56#define MX53_BM_OVER_CUR_DIS_UHx        BIT(30)
  57#define MX53_USB_CTRL_1_UH2_ULPI_EN     BIT(26)
  58#define MX53_USB_CTRL_1_UH3_ULPI_EN     BIT(27)
  59#define MX53_USB_UHx_CTRL_WAKE_UP_EN    BIT(7)
  60#define MX53_USB_UHx_CTRL_ULPI_INT_EN   BIT(8)
  61#define MX53_USB_PHYCTRL1_PLLDIV_MASK   0x3
  62#define MX53_USB_PLL_DIV_24_MHZ         0x01
  63
  64#define MX6_BM_NON_BURST_SETTING        BIT(1)
  65#define MX6_BM_OVER_CUR_DIS             BIT(7)
  66#define MX6_BM_OVER_CUR_POLARITY        BIT(8)
  67#define MX6_BM_PWR_POLARITY             BIT(9)
  68#define MX6_BM_WAKEUP_ENABLE            BIT(10)
  69#define MX6_BM_UTMI_ON_CLOCK            BIT(13)
  70#define MX6_BM_ID_WAKEUP                BIT(16)
  71#define MX6_BM_VBUS_WAKEUP              BIT(17)
  72#define MX6SX_BM_DPDM_WAKEUP_EN         BIT(29)
  73#define MX6_BM_WAKEUP_INTR              BIT(31)
  74
  75#define MX6_USB_HSIC_CTRL_OFFSET        0x10
  76/* Send resume signal without 480Mhz PHY clock */
  77#define MX6SX_BM_HSIC_AUTO_RESUME       BIT(23)
  78/* set before portsc.suspendM = 1 */
  79#define MX6_BM_HSIC_DEV_CONN            BIT(21)
  80/* HSIC enable */
  81#define MX6_BM_HSIC_EN                  BIT(12)
  82/* Force HSIC module 480M clock on, even when in Host is in suspend mode */
  83#define MX6_BM_HSIC_CLK_ON              BIT(11)
  84
  85#define MX6_USB_OTG1_PHY_CTRL           0x18
  86/* For imx6dql, it is host-only controller, for later imx6, it is otg's */
  87#define MX6_USB_OTG2_PHY_CTRL           0x1c
  88#define MX6SX_USB_VBUS_WAKEUP_SOURCE(v) (v << 8)
  89#define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS       MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
  90#define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID     MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
  91#define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID     MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
  92#define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END   MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
  93
  94#define VF610_OVER_CUR_DIS              BIT(7)
  95
  96#define MX7D_USBNC_USB_CTRL2            0x4
  97#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK        0x3
  98#define MX7D_USB_VBUS_WAKEUP_SOURCE(v)          (v << 0)
  99#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS        MX7D_USB_VBUS_WAKEUP_SOURCE(0)
 100#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID      MX7D_USB_VBUS_WAKEUP_SOURCE(1)
 101#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID      MX7D_USB_VBUS_WAKEUP_SOURCE(2)
 102#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END    MX7D_USB_VBUS_WAKEUP_SOURCE(3)
 103#define MX7D_USBNC_AUTO_RESUME                          BIT(2)
 104/* The default DM/DP value is pull-down */
 105#define MX7D_USBNC_USB_CTRL2_OPMODE(v)                  (v << 6)
 106#define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1)
 107#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK       (BIT(7) | BIT(6))
 108#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN         BIT(8)
 109#define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_VAL            BIT(12)
 110#define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_EN             BIT(13)
 111#define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_VAL            BIT(14)
 112#define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_EN             BIT(15)
 113#define MX7D_USBNC_USB_CTRL2_DP_DM_MASK                 (BIT(12) | BIT(13) | \
 114                                                        BIT(14) | BIT(15))
 115
 116#define MX7D_USB_OTG_PHY_CFG1           0x30
 117#define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL      BIT(0)
 118#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0  BIT(1)
 119#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0  BIT(2)
 120#define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB       BIT(3)
 121#define MX7D_USB_OTG_PHY_CFG2_DRVVBUS0          BIT(16)
 122
 123#define MX7D_USB_OTG_PHY_CFG2           0x34
 124
 125#define MX7D_USB_OTG_PHY_STATUS         0x3c
 126#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0     BIT(0)
 127#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1     BIT(1)
 128#define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD        BIT(3)
 129#define MX7D_USB_OTG_PHY_STATUS_CHRGDET         BIT(29)
 130
 131#define MX7D_USB_OTG_PHY_CFG1           0x30
 132#define TXPREEMPAMPTUNE0_BIT            28
 133#define TXPREEMPAMPTUNE0_MASK           (3 << 28)
 134#define TXVREFTUNE0_BIT                 20
 135#define TXVREFTUNE0_MASK                (0xf << 20)
 136
 137#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
 138                                 MX6_BM_ID_WAKEUP)
 139
 140struct usbmisc_ops {
 141        /* It's called once when probe a usb device */
 142        int (*init)(struct imx_usbmisc_data *data);
 143        /* It's called once after adding a usb device */
 144        int (*post)(struct imx_usbmisc_data *data);
 145        /* It's called when we need to enable/disable usb wakeup */
 146        int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
 147        /* It's called before setting portsc.suspendM */
 148        int (*hsic_set_connect)(struct imx_usbmisc_data *data);
 149        /* It's called during suspend/resume */
 150        int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
 151        /* usb charger detection */
 152        int (*charger_detection)(struct imx_usbmisc_data *data);
 153};
 154
 155struct imx_usbmisc {
 156        void __iomem *base;
 157        spinlock_t lock;
 158        const struct usbmisc_ops *ops;
 159};
 160
 161static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
 162
 163static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
 164{
 165        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 166        unsigned long flags;
 167        u32 val = 0;
 168
 169        if (data->index > 1)
 170                return -EINVAL;
 171
 172        spin_lock_irqsave(&usbmisc->lock, flags);
 173        switch (data->index) {
 174        case 0:
 175                val = readl(usbmisc->base);
 176                val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
 177                val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
 178                val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
 179
 180                /*
 181                 * If the polarity is not configured assume active high for
 182                 * historical reasons.
 183                 */
 184                if (data->oc_pol_configured && data->oc_pol_active_low)
 185                        val &= ~MX25_OTG_OCPOL_BIT;
 186
 187                writel(val, usbmisc->base);
 188                break;
 189        case 1:
 190                val = readl(usbmisc->base);
 191                val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
 192                val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
 193                val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
 194                        MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
 195
 196                /*
 197                 * If the polarity is not configured assume active high for
 198                 * historical reasons.
 199                 */
 200                if (data->oc_pol_configured && data->oc_pol_active_low)
 201                        val &= ~MX25_H1_OCPOL_BIT;
 202
 203                writel(val, usbmisc->base);
 204
 205                break;
 206        }
 207        spin_unlock_irqrestore(&usbmisc->lock, flags);
 208
 209        return 0;
 210}
 211
 212static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
 213{
 214        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 215        void __iomem *reg;
 216        unsigned long flags;
 217        u32 val;
 218
 219        if (data->index > 2)
 220                return -EINVAL;
 221
 222        if (data->index)
 223                return 0;
 224
 225        spin_lock_irqsave(&usbmisc->lock, flags);
 226        reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
 227        val = readl(reg);
 228
 229        if (data->evdo)
 230                val |= MX25_BM_EXTERNAL_VBUS_DIVIDER;
 231        else
 232                val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER;
 233
 234        writel(val, reg);
 235        spin_unlock_irqrestore(&usbmisc->lock, flags);
 236        usleep_range(5000, 10000); /* needed to stabilize voltage */
 237
 238        return 0;
 239}
 240
 241static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
 242{
 243        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 244        unsigned long flags;
 245        u32 val;
 246
 247        switch (data->index) {
 248        case 0:
 249                val = MX27_OTG_PM_BIT;
 250                break;
 251        case 1:
 252                val = MX27_H1_PM_BIT;
 253                break;
 254        case 2:
 255                val = MX27_H2_PM_BIT;
 256                break;
 257        default:
 258                return -EINVAL;
 259        }
 260
 261        spin_lock_irqsave(&usbmisc->lock, flags);
 262        if (data->disable_oc)
 263                val = readl(usbmisc->base) | val;
 264        else
 265                val = readl(usbmisc->base) & ~val;
 266        writel(val, usbmisc->base);
 267        spin_unlock_irqrestore(&usbmisc->lock, flags);
 268
 269        return 0;
 270}
 271
 272static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
 273{
 274        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 275        void __iomem *reg = NULL;
 276        unsigned long flags;
 277        u32 val = 0;
 278
 279        if (data->index > 3)
 280                return -EINVAL;
 281
 282        /* Select a 24 MHz reference clock for the PHY  */
 283        val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 284        val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
 285        val |= MX53_USB_PLL_DIV_24_MHZ;
 286        writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 287
 288        spin_lock_irqsave(&usbmisc->lock, flags);
 289
 290        switch (data->index) {
 291        case 0:
 292                if (data->disable_oc) {
 293                        reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
 294                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
 295                        writel(val, reg);
 296                }
 297                break;
 298        case 1:
 299                if (data->disable_oc) {
 300                        reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
 301                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
 302                        writel(val, reg);
 303                }
 304                break;
 305        case 2:
 306                if (data->ulpi) {
 307                        /* set USBH2 into ULPI-mode. */
 308                        reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
 309                        val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
 310                        /* select ULPI clock */
 311                        val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
 312                        val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
 313                        writel(val, reg);
 314                        /* Set interrupt wake up enable */
 315                        reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
 316                        val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
 317                                | MX53_USB_UHx_CTRL_ULPI_INT_EN;
 318                        writel(val, reg);
 319                        if (is_imx53_usbmisc(data)) {
 320                                /* Disable internal 60Mhz clock */
 321                                reg = usbmisc->base +
 322                                        MX53_USB_CLKONOFF_CTRL_OFFSET;
 323                                val = readl(reg) |
 324                                        MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
 325                                writel(val, reg);
 326                        }
 327
 328                }
 329                if (data->disable_oc) {
 330                        reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
 331                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
 332                        writel(val, reg);
 333                }
 334                break;
 335        case 3:
 336                if (data->ulpi) {
 337                        /* set USBH3 into ULPI-mode. */
 338                        reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
 339                        val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
 340                        /* select ULPI clock */
 341                        val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
 342                        val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
 343                        writel(val, reg);
 344                        /* Set interrupt wake up enable */
 345                        reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
 346                        val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
 347                                | MX53_USB_UHx_CTRL_ULPI_INT_EN;
 348                        writel(val, reg);
 349
 350                        if (is_imx53_usbmisc(data)) {
 351                                /* Disable internal 60Mhz clock */
 352                                reg = usbmisc->base +
 353                                        MX53_USB_CLKONOFF_CTRL_OFFSET;
 354                                val = readl(reg) |
 355                                        MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
 356                                writel(val, reg);
 357                        }
 358                }
 359                if (data->disable_oc) {
 360                        reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
 361                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
 362                        writel(val, reg);
 363                }
 364                break;
 365        }
 366
 367        spin_unlock_irqrestore(&usbmisc->lock, flags);
 368
 369        return 0;
 370}
 371
 372static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
 373{
 374        u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
 375
 376        if (data->ext_id || data->available_role != USB_DR_MODE_OTG)
 377                wakeup_setting &= ~MX6_BM_ID_WAKEUP;
 378
 379        if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST)
 380                wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
 381
 382        return wakeup_setting;
 383}
 384
 385static int usbmisc_imx6q_set_wakeup
 386        (struct imx_usbmisc_data *data, bool enabled)
 387{
 388        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 389        unsigned long flags;
 390        u32 val;
 391        int ret = 0;
 392
 393        if (data->index > 3)
 394                return -EINVAL;
 395
 396        spin_lock_irqsave(&usbmisc->lock, flags);
 397        val = readl(usbmisc->base + data->index * 4);
 398        if (enabled) {
 399                val &= ~MX6_USB_OTG_WAKEUP_BITS;
 400                val |= usbmisc_wakeup_setting(data);
 401        } else {
 402                if (val & MX6_BM_WAKEUP_INTR)
 403                        pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
 404                val &= ~MX6_USB_OTG_WAKEUP_BITS;
 405        }
 406        writel(val, usbmisc->base + data->index * 4);
 407        spin_unlock_irqrestore(&usbmisc->lock, flags);
 408
 409        return ret;
 410}
 411
 412static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
 413{
 414        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 415        unsigned long flags;
 416        u32 reg;
 417
 418        if (data->index > 3)
 419                return -EINVAL;
 420
 421        spin_lock_irqsave(&usbmisc->lock, flags);
 422
 423        reg = readl(usbmisc->base + data->index * 4);
 424        if (data->disable_oc) {
 425                reg |= MX6_BM_OVER_CUR_DIS;
 426        } else {
 427                reg &= ~MX6_BM_OVER_CUR_DIS;
 428
 429                /*
 430                 * If the polarity is not configured keep it as setup by the
 431                 * bootloader.
 432                 */
 433                if (data->oc_pol_configured && data->oc_pol_active_low)
 434                        reg |= MX6_BM_OVER_CUR_POLARITY;
 435                else if (data->oc_pol_configured)
 436                        reg &= ~MX6_BM_OVER_CUR_POLARITY;
 437        }
 438        /* If the polarity is not set keep it as setup by the bootlader */
 439        if (data->pwr_pol == 1)
 440                reg |= MX6_BM_PWR_POLARITY;
 441        writel(reg, usbmisc->base + data->index * 4);
 442
 443        /* SoC non-burst setting */
 444        reg = readl(usbmisc->base + data->index * 4);
 445        writel(reg | MX6_BM_NON_BURST_SETTING,
 446                        usbmisc->base + data->index * 4);
 447
 448        /* For HSIC controller */
 449        if (data->hsic) {
 450                reg = readl(usbmisc->base + data->index * 4);
 451                writel(reg | MX6_BM_UTMI_ON_CLOCK,
 452                        usbmisc->base + data->index * 4);
 453                reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
 454                        + (data->index - 2) * 4);
 455                reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
 456                writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
 457                        + (data->index - 2) * 4);
 458        }
 459
 460        spin_unlock_irqrestore(&usbmisc->lock, flags);
 461
 462        usbmisc_imx6q_set_wakeup(data, false);
 463
 464        return 0;
 465}
 466
 467static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
 468{
 469        int offset, ret = 0;
 470
 471        if (data->index == 2 || data->index == 3) {
 472                offset = (data->index - 2) * 4;
 473        } else if (data->index == 0) {
 474                /*
 475                 * For SoCs like i.MX7D and later, each USB controller has
 476                 * its own non-core register region. For SoCs before i.MX7D,
 477                 * the first two USB controllers are non-HSIC controllers.
 478                 */
 479                offset = 0;
 480        } else {
 481                dev_err(data->dev, "index is error for usbmisc\n");
 482                ret = -EINVAL;
 483        }
 484
 485        return ret ? ret : offset;
 486}
 487
 488static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
 489{
 490        unsigned long flags;
 491        u32 val;
 492        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 493        int offset;
 494
 495        spin_lock_irqsave(&usbmisc->lock, flags);
 496        offset = usbmisc_imx6_hsic_get_reg_offset(data);
 497        if (offset < 0) {
 498                spin_unlock_irqrestore(&usbmisc->lock, flags);
 499                return offset;
 500        }
 501
 502        val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 503        if (!(val & MX6_BM_HSIC_DEV_CONN))
 504                writel(val | MX6_BM_HSIC_DEV_CONN,
 505                        usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 506
 507        spin_unlock_irqrestore(&usbmisc->lock, flags);
 508
 509        return 0;
 510}
 511
 512static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
 513{
 514        unsigned long flags;
 515        u32 val;
 516        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 517        int offset;
 518
 519        spin_lock_irqsave(&usbmisc->lock, flags);
 520        offset = usbmisc_imx6_hsic_get_reg_offset(data);
 521        if (offset < 0) {
 522                spin_unlock_irqrestore(&usbmisc->lock, flags);
 523                return offset;
 524        }
 525
 526        val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 527        val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
 528        if (on)
 529                val |= MX6_BM_HSIC_CLK_ON;
 530        else
 531                val &= ~MX6_BM_HSIC_CLK_ON;
 532
 533        writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 534        spin_unlock_irqrestore(&usbmisc->lock, flags);
 535
 536        return 0;
 537}
 538
 539
 540static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
 541{
 542        void __iomem *reg = NULL;
 543        unsigned long flags;
 544        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 545        u32 val;
 546
 547        usbmisc_imx6q_init(data);
 548
 549        if (data->index == 0 || data->index == 1) {
 550                reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
 551                spin_lock_irqsave(&usbmisc->lock, flags);
 552                /* Set vbus wakeup source as bvalid */
 553                val = readl(reg);
 554                writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
 555                /*
 556                 * Disable dp/dm wakeup in device mode when vbus is
 557                 * not there.
 558                 */
 559                val = readl(usbmisc->base + data->index * 4);
 560                writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
 561                        usbmisc->base + data->index * 4);
 562                spin_unlock_irqrestore(&usbmisc->lock, flags);
 563        }
 564
 565        /* For HSIC controller */
 566        if (data->hsic) {
 567                val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
 568                val |= MX6SX_BM_HSIC_AUTO_RESUME;
 569                writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
 570        }
 571
 572        return 0;
 573}
 574
 575static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
 576{
 577        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 578        u32 reg;
 579
 580        /*
 581         * Vybrid only has one misc register set, but in two different
 582         * areas. These is reflected in two instances of this driver.
 583         */
 584        if (data->index >= 1)
 585                return -EINVAL;
 586
 587        if (data->disable_oc) {
 588                reg = readl(usbmisc->base);
 589                writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
 590        }
 591
 592        return 0;
 593}
 594
 595static int usbmisc_imx7d_set_wakeup
 596        (struct imx_usbmisc_data *data, bool enabled)
 597{
 598        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 599        unsigned long flags;
 600        u32 val;
 601
 602        spin_lock_irqsave(&usbmisc->lock, flags);
 603        val = readl(usbmisc->base);
 604        if (enabled) {
 605                val &= ~MX6_USB_OTG_WAKEUP_BITS;
 606                val |= usbmisc_wakeup_setting(data);
 607                writel(val, usbmisc->base);
 608        } else {
 609                if (val & MX6_BM_WAKEUP_INTR)
 610                        dev_dbg(data->dev, "wakeup int\n");
 611                writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
 612        }
 613        spin_unlock_irqrestore(&usbmisc->lock, flags);
 614
 615        return 0;
 616}
 617
 618static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
 619{
 620        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 621        unsigned long flags;
 622        u32 reg;
 623
 624        if (data->index >= 1)
 625                return -EINVAL;
 626
 627        spin_lock_irqsave(&usbmisc->lock, flags);
 628        reg = readl(usbmisc->base);
 629        if (data->disable_oc) {
 630                reg |= MX6_BM_OVER_CUR_DIS;
 631        } else {
 632                reg &= ~MX6_BM_OVER_CUR_DIS;
 633
 634                /*
 635                 * If the polarity is not configured keep it as setup by the
 636                 * bootloader.
 637                 */
 638                if (data->oc_pol_configured && data->oc_pol_active_low)
 639                        reg |= MX6_BM_OVER_CUR_POLARITY;
 640                else if (data->oc_pol_configured)
 641                        reg &= ~MX6_BM_OVER_CUR_POLARITY;
 642        }
 643        /* If the polarity is not set keep it as setup by the bootlader */
 644        if (data->pwr_pol == 1)
 645                reg |= MX6_BM_PWR_POLARITY;
 646        writel(reg, usbmisc->base);
 647
 648        /* SoC non-burst setting */
 649        reg = readl(usbmisc->base);
 650        writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
 651
 652        if (!data->hsic) {
 653                reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 654                reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
 655                writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID
 656                        | MX7D_USBNC_AUTO_RESUME,
 657                        usbmisc->base + MX7D_USBNC_USB_CTRL2);
 658                /* PHY tuning for signal quality */
 659                reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
 660                if (data->emp_curr_control && data->emp_curr_control <=
 661                        (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) {
 662                        reg &= ~TXPREEMPAMPTUNE0_MASK;
 663                        reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT);
 664                }
 665
 666                if (data->dc_vol_level_adjust && data->dc_vol_level_adjust <=
 667                        (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) {
 668                        reg &= ~TXVREFTUNE0_MASK;
 669                        reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT);
 670                }
 671
 672                writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
 673        }
 674
 675        spin_unlock_irqrestore(&usbmisc->lock, flags);
 676
 677        usbmisc_imx7d_set_wakeup(data, false);
 678
 679        return 0;
 680}
 681
 682static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
 683{
 684        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 685        struct usb_phy *usb_phy = data->usb_phy;
 686        int val;
 687        unsigned long flags;
 688
 689        /* Clear VDATSRCENB0 to disable VDP_SRC and IDM_SNK required by BC 1.2 spec */
 690        spin_lock_irqsave(&usbmisc->lock, flags);
 691        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 692        val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0;
 693        writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 694        spin_unlock_irqrestore(&usbmisc->lock, flags);
 695
 696        /* TVDMSRC_DIS */
 697        msleep(20);
 698
 699        /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */
 700        spin_lock_irqsave(&usbmisc->lock, flags);
 701        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 702        writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
 703                        MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
 704                        MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL,
 705                                usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 706        spin_unlock_irqrestore(&usbmisc->lock, flags);
 707
 708        /* TVDMSRC_ON */
 709        msleep(40);
 710
 711        /*
 712         * Per BC 1.2, check voltage of D+:
 713         * DCP: if greater than VDAT_REF;
 714         * CDP: if less than VDAT_REF.
 715         */
 716        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
 717        if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) {
 718                dev_dbg(data->dev, "It is a dedicate charging port\n");
 719                usb_phy->chg_type = DCP_TYPE;
 720        } else {
 721                dev_dbg(data->dev, "It is a charging downstream port\n");
 722                usb_phy->chg_type = CDP_TYPE;
 723        }
 724
 725        return 0;
 726}
 727
 728static void imx7_disable_charger_detector(struct imx_usbmisc_data *data)
 729{
 730        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 731        unsigned long flags;
 732        u32 val;
 733
 734        spin_lock_irqsave(&usbmisc->lock, flags);
 735        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 736        val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB |
 737                        MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
 738                        MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
 739                        MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL);
 740        writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 741
 742        /* Set OPMODE to be 2'b00 and disable its override */
 743        val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 744        val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
 745        writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
 746
 747        val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 748        writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
 749                        usbmisc->base + MX7D_USBNC_USB_CTRL2);
 750        spin_unlock_irqrestore(&usbmisc->lock, flags);
 751}
 752
 753static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data)
 754{
 755        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 756        unsigned long flags;
 757        u32 val;
 758        int i, data_pin_contact_count = 0;
 759
 760        /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */
 761        spin_lock_irqsave(&usbmisc->lock, flags);
 762        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 763        writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
 764                        usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 765        spin_unlock_irqrestore(&usbmisc->lock, flags);
 766
 767        for (i = 0; i < 100; i = i + 1) {
 768                val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
 769                if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) {
 770                        if (data_pin_contact_count++ > 5)
 771                                /* Data pin makes contact */
 772                                break;
 773                        usleep_range(5000, 10000);
 774                } else {
 775                        data_pin_contact_count = 0;
 776                        usleep_range(5000, 6000);
 777                }
 778        }
 779
 780        /* Disable DCD after finished data contact check */
 781        spin_lock_irqsave(&usbmisc->lock, flags);
 782        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 783        writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
 784                        usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 785        spin_unlock_irqrestore(&usbmisc->lock, flags);
 786
 787        if (i == 100) {
 788                dev_err(data->dev,
 789                        "VBUS is coming from a dedicated power supply.\n");
 790                return -ENXIO;
 791        }
 792
 793        return 0;
 794}
 795
 796static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
 797{
 798        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 799        struct usb_phy *usb_phy = data->usb_phy;
 800        unsigned long flags;
 801        u32 val;
 802
 803        /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */
 804        spin_lock_irqsave(&usbmisc->lock, flags);
 805        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 806        val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL;
 807        writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
 808                        MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
 809                                usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
 810        spin_unlock_irqrestore(&usbmisc->lock, flags);
 811
 812        /* TVDPSRC_ON */
 813        msleep(40);
 814
 815        /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */
 816        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
 817        if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
 818                dev_dbg(data->dev, "It is a standard downstream port\n");
 819                usb_phy->chg_type = SDP_TYPE;
 820        }
 821
 822        return 0;
 823}
 824
 825/*
 826 * Whole charger detection process:
 827 * 1. OPMODE override to be non-driving
 828 * 2. Data contact check
 829 * 3. Primary detection
 830 * 4. Secondary detection
 831 * 5. Disable charger detection
 832 */
 833static int imx7d_charger_detection(struct imx_usbmisc_data *data)
 834{
 835        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 836        struct usb_phy *usb_phy = data->usb_phy;
 837        unsigned long flags;
 838        u32 val;
 839        int ret;
 840
 841        /* Check if vbus is valid */
 842        val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
 843        if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) {
 844                dev_err(data->dev, "vbus is error\n");
 845                return -EINVAL;
 846        }
 847
 848        /*
 849         * Keep OPMODE to be non-driving mode during the whole
 850         * charger detection process.
 851         */
 852        spin_lock_irqsave(&usbmisc->lock, flags);
 853        val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 854        val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
 855        val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING;
 856        writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
 857
 858        val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 859        writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
 860                        usbmisc->base + MX7D_USBNC_USB_CTRL2);
 861        spin_unlock_irqrestore(&usbmisc->lock, flags);
 862
 863        ret = imx7d_charger_data_contact_detect(data);
 864        if (ret)
 865                return ret;
 866
 867        ret = imx7d_charger_primary_detection(data);
 868        if (!ret && usb_phy->chg_type != SDP_TYPE)
 869                ret = imx7d_charger_secondary_detection(data);
 870
 871        imx7_disable_charger_detector(data);
 872
 873        return ret;
 874}
 875
 876static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data)
 877{
 878        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 879        unsigned long flags;
 880        u32 reg;
 881
 882        if (data->index >= 1)
 883                return -EINVAL;
 884
 885        spin_lock_irqsave(&usbmisc->lock, flags);
 886        reg = readl(usbmisc->base);
 887        if (data->disable_oc) {
 888                reg |= MX6_BM_OVER_CUR_DIS;
 889        } else {
 890                reg &= ~MX6_BM_OVER_CUR_DIS;
 891
 892                /*
 893                 * If the polarity is not configured keep it as setup by the
 894                 * bootloader.
 895                 */
 896                if (data->oc_pol_configured && data->oc_pol_active_low)
 897                        reg |= MX6_BM_OVER_CUR_POLARITY;
 898                else if (data->oc_pol_configured)
 899                        reg &= ~MX6_BM_OVER_CUR_POLARITY;
 900        }
 901        /* If the polarity is not set keep it as setup by the bootlader */
 902        if (data->pwr_pol == 1)
 903                reg |= MX6_BM_PWR_POLARITY;
 904
 905        writel(reg, usbmisc->base);
 906
 907        /* SoC non-burst setting */
 908        reg = readl(usbmisc->base);
 909        writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
 910
 911        if (data->hsic) {
 912                reg = readl(usbmisc->base);
 913                writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base);
 914
 915                reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
 916                reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
 917                writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
 918
 919                /*
 920                 * For non-HSIC controller, the autoresume is enabled
 921                 * at MXS PHY driver (usbphy_ctrl bit18).
 922                 */
 923                reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 924                writel(reg | MX7D_USBNC_AUTO_RESUME,
 925                        usbmisc->base + MX7D_USBNC_USB_CTRL2);
 926        } else {
 927                reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 928                reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
 929                writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
 930                         usbmisc->base + MX7D_USBNC_USB_CTRL2);
 931        }
 932
 933        spin_unlock_irqrestore(&usbmisc->lock, flags);
 934
 935        usbmisc_imx7d_set_wakeup(data, false);
 936
 937        return 0;
 938}
 939
 940static const struct usbmisc_ops imx25_usbmisc_ops = {
 941        .init = usbmisc_imx25_init,
 942        .post = usbmisc_imx25_post,
 943};
 944
 945static const struct usbmisc_ops imx27_usbmisc_ops = {
 946        .init = usbmisc_imx27_init,
 947};
 948
 949static const struct usbmisc_ops imx51_usbmisc_ops = {
 950        .init = usbmisc_imx53_init,
 951};
 952
 953static const struct usbmisc_ops imx53_usbmisc_ops = {
 954        .init = usbmisc_imx53_init,
 955};
 956
 957static const struct usbmisc_ops imx6q_usbmisc_ops = {
 958        .set_wakeup = usbmisc_imx6q_set_wakeup,
 959        .init = usbmisc_imx6q_init,
 960        .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
 961        .hsic_set_clk   = usbmisc_imx6_hsic_set_clk,
 962};
 963
 964static const struct usbmisc_ops vf610_usbmisc_ops = {
 965        .init = usbmisc_vf610_init,
 966};
 967
 968static const struct usbmisc_ops imx6sx_usbmisc_ops = {
 969        .set_wakeup = usbmisc_imx6q_set_wakeup,
 970        .init = usbmisc_imx6sx_init,
 971        .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
 972        .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
 973};
 974
 975static const struct usbmisc_ops imx7d_usbmisc_ops = {
 976        .init = usbmisc_imx7d_init,
 977        .set_wakeup = usbmisc_imx7d_set_wakeup,
 978        .charger_detection = imx7d_charger_detection,
 979};
 980
 981static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
 982        .init = usbmisc_imx7ulp_init,
 983        .set_wakeup = usbmisc_imx7d_set_wakeup,
 984        .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
 985        .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
 986};
 987
 988static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
 989{
 990        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 991
 992        return usbmisc->ops == &imx53_usbmisc_ops;
 993}
 994
 995int imx_usbmisc_init(struct imx_usbmisc_data *data)
 996{
 997        struct imx_usbmisc *usbmisc;
 998
 999        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}
1007EXPORT_SYMBOL_GPL(imx_usbmisc_init);
1008
1009int 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}
1021EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
1022
1023int 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}
1035EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
1036
1037int 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}
1049EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
1050
1051int 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}
1063EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
1064
1065int 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}
1095EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);
1096
1097static 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};
1144MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
1145
1146static 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
1166static int usbmisc_imx_remove(struct platform_device *pdev)
1167{
1168        return 0;
1169}
1170
1171static 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
1180module_platform_driver(usbmisc_imx_driver);
1181
1182MODULE_ALIAS("platform:usbmisc-imx");
1183MODULE_LICENSE("GPL");
1184MODULE_DESCRIPTION("driver for imx usb non-core registers");
1185MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
1186