| .. | .. |
|---|
| 8 | 8 | #include <linux/err.h> |
|---|
| 9 | 9 | #include <linux/io.h> |
|---|
| 10 | 10 | #include <linux/delay.h> |
|---|
| 11 | +#include <linux/usb/otg.h> |
|---|
| 11 | 12 | |
|---|
| 12 | 13 | #include "ci_hdrc_imx.h" |
|---|
| 13 | 14 | |
|---|
| .. | .. |
|---|
| 63 | 64 | #define MX6_BM_NON_BURST_SETTING BIT(1) |
|---|
| 64 | 65 | #define MX6_BM_OVER_CUR_DIS BIT(7) |
|---|
| 65 | 66 | #define MX6_BM_OVER_CUR_POLARITY BIT(8) |
|---|
| 67 | +#define MX6_BM_PWR_POLARITY BIT(9) |
|---|
| 66 | 68 | #define MX6_BM_WAKEUP_ENABLE BIT(10) |
|---|
| 69 | +#define MX6_BM_UTMI_ON_CLOCK BIT(13) |
|---|
| 67 | 70 | #define MX6_BM_ID_WAKEUP BIT(16) |
|---|
| 68 | 71 | #define MX6_BM_VBUS_WAKEUP BIT(17) |
|---|
| 69 | 72 | #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29) |
|---|
| 70 | 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 | + |
|---|
| 71 | 85 | #define MX6_USB_OTG1_PHY_CTRL 0x18 |
|---|
| 72 | 86 | /* For imx6dql, it is host-only controller, for later imx6, it is otg's */ |
|---|
| 73 | 87 | #define MX6_USB_OTG2_PHY_CTRL 0x1c |
|---|
| .. | .. |
|---|
| 86 | 100 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1) |
|---|
| 87 | 101 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2) |
|---|
| 88 | 102 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3) |
|---|
| 103 | +#define MX7D_USBNC_AUTO_RESUME BIT(2) |
|---|
| 104 | +/* The default DM/DP value is pull-down */ |
|---|
| 105 | +#define MX7D_USBNC_USB_CTRL2_OPMODE(v) (v << 6) |
|---|
| 106 | +#define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1) |
|---|
| 107 | +#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK (BIT(7) | BIT(6)) |
|---|
| 108 | +#define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN BIT(8) |
|---|
| 109 | +#define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_VAL BIT(12) |
|---|
| 110 | +#define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_EN BIT(13) |
|---|
| 111 | +#define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_VAL BIT(14) |
|---|
| 112 | +#define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_EN BIT(15) |
|---|
| 113 | +#define MX7D_USBNC_USB_CTRL2_DP_DM_MASK (BIT(12) | BIT(13) | \ |
|---|
| 114 | + BIT(14) | BIT(15)) |
|---|
| 115 | + |
|---|
| 116 | +#define MX7D_USB_OTG_PHY_CFG1 0x30 |
|---|
| 117 | +#define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0) |
|---|
| 118 | +#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1) |
|---|
| 119 | +#define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2) |
|---|
| 120 | +#define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3) |
|---|
| 121 | +#define MX7D_USB_OTG_PHY_CFG2_DRVVBUS0 BIT(16) |
|---|
| 122 | + |
|---|
| 123 | +#define MX7D_USB_OTG_PHY_CFG2 0x34 |
|---|
| 124 | + |
|---|
| 125 | +#define MX7D_USB_OTG_PHY_STATUS 0x3c |
|---|
| 126 | +#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0) |
|---|
| 127 | +#define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1) |
|---|
| 128 | +#define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3) |
|---|
| 129 | +#define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29) |
|---|
| 130 | + |
|---|
| 131 | +#define MX7D_USB_OTG_PHY_CFG1 0x30 |
|---|
| 132 | +#define TXPREEMPAMPTUNE0_BIT 28 |
|---|
| 133 | +#define TXPREEMPAMPTUNE0_MASK (3 << 28) |
|---|
| 134 | +#define TXVREFTUNE0_BIT 20 |
|---|
| 135 | +#define TXVREFTUNE0_MASK (0xf << 20) |
|---|
| 136 | + |
|---|
| 137 | +#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ |
|---|
| 138 | + MX6_BM_ID_WAKEUP | MX6SX_BM_DPDM_WAKEUP_EN) |
|---|
| 89 | 139 | |
|---|
| 90 | 140 | struct usbmisc_ops { |
|---|
| 91 | 141 | /* It's called once when probe a usb device */ |
|---|
| .. | .. |
|---|
| 94 | 144 | int (*post)(struct imx_usbmisc_data *data); |
|---|
| 95 | 145 | /* It's called when we need to enable/disable usb wakeup */ |
|---|
| 96 | 146 | int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); |
|---|
| 147 | + /* It's called before setting portsc.suspendM */ |
|---|
| 148 | + int (*hsic_set_connect)(struct imx_usbmisc_data *data); |
|---|
| 149 | + /* It's called during suspend/resume */ |
|---|
| 150 | + int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); |
|---|
| 151 | + /* usb charger detection */ |
|---|
| 152 | + int (*charger_detection)(struct imx_usbmisc_data *data); |
|---|
| 97 | 153 | }; |
|---|
| 98 | 154 | |
|---|
| 99 | 155 | struct imx_usbmisc { |
|---|
| .. | .. |
|---|
| 120 | 176 | val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT); |
|---|
| 121 | 177 | val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; |
|---|
| 122 | 178 | val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT); |
|---|
| 179 | + |
|---|
| 180 | + /* |
|---|
| 181 | + * If the polarity is not configured assume active high for |
|---|
| 182 | + * historical reasons. |
|---|
| 183 | + */ |
|---|
| 184 | + if (data->oc_pol_configured && data->oc_pol_active_low) |
|---|
| 185 | + val &= ~MX25_OTG_OCPOL_BIT; |
|---|
| 186 | + |
|---|
| 123 | 187 | writel(val, usbmisc->base); |
|---|
| 124 | 188 | break; |
|---|
| 125 | 189 | case 1: |
|---|
| .. | .. |
|---|
| 128 | 192 | val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; |
|---|
| 129 | 193 | val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | |
|---|
| 130 | 194 | MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT); |
|---|
| 195 | + |
|---|
| 196 | + /* |
|---|
| 197 | + * If the polarity is not configured assume active high for |
|---|
| 198 | + * historical reasons. |
|---|
| 199 | + */ |
|---|
| 200 | + if (data->oc_pol_configured && data->oc_pol_active_low) |
|---|
| 201 | + val &= ~MX25_H1_OCPOL_BIT; |
|---|
| 131 | 202 | |
|---|
| 132 | 203 | writel(val, usbmisc->base); |
|---|
| 133 | 204 | |
|---|
| .. | .. |
|---|
| 298 | 369 | return 0; |
|---|
| 299 | 370 | } |
|---|
| 300 | 371 | |
|---|
| 372 | +static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data) |
|---|
| 373 | +{ |
|---|
| 374 | + u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS; |
|---|
| 375 | + |
|---|
| 376 | + if (data->ext_id || data->available_role != USB_DR_MODE_OTG) |
|---|
| 377 | + wakeup_setting &= ~MX6_BM_ID_WAKEUP; |
|---|
| 378 | + |
|---|
| 379 | + if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST) |
|---|
| 380 | + wakeup_setting &= ~MX6_BM_VBUS_WAKEUP; |
|---|
| 381 | + |
|---|
| 382 | + return wakeup_setting; |
|---|
| 383 | +} |
|---|
| 384 | + |
|---|
| 301 | 385 | static int usbmisc_imx6q_set_wakeup |
|---|
| 302 | 386 | (struct imx_usbmisc_data *data, bool enabled) |
|---|
| 303 | 387 | { |
|---|
| 304 | 388 | struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 305 | 389 | unsigned long flags; |
|---|
| 306 | 390 | u32 val; |
|---|
| 307 | | - u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE | |
|---|
| 308 | | - MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP); |
|---|
| 309 | 391 | int ret = 0; |
|---|
| 310 | 392 | |
|---|
| 311 | 393 | if (data->index > 3) |
|---|
| .. | .. |
|---|
| 314 | 396 | spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 315 | 397 | val = readl(usbmisc->base + data->index * 4); |
|---|
| 316 | 398 | if (enabled) { |
|---|
| 317 | | - val |= wakeup_setting; |
|---|
| 399 | + val &= ~MX6_USB_OTG_WAKEUP_BITS; |
|---|
| 400 | + val |= usbmisc_wakeup_setting(data); |
|---|
| 318 | 401 | } else { |
|---|
| 319 | 402 | if (val & MX6_BM_WAKEUP_INTR) |
|---|
| 320 | 403 | pr_debug("wakeup int at ci_hdrc.%d\n", data->index); |
|---|
| 321 | | - val &= ~wakeup_setting; |
|---|
| 404 | + val &= ~MX6_USB_OTG_WAKEUP_BITS; |
|---|
| 322 | 405 | } |
|---|
| 323 | 406 | writel(val, usbmisc->base + data->index * 4); |
|---|
| 324 | 407 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| .. | .. |
|---|
| 340 | 423 | reg = readl(usbmisc->base + data->index * 4); |
|---|
| 341 | 424 | if (data->disable_oc) { |
|---|
| 342 | 425 | reg |= MX6_BM_OVER_CUR_DIS; |
|---|
| 343 | | - } else if (data->oc_polarity == 1) { |
|---|
| 344 | | - /* High active */ |
|---|
| 345 | | - reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); |
|---|
| 346 | 426 | } else { |
|---|
| 347 | | - reg &= ~(MX6_BM_OVER_CUR_DIS); |
|---|
| 427 | + reg &= ~MX6_BM_OVER_CUR_DIS; |
|---|
| 428 | + |
|---|
| 429 | + /* |
|---|
| 430 | + * If the polarity is not configured keep it as setup by the |
|---|
| 431 | + * bootloader. |
|---|
| 432 | + */ |
|---|
| 433 | + if (data->oc_pol_configured && data->oc_pol_active_low) |
|---|
| 434 | + reg |= MX6_BM_OVER_CUR_POLARITY; |
|---|
| 435 | + else if (data->oc_pol_configured) |
|---|
| 436 | + reg &= ~MX6_BM_OVER_CUR_POLARITY; |
|---|
| 348 | 437 | } |
|---|
| 438 | + /* If the polarity is not set keep it as setup by the bootlader */ |
|---|
| 439 | + if (data->pwr_pol == 1) |
|---|
| 440 | + reg |= MX6_BM_PWR_POLARITY; |
|---|
| 349 | 441 | writel(reg, usbmisc->base + data->index * 4); |
|---|
| 350 | 442 | |
|---|
| 351 | 443 | /* SoC non-burst setting */ |
|---|
| .. | .. |
|---|
| 353 | 445 | writel(reg | MX6_BM_NON_BURST_SETTING, |
|---|
| 354 | 446 | usbmisc->base + data->index * 4); |
|---|
| 355 | 447 | |
|---|
| 448 | + /* For HSIC controller */ |
|---|
| 449 | + if (data->hsic) { |
|---|
| 450 | + reg = readl(usbmisc->base + data->index * 4); |
|---|
| 451 | + writel(reg | MX6_BM_UTMI_ON_CLOCK, |
|---|
| 452 | + usbmisc->base + data->index * 4); |
|---|
| 453 | + reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET |
|---|
| 454 | + + (data->index - 2) * 4); |
|---|
| 455 | + reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; |
|---|
| 456 | + writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET |
|---|
| 457 | + + (data->index - 2) * 4); |
|---|
| 458 | + } |
|---|
| 459 | + |
|---|
| 356 | 460 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 357 | 461 | |
|---|
| 358 | 462 | usbmisc_imx6q_set_wakeup(data, false); |
|---|
| 359 | 463 | |
|---|
| 360 | 464 | return 0; |
|---|
| 361 | 465 | } |
|---|
| 466 | + |
|---|
| 467 | +static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data) |
|---|
| 468 | +{ |
|---|
| 469 | + int offset, ret = 0; |
|---|
| 470 | + |
|---|
| 471 | + if (data->index == 2 || data->index == 3) { |
|---|
| 472 | + offset = (data->index - 2) * 4; |
|---|
| 473 | + } else if (data->index == 0) { |
|---|
| 474 | + /* |
|---|
| 475 | + * For SoCs like i.MX7D and later, each USB controller has |
|---|
| 476 | + * its own non-core register region. For SoCs before i.MX7D, |
|---|
| 477 | + * the first two USB controllers are non-HSIC controllers. |
|---|
| 478 | + */ |
|---|
| 479 | + offset = 0; |
|---|
| 480 | + } else { |
|---|
| 481 | + dev_err(data->dev, "index is error for usbmisc\n"); |
|---|
| 482 | + ret = -EINVAL; |
|---|
| 483 | + } |
|---|
| 484 | + |
|---|
| 485 | + return ret ? ret : offset; |
|---|
| 486 | +} |
|---|
| 487 | + |
|---|
| 488 | +static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data) |
|---|
| 489 | +{ |
|---|
| 490 | + unsigned long flags; |
|---|
| 491 | + u32 val; |
|---|
| 492 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 493 | + int offset; |
|---|
| 494 | + |
|---|
| 495 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 496 | + offset = usbmisc_imx6_hsic_get_reg_offset(data); |
|---|
| 497 | + if (offset < 0) { |
|---|
| 498 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 499 | + return offset; |
|---|
| 500 | + } |
|---|
| 501 | + |
|---|
| 502 | + val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); |
|---|
| 503 | + if (!(val & MX6_BM_HSIC_DEV_CONN)) |
|---|
| 504 | + writel(val | MX6_BM_HSIC_DEV_CONN, |
|---|
| 505 | + usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); |
|---|
| 506 | + |
|---|
| 507 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 508 | + |
|---|
| 509 | + return 0; |
|---|
| 510 | +} |
|---|
| 511 | + |
|---|
| 512 | +static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on) |
|---|
| 513 | +{ |
|---|
| 514 | + unsigned long flags; |
|---|
| 515 | + u32 val; |
|---|
| 516 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 517 | + int offset; |
|---|
| 518 | + |
|---|
| 519 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 520 | + offset = usbmisc_imx6_hsic_get_reg_offset(data); |
|---|
| 521 | + if (offset < 0) { |
|---|
| 522 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 523 | + return offset; |
|---|
| 524 | + } |
|---|
| 525 | + |
|---|
| 526 | + val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); |
|---|
| 527 | + val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; |
|---|
| 528 | + if (on) |
|---|
| 529 | + val |= MX6_BM_HSIC_CLK_ON; |
|---|
| 530 | + else |
|---|
| 531 | + val &= ~MX6_BM_HSIC_CLK_ON; |
|---|
| 532 | + |
|---|
| 533 | + writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); |
|---|
| 534 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 535 | + |
|---|
| 536 | + return 0; |
|---|
| 537 | +} |
|---|
| 538 | + |
|---|
| 362 | 539 | |
|---|
| 363 | 540 | static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) |
|---|
| 364 | 541 | { |
|---|
| .. | .. |
|---|
| 383 | 560 | writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN, |
|---|
| 384 | 561 | usbmisc->base + data->index * 4); |
|---|
| 385 | 562 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 563 | + } |
|---|
| 564 | + |
|---|
| 565 | + /* For HSIC controller */ |
|---|
| 566 | + if (data->hsic) { |
|---|
| 567 | + val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); |
|---|
| 568 | + val |= MX6SX_BM_HSIC_AUTO_RESUME; |
|---|
| 569 | + writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); |
|---|
| 386 | 570 | } |
|---|
| 387 | 571 | |
|---|
| 388 | 572 | return 0; |
|---|
| .. | .. |
|---|
| 414 | 598 | struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 415 | 599 | unsigned long flags; |
|---|
| 416 | 600 | u32 val; |
|---|
| 417 | | - u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE | |
|---|
| 418 | | - MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP); |
|---|
| 419 | 601 | |
|---|
| 420 | 602 | spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 421 | 603 | val = readl(usbmisc->base); |
|---|
| 422 | 604 | if (enabled) { |
|---|
| 423 | | - writel(val | wakeup_setting, usbmisc->base); |
|---|
| 605 | + val &= ~MX6_USB_OTG_WAKEUP_BITS; |
|---|
| 606 | + val |= usbmisc_wakeup_setting(data); |
|---|
| 607 | + writel(val, usbmisc->base); |
|---|
| 424 | 608 | } else { |
|---|
| 425 | 609 | if (val & MX6_BM_WAKEUP_INTR) |
|---|
| 426 | 610 | dev_dbg(data->dev, "wakeup int\n"); |
|---|
| 427 | | - writel(val & ~wakeup_setting, usbmisc->base); |
|---|
| 611 | + writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base); |
|---|
| 428 | 612 | } |
|---|
| 429 | 613 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 430 | 614 | |
|---|
| .. | .. |
|---|
| 444 | 628 | reg = readl(usbmisc->base); |
|---|
| 445 | 629 | if (data->disable_oc) { |
|---|
| 446 | 630 | reg |= MX6_BM_OVER_CUR_DIS; |
|---|
| 447 | | - } else if (data->oc_polarity == 1) { |
|---|
| 448 | | - /* High active */ |
|---|
| 449 | | - reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); |
|---|
| 631 | + } else { |
|---|
| 632 | + reg &= ~MX6_BM_OVER_CUR_DIS; |
|---|
| 633 | + |
|---|
| 634 | + /* |
|---|
| 635 | + * If the polarity is not configured keep it as setup by the |
|---|
| 636 | + * bootloader. |
|---|
| 637 | + */ |
|---|
| 638 | + if (data->oc_pol_configured && data->oc_pol_active_low) |
|---|
| 639 | + reg |= MX6_BM_OVER_CUR_POLARITY; |
|---|
| 640 | + else if (data->oc_pol_configured) |
|---|
| 641 | + reg &= ~MX6_BM_OVER_CUR_POLARITY; |
|---|
| 450 | 642 | } |
|---|
| 643 | + /* If the polarity is not set keep it as setup by the bootlader */ |
|---|
| 644 | + if (data->pwr_pol == 1) |
|---|
| 645 | + reg |= MX6_BM_PWR_POLARITY; |
|---|
| 451 | 646 | writel(reg, usbmisc->base); |
|---|
| 452 | 647 | |
|---|
| 453 | | - reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 454 | | - reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; |
|---|
| 455 | | - writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, |
|---|
| 456 | | - usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 648 | + /* SoC non-burst setting */ |
|---|
| 649 | + reg = readl(usbmisc->base); |
|---|
| 650 | + writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base); |
|---|
| 651 | + |
|---|
| 652 | + if (!data->hsic) { |
|---|
| 653 | + reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 654 | + reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; |
|---|
| 655 | + writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID |
|---|
| 656 | + | MX7D_USBNC_AUTO_RESUME, |
|---|
| 657 | + usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 658 | + /* PHY tuning for signal quality */ |
|---|
| 659 | + reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1); |
|---|
| 660 | + if (data->emp_curr_control >= 0 && |
|---|
| 661 | + data->emp_curr_control <= |
|---|
| 662 | + (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) { |
|---|
| 663 | + reg &= ~TXPREEMPAMPTUNE0_MASK; |
|---|
| 664 | + reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT); |
|---|
| 665 | + } |
|---|
| 666 | + |
|---|
| 667 | + if (data->dc_vol_level_adjust >= 0 && |
|---|
| 668 | + data->dc_vol_level_adjust <= |
|---|
| 669 | + (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) { |
|---|
| 670 | + reg &= ~TXVREFTUNE0_MASK; |
|---|
| 671 | + reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT); |
|---|
| 672 | + } |
|---|
| 673 | + |
|---|
| 674 | + writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1); |
|---|
| 675 | + } |
|---|
| 676 | + |
|---|
| 677 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 678 | + |
|---|
| 679 | + usbmisc_imx7d_set_wakeup(data, false); |
|---|
| 680 | + |
|---|
| 681 | + return 0; |
|---|
| 682 | +} |
|---|
| 683 | + |
|---|
| 684 | +static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data) |
|---|
| 685 | +{ |
|---|
| 686 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 687 | + struct usb_phy *usb_phy = data->usb_phy; |
|---|
| 688 | + int val; |
|---|
| 689 | + unsigned long flags; |
|---|
| 690 | + |
|---|
| 691 | + /* Clear VDATSRCENB0 to disable VDP_SRC and IDM_SNK required by BC 1.2 spec */ |
|---|
| 692 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 693 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 694 | + val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0; |
|---|
| 695 | + writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 696 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 697 | + |
|---|
| 698 | + /* TVDMSRC_DIS */ |
|---|
| 699 | + msleep(20); |
|---|
| 700 | + |
|---|
| 701 | + /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */ |
|---|
| 702 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 703 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 704 | + writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | |
|---|
| 705 | + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 | |
|---|
| 706 | + MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL, |
|---|
| 707 | + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 708 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 709 | + |
|---|
| 710 | + /* TVDMSRC_ON */ |
|---|
| 711 | + msleep(40); |
|---|
| 712 | + |
|---|
| 713 | + /* |
|---|
| 714 | + * Per BC 1.2, check voltage of D+: |
|---|
| 715 | + * DCP: if greater than VDAT_REF; |
|---|
| 716 | + * CDP: if less than VDAT_REF. |
|---|
| 717 | + */ |
|---|
| 718 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); |
|---|
| 719 | + if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) { |
|---|
| 720 | + dev_dbg(data->dev, "It is a dedicate charging port\n"); |
|---|
| 721 | + usb_phy->chg_type = DCP_TYPE; |
|---|
| 722 | + } else { |
|---|
| 723 | + dev_dbg(data->dev, "It is a charging downstream port\n"); |
|---|
| 724 | + usb_phy->chg_type = CDP_TYPE; |
|---|
| 725 | + } |
|---|
| 726 | + |
|---|
| 727 | + return 0; |
|---|
| 728 | +} |
|---|
| 729 | + |
|---|
| 730 | +static void imx7_disable_charger_detector(struct imx_usbmisc_data *data) |
|---|
| 731 | +{ |
|---|
| 732 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 733 | + unsigned long flags; |
|---|
| 734 | + u32 val; |
|---|
| 735 | + |
|---|
| 736 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 737 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 738 | + val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB | |
|---|
| 739 | + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | |
|---|
| 740 | + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 | |
|---|
| 741 | + MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL); |
|---|
| 742 | + writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 743 | + |
|---|
| 744 | + /* Set OPMODE to be 2'b00 and disable its override */ |
|---|
| 745 | + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 746 | + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; |
|---|
| 747 | + writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 748 | + |
|---|
| 749 | + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 750 | + writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN, |
|---|
| 751 | + usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 752 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 753 | +} |
|---|
| 754 | + |
|---|
| 755 | +static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data) |
|---|
| 756 | +{ |
|---|
| 757 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 758 | + unsigned long flags; |
|---|
| 759 | + u32 val; |
|---|
| 760 | + int i, data_pin_contact_count = 0; |
|---|
| 761 | + |
|---|
| 762 | + /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */ |
|---|
| 763 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 764 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 765 | + writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB, |
|---|
| 766 | + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 767 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 768 | + |
|---|
| 769 | + for (i = 0; i < 100; i = i + 1) { |
|---|
| 770 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); |
|---|
| 771 | + if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) { |
|---|
| 772 | + if (data_pin_contact_count++ > 5) |
|---|
| 773 | + /* Data pin makes contact */ |
|---|
| 774 | + break; |
|---|
| 775 | + usleep_range(5000, 10000); |
|---|
| 776 | + } else { |
|---|
| 777 | + data_pin_contact_count = 0; |
|---|
| 778 | + usleep_range(5000, 6000); |
|---|
| 779 | + } |
|---|
| 780 | + } |
|---|
| 781 | + |
|---|
| 782 | + /* Disable DCD after finished data contact check */ |
|---|
| 783 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 784 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 785 | + writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB, |
|---|
| 786 | + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 787 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 788 | + |
|---|
| 789 | + if (i == 100) { |
|---|
| 790 | + dev_err(data->dev, |
|---|
| 791 | + "VBUS is coming from a dedicated power supply.\n"); |
|---|
| 792 | + return -ENXIO; |
|---|
| 793 | + } |
|---|
| 794 | + |
|---|
| 795 | + return 0; |
|---|
| 796 | +} |
|---|
| 797 | + |
|---|
| 798 | +static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data) |
|---|
| 799 | +{ |
|---|
| 800 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 801 | + struct usb_phy *usb_phy = data->usb_phy; |
|---|
| 802 | + unsigned long flags; |
|---|
| 803 | + u32 val; |
|---|
| 804 | + |
|---|
| 805 | + /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */ |
|---|
| 806 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 807 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 808 | + val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL; |
|---|
| 809 | + writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | |
|---|
| 810 | + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0, |
|---|
| 811 | + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); |
|---|
| 812 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 813 | + |
|---|
| 814 | + /* TVDPSRC_ON */ |
|---|
| 815 | + msleep(40); |
|---|
| 816 | + |
|---|
| 817 | + /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */ |
|---|
| 818 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); |
|---|
| 819 | + if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) { |
|---|
| 820 | + dev_dbg(data->dev, "It is a standard downstream port\n"); |
|---|
| 821 | + usb_phy->chg_type = SDP_TYPE; |
|---|
| 822 | + } |
|---|
| 823 | + |
|---|
| 824 | + return 0; |
|---|
| 825 | +} |
|---|
| 826 | + |
|---|
| 827 | +/* |
|---|
| 828 | + * Whole charger detection process: |
|---|
| 829 | + * 1. OPMODE override to be non-driving |
|---|
| 830 | + * 2. Data contact check |
|---|
| 831 | + * 3. Primary detection |
|---|
| 832 | + * 4. Secondary detection |
|---|
| 833 | + * 5. Disable charger detection |
|---|
| 834 | + */ |
|---|
| 835 | +static int imx7d_charger_detection(struct imx_usbmisc_data *data) |
|---|
| 836 | +{ |
|---|
| 837 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 838 | + struct usb_phy *usb_phy = data->usb_phy; |
|---|
| 839 | + unsigned long flags; |
|---|
| 840 | + u32 val; |
|---|
| 841 | + int ret; |
|---|
| 842 | + |
|---|
| 843 | + /* Check if vbus is valid */ |
|---|
| 844 | + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); |
|---|
| 845 | + if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) { |
|---|
| 846 | + dev_err(data->dev, "vbus is error\n"); |
|---|
| 847 | + return -EINVAL; |
|---|
| 848 | + } |
|---|
| 849 | + |
|---|
| 850 | + /* |
|---|
| 851 | + * Keep OPMODE to be non-driving mode during the whole |
|---|
| 852 | + * charger detection process. |
|---|
| 853 | + */ |
|---|
| 854 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 855 | + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 856 | + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; |
|---|
| 857 | + val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING; |
|---|
| 858 | + writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 859 | + |
|---|
| 860 | + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 861 | + writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN, |
|---|
| 862 | + usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 863 | + spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 864 | + |
|---|
| 865 | + ret = imx7d_charger_data_contact_detect(data); |
|---|
| 866 | + if (ret) |
|---|
| 867 | + return ret; |
|---|
| 868 | + |
|---|
| 869 | + ret = imx7d_charger_primary_detection(data); |
|---|
| 870 | + if (!ret && usb_phy->chg_type != SDP_TYPE) |
|---|
| 871 | + ret = imx7d_charger_secondary_detection(data); |
|---|
| 872 | + |
|---|
| 873 | + imx7_disable_charger_detector(data); |
|---|
| 874 | + |
|---|
| 875 | + return ret; |
|---|
| 876 | +} |
|---|
| 877 | + |
|---|
| 878 | +static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data) |
|---|
| 879 | +{ |
|---|
| 880 | + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); |
|---|
| 881 | + unsigned long flags; |
|---|
| 882 | + u32 reg; |
|---|
| 883 | + |
|---|
| 884 | + if (data->index >= 1) |
|---|
| 885 | + return -EINVAL; |
|---|
| 886 | + |
|---|
| 887 | + spin_lock_irqsave(&usbmisc->lock, flags); |
|---|
| 888 | + reg = readl(usbmisc->base); |
|---|
| 889 | + if (data->disable_oc) { |
|---|
| 890 | + reg |= MX6_BM_OVER_CUR_DIS; |
|---|
| 891 | + } else { |
|---|
| 892 | + reg &= ~MX6_BM_OVER_CUR_DIS; |
|---|
| 893 | + |
|---|
| 894 | + /* |
|---|
| 895 | + * If the polarity is not configured keep it as setup by the |
|---|
| 896 | + * bootloader. |
|---|
| 897 | + */ |
|---|
| 898 | + if (data->oc_pol_configured && data->oc_pol_active_low) |
|---|
| 899 | + reg |= MX6_BM_OVER_CUR_POLARITY; |
|---|
| 900 | + else if (data->oc_pol_configured) |
|---|
| 901 | + reg &= ~MX6_BM_OVER_CUR_POLARITY; |
|---|
| 902 | + } |
|---|
| 903 | + /* If the polarity is not set keep it as setup by the bootlader */ |
|---|
| 904 | + if (data->pwr_pol == 1) |
|---|
| 905 | + reg |= MX6_BM_PWR_POLARITY; |
|---|
| 906 | + |
|---|
| 907 | + writel(reg, usbmisc->base); |
|---|
| 908 | + |
|---|
| 909 | + /* SoC non-burst setting */ |
|---|
| 910 | + reg = readl(usbmisc->base); |
|---|
| 911 | + writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base); |
|---|
| 912 | + |
|---|
| 913 | + if (data->hsic) { |
|---|
| 914 | + reg = readl(usbmisc->base); |
|---|
| 915 | + writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base); |
|---|
| 916 | + |
|---|
| 917 | + reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); |
|---|
| 918 | + reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; |
|---|
| 919 | + writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); |
|---|
| 920 | + |
|---|
| 921 | + /* |
|---|
| 922 | + * For non-HSIC controller, the autoresume is enabled |
|---|
| 923 | + * at MXS PHY driver (usbphy_ctrl bit18). |
|---|
| 924 | + */ |
|---|
| 925 | + reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 926 | + writel(reg | MX7D_USBNC_AUTO_RESUME, |
|---|
| 927 | + usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 928 | + } else { |
|---|
| 929 | + reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 930 | + reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; |
|---|
| 931 | + writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, |
|---|
| 932 | + usbmisc->base + MX7D_USBNC_USB_CTRL2); |
|---|
| 933 | + } |
|---|
| 934 | + |
|---|
| 457 | 935 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
|---|
| 458 | 936 | |
|---|
| 459 | 937 | usbmisc_imx7d_set_wakeup(data, false); |
|---|
| .. | .. |
|---|
| 481 | 959 | static const struct usbmisc_ops imx6q_usbmisc_ops = { |
|---|
| 482 | 960 | .set_wakeup = usbmisc_imx6q_set_wakeup, |
|---|
| 483 | 961 | .init = usbmisc_imx6q_init, |
|---|
| 962 | + .hsic_set_connect = usbmisc_imx6_hsic_set_connect, |
|---|
| 963 | + .hsic_set_clk = usbmisc_imx6_hsic_set_clk, |
|---|
| 484 | 964 | }; |
|---|
| 485 | 965 | |
|---|
| 486 | 966 | static const struct usbmisc_ops vf610_usbmisc_ops = { |
|---|
| .. | .. |
|---|
| 490 | 970 | static const struct usbmisc_ops imx6sx_usbmisc_ops = { |
|---|
| 491 | 971 | .set_wakeup = usbmisc_imx6q_set_wakeup, |
|---|
| 492 | 972 | .init = usbmisc_imx6sx_init, |
|---|
| 973 | + .hsic_set_connect = usbmisc_imx6_hsic_set_connect, |
|---|
| 974 | + .hsic_set_clk = usbmisc_imx6_hsic_set_clk, |
|---|
| 493 | 975 | }; |
|---|
| 494 | 976 | |
|---|
| 495 | 977 | static const struct usbmisc_ops imx7d_usbmisc_ops = { |
|---|
| 496 | 978 | .init = usbmisc_imx7d_init, |
|---|
| 497 | 979 | .set_wakeup = usbmisc_imx7d_set_wakeup, |
|---|
| 980 | + .charger_detection = imx7d_charger_detection, |
|---|
| 981 | +}; |
|---|
| 982 | + |
|---|
| 983 | +static const struct usbmisc_ops imx7ulp_usbmisc_ops = { |
|---|
| 984 | + .init = usbmisc_imx7ulp_init, |
|---|
| 985 | + .set_wakeup = usbmisc_imx7d_set_wakeup, |
|---|
| 986 | + .hsic_set_connect = usbmisc_imx6_hsic_set_connect, |
|---|
| 987 | + .hsic_set_clk = usbmisc_imx6_hsic_set_clk, |
|---|
| 498 | 988 | }; |
|---|
| 499 | 989 | |
|---|
| 500 | 990 | static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data) |
|---|
| .. | .. |
|---|
| 546 | 1036 | } |
|---|
| 547 | 1037 | EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); |
|---|
| 548 | 1038 | |
|---|
| 1039 | +int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data) |
|---|
| 1040 | +{ |
|---|
| 1041 | + struct imx_usbmisc *usbmisc; |
|---|
| 1042 | + |
|---|
| 1043 | + if (!data) |
|---|
| 1044 | + return 0; |
|---|
| 1045 | + |
|---|
| 1046 | + usbmisc = dev_get_drvdata(data->dev); |
|---|
| 1047 | + if (!usbmisc->ops->hsic_set_connect || !data->hsic) |
|---|
| 1048 | + return 0; |
|---|
| 1049 | + return usbmisc->ops->hsic_set_connect(data); |
|---|
| 1050 | +} |
|---|
| 1051 | +EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect); |
|---|
| 1052 | + |
|---|
| 1053 | +int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on) |
|---|
| 1054 | +{ |
|---|
| 1055 | + struct imx_usbmisc *usbmisc; |
|---|
| 1056 | + |
|---|
| 1057 | + if (!data) |
|---|
| 1058 | + return 0; |
|---|
| 1059 | + |
|---|
| 1060 | + usbmisc = dev_get_drvdata(data->dev); |
|---|
| 1061 | + if (!usbmisc->ops->hsic_set_clk || !data->hsic) |
|---|
| 1062 | + return 0; |
|---|
| 1063 | + return usbmisc->ops->hsic_set_clk(data, on); |
|---|
| 1064 | +} |
|---|
| 1065 | +EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); |
|---|
| 1066 | + |
|---|
| 1067 | +int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect) |
|---|
| 1068 | +{ |
|---|
| 1069 | + struct imx_usbmisc *usbmisc; |
|---|
| 1070 | + struct usb_phy *usb_phy; |
|---|
| 1071 | + int ret = 0; |
|---|
| 1072 | + |
|---|
| 1073 | + if (!data) |
|---|
| 1074 | + return -EINVAL; |
|---|
| 1075 | + |
|---|
| 1076 | + usbmisc = dev_get_drvdata(data->dev); |
|---|
| 1077 | + usb_phy = data->usb_phy; |
|---|
| 1078 | + if (!usbmisc->ops->charger_detection) |
|---|
| 1079 | + return -ENOTSUPP; |
|---|
| 1080 | + |
|---|
| 1081 | + if (connect) { |
|---|
| 1082 | + ret = usbmisc->ops->charger_detection(data); |
|---|
| 1083 | + if (ret) { |
|---|
| 1084 | + dev_err(data->dev, |
|---|
| 1085 | + "Error occurs during detection: %d\n", |
|---|
| 1086 | + ret); |
|---|
| 1087 | + usb_phy->chg_state = USB_CHARGER_ABSENT; |
|---|
| 1088 | + } else { |
|---|
| 1089 | + usb_phy->chg_state = USB_CHARGER_PRESENT; |
|---|
| 1090 | + } |
|---|
| 1091 | + } else { |
|---|
| 1092 | + usb_phy->chg_state = USB_CHARGER_ABSENT; |
|---|
| 1093 | + usb_phy->chg_type = UNKNOWN_TYPE; |
|---|
| 1094 | + } |
|---|
| 1095 | + return ret; |
|---|
| 1096 | +} |
|---|
| 1097 | +EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection); |
|---|
| 1098 | + |
|---|
| 549 | 1099 | static const struct of_device_id usbmisc_imx_dt_ids[] = { |
|---|
| 550 | 1100 | { |
|---|
| 551 | 1101 | .compatible = "fsl,imx25-usbmisc", |
|---|
| .. | .. |
|---|
| 587 | 1137 | .compatible = "fsl,imx7d-usbmisc", |
|---|
| 588 | 1138 | .data = &imx7d_usbmisc_ops, |
|---|
| 589 | 1139 | }, |
|---|
| 1140 | + { |
|---|
| 1141 | + .compatible = "fsl,imx7ulp-usbmisc", |
|---|
| 1142 | + .data = &imx7ulp_usbmisc_ops, |
|---|
| 1143 | + }, |
|---|
| 590 | 1144 | { /* sentinel */ } |
|---|
| 591 | 1145 | }; |
|---|
| 592 | 1146 | MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); |
|---|
| 593 | 1147 | |
|---|
| 594 | 1148 | static int usbmisc_imx_probe(struct platform_device *pdev) |
|---|
| 595 | 1149 | { |
|---|
| 596 | | - struct resource *res; |
|---|
| 597 | 1150 | struct imx_usbmisc *data; |
|---|
| 598 | 1151 | const struct of_device_id *of_id; |
|---|
| 599 | 1152 | |
|---|
| .. | .. |
|---|
| 607 | 1160 | |
|---|
| 608 | 1161 | spin_lock_init(&data->lock); |
|---|
| 609 | 1162 | |
|---|
| 610 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 611 | | - data->base = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 1163 | + data->base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 612 | 1164 | if (IS_ERR(data->base)) |
|---|
| 613 | 1165 | return PTR_ERR(data->base); |
|---|
| 614 | 1166 | |
|---|
| .. | .. |
|---|
| 635 | 1187 | module_platform_driver(usbmisc_imx_driver); |
|---|
| 636 | 1188 | |
|---|
| 637 | 1189 | MODULE_ALIAS("platform:usbmisc-imx"); |
|---|
| 638 | | -MODULE_LICENSE("GPL v2"); |
|---|
| 1190 | +MODULE_LICENSE("GPL"); |
|---|
| 639 | 1191 | MODULE_DESCRIPTION("driver for imx usb non-core registers"); |
|---|
| 640 | 1192 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); |
|---|