forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/usb/chipidea/usbmisc_imx.c
....@@ -8,6 +8,7 @@
88 #include <linux/err.h>
99 #include <linux/io.h>
1010 #include <linux/delay.h>
11
+#include <linux/usb/otg.h>
1112
1213 #include "ci_hdrc_imx.h"
1314
....@@ -63,11 +64,24 @@
6364 #define MX6_BM_NON_BURST_SETTING BIT(1)
6465 #define MX6_BM_OVER_CUR_DIS BIT(7)
6566 #define MX6_BM_OVER_CUR_POLARITY BIT(8)
67
+#define MX6_BM_PWR_POLARITY BIT(9)
6668 #define MX6_BM_WAKEUP_ENABLE BIT(10)
69
+#define MX6_BM_UTMI_ON_CLOCK BIT(13)
6770 #define MX6_BM_ID_WAKEUP BIT(16)
6871 #define MX6_BM_VBUS_WAKEUP BIT(17)
6972 #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29)
7073 #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
+
7185 #define MX6_USB_OTG1_PHY_CTRL 0x18
7286 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
7387 #define MX6_USB_OTG2_PHY_CTRL 0x1c
....@@ -86,6 +100,42 @@
86100 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1)
87101 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
88102 #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)
89139
90140 struct usbmisc_ops {
91141 /* It's called once when probe a usb device */
....@@ -94,6 +144,12 @@
94144 int (*post)(struct imx_usbmisc_data *data);
95145 /* It's called when we need to enable/disable usb wakeup */
96146 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);
97153 };
98154
99155 struct imx_usbmisc {
....@@ -120,6 +176,14 @@
120176 val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
121177 val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
122178 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
+
123187 writel(val, usbmisc->base);
124188 break;
125189 case 1:
....@@ -128,6 +192,13 @@
128192 val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
129193 val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
130194 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;
131202
132203 writel(val, usbmisc->base);
133204
....@@ -298,14 +369,25 @@
298369 return 0;
299370 }
300371
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
+
301385 static int usbmisc_imx6q_set_wakeup
302386 (struct imx_usbmisc_data *data, bool enabled)
303387 {
304388 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
305389 unsigned long flags;
306390 u32 val;
307
- u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
308
- MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
309391 int ret = 0;
310392
311393 if (data->index > 3)
....@@ -314,11 +396,12 @@
314396 spin_lock_irqsave(&usbmisc->lock, flags);
315397 val = readl(usbmisc->base + data->index * 4);
316398 if (enabled) {
317
- val |= wakeup_setting;
399
+ val &= ~MX6_USB_OTG_WAKEUP_BITS;
400
+ val |= usbmisc_wakeup_setting(data);
318401 } else {
319402 if (val & MX6_BM_WAKEUP_INTR)
320403 pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
321
- val &= ~wakeup_setting;
404
+ val &= ~MX6_USB_OTG_WAKEUP_BITS;
322405 }
323406 writel(val, usbmisc->base + data->index * 4);
324407 spin_unlock_irqrestore(&usbmisc->lock, flags);
....@@ -340,12 +423,21 @@
340423 reg = readl(usbmisc->base + data->index * 4);
341424 if (data->disable_oc) {
342425 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);
346426 } 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;
348437 }
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;
349441 writel(reg, usbmisc->base + data->index * 4);
350442
351443 /* SoC non-burst setting */
....@@ -353,12 +445,97 @@
353445 writel(reg | MX6_BM_NON_BURST_SETTING,
354446 usbmisc->base + data->index * 4);
355447
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
+
356460 spin_unlock_irqrestore(&usbmisc->lock, flags);
357461
358462 usbmisc_imx6q_set_wakeup(data, false);
359463
360464 return 0;
361465 }
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
+
362539
363540 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
364541 {
....@@ -383,6 +560,13 @@
383560 writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
384561 usbmisc->base + data->index * 4);
385562 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);
386570 }
387571
388572 return 0;
....@@ -414,17 +598,17 @@
414598 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
415599 unsigned long flags;
416600 u32 val;
417
- u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
418
- MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
419601
420602 spin_lock_irqsave(&usbmisc->lock, flags);
421603 val = readl(usbmisc->base);
422604 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);
424608 } else {
425609 if (val & MX6_BM_WAKEUP_INTR)
426610 dev_dbg(data->dev, "wakeup int\n");
427
- writel(val & ~wakeup_setting, usbmisc->base);
611
+ writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
428612 }
429613 spin_unlock_irqrestore(&usbmisc->lock, flags);
430614
....@@ -444,16 +628,308 @@
444628 reg = readl(usbmisc->base);
445629 if (data->disable_oc) {
446630 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;
450642 }
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;
451646 writel(reg, usbmisc->base);
452647
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 && data->emp_curr_control <=
661
+ (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) {
662
+ reg &= ~TXPREEMPAMPTUNE0_MASK;
663
+ reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT);
664
+ }
665
+
666
+ if (data->dc_vol_level_adjust && data->dc_vol_level_adjust <=
667
+ (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) {
668
+ reg &= ~TXVREFTUNE0_MASK;
669
+ reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT);
670
+ }
671
+
672
+ writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
673
+ }
674
+
675
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
676
+
677
+ usbmisc_imx7d_set_wakeup(data, false);
678
+
679
+ return 0;
680
+}
681
+
682
+static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
683
+{
684
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
685
+ struct usb_phy *usb_phy = data->usb_phy;
686
+ int val;
687
+ unsigned long flags;
688
+
689
+ /* Clear VDATSRCENB0 to disable VDP_SRC and IDM_SNK required by BC 1.2 spec */
690
+ spin_lock_irqsave(&usbmisc->lock, flags);
691
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
692
+ val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0;
693
+ writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
694
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
695
+
696
+ /* TVDMSRC_DIS */
697
+ msleep(20);
698
+
699
+ /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */
700
+ spin_lock_irqsave(&usbmisc->lock, flags);
701
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
702
+ writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
703
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
704
+ MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL,
705
+ usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
706
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
707
+
708
+ /* TVDMSRC_ON */
709
+ msleep(40);
710
+
711
+ /*
712
+ * Per BC 1.2, check voltage of D+:
713
+ * DCP: if greater than VDAT_REF;
714
+ * CDP: if less than VDAT_REF.
715
+ */
716
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
717
+ if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) {
718
+ dev_dbg(data->dev, "It is a dedicate charging port\n");
719
+ usb_phy->chg_type = DCP_TYPE;
720
+ } else {
721
+ dev_dbg(data->dev, "It is a charging downstream port\n");
722
+ usb_phy->chg_type = CDP_TYPE;
723
+ }
724
+
725
+ return 0;
726
+}
727
+
728
+static void imx7_disable_charger_detector(struct imx_usbmisc_data *data)
729
+{
730
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
731
+ unsigned long flags;
732
+ u32 val;
733
+
734
+ spin_lock_irqsave(&usbmisc->lock, flags);
735
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
736
+ val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB |
737
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
738
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
739
+ MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL);
740
+ writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
741
+
742
+ /* Set OPMODE to be 2'b00 and disable its override */
743
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
744
+ val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
745
+ writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
746
+
747
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
748
+ writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
749
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
750
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
751
+}
752
+
753
+static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data)
754
+{
755
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
756
+ unsigned long flags;
757
+ u32 val;
758
+ int i, data_pin_contact_count = 0;
759
+
760
+ /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */
761
+ spin_lock_irqsave(&usbmisc->lock, flags);
762
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
763
+ writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
764
+ usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
765
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
766
+
767
+ for (i = 0; i < 100; i = i + 1) {
768
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
769
+ if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) {
770
+ if (data_pin_contact_count++ > 5)
771
+ /* Data pin makes contact */
772
+ break;
773
+ usleep_range(5000, 10000);
774
+ } else {
775
+ data_pin_contact_count = 0;
776
+ usleep_range(5000, 6000);
777
+ }
778
+ }
779
+
780
+ /* Disable DCD after finished data contact check */
781
+ spin_lock_irqsave(&usbmisc->lock, flags);
782
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
783
+ writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
784
+ usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
785
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
786
+
787
+ if (i == 100) {
788
+ dev_err(data->dev,
789
+ "VBUS is coming from a dedicated power supply.\n");
790
+ return -ENXIO;
791
+ }
792
+
793
+ return 0;
794
+}
795
+
796
+static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
797
+{
798
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
799
+ struct usb_phy *usb_phy = data->usb_phy;
800
+ unsigned long flags;
801
+ u32 val;
802
+
803
+ /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */
804
+ spin_lock_irqsave(&usbmisc->lock, flags);
805
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
806
+ val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL;
807
+ writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
808
+ MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
809
+ usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
810
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
811
+
812
+ /* TVDPSRC_ON */
813
+ msleep(40);
814
+
815
+ /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */
816
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
817
+ if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
818
+ dev_dbg(data->dev, "It is a standard downstream port\n");
819
+ usb_phy->chg_type = SDP_TYPE;
820
+ }
821
+
822
+ return 0;
823
+}
824
+
825
+/*
826
+ * Whole charger detection process:
827
+ * 1. OPMODE override to be non-driving
828
+ * 2. Data contact check
829
+ * 3. Primary detection
830
+ * 4. Secondary detection
831
+ * 5. Disable charger detection
832
+ */
833
+static int imx7d_charger_detection(struct imx_usbmisc_data *data)
834
+{
835
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
836
+ struct usb_phy *usb_phy = data->usb_phy;
837
+ unsigned long flags;
838
+ u32 val;
839
+ int ret;
840
+
841
+ /* Check if vbus is valid */
842
+ val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
843
+ if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) {
844
+ dev_err(data->dev, "vbus is error\n");
845
+ return -EINVAL;
846
+ }
847
+
848
+ /*
849
+ * Keep OPMODE to be non-driving mode during the whole
850
+ * charger detection process.
851
+ */
852
+ spin_lock_irqsave(&usbmisc->lock, flags);
853
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
854
+ val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
855
+ val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING;
856
+ writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
857
+
858
+ val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
859
+ writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
860
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
861
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
862
+
863
+ ret = imx7d_charger_data_contact_detect(data);
864
+ if (ret)
865
+ return ret;
866
+
867
+ ret = imx7d_charger_primary_detection(data);
868
+ if (!ret && usb_phy->chg_type != SDP_TYPE)
869
+ ret = imx7d_charger_secondary_detection(data);
870
+
871
+ imx7_disable_charger_detector(data);
872
+
873
+ return ret;
874
+}
875
+
876
+static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data)
877
+{
878
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
879
+ unsigned long flags;
880
+ u32 reg;
881
+
882
+ if (data->index >= 1)
883
+ return -EINVAL;
884
+
885
+ spin_lock_irqsave(&usbmisc->lock, flags);
886
+ reg = readl(usbmisc->base);
887
+ if (data->disable_oc) {
888
+ reg |= MX6_BM_OVER_CUR_DIS;
889
+ } else {
890
+ reg &= ~MX6_BM_OVER_CUR_DIS;
891
+
892
+ /*
893
+ * If the polarity is not configured keep it as setup by the
894
+ * bootloader.
895
+ */
896
+ if (data->oc_pol_configured && data->oc_pol_active_low)
897
+ reg |= MX6_BM_OVER_CUR_POLARITY;
898
+ else if (data->oc_pol_configured)
899
+ reg &= ~MX6_BM_OVER_CUR_POLARITY;
900
+ }
901
+ /* If the polarity is not set keep it as setup by the bootlader */
902
+ if (data->pwr_pol == 1)
903
+ reg |= MX6_BM_PWR_POLARITY;
904
+
905
+ writel(reg, usbmisc->base);
906
+
907
+ /* SoC non-burst setting */
908
+ reg = readl(usbmisc->base);
909
+ writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
910
+
911
+ if (data->hsic) {
912
+ reg = readl(usbmisc->base);
913
+ writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base);
914
+
915
+ reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
916
+ reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
917
+ writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
918
+
919
+ /*
920
+ * For non-HSIC controller, the autoresume is enabled
921
+ * at MXS PHY driver (usbphy_ctrl bit18).
922
+ */
923
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
924
+ writel(reg | MX7D_USBNC_AUTO_RESUME,
925
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
926
+ } else {
927
+ reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
928
+ reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
929
+ writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
930
+ usbmisc->base + MX7D_USBNC_USB_CTRL2);
931
+ }
932
+
457933 spin_unlock_irqrestore(&usbmisc->lock, flags);
458934
459935 usbmisc_imx7d_set_wakeup(data, false);
....@@ -481,6 +957,8 @@
481957 static const struct usbmisc_ops imx6q_usbmisc_ops = {
482958 .set_wakeup = usbmisc_imx6q_set_wakeup,
483959 .init = usbmisc_imx6q_init,
960
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
961
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
484962 };
485963
486964 static const struct usbmisc_ops vf610_usbmisc_ops = {
....@@ -490,11 +968,21 @@
490968 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
491969 .set_wakeup = usbmisc_imx6q_set_wakeup,
492970 .init = usbmisc_imx6sx_init,
971
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
972
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
493973 };
494974
495975 static const struct usbmisc_ops imx7d_usbmisc_ops = {
496976 .init = usbmisc_imx7d_init,
497977 .set_wakeup = usbmisc_imx7d_set_wakeup,
978
+ .charger_detection = imx7d_charger_detection,
979
+};
980
+
981
+static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
982
+ .init = usbmisc_imx7ulp_init,
983
+ .set_wakeup = usbmisc_imx7d_set_wakeup,
984
+ .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
985
+ .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
498986 };
499987
500988 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
....@@ -546,6 +1034,66 @@
5461034 }
5471035 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
5481036
1037
+int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
1038
+{
1039
+ struct imx_usbmisc *usbmisc;
1040
+
1041
+ if (!data)
1042
+ return 0;
1043
+
1044
+ usbmisc = dev_get_drvdata(data->dev);
1045
+ if (!usbmisc->ops->hsic_set_connect || !data->hsic)
1046
+ return 0;
1047
+ return usbmisc->ops->hsic_set_connect(data);
1048
+}
1049
+EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
1050
+
1051
+int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
1052
+{
1053
+ struct imx_usbmisc *usbmisc;
1054
+
1055
+ if (!data)
1056
+ return 0;
1057
+
1058
+ usbmisc = dev_get_drvdata(data->dev);
1059
+ if (!usbmisc->ops->hsic_set_clk || !data->hsic)
1060
+ return 0;
1061
+ return usbmisc->ops->hsic_set_clk(data, on);
1062
+}
1063
+EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
1064
+
1065
+int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
1066
+{
1067
+ struct imx_usbmisc *usbmisc;
1068
+ struct usb_phy *usb_phy;
1069
+ int ret = 0;
1070
+
1071
+ if (!data)
1072
+ return -EINVAL;
1073
+
1074
+ usbmisc = dev_get_drvdata(data->dev);
1075
+ usb_phy = data->usb_phy;
1076
+ if (!usbmisc->ops->charger_detection)
1077
+ return -ENOTSUPP;
1078
+
1079
+ if (connect) {
1080
+ ret = usbmisc->ops->charger_detection(data);
1081
+ if (ret) {
1082
+ dev_err(data->dev,
1083
+ "Error occurs during detection: %d\n",
1084
+ ret);
1085
+ usb_phy->chg_state = USB_CHARGER_ABSENT;
1086
+ } else {
1087
+ usb_phy->chg_state = USB_CHARGER_PRESENT;
1088
+ }
1089
+ } else {
1090
+ usb_phy->chg_state = USB_CHARGER_ABSENT;
1091
+ usb_phy->chg_type = UNKNOWN_TYPE;
1092
+ }
1093
+ return ret;
1094
+}
1095
+EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);
1096
+
5491097 static const struct of_device_id usbmisc_imx_dt_ids[] = {
5501098 {
5511099 .compatible = "fsl,imx25-usbmisc",
....@@ -587,13 +1135,16 @@
5871135 .compatible = "fsl,imx7d-usbmisc",
5881136 .data = &imx7d_usbmisc_ops,
5891137 },
1138
+ {
1139
+ .compatible = "fsl,imx7ulp-usbmisc",
1140
+ .data = &imx7ulp_usbmisc_ops,
1141
+ },
5901142 { /* sentinel */ }
5911143 };
5921144 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
5931145
5941146 static int usbmisc_imx_probe(struct platform_device *pdev)
5951147 {
596
- struct resource *res;
5971148 struct imx_usbmisc *data;
5981149 const struct of_device_id *of_id;
5991150
....@@ -607,8 +1158,7 @@
6071158
6081159 spin_lock_init(&data->lock);
6091160
610
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
611
- data->base = devm_ioremap_resource(&pdev->dev, res);
1161
+ data->base = devm_platform_ioremap_resource(pdev, 0);
6121162 if (IS_ERR(data->base))
6131163 return PTR_ERR(data->base);
6141164
....@@ -635,6 +1185,6 @@
6351185 module_platform_driver(usbmisc_imx_driver);
6361186
6371187 MODULE_ALIAS("platform:usbmisc-imx");
638
-MODULE_LICENSE("GPL v2");
1188
+MODULE_LICENSE("GPL");
6391189 MODULE_DESCRIPTION("driver for imx usb non-core registers");
6401190 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");