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 MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ 132 MX6_BM_ID_WAKEUP) 133 134 struct usbmisc_ops { 135 /* It's called once when probe a usb device */ 136 int (*init)(struct imx_usbmisc_data *data); 137 /* It's called once after adding a usb device */ 138 int (*post)(struct imx_usbmisc_data *data); 139 /* It's called when we need to enable/disable usb wakeup */ 140 int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); 141 /* It's called before setting portsc.suspendM */ 142 int (*hsic_set_connect)(struct imx_usbmisc_data *data); 143 /* It's called during suspend/resume */ 144 int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); 145 /* usb charger detection */ 146 int (*charger_detection)(struct imx_usbmisc_data *data); 147 }; 148 149 struct imx_usbmisc { 150 void __iomem *base; 151 spinlock_t lock; 152 const struct usbmisc_ops *ops; 153 }; 154 155 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data); 156 157 static int usbmisc_imx25_init(struct imx_usbmisc_data *data) 158 { 159 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 160 unsigned long flags; 161 u32 val = 0; 162 163 if (data->index > 1) 164 return -EINVAL; 165 166 spin_lock_irqsave(&usbmisc->lock, flags); 167 switch (data->index) { 168 case 0: 169 val = readl(usbmisc->base); 170 val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT); 171 val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; 172 val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT); 173 174 /* 175 * If the polarity is not configured assume active high for 176 * historical reasons. 177 */ 178 if (data->oc_pol_configured && data->oc_pol_active_low) 179 val &= ~MX25_OTG_OCPOL_BIT; 180 181 writel(val, usbmisc->base); 182 break; 183 case 1: 184 val = readl(usbmisc->base); 185 val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT | MX25_H1_IPPUE_UP_BIT); 186 val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; 187 val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | 188 MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT); 189 190 /* 191 * If the polarity is not configured assume active high for 192 * historical reasons. 193 */ 194 if (data->oc_pol_configured && data->oc_pol_active_low) 195 val &= ~MX25_H1_OCPOL_BIT; 196 197 writel(val, usbmisc->base); 198 199 break; 200 } 201 spin_unlock_irqrestore(&usbmisc->lock, flags); 202 203 return 0; 204 } 205 206 static int usbmisc_imx25_post(struct imx_usbmisc_data *data) 207 { 208 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 209 void __iomem *reg; 210 unsigned long flags; 211 u32 val; 212 213 if (data->index > 2) 214 return -EINVAL; 215 216 if (data->index) 217 return 0; 218 219 spin_lock_irqsave(&usbmisc->lock, flags); 220 reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET; 221 val = readl(reg); 222 223 if (data->evdo) 224 val |= MX25_BM_EXTERNAL_VBUS_DIVIDER; 225 else 226 val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER; 227 228 writel(val, reg); 229 spin_unlock_irqrestore(&usbmisc->lock, flags); 230 usleep_range(5000, 10000); /* needed to stabilize voltage */ 231 232 return 0; 233 } 234 235 static int usbmisc_imx27_init(struct imx_usbmisc_data *data) 236 { 237 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 238 unsigned long flags; 239 u32 val; 240 241 switch (data->index) { 242 case 0: 243 val = MX27_OTG_PM_BIT; 244 break; 245 case 1: 246 val = MX27_H1_PM_BIT; 247 break; 248 case 2: 249 val = MX27_H2_PM_BIT; 250 break; 251 default: 252 return -EINVAL; 253 } 254 255 spin_lock_irqsave(&usbmisc->lock, flags); 256 if (data->disable_oc) 257 val = readl(usbmisc->base) | val; 258 else 259 val = readl(usbmisc->base) & ~val; 260 writel(val, usbmisc->base); 261 spin_unlock_irqrestore(&usbmisc->lock, flags); 262 263 return 0; 264 } 265 266 static int usbmisc_imx53_init(struct imx_usbmisc_data *data) 267 { 268 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 269 void __iomem *reg = NULL; 270 unsigned long flags; 271 u32 val = 0; 272 273 if (data->index > 3) 274 return -EINVAL; 275 276 /* Select a 24 MHz reference clock for the PHY */ 277 val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET); 278 val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK; 279 val |= MX53_USB_PLL_DIV_24_MHZ; 280 writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET); 281 282 spin_lock_irqsave(&usbmisc->lock, flags); 283 284 switch (data->index) { 285 case 0: 286 if (data->disable_oc) { 287 reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; 288 val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG; 289 writel(val, reg); 290 } 291 break; 292 case 1: 293 if (data->disable_oc) { 294 reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; 295 val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1; 296 writel(val, reg); 297 } 298 break; 299 case 2: 300 if (data->ulpi) { 301 /* set USBH2 into ULPI-mode. */ 302 reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET; 303 val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN; 304 /* select ULPI clock */ 305 val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK; 306 val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI; 307 writel(val, reg); 308 /* Set interrupt wake up enable */ 309 reg = usbmisc->base + MX53_USB_UH2_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 if (is_imx53_usbmisc(data)) { 314 /* Disable internal 60Mhz clock */ 315 reg = usbmisc->base + 316 MX53_USB_CLKONOFF_CTRL_OFFSET; 317 val = readl(reg) | 318 MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF; 319 writel(val, reg); 320 } 321 322 } 323 if (data->disable_oc) { 324 reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET; 325 val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; 326 writel(val, reg); 327 } 328 break; 329 case 3: 330 if (data->ulpi) { 331 /* set USBH3 into ULPI-mode. */ 332 reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET; 333 val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN; 334 /* select ULPI clock */ 335 val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK; 336 val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI; 337 writel(val, reg); 338 /* Set interrupt wake up enable */ 339 reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; 340 val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN 341 | MX53_USB_UHx_CTRL_ULPI_INT_EN; 342 writel(val, reg); 343 344 if (is_imx53_usbmisc(data)) { 345 /* Disable internal 60Mhz clock */ 346 reg = usbmisc->base + 347 MX53_USB_CLKONOFF_CTRL_OFFSET; 348 val = readl(reg) | 349 MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF; 350 writel(val, reg); 351 } 352 } 353 if (data->disable_oc) { 354 reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; 355 val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; 356 writel(val, reg); 357 } 358 break; 359 } 360 361 spin_unlock_irqrestore(&usbmisc->lock, flags); 362 363 return 0; 364 } 365 366 static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data) 367 { 368 u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS; 369 370 if (data->ext_id || data->available_role != USB_DR_MODE_OTG) 371 wakeup_setting &= ~MX6_BM_ID_WAKEUP; 372 373 if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST) 374 wakeup_setting &= ~MX6_BM_VBUS_WAKEUP; 375 376 return wakeup_setting; 377 } 378 379 static int usbmisc_imx6q_set_wakeup 380 (struct imx_usbmisc_data *data, bool enabled) 381 { 382 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 383 unsigned long flags; 384 u32 val; 385 int ret = 0; 386 387 if (data->index > 3) 388 return -EINVAL; 389 390 spin_lock_irqsave(&usbmisc->lock, flags); 391 val = readl(usbmisc->base + data->index * 4); 392 if (enabled) { 393 val &= ~MX6_USB_OTG_WAKEUP_BITS; 394 val |= usbmisc_wakeup_setting(data); 395 } else { 396 if (val & MX6_BM_WAKEUP_INTR) 397 pr_debug("wakeup int at ci_hdrc.%d\n", data->index); 398 val &= ~MX6_USB_OTG_WAKEUP_BITS; 399 } 400 writel(val, usbmisc->base + data->index * 4); 401 spin_unlock_irqrestore(&usbmisc->lock, flags); 402 403 return ret; 404 } 405 406 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) 407 { 408 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 409 unsigned long flags; 410 u32 reg; 411 412 if (data->index > 3) 413 return -EINVAL; 414 415 spin_lock_irqsave(&usbmisc->lock, flags); 416 417 reg = readl(usbmisc->base + data->index * 4); 418 if (data->disable_oc) { 419 reg |= MX6_BM_OVER_CUR_DIS; 420 } else { 421 reg &= ~MX6_BM_OVER_CUR_DIS; 422 423 /* 424 * If the polarity is not configured keep it as setup by the 425 * bootloader. 426 */ 427 if (data->oc_pol_configured && data->oc_pol_active_low) 428 reg |= MX6_BM_OVER_CUR_POLARITY; 429 else if (data->oc_pol_configured) 430 reg &= ~MX6_BM_OVER_CUR_POLARITY; 431 } 432 /* If the polarity is not set keep it as setup by the bootlader */ 433 if (data->pwr_pol == 1) 434 reg |= MX6_BM_PWR_POLARITY; 435 writel(reg, usbmisc->base + data->index * 4); 436 437 /* SoC non-burst setting */ 438 reg = readl(usbmisc->base + data->index * 4); 439 writel(reg | MX6_BM_NON_BURST_SETTING, 440 usbmisc->base + data->index * 4); 441 442 /* For HSIC controller */ 443 if (data->hsic) { 444 reg = readl(usbmisc->base + data->index * 4); 445 writel(reg | MX6_BM_UTMI_ON_CLOCK, 446 usbmisc->base + data->index * 4); 447 reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET 448 + (data->index - 2) * 4); 449 reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; 450 writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET 451 + (data->index - 2) * 4); 452 } 453 454 spin_unlock_irqrestore(&usbmisc->lock, flags); 455 456 usbmisc_imx6q_set_wakeup(data, false); 457 458 return 0; 459 } 460 461 static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data) 462 { 463 int offset, ret = 0; 464 465 if (data->index == 2 || data->index == 3) { 466 offset = (data->index - 2) * 4; 467 } else if (data->index == 0) { 468 /* 469 * For SoCs like i.MX7D and later, each USB controller has 470 * its own non-core register region. For SoCs before i.MX7D, 471 * the first two USB controllers are non-HSIC controllers. 472 */ 473 offset = 0; 474 } else { 475 dev_err(data->dev, "index is error for usbmisc\n"); 476 ret = -EINVAL; 477 } 478 479 return ret ? ret : offset; 480 } 481 482 static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data) 483 { 484 unsigned long flags; 485 u32 val; 486 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 487 int offset; 488 489 spin_lock_irqsave(&usbmisc->lock, flags); 490 offset = usbmisc_imx6_hsic_get_reg_offset(data); 491 if (offset < 0) { 492 spin_unlock_irqrestore(&usbmisc->lock, flags); 493 return offset; 494 } 495 496 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 497 if (!(val & MX6_BM_HSIC_DEV_CONN)) 498 writel(val | MX6_BM_HSIC_DEV_CONN, 499 usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 500 501 spin_unlock_irqrestore(&usbmisc->lock, flags); 502 503 return 0; 504 } 505 506 static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on) 507 { 508 unsigned long flags; 509 u32 val; 510 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 511 int offset; 512 513 spin_lock_irqsave(&usbmisc->lock, flags); 514 offset = usbmisc_imx6_hsic_get_reg_offset(data); 515 if (offset < 0) { 516 spin_unlock_irqrestore(&usbmisc->lock, flags); 517 return offset; 518 } 519 520 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 521 val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; 522 if (on) 523 val |= MX6_BM_HSIC_CLK_ON; 524 else 525 val &= ~MX6_BM_HSIC_CLK_ON; 526 527 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 528 spin_unlock_irqrestore(&usbmisc->lock, flags); 529 530 return 0; 531 } 532 533 534 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) 535 { 536 void __iomem *reg = NULL; 537 unsigned long flags; 538 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 539 u32 val; 540 541 usbmisc_imx6q_init(data); 542 543 if (data->index == 0 || data->index == 1) { 544 reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4; 545 spin_lock_irqsave(&usbmisc->lock, flags); 546 /* Set vbus wakeup source as bvalid */ 547 val = readl(reg); 548 writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg); 549 /* 550 * Disable dp/dm wakeup in device mode when vbus is 551 * not there. 552 */ 553 val = readl(usbmisc->base + data->index * 4); 554 writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN, 555 usbmisc->base + data->index * 4); 556 spin_unlock_irqrestore(&usbmisc->lock, flags); 557 } 558 559 /* For HSIC controller */ 560 if (data->hsic) { 561 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 562 val |= MX6SX_BM_HSIC_AUTO_RESUME; 563 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 564 } 565 566 return 0; 567 } 568 569 static int usbmisc_vf610_init(struct imx_usbmisc_data *data) 570 { 571 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 572 u32 reg; 573 574 /* 575 * Vybrid only has one misc register set, but in two different 576 * areas. These is reflected in two instances of this driver. 577 */ 578 if (data->index >= 1) 579 return -EINVAL; 580 581 if (data->disable_oc) { 582 reg = readl(usbmisc->base); 583 writel(reg | VF610_OVER_CUR_DIS, usbmisc->base); 584 } 585 586 return 0; 587 } 588 589 static int usbmisc_imx7d_set_wakeup 590 (struct imx_usbmisc_data *data, bool enabled) 591 { 592 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 593 unsigned long flags; 594 u32 val; 595 596 spin_lock_irqsave(&usbmisc->lock, flags); 597 val = readl(usbmisc->base); 598 if (enabled) { 599 val &= ~MX6_USB_OTG_WAKEUP_BITS; 600 val |= usbmisc_wakeup_setting(data); 601 writel(val, usbmisc->base); 602 } else { 603 if (val & MX6_BM_WAKEUP_INTR) 604 dev_dbg(data->dev, "wakeup int\n"); 605 writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base); 606 } 607 spin_unlock_irqrestore(&usbmisc->lock, flags); 608 609 return 0; 610 } 611 612 static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) 613 { 614 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 615 unsigned long flags; 616 u32 reg; 617 618 if (data->index >= 1) 619 return -EINVAL; 620 621 spin_lock_irqsave(&usbmisc->lock, flags); 622 reg = readl(usbmisc->base); 623 if (data->disable_oc) { 624 reg |= MX6_BM_OVER_CUR_DIS; 625 } else { 626 reg &= ~MX6_BM_OVER_CUR_DIS; 627 628 /* 629 * If the polarity is not configured keep it as setup by the 630 * bootloader. 631 */ 632 if (data->oc_pol_configured && data->oc_pol_active_low) 633 reg |= MX6_BM_OVER_CUR_POLARITY; 634 else if (data->oc_pol_configured) 635 reg &= ~MX6_BM_OVER_CUR_POLARITY; 636 } 637 /* If the polarity is not set keep it as setup by the bootlader */ 638 if (data->pwr_pol == 1) 639 reg |= MX6_BM_PWR_POLARITY; 640 writel(reg, usbmisc->base); 641 642 /* SoC non-burst setting */ 643 reg = readl(usbmisc->base); 644 writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base); 645 646 if (!data->hsic) { 647 reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 648 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 649 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID 650 | MX7D_USBNC_AUTO_RESUME, 651 usbmisc->base + MX7D_USBNC_USB_CTRL2); 652 } 653 654 spin_unlock_irqrestore(&usbmisc->lock, flags); 655 656 usbmisc_imx7d_set_wakeup(data, false); 657 658 return 0; 659 } 660 661 static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data) 662 { 663 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 664 struct usb_phy *usb_phy = data->usb_phy; 665 int val; 666 unsigned long flags; 667 668 /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */ 669 spin_lock_irqsave(&usbmisc->lock, flags); 670 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 671 writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | 672 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 | 673 MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL, 674 usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 675 spin_unlock_irqrestore(&usbmisc->lock, flags); 676 677 usleep_range(1000, 2000); 678 679 /* 680 * Per BC 1.2, check voltage of D+: 681 * DCP: if greater than VDAT_REF; 682 * CDP: if less than VDAT_REF. 683 */ 684 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 685 if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) { 686 dev_dbg(data->dev, "It is a dedicate charging port\n"); 687 usb_phy->chg_type = DCP_TYPE; 688 } else { 689 dev_dbg(data->dev, "It is a charging downstream port\n"); 690 usb_phy->chg_type = CDP_TYPE; 691 } 692 693 return 0; 694 } 695 696 static void imx7_disable_charger_detector(struct imx_usbmisc_data *data) 697 { 698 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 699 unsigned long flags; 700 u32 val; 701 702 spin_lock_irqsave(&usbmisc->lock, flags); 703 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 704 val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB | 705 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | 706 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 | 707 MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL); 708 writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 709 710 /* Set OPMODE to be 2'b00 and disable its override */ 711 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 712 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; 713 writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); 714 715 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 716 writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN, 717 usbmisc->base + MX7D_USBNC_USB_CTRL2); 718 spin_unlock_irqrestore(&usbmisc->lock, flags); 719 } 720 721 static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data) 722 { 723 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 724 unsigned long flags; 725 u32 val; 726 int i, data_pin_contact_count = 0; 727 728 /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */ 729 spin_lock_irqsave(&usbmisc->lock, flags); 730 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 731 writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB, 732 usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 733 spin_unlock_irqrestore(&usbmisc->lock, flags); 734 735 for (i = 0; i < 100; i = i + 1) { 736 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 737 if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) { 738 if (data_pin_contact_count++ > 5) 739 /* Data pin makes contact */ 740 break; 741 usleep_range(5000, 10000); 742 } else { 743 data_pin_contact_count = 0; 744 usleep_range(5000, 6000); 745 } 746 } 747 748 /* Disable DCD after finished data contact check */ 749 spin_lock_irqsave(&usbmisc->lock, flags); 750 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 751 writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB, 752 usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 753 spin_unlock_irqrestore(&usbmisc->lock, flags); 754 755 if (i == 100) { 756 dev_err(data->dev, 757 "VBUS is coming from a dedicated power supply.\n"); 758 return -ENXIO; 759 } 760 761 return 0; 762 } 763 764 static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data) 765 { 766 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 767 struct usb_phy *usb_phy = data->usb_phy; 768 unsigned long flags; 769 u32 val; 770 771 /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */ 772 spin_lock_irqsave(&usbmisc->lock, flags); 773 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 774 val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL; 775 writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | 776 MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0, 777 usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 778 spin_unlock_irqrestore(&usbmisc->lock, flags); 779 780 usleep_range(1000, 2000); 781 782 /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */ 783 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 784 if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) { 785 dev_dbg(data->dev, "It is a standard downstream port\n"); 786 usb_phy->chg_type = SDP_TYPE; 787 } 788 789 return 0; 790 } 791 792 /* 793 * Whole charger detection process: 794 * 1. OPMODE override to be non-driving 795 * 2. Data contact check 796 * 3. Primary detection 797 * 4. Secondary detection 798 * 5. Disable charger detection 799 */ 800 static int imx7d_charger_detection(struct imx_usbmisc_data *data) 801 { 802 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 803 struct usb_phy *usb_phy = data->usb_phy; 804 unsigned long flags; 805 u32 val; 806 int ret; 807 808 /* Check if vbus is valid */ 809 val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 810 if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) { 811 dev_err(data->dev, "vbus is error\n"); 812 return -EINVAL; 813 } 814 815 /* 816 * Keep OPMODE to be non-driving mode during the whole 817 * charger detection process. 818 */ 819 spin_lock_irqsave(&usbmisc->lock, flags); 820 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 821 val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; 822 val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING; 823 writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); 824 825 val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 826 writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN, 827 usbmisc->base + MX7D_USBNC_USB_CTRL2); 828 spin_unlock_irqrestore(&usbmisc->lock, flags); 829 830 ret = imx7d_charger_data_contact_detect(data); 831 if (ret) 832 return ret; 833 834 ret = imx7d_charger_primary_detection(data); 835 if (!ret && usb_phy->chg_type != SDP_TYPE) 836 ret = imx7d_charger_secondary_detection(data); 837 838 imx7_disable_charger_detector(data); 839 840 return ret; 841 } 842 843 static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data) 844 { 845 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 846 unsigned long flags; 847 u32 reg; 848 849 if (data->index >= 1) 850 return -EINVAL; 851 852 spin_lock_irqsave(&usbmisc->lock, flags); 853 reg = readl(usbmisc->base); 854 if (data->disable_oc) { 855 reg |= MX6_BM_OVER_CUR_DIS; 856 } else { 857 reg &= ~MX6_BM_OVER_CUR_DIS; 858 859 /* 860 * If the polarity is not configured keep it as setup by the 861 * bootloader. 862 */ 863 if (data->oc_pol_configured && data->oc_pol_active_low) 864 reg |= MX6_BM_OVER_CUR_POLARITY; 865 else if (data->oc_pol_configured) 866 reg &= ~MX6_BM_OVER_CUR_POLARITY; 867 } 868 /* If the polarity is not set keep it as setup by the bootlader */ 869 if (data->pwr_pol == 1) 870 reg |= MX6_BM_PWR_POLARITY; 871 872 writel(reg, usbmisc->base); 873 874 /* SoC non-burst setting */ 875 reg = readl(usbmisc->base); 876 writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base); 877 878 if (data->hsic) { 879 reg = readl(usbmisc->base); 880 writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base); 881 882 reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 883 reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; 884 writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 885 886 /* 887 * For non-HSIC controller, the autoresume is enabled 888 * at MXS PHY driver (usbphy_ctrl bit18). 889 */ 890 reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 891 writel(reg | MX7D_USBNC_AUTO_RESUME, 892 usbmisc->base + MX7D_USBNC_USB_CTRL2); 893 } else { 894 reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 895 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 896 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, 897 usbmisc->base + MX7D_USBNC_USB_CTRL2); 898 } 899 900 spin_unlock_irqrestore(&usbmisc->lock, flags); 901 902 usbmisc_imx7d_set_wakeup(data, false); 903 904 return 0; 905 } 906 907 static const struct usbmisc_ops imx25_usbmisc_ops = { 908 .init = usbmisc_imx25_init, 909 .post = usbmisc_imx25_post, 910 }; 911 912 static const struct usbmisc_ops imx27_usbmisc_ops = { 913 .init = usbmisc_imx27_init, 914 }; 915 916 static const struct usbmisc_ops imx51_usbmisc_ops = { 917 .init = usbmisc_imx53_init, 918 }; 919 920 static const struct usbmisc_ops imx53_usbmisc_ops = { 921 .init = usbmisc_imx53_init, 922 }; 923 924 static const struct usbmisc_ops imx6q_usbmisc_ops = { 925 .set_wakeup = usbmisc_imx6q_set_wakeup, 926 .init = usbmisc_imx6q_init, 927 .hsic_set_connect = usbmisc_imx6_hsic_set_connect, 928 .hsic_set_clk = usbmisc_imx6_hsic_set_clk, 929 }; 930 931 static const struct usbmisc_ops vf610_usbmisc_ops = { 932 .init = usbmisc_vf610_init, 933 }; 934 935 static const struct usbmisc_ops imx6sx_usbmisc_ops = { 936 .set_wakeup = usbmisc_imx6q_set_wakeup, 937 .init = usbmisc_imx6sx_init, 938 .hsic_set_connect = usbmisc_imx6_hsic_set_connect, 939 .hsic_set_clk = usbmisc_imx6_hsic_set_clk, 940 }; 941 942 static const struct usbmisc_ops imx7d_usbmisc_ops = { 943 .init = usbmisc_imx7d_init, 944 .set_wakeup = usbmisc_imx7d_set_wakeup, 945 .charger_detection = imx7d_charger_detection, 946 }; 947 948 static const struct usbmisc_ops imx7ulp_usbmisc_ops = { 949 .init = usbmisc_imx7ulp_init, 950 .set_wakeup = usbmisc_imx7d_set_wakeup, 951 .hsic_set_connect = usbmisc_imx6_hsic_set_connect, 952 .hsic_set_clk = usbmisc_imx6_hsic_set_clk, 953 }; 954 955 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data) 956 { 957 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 958 959 return usbmisc->ops == &imx53_usbmisc_ops; 960 } 961 962 int imx_usbmisc_init(struct imx_usbmisc_data *data) 963 { 964 struct imx_usbmisc *usbmisc; 965 966 if (!data) 967 return 0; 968 969 usbmisc = dev_get_drvdata(data->dev); 970 if (!usbmisc->ops->init) 971 return 0; 972 return usbmisc->ops->init(data); 973 } 974 EXPORT_SYMBOL_GPL(imx_usbmisc_init); 975 976 int imx_usbmisc_init_post(struct imx_usbmisc_data *data) 977 { 978 struct imx_usbmisc *usbmisc; 979 980 if (!data) 981 return 0; 982 983 usbmisc = dev_get_drvdata(data->dev); 984 if (!usbmisc->ops->post) 985 return 0; 986 return usbmisc->ops->post(data); 987 } 988 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post); 989 990 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled) 991 { 992 struct imx_usbmisc *usbmisc; 993 994 if (!data) 995 return 0; 996 997 usbmisc = dev_get_drvdata(data->dev); 998 if (!usbmisc->ops->set_wakeup) 999 return 0; 1000 return usbmisc->ops->set_wakeup(data, enabled); 1001 } 1002 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); 1003 1004 int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data) 1005 { 1006 struct imx_usbmisc *usbmisc; 1007 1008 if (!data) 1009 return 0; 1010 1011 usbmisc = dev_get_drvdata(data->dev); 1012 if (!usbmisc->ops->hsic_set_connect || !data->hsic) 1013 return 0; 1014 return usbmisc->ops->hsic_set_connect(data); 1015 } 1016 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect); 1017 1018 int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on) 1019 { 1020 struct imx_usbmisc *usbmisc; 1021 1022 if (!data) 1023 return 0; 1024 1025 usbmisc = dev_get_drvdata(data->dev); 1026 if (!usbmisc->ops->hsic_set_clk || !data->hsic) 1027 return 0; 1028 return usbmisc->ops->hsic_set_clk(data, on); 1029 } 1030 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); 1031 1032 int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect) 1033 { 1034 struct imx_usbmisc *usbmisc; 1035 struct usb_phy *usb_phy; 1036 int ret = 0; 1037 1038 if (!data) 1039 return -EINVAL; 1040 1041 usbmisc = dev_get_drvdata(data->dev); 1042 usb_phy = data->usb_phy; 1043 if (!usbmisc->ops->charger_detection) 1044 return -ENOTSUPP; 1045 1046 if (connect) { 1047 ret = usbmisc->ops->charger_detection(data); 1048 if (ret) { 1049 dev_err(data->dev, 1050 "Error occurs during detection: %d\n", 1051 ret); 1052 usb_phy->chg_state = USB_CHARGER_ABSENT; 1053 } else { 1054 usb_phy->chg_state = USB_CHARGER_PRESENT; 1055 } 1056 } else { 1057 usb_phy->chg_state = USB_CHARGER_ABSENT; 1058 usb_phy->chg_type = UNKNOWN_TYPE; 1059 } 1060 return ret; 1061 } 1062 EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection); 1063 1064 static const struct of_device_id usbmisc_imx_dt_ids[] = { 1065 { 1066 .compatible = "fsl,imx25-usbmisc", 1067 .data = &imx25_usbmisc_ops, 1068 }, 1069 { 1070 .compatible = "fsl,imx35-usbmisc", 1071 .data = &imx25_usbmisc_ops, 1072 }, 1073 { 1074 .compatible = "fsl,imx27-usbmisc", 1075 .data = &imx27_usbmisc_ops, 1076 }, 1077 { 1078 .compatible = "fsl,imx51-usbmisc", 1079 .data = &imx51_usbmisc_ops, 1080 }, 1081 { 1082 .compatible = "fsl,imx53-usbmisc", 1083 .data = &imx53_usbmisc_ops, 1084 }, 1085 { 1086 .compatible = "fsl,imx6q-usbmisc", 1087 .data = &imx6q_usbmisc_ops, 1088 }, 1089 { 1090 .compatible = "fsl,vf610-usbmisc", 1091 .data = &vf610_usbmisc_ops, 1092 }, 1093 { 1094 .compatible = "fsl,imx6sx-usbmisc", 1095 .data = &imx6sx_usbmisc_ops, 1096 }, 1097 { 1098 .compatible = "fsl,imx6ul-usbmisc", 1099 .data = &imx6sx_usbmisc_ops, 1100 }, 1101 { 1102 .compatible = "fsl,imx7d-usbmisc", 1103 .data = &imx7d_usbmisc_ops, 1104 }, 1105 { 1106 .compatible = "fsl,imx7ulp-usbmisc", 1107 .data = &imx7ulp_usbmisc_ops, 1108 }, 1109 { /* sentinel */ } 1110 }; 1111 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); 1112 1113 static int usbmisc_imx_probe(struct platform_device *pdev) 1114 { 1115 struct imx_usbmisc *data; 1116 const struct of_device_id *of_id; 1117 1118 of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev); 1119 if (!of_id) 1120 return -ENODEV; 1121 1122 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 1123 if (!data) 1124 return -ENOMEM; 1125 1126 spin_lock_init(&data->lock); 1127 1128 data->base = devm_platform_ioremap_resource(pdev, 0); 1129 if (IS_ERR(data->base)) 1130 return PTR_ERR(data->base); 1131 1132 data->ops = (const struct usbmisc_ops *)of_id->data; 1133 platform_set_drvdata(pdev, data); 1134 1135 return 0; 1136 } 1137 1138 static int usbmisc_imx_remove(struct platform_device *pdev) 1139 { 1140 return 0; 1141 } 1142 1143 static struct platform_driver usbmisc_imx_driver = { 1144 .probe = usbmisc_imx_probe, 1145 .remove = usbmisc_imx_remove, 1146 .driver = { 1147 .name = "usbmisc_imx", 1148 .of_match_table = usbmisc_imx_dt_ids, 1149 }, 1150 }; 1151 1152 module_platform_driver(usbmisc_imx_driver); 1153 1154 MODULE_ALIAS("platform:usbmisc-imx"); 1155 MODULE_LICENSE("GPL"); 1156 MODULE_DESCRIPTION("driver for imx usb non-core registers"); 1157 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); 1158