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
  12#include "ci_hdrc_imx.h"
  13
  14#define MX25_USB_PHY_CTRL_OFFSET        0x08
  15#define MX25_BM_EXTERNAL_VBUS_DIVIDER   BIT(23)
  16
  17#define MX25_EHCI_INTERFACE_SINGLE_UNI  (2 << 0)
  18#define MX25_EHCI_INTERFACE_DIFF_UNI    (0 << 0)
  19#define MX25_EHCI_INTERFACE_MASK        (0xf)
  20
  21#define MX25_OTG_SIC_SHIFT              29
  22#define MX25_OTG_SIC_MASK               (0x3 << MX25_OTG_SIC_SHIFT)
  23#define MX25_OTG_PM_BIT                 BIT(24)
  24#define MX25_OTG_PP_BIT                 BIT(11)
  25#define MX25_OTG_OCPOL_BIT              BIT(3)
  26
  27#define MX25_H1_SIC_SHIFT               21
  28#define MX25_H1_SIC_MASK                (0x3 << MX25_H1_SIC_SHIFT)
  29#define MX25_H1_PP_BIT                  BIT(18)
  30#define MX25_H1_PM_BIT                  BIT(16)
  31#define MX25_H1_IPPUE_UP_BIT            BIT(7)
  32#define MX25_H1_IPPUE_DOWN_BIT          BIT(6)
  33#define MX25_H1_TLL_BIT                 BIT(5)
  34#define MX25_H1_USBTE_BIT               BIT(4)
  35#define MX25_H1_OCPOL_BIT               BIT(2)
  36
  37#define MX27_H1_PM_BIT                  BIT(8)
  38#define MX27_H2_PM_BIT                  BIT(16)
  39#define MX27_OTG_PM_BIT                 BIT(24)
  40
  41#define MX53_USB_OTG_PHY_CTRL_0_OFFSET  0x08
  42#define MX53_USB_OTG_PHY_CTRL_1_OFFSET  0x0c
  43#define MX53_USB_CTRL_1_OFFSET          0x10
  44#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
  45#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
  46#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
  47#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
  48#define MX53_USB_UH2_CTRL_OFFSET        0x14
  49#define MX53_USB_UH3_CTRL_OFFSET        0x18
  50#define MX53_USB_CLKONOFF_CTRL_OFFSET   0x24
  51#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
  52#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
  53#define MX53_BM_OVER_CUR_DIS_H1         BIT(5)
  54#define MX53_BM_OVER_CUR_DIS_OTG        BIT(8)
  55#define MX53_BM_OVER_CUR_DIS_UHx        BIT(30)
  56#define MX53_USB_CTRL_1_UH2_ULPI_EN     BIT(26)
  57#define MX53_USB_CTRL_1_UH3_ULPI_EN     BIT(27)
  58#define MX53_USB_UHx_CTRL_WAKE_UP_EN    BIT(7)
  59#define MX53_USB_UHx_CTRL_ULPI_INT_EN   BIT(8)
  60#define MX53_USB_PHYCTRL1_PLLDIV_MASK   0x3
  61#define MX53_USB_PLL_DIV_24_MHZ         0x01
  62
  63#define MX6_BM_NON_BURST_SETTING        BIT(1)
  64#define MX6_BM_OVER_CUR_DIS             BIT(7)
  65#define MX6_BM_OVER_CUR_POLARITY        BIT(8)
  66#define MX6_BM_PWR_POLARITY             BIT(9)
  67#define MX6_BM_WAKEUP_ENABLE            BIT(10)
  68#define MX6_BM_UTMI_ON_CLOCK            BIT(13)
  69#define MX6_BM_ID_WAKEUP                BIT(16)
  70#define MX6_BM_VBUS_WAKEUP              BIT(17)
  71#define MX6SX_BM_DPDM_WAKEUP_EN         BIT(29)
  72#define MX6_BM_WAKEUP_INTR              BIT(31)
  73
  74#define MX6_USB_HSIC_CTRL_OFFSET        0x10
  75/* Send resume signal without 480Mhz PHY clock */
  76#define MX6SX_BM_HSIC_AUTO_RESUME       BIT(23)
  77/* set before portsc.suspendM = 1 */
  78#define MX6_BM_HSIC_DEV_CONN            BIT(21)
  79/* HSIC enable */
  80#define MX6_BM_HSIC_EN                  BIT(12)
  81/* Force HSIC module 480M clock on, even when in Host is in suspend mode */
  82#define MX6_BM_HSIC_CLK_ON              BIT(11)
  83
  84#define MX6_USB_OTG1_PHY_CTRL           0x18
  85/* For imx6dql, it is host-only controller, for later imx6, it is otg's */
  86#define MX6_USB_OTG2_PHY_CTRL           0x1c
  87#define MX6SX_USB_VBUS_WAKEUP_SOURCE(v) (v << 8)
  88#define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS       MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
  89#define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID     MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
  90#define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID     MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
  91#define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END   MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
  92
  93#define VF610_OVER_CUR_DIS              BIT(7)
  94
  95#define MX7D_USBNC_USB_CTRL2            0x4
  96#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK        0x3
  97#define MX7D_USB_VBUS_WAKEUP_SOURCE(v)          (v << 0)
  98#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS        MX7D_USB_VBUS_WAKEUP_SOURCE(0)
  99#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID      MX7D_USB_VBUS_WAKEUP_SOURCE(1)
 100#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID      MX7D_USB_VBUS_WAKEUP_SOURCE(2)
 101#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END    MX7D_USB_VBUS_WAKEUP_SOURCE(3)
 102
 103#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
 104                                 MX6_BM_ID_WAKEUP)
 105
 106struct usbmisc_ops {
 107        /* It's called once when probe a usb device */
 108        int (*init)(struct imx_usbmisc_data *data);
 109        /* It's called once after adding a usb device */
 110        int (*post)(struct imx_usbmisc_data *data);
 111        /* It's called when we need to enable/disable usb wakeup */
 112        int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
 113        /* It's called before setting portsc.suspendM */
 114        int (*hsic_set_connect)(struct imx_usbmisc_data *data);
 115        /* It's called during suspend/resume */
 116        int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
 117};
 118
 119struct imx_usbmisc {
 120        void __iomem *base;
 121        spinlock_t lock;
 122        const struct usbmisc_ops *ops;
 123};
 124
 125static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
 126
 127static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
 128{
 129        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 130        unsigned long flags;
 131        u32 val = 0;
 132
 133        if (data->index > 1)
 134                return -EINVAL;
 135
 136        spin_lock_irqsave(&usbmisc->lock, flags);
 137        switch (data->index) {
 138        case 0:
 139                val = readl(usbmisc->base);
 140                val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
 141                val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
 142                val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
 143
 144                /*
 145                 * If the polarity is not configured assume active high for
 146                 * historical reasons.
 147                 */
 148                if (data->oc_pol_configured && data->oc_pol_active_low)
 149                        val &= ~MX25_OTG_OCPOL_BIT;
 150
 151                writel(val, usbmisc->base);
 152                break;
 153        case 1:
 154                val = readl(usbmisc->base);
 155                val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
 156                val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
 157                val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
 158                        MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
 159
 160                /*
 161                 * If the polarity is not configured assume active high for
 162                 * historical reasons.
 163                 */
 164                if (data->oc_pol_configured && data->oc_pol_active_low)
 165                        val &= ~MX25_H1_OCPOL_BIT;
 166
 167                writel(val, usbmisc->base);
 168
 169                break;
 170        }
 171        spin_unlock_irqrestore(&usbmisc->lock, flags);
 172
 173        return 0;
 174}
 175
 176static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
 177{
 178        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 179        void __iomem *reg;
 180        unsigned long flags;
 181        u32 val;
 182
 183        if (data->index > 2)
 184                return -EINVAL;
 185
 186        if (data->index)
 187                return 0;
 188
 189        spin_lock_irqsave(&usbmisc->lock, flags);
 190        reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
 191        val = readl(reg);
 192
 193        if (data->evdo)
 194                val |= MX25_BM_EXTERNAL_VBUS_DIVIDER;
 195        else
 196                val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER;
 197
 198        writel(val, reg);
 199        spin_unlock_irqrestore(&usbmisc->lock, flags);
 200        usleep_range(5000, 10000); /* needed to stabilize voltage */
 201
 202        return 0;
 203}
 204
 205static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
 206{
 207        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 208        unsigned long flags;
 209        u32 val;
 210
 211        switch (data->index) {
 212        case 0:
 213                val = MX27_OTG_PM_BIT;
 214                break;
 215        case 1:
 216                val = MX27_H1_PM_BIT;
 217                break;
 218        case 2:
 219                val = MX27_H2_PM_BIT;
 220                break;
 221        default:
 222                return -EINVAL;
 223        }
 224
 225        spin_lock_irqsave(&usbmisc->lock, flags);
 226        if (data->disable_oc)
 227                val = readl(usbmisc->base) | val;
 228        else
 229                val = readl(usbmisc->base) & ~val;
 230        writel(val, usbmisc->base);
 231        spin_unlock_irqrestore(&usbmisc->lock, flags);
 232
 233        return 0;
 234}
 235
 236static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
 237{
 238        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 239        void __iomem *reg = NULL;
 240        unsigned long flags;
 241        u32 val = 0;
 242
 243        if (data->index > 3)
 244                return -EINVAL;
 245
 246        /* Select a 24 MHz reference clock for the PHY  */
 247        val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 248        val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
 249        val |= MX53_USB_PLL_DIV_24_MHZ;
 250        writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 251
 252        spin_lock_irqsave(&usbmisc->lock, flags);
 253
 254        switch (data->index) {
 255        case 0:
 256                if (data->disable_oc) {
 257                        reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
 258                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
 259                        writel(val, reg);
 260                }
 261                break;
 262        case 1:
 263                if (data->disable_oc) {
 264                        reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
 265                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
 266                        writel(val, reg);
 267                }
 268                break;
 269        case 2:
 270                if (data->ulpi) {
 271                        /* set USBH2 into ULPI-mode. */
 272                        reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
 273                        val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
 274                        /* select ULPI clock */
 275                        val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
 276                        val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
 277                        writel(val, reg);
 278                        /* Set interrupt wake up enable */
 279                        reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
 280                        val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
 281                                | MX53_USB_UHx_CTRL_ULPI_INT_EN;
 282                        writel(val, reg);
 283                        if (is_imx53_usbmisc(data)) {
 284                                /* Disable internal 60Mhz clock */
 285                                reg = usbmisc->base +
 286                                        MX53_USB_CLKONOFF_CTRL_OFFSET;
 287                                val = readl(reg) |
 288                                        MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
 289                                writel(val, reg);
 290                        }
 291
 292                }
 293                if (data->disable_oc) {
 294                        reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
 295                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
 296                        writel(val, reg);
 297                }
 298                break;
 299        case 3:
 300                if (data->ulpi) {
 301                        /* set USBH3 into ULPI-mode. */
 302                        reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
 303                        val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
 304                        /* select ULPI clock */
 305                        val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
 306                        val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
 307                        writel(val, reg);
 308                        /* Set interrupt wake up enable */
 309                        reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
 310                        val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
 311                                | MX53_USB_UHx_CTRL_ULPI_INT_EN;
 312                        writel(val, reg);
 313
 314                        if (is_imx53_usbmisc(data)) {
 315                                /* Disable internal 60Mhz clock */
 316                                reg = usbmisc->base +
 317                                        MX53_USB_CLKONOFF_CTRL_OFFSET;
 318                                val = readl(reg) |
 319                                        MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
 320                                writel(val, reg);
 321                        }
 322                }
 323                if (data->disable_oc) {
 324                        reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
 325                        val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
 326                        writel(val, reg);
 327                }
 328                break;
 329        }
 330
 331        spin_unlock_irqrestore(&usbmisc->lock, flags);
 332
 333        return 0;
 334}
 335
 336static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
 337{
 338        u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
 339
 340        if (data->ext_id)
 341                wakeup_setting &= ~MX6_BM_ID_WAKEUP;
 342
 343        if (data->ext_vbus)
 344                wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
 345
 346        return wakeup_setting;
 347}
 348
 349static int usbmisc_imx6q_set_wakeup
 350        (struct imx_usbmisc_data *data, bool enabled)
 351{
 352        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 353        unsigned long flags;
 354        u32 val;
 355        int ret = 0;
 356
 357        if (data->index > 3)
 358                return -EINVAL;
 359
 360        spin_lock_irqsave(&usbmisc->lock, flags);
 361        val = readl(usbmisc->base + data->index * 4);
 362        if (enabled) {
 363                val &= ~MX6_USB_OTG_WAKEUP_BITS;
 364                val |= usbmisc_wakeup_setting(data);
 365        } else {
 366                if (val & MX6_BM_WAKEUP_INTR)
 367                        pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
 368                val &= ~MX6_USB_OTG_WAKEUP_BITS;
 369        }
 370        writel(val, usbmisc->base + data->index * 4);
 371        spin_unlock_irqrestore(&usbmisc->lock, flags);
 372
 373        return ret;
 374}
 375
 376static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
 377{
 378        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 379        unsigned long flags;
 380        u32 reg;
 381
 382        if (data->index > 3)
 383                return -EINVAL;
 384
 385        spin_lock_irqsave(&usbmisc->lock, flags);
 386
 387        reg = readl(usbmisc->base + data->index * 4);
 388        if (data->disable_oc) {
 389                reg |= MX6_BM_OVER_CUR_DIS;
 390        } else {
 391                reg &= ~MX6_BM_OVER_CUR_DIS;
 392
 393                /*
 394                 * If the polarity is not configured keep it as setup by the
 395                 * bootloader.
 396                 */
 397                if (data->oc_pol_configured && data->oc_pol_active_low)
 398                        reg |= MX6_BM_OVER_CUR_POLARITY;
 399                else if (data->oc_pol_configured)
 400                        reg &= ~MX6_BM_OVER_CUR_POLARITY;
 401        }
 402        /* If the polarity is not set keep it as setup by the bootlader */
 403        if (data->pwr_pol == 1)
 404                reg |= MX6_BM_PWR_POLARITY;
 405        writel(reg, usbmisc->base + data->index * 4);
 406
 407        /* SoC non-burst setting */
 408        reg = readl(usbmisc->base + data->index * 4);
 409        writel(reg | MX6_BM_NON_BURST_SETTING,
 410                        usbmisc->base + data->index * 4);
 411
 412        /* For HSIC controller */
 413        if (data->hsic) {
 414                reg = readl(usbmisc->base + data->index * 4);
 415                writel(reg | MX6_BM_UTMI_ON_CLOCK,
 416                        usbmisc->base + data->index * 4);
 417                reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
 418                        + (data->index - 2) * 4);
 419                reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
 420                writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
 421                        + (data->index - 2) * 4);
 422        }
 423
 424        spin_unlock_irqrestore(&usbmisc->lock, flags);
 425
 426        usbmisc_imx6q_set_wakeup(data, false);
 427
 428        return 0;
 429}
 430
 431static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
 432{
 433        int offset, ret = 0;
 434
 435        if (data->index == 2 || data->index == 3) {
 436                offset = (data->index - 2) * 4;
 437        } else if (data->index == 0) {
 438                /*
 439                 * For SoCs like i.MX7D and later, each USB controller has
 440                 * its own non-core register region. For SoCs before i.MX7D,
 441                 * the first two USB controllers are non-HSIC controllers.
 442                 */
 443                offset = 0;
 444        } else {
 445                dev_err(data->dev, "index is error for usbmisc\n");
 446                ret = -EINVAL;
 447        }
 448
 449        return ret ? ret : offset;
 450}
 451
 452static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
 453{
 454        unsigned long flags;
 455        u32 val;
 456        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 457        int offset;
 458
 459        spin_lock_irqsave(&usbmisc->lock, flags);
 460        offset = usbmisc_imx6_hsic_get_reg_offset(data);
 461        if (offset < 0) {
 462                spin_unlock_irqrestore(&usbmisc->lock, flags);
 463                return offset;
 464        }
 465
 466        val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 467        if (!(val & MX6_BM_HSIC_DEV_CONN))
 468                writel(val | MX6_BM_HSIC_DEV_CONN,
 469                        usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 470
 471        spin_unlock_irqrestore(&usbmisc->lock, flags);
 472
 473        return 0;
 474}
 475
 476static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
 477{
 478        unsigned long flags;
 479        u32 val;
 480        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 481        int offset;
 482
 483        spin_lock_irqsave(&usbmisc->lock, flags);
 484        offset = usbmisc_imx6_hsic_get_reg_offset(data);
 485        if (offset < 0) {
 486                spin_unlock_irqrestore(&usbmisc->lock, flags);
 487                return offset;
 488        }
 489
 490        val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 491        val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
 492        if (on)
 493                val |= MX6_BM_HSIC_CLK_ON;
 494        else
 495                val &= ~MX6_BM_HSIC_CLK_ON;
 496
 497        writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
 498        spin_unlock_irqrestore(&usbmisc->lock, flags);
 499
 500        return 0;
 501}
 502
 503
 504static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
 505{
 506        void __iomem *reg = NULL;
 507        unsigned long flags;
 508        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 509        u32 val;
 510
 511        usbmisc_imx6q_init(data);
 512
 513        if (data->index == 0 || data->index == 1) {
 514                reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
 515                spin_lock_irqsave(&usbmisc->lock, flags);
 516                /* Set vbus wakeup source as bvalid */
 517                val = readl(reg);
 518                writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
 519                /*
 520                 * Disable dp/dm wakeup in device mode when vbus is
 521                 * not there.
 522                 */
 523                val = readl(usbmisc->base + data->index * 4);
 524                writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
 525                        usbmisc->base + data->index * 4);
 526                spin_unlock_irqrestore(&usbmisc->lock, flags);
 527        }
 528
 529        /* For HSIC controller */
 530        if (data->hsic) {
 531                val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
 532                val |= MX6SX_BM_HSIC_AUTO_RESUME;
 533                writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
 534        }
 535
 536        return 0;
 537}
 538
 539static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
 540{
 541        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 542        u32 reg;
 543
 544        /*
 545         * Vybrid only has one misc register set, but in two different
 546         * areas. These is reflected in two instances of this driver.
 547         */
 548        if (data->index >= 1)
 549                return -EINVAL;
 550
 551        if (data->disable_oc) {
 552                reg = readl(usbmisc->base);
 553                writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
 554        }
 555
 556        return 0;
 557}
 558
 559static int usbmisc_imx7d_set_wakeup
 560        (struct imx_usbmisc_data *data, bool enabled)
 561{
 562        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 563        unsigned long flags;
 564        u32 val;
 565
 566        spin_lock_irqsave(&usbmisc->lock, flags);
 567        val = readl(usbmisc->base);
 568        if (enabled) {
 569                val &= ~MX6_USB_OTG_WAKEUP_BITS;
 570                val |= usbmisc_wakeup_setting(data);
 571                writel(val, usbmisc->base);
 572        } else {
 573                if (val & MX6_BM_WAKEUP_INTR)
 574                        dev_dbg(data->dev, "wakeup int\n");
 575                writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
 576        }
 577        spin_unlock_irqrestore(&usbmisc->lock, flags);
 578
 579        return 0;
 580}
 581
 582static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
 583{
 584        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 585        unsigned long flags;
 586        u32 reg;
 587
 588        if (data->index >= 1)
 589                return -EINVAL;
 590
 591        spin_lock_irqsave(&usbmisc->lock, flags);
 592        reg = readl(usbmisc->base);
 593        if (data->disable_oc) {
 594                reg |= MX6_BM_OVER_CUR_DIS;
 595        } else {
 596                reg &= ~MX6_BM_OVER_CUR_DIS;
 597
 598                /*
 599                 * If the polarity is not configured keep it as setup by the
 600                 * bootloader.
 601                 */
 602                if (data->oc_pol_configured && data->oc_pol_active_low)
 603                        reg |= MX6_BM_OVER_CUR_POLARITY;
 604                else if (data->oc_pol_configured)
 605                        reg &= ~MX6_BM_OVER_CUR_POLARITY;
 606        }
 607        /* If the polarity is not set keep it as setup by the bootlader */
 608        if (data->pwr_pol == 1)
 609                reg |= MX6_BM_PWR_POLARITY;
 610        writel(reg, usbmisc->base);
 611
 612        reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
 613        reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
 614        writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
 615                 usbmisc->base + MX7D_USBNC_USB_CTRL2);
 616
 617        spin_unlock_irqrestore(&usbmisc->lock, flags);
 618
 619        usbmisc_imx7d_set_wakeup(data, false);
 620
 621        return 0;
 622}
 623
 624static const struct usbmisc_ops imx25_usbmisc_ops = {
 625        .init = usbmisc_imx25_init,
 626        .post = usbmisc_imx25_post,
 627};
 628
 629static const struct usbmisc_ops imx27_usbmisc_ops = {
 630        .init = usbmisc_imx27_init,
 631};
 632
 633static const struct usbmisc_ops imx51_usbmisc_ops = {
 634        .init = usbmisc_imx53_init,
 635};
 636
 637static const struct usbmisc_ops imx53_usbmisc_ops = {
 638        .init = usbmisc_imx53_init,
 639};
 640
 641static const struct usbmisc_ops imx6q_usbmisc_ops = {
 642        .set_wakeup = usbmisc_imx6q_set_wakeup,
 643        .init = usbmisc_imx6q_init,
 644        .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
 645        .hsic_set_clk   = usbmisc_imx6_hsic_set_clk,
 646};
 647
 648static const struct usbmisc_ops vf610_usbmisc_ops = {
 649        .init = usbmisc_vf610_init,
 650};
 651
 652static const struct usbmisc_ops imx6sx_usbmisc_ops = {
 653        .set_wakeup = usbmisc_imx6q_set_wakeup,
 654        .init = usbmisc_imx6sx_init,
 655        .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
 656        .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
 657};
 658
 659static const struct usbmisc_ops imx7d_usbmisc_ops = {
 660        .init = usbmisc_imx7d_init,
 661        .set_wakeup = usbmisc_imx7d_set_wakeup,
 662};
 663
 664static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
 665{
 666        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
 667
 668        return usbmisc->ops == &imx53_usbmisc_ops;
 669}
 670
 671int imx_usbmisc_init(struct imx_usbmisc_data *data)
 672{
 673        struct imx_usbmisc *usbmisc;
 674
 675        if (!data)
 676                return 0;
 677
 678        usbmisc = dev_get_drvdata(data->dev);
 679        if (!usbmisc->ops->init)
 680                return 0;
 681        return usbmisc->ops->init(data);
 682}
 683EXPORT_SYMBOL_GPL(imx_usbmisc_init);
 684
 685int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
 686{
 687        struct imx_usbmisc *usbmisc;
 688
 689        if (!data)
 690                return 0;
 691
 692        usbmisc = dev_get_drvdata(data->dev);
 693        if (!usbmisc->ops->post)
 694                return 0;
 695        return usbmisc->ops->post(data);
 696}
 697EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
 698
 699int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
 700{
 701        struct imx_usbmisc *usbmisc;
 702
 703        if (!data)
 704                return 0;
 705
 706        usbmisc = dev_get_drvdata(data->dev);
 707        if (!usbmisc->ops->set_wakeup)
 708                return 0;
 709        return usbmisc->ops->set_wakeup(data, enabled);
 710}
 711EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
 712
 713int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
 714{
 715        struct imx_usbmisc *usbmisc;
 716
 717        if (!data)
 718                return 0;
 719
 720        usbmisc = dev_get_drvdata(data->dev);
 721        if (!usbmisc->ops->hsic_set_connect || !data->hsic)
 722                return 0;
 723        return usbmisc->ops->hsic_set_connect(data);
 724}
 725EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
 726
 727int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
 728{
 729        struct imx_usbmisc *usbmisc;
 730
 731        if (!data)
 732                return 0;
 733
 734        usbmisc = dev_get_drvdata(data->dev);
 735        if (!usbmisc->ops->hsic_set_clk || !data->hsic)
 736                return 0;
 737        return usbmisc->ops->hsic_set_clk(data, on);
 738}
 739EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
 740static const struct of_device_id usbmisc_imx_dt_ids[] = {
 741        {
 742                .compatible = "fsl,imx25-usbmisc",
 743                .data = &imx25_usbmisc_ops,
 744        },
 745        {
 746                .compatible = "fsl,imx35-usbmisc",
 747                .data = &imx25_usbmisc_ops,
 748        },
 749        {
 750                .compatible = "fsl,imx27-usbmisc",
 751                .data = &imx27_usbmisc_ops,
 752        },
 753        {
 754                .compatible = "fsl,imx51-usbmisc",
 755                .data = &imx51_usbmisc_ops,
 756        },
 757        {
 758                .compatible = "fsl,imx53-usbmisc",
 759                .data = &imx53_usbmisc_ops,
 760        },
 761        {
 762                .compatible = "fsl,imx6q-usbmisc",
 763                .data = &imx6q_usbmisc_ops,
 764        },
 765        {
 766                .compatible = "fsl,vf610-usbmisc",
 767                .data = &vf610_usbmisc_ops,
 768        },
 769        {
 770                .compatible = "fsl,imx6sx-usbmisc",
 771                .data = &imx6sx_usbmisc_ops,
 772        },
 773        {
 774                .compatible = "fsl,imx6ul-usbmisc",
 775                .data = &imx6sx_usbmisc_ops,
 776        },
 777        {
 778                .compatible = "fsl,imx7d-usbmisc",
 779                .data = &imx7d_usbmisc_ops,
 780        },
 781        {
 782                .compatible = "fsl,imx7ulp-usbmisc",
 783                .data = &imx7d_usbmisc_ops,
 784        },
 785        { /* sentinel */ }
 786};
 787MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
 788
 789static int usbmisc_imx_probe(struct platform_device *pdev)
 790{
 791        struct imx_usbmisc *data;
 792        const struct of_device_id *of_id;
 793
 794        of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
 795        if (!of_id)
 796                return -ENODEV;
 797
 798        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 799        if (!data)
 800                return -ENOMEM;
 801
 802        spin_lock_init(&data->lock);
 803
 804        data->base = devm_platform_ioremap_resource(pdev, 0);
 805        if (IS_ERR(data->base))
 806                return PTR_ERR(data->base);
 807
 808        data->ops = (const struct usbmisc_ops *)of_id->data;
 809        platform_set_drvdata(pdev, data);
 810
 811        return 0;
 812}
 813
 814static int usbmisc_imx_remove(struct platform_device *pdev)
 815{
 816        return 0;
 817}
 818
 819static struct platform_driver usbmisc_imx_driver = {
 820        .probe = usbmisc_imx_probe,
 821        .remove = usbmisc_imx_remove,
 822        .driver = {
 823                .name = "usbmisc_imx",
 824                .of_match_table = usbmisc_imx_dt_ids,
 825         },
 826};
 827
 828module_platform_driver(usbmisc_imx_driver);
 829
 830MODULE_ALIAS("platform:usbmisc-imx");
 831MODULE_LICENSE("GPL");
 832MODULE_DESCRIPTION("driver for imx usb non-core registers");
 833MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
 834