root/drivers/usb/chipidea/usbmisc_imx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbmisc_imx25_init
  2. usbmisc_imx25_post
  3. usbmisc_imx27_init
  4. usbmisc_imx53_init
  5. usbmisc_imx6q_init
  6. usbmisc_imx6_hsic_get_reg_offset
  7. usbmisc_imx6_hsic_set_connect
  8. usbmisc_imx6_hsic_set_clk
  9. usbmisc_imx6sx_init
  10. usbmisc_vf610_init
  11. usbmisc_imx7d_init
  12. is_imx53_usbmisc
  13. imx_usbmisc_init
  14. imx_usbmisc_init_post
  15. imx_usbmisc_set_wakeup
  16. imx_usbmisc_hsic_set_connect
  17. imx_usbmisc_hsic_set_clk
  18. usbmisc_imx_probe
  19. usbmisc_imx_remove

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

/* [<][>][^][v][top][bottom][index][help] */