0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #include <linux/kernel.h>
0042 #include <linux/module.h>
0043 #include <linux/moduleparam.h>
0044 #include <linux/spinlock.h>
0045 #include <linux/interrupt.h>
0046 #include <linux/dma-mapping.h>
0047 #include <linux/io.h>
0048 #include <linux/slab.h>
0049 #include <linux/usb.h>
0050
0051 #include <linux/usb/hcd.h>
0052 #include <linux/usb/ch11.h>
0053
0054 #include "core.h"
0055 #include "hcd.h"
0056
0057 static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
0058 {
0059 switch (hsotg->op_state) {
0060 case OTG_STATE_A_HOST:
0061 return "a_host";
0062 case OTG_STATE_A_SUSPEND:
0063 return "a_suspend";
0064 case OTG_STATE_A_PERIPHERAL:
0065 return "a_peripheral";
0066 case OTG_STATE_B_PERIPHERAL:
0067 return "b_peripheral";
0068 case OTG_STATE_B_HOST:
0069 return "b_host";
0070 default:
0071 return "unknown";
0072 }
0073 }
0074
0075
0076
0077
0078
0079
0080
0081
0082 static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
0083 {
0084 u32 hprt0 = dwc2_readl(hsotg, HPRT0);
0085
0086 if (hprt0 & HPRT0_ENACHG) {
0087 hprt0 &= ~HPRT0_ENA;
0088 dwc2_writel(hsotg, hprt0, HPRT0);
0089 }
0090 }
0091
0092
0093
0094
0095
0096
0097 static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
0098 {
0099
0100 dwc2_writel(hsotg, GINTSTS_MODEMIS, GINTSTS);
0101
0102 dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
0103 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
0104 }
0105
0106
0107
0108
0109
0110
0111
0112 static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
0113 {
0114 u32 gotgint;
0115 u32 gotgctl;
0116 u32 gintmsk;
0117
0118 gotgint = dwc2_readl(hsotg, GOTGINT);
0119 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0120 dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
0121 dwc2_op_state_str(hsotg));
0122
0123 if (gotgint & GOTGINT_SES_END_DET) {
0124 dev_dbg(hsotg->dev,
0125 " ++OTG Interrupt: Session End Detected++ (%s)\n",
0126 dwc2_op_state_str(hsotg));
0127 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0128
0129 if (dwc2_is_device_mode(hsotg))
0130 dwc2_hsotg_disconnect(hsotg);
0131
0132 if (hsotg->op_state == OTG_STATE_B_HOST) {
0133 hsotg->op_state = OTG_STATE_B_PERIPHERAL;
0134 } else {
0135
0136
0137
0138
0139 if (gotgctl & GOTGCTL_DEVHNPEN) {
0140 dev_dbg(hsotg->dev, "Session End Detected\n");
0141 dev_err(hsotg->dev,
0142 "Device Not Connected/Responding!\n");
0143 }
0144
0145
0146
0147
0148
0149
0150 hsotg->lx_state = DWC2_L0;
0151 }
0152
0153 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0154 gotgctl &= ~GOTGCTL_DEVHNPEN;
0155 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0156 }
0157
0158 if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
0159 dev_dbg(hsotg->dev,
0160 " ++OTG Interrupt: Session Request Success Status Change++\n");
0161 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0162 if (gotgctl & GOTGCTL_SESREQSCS) {
0163 if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
0164 hsotg->params.i2c_enable) {
0165 hsotg->srp_success = 1;
0166 } else {
0167
0168 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0169 gotgctl &= ~GOTGCTL_SESREQ;
0170 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0171 }
0172 }
0173 }
0174
0175 if (gotgint & GOTGINT_HST_NEG_SUC_STS_CHNG) {
0176
0177
0178
0179
0180 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0181
0182
0183
0184
0185 if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)
0186 udelay(100);
0187 if (gotgctl & GOTGCTL_HSTNEGSCS) {
0188 if (dwc2_is_host_mode(hsotg)) {
0189 hsotg->op_state = OTG_STATE_B_HOST;
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 gintmsk = dwc2_readl(hsotg, GINTMSK);
0201 gintmsk &= ~GINTSTS_SOF;
0202 dwc2_writel(hsotg, gintmsk, GINTMSK);
0203
0204
0205
0206
0207
0208 spin_unlock(&hsotg->lock);
0209
0210
0211 dwc2_hcd_start(hsotg);
0212 spin_lock(&hsotg->lock);
0213 hsotg->op_state = OTG_STATE_B_HOST;
0214 }
0215 } else {
0216 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0217 gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
0218 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0219 dev_dbg(hsotg->dev, "HNP Failed\n");
0220 dev_err(hsotg->dev,
0221 "Device Not Connected/Responding\n");
0222 }
0223 }
0224
0225 if (gotgint & GOTGINT_HST_NEG_DET) {
0226
0227
0228
0229
0230
0231
0232 dev_dbg(hsotg->dev,
0233 " ++OTG Interrupt: Host Negotiation Detected++ (%s)\n",
0234 (dwc2_is_host_mode(hsotg) ? "Host" : "Device"));
0235 if (dwc2_is_device_mode(hsotg)) {
0236 dev_dbg(hsotg->dev, "a_suspend->a_peripheral (%d)\n",
0237 hsotg->op_state);
0238 spin_unlock(&hsotg->lock);
0239 dwc2_hcd_disconnect(hsotg, false);
0240 spin_lock(&hsotg->lock);
0241 hsotg->op_state = OTG_STATE_A_PERIPHERAL;
0242 } else {
0243
0244 gintmsk = dwc2_readl(hsotg, GINTMSK);
0245 gintmsk &= ~GINTSTS_SOF;
0246 dwc2_writel(hsotg, gintmsk, GINTMSK);
0247 spin_unlock(&hsotg->lock);
0248 dwc2_hcd_start(hsotg);
0249 spin_lock(&hsotg->lock);
0250 hsotg->op_state = OTG_STATE_A_HOST;
0251 }
0252 }
0253
0254 if (gotgint & GOTGINT_A_DEV_TOUT_CHG)
0255 dev_dbg(hsotg->dev,
0256 " ++OTG Interrupt: A-Device Timeout Change++\n");
0257 if (gotgint & GOTGINT_DBNCE_DONE)
0258 dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
0259
0260
0261 dwc2_writel(hsotg, gotgint, GOTGINT);
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
0275 {
0276 u32 gintmsk;
0277
0278
0279 dwc2_writel(hsotg, GINTSTS_CONIDSTSCHNG, GINTSTS);
0280
0281
0282 gintmsk = dwc2_readl(hsotg, GINTMSK);
0283 gintmsk &= ~GINTSTS_SOF;
0284 dwc2_writel(hsotg, gintmsk, GINTMSK);
0285
0286 dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++ (%s)\n",
0287 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
0288
0289
0290
0291
0292 if (hsotg->wq_otg)
0293 queue_work(hsotg->wq_otg, &hsotg->wf_otg);
0294 }
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
0308 {
0309 int ret;
0310 u32 hprt0;
0311
0312
0313 dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
0314
0315 dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
0316 hsotg->lx_state);
0317
0318 if (dwc2_is_device_mode(hsotg)) {
0319 if (hsotg->lx_state == DWC2_L2) {
0320 if (hsotg->in_ppd) {
0321 ret = dwc2_exit_partial_power_down(hsotg, 0,
0322 true);
0323 if (ret)
0324 dev_err(hsotg->dev,
0325 "exit power_down failed\n");
0326 }
0327
0328
0329 if (hsotg->params.power_down ==
0330 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
0331 dwc2_gadget_exit_clock_gating(hsotg, 0);
0332 }
0333
0334
0335
0336
0337
0338 dwc2_hsotg_disconnect(hsotg);
0339 } else {
0340
0341 hprt0 = dwc2_read_hprt0(hsotg);
0342 hprt0 |= HPRT0_PWR;
0343 dwc2_writel(hsotg, hprt0, HPRT0);
0344
0345 dwc2_hcd_connect(hsotg);
0346 }
0347 }
0348
0349
0350
0351
0352
0353
0354
0355 static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
0356 {
0357 u32 glpmcfg;
0358 u32 i = 0;
0359
0360 if (hsotg->lx_state != DWC2_L1) {
0361 dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
0362 return;
0363 }
0364
0365 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0366 if (dwc2_is_device_mode(hsotg)) {
0367 dev_dbg(hsotg->dev, "Exit from L1 state\n");
0368 glpmcfg &= ~GLPMCFG_ENBLSLPM;
0369 glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
0370 dwc2_writel(hsotg, glpmcfg, GLPMCFG);
0371
0372 do {
0373 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0374
0375 if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
0376 GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
0377 break;
0378
0379 udelay(1);
0380 } while (++i < 200);
0381
0382 if (i == 200) {
0383 dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
0384 return;
0385 }
0386 dwc2_gadget_init_lpm(hsotg);
0387 } else {
0388
0389 dev_err(hsotg->dev, "Host side LPM is not supported.\n");
0390 return;
0391 }
0392
0393
0394 hsotg->lx_state = DWC2_L0;
0395
0396
0397 call_gadget(hsotg, resume);
0398 }
0399
0400
0401
0402
0403
0404
0405
0406
0407 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
0408 {
0409 int ret;
0410
0411
0412 dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
0413
0414 dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
0415 dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
0416
0417 if (hsotg->lx_state == DWC2_L1) {
0418 dwc2_wakeup_from_lpm_l1(hsotg);
0419 return;
0420 }
0421
0422 if (dwc2_is_device_mode(hsotg)) {
0423 dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
0424 dwc2_readl(hsotg, DSTS));
0425 if (hsotg->lx_state == DWC2_L2) {
0426 if (hsotg->in_ppd) {
0427 u32 dctl = dwc2_readl(hsotg, DCTL);
0428
0429 dctl &= ~DCTL_RMTWKUPSIG;
0430 dwc2_writel(hsotg, dctl, DCTL);
0431 ret = dwc2_exit_partial_power_down(hsotg, 1,
0432 true);
0433 if (ret)
0434 dev_err(hsotg->dev,
0435 "exit partial_power_down failed\n");
0436 call_gadget(hsotg, resume);
0437 }
0438
0439
0440 if (hsotg->params.power_down ==
0441 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
0442 dwc2_gadget_exit_clock_gating(hsotg, 0);
0443 } else {
0444
0445 hsotg->lx_state = DWC2_L0;
0446 }
0447 } else {
0448 if (hsotg->lx_state == DWC2_L2) {
0449 if (hsotg->in_ppd) {
0450 ret = dwc2_exit_partial_power_down(hsotg, 1,
0451 true);
0452 if (ret)
0453 dev_err(hsotg->dev,
0454 "exit partial_power_down failed\n");
0455 }
0456
0457 if (hsotg->params.power_down ==
0458 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
0459 dwc2_host_exit_clock_gating(hsotg, 1);
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 if (hsotg->reset_phy_on_wake)
0470 dwc2_host_schedule_phy_reset(hsotg);
0471
0472 mod_timer(&hsotg->wkp_timer,
0473 jiffies + msecs_to_jiffies(71));
0474 } else {
0475
0476 hsotg->lx_state = DWC2_L0;
0477 }
0478 }
0479 }
0480
0481
0482
0483
0484
0485 static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
0486 {
0487 dwc2_writel(hsotg, GINTSTS_DISCONNINT, GINTSTS);
0488
0489 dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
0490 dwc2_is_host_mode(hsotg) ? "Host" : "Device",
0491 dwc2_op_state_str(hsotg));
0492
0493 if (hsotg->op_state == OTG_STATE_A_HOST)
0494 dwc2_hcd_disconnect(hsotg, false);
0495 }
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505 static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
0506 {
0507 u32 dsts;
0508 int ret;
0509
0510
0511 dwc2_writel(hsotg, GINTSTS_USBSUSP, GINTSTS);
0512
0513 dev_dbg(hsotg->dev, "USB SUSPEND\n");
0514
0515 if (dwc2_is_device_mode(hsotg)) {
0516
0517
0518
0519
0520 dsts = dwc2_readl(hsotg, DSTS);
0521 dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
0522 dev_dbg(hsotg->dev,
0523 "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d HWCFG4.Hibernation=%d\n",
0524 !!(dsts & DSTS_SUSPSTS),
0525 hsotg->hw_params.power_optimized,
0526 hsotg->hw_params.hibernation);
0527
0528
0529 if (!dwc2_is_device_connected(hsotg)) {
0530 dev_dbg(hsotg->dev,
0531 "ignore suspend request before enumeration\n");
0532 return;
0533 }
0534 if (dsts & DSTS_SUSPSTS) {
0535 switch (hsotg->params.power_down) {
0536 case DWC2_POWER_DOWN_PARAM_PARTIAL:
0537 ret = dwc2_enter_partial_power_down(hsotg);
0538 if (ret)
0539 dev_err(hsotg->dev,
0540 "enter partial_power_down failed\n");
0541
0542 udelay(100);
0543
0544
0545 if (!IS_ERR_OR_NULL(hsotg->uphy))
0546 usb_phy_set_suspend(hsotg->uphy, true);
0547 break;
0548 case DWC2_POWER_DOWN_PARAM_HIBERNATION:
0549 ret = dwc2_enter_hibernation(hsotg, 0);
0550 if (ret)
0551 dev_err(hsotg->dev,
0552 "enter hibernation failed\n");
0553 break;
0554 case DWC2_POWER_DOWN_PARAM_NONE:
0555
0556
0557
0558
0559 if (!hsotg->params.no_clock_gating)
0560 dwc2_gadget_enter_clock_gating(hsotg);
0561 }
0562
0563
0564
0565
0566
0567 hsotg->lx_state = DWC2_L2;
0568
0569
0570 call_gadget(hsotg, suspend);
0571 }
0572 } else {
0573 if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
0574 dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
0575
0576
0577 hsotg->lx_state = DWC2_L2;
0578
0579 spin_unlock(&hsotg->lock);
0580 dwc2_hcd_start(hsotg);
0581 spin_lock(&hsotg->lock);
0582 hsotg->op_state = OTG_STATE_A_HOST;
0583 }
0584 }
0585 }
0586
0587
0588
0589
0590
0591
0592
0593 static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
0594 {
0595 u32 glpmcfg;
0596 u32 pcgcctl;
0597 u32 hird;
0598 u32 hird_thres;
0599 u32 hird_thres_en;
0600 u32 enslpm;
0601
0602
0603 dwc2_writel(hsotg, GINTSTS_LPMTRANRCVD, GINTSTS);
0604
0605 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0606
0607 if (!(glpmcfg & GLPMCFG_LPMCAP)) {
0608 dev_err(hsotg->dev, "Unexpected LPM interrupt\n");
0609 return;
0610 }
0611
0612 hird = (glpmcfg & GLPMCFG_HIRD_MASK) >> GLPMCFG_HIRD_SHIFT;
0613 hird_thres = (glpmcfg & GLPMCFG_HIRD_THRES_MASK &
0614 ~GLPMCFG_HIRD_THRES_EN) >> GLPMCFG_HIRD_THRES_SHIFT;
0615 hird_thres_en = glpmcfg & GLPMCFG_HIRD_THRES_EN;
0616 enslpm = glpmcfg & GLPMCFG_ENBLSLPM;
0617
0618 if (dwc2_is_device_mode(hsotg)) {
0619 dev_dbg(hsotg->dev, "HIRD_THRES_EN = %d\n", hird_thres_en);
0620
0621 if (hird_thres_en && hird >= hird_thres) {
0622 dev_dbg(hsotg->dev, "L1 with utmi_l1_suspend_n\n");
0623 } else if (enslpm) {
0624 dev_dbg(hsotg->dev, "L1 with utmi_sleep_n\n");
0625 } else {
0626 dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n");
0627
0628 pcgcctl = dwc2_readl(hsotg, PCGCTL);
0629 pcgcctl |= PCGCTL_ENBL_SLEEP_GATING;
0630 dwc2_writel(hsotg, pcgcctl, PCGCTL);
0631 }
0632
0633
0634
0635 udelay(10);
0636
0637 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
0638
0639 if (glpmcfg & GLPMCFG_SLPSTS) {
0640
0641 hsotg->lx_state = DWC2_L1;
0642 dev_dbg(hsotg->dev,
0643 "Core is in L1 sleep glpmcfg=%08x\n", glpmcfg);
0644
0645
0646 call_gadget(hsotg, suspend);
0647 }
0648 }
0649 }
0650
0651 #define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \
0652 GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT | \
0653 GINTSTS_MODEMIS | GINTSTS_DISCONNINT | \
0654 GINTSTS_USBSUSP | GINTSTS_PRTINT | \
0655 GINTSTS_LPMTRANRCVD)
0656
0657
0658
0659
0660 static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
0661 {
0662 u32 gintsts;
0663 u32 gintmsk;
0664 u32 gahbcfg;
0665 u32 gintmsk_common = GINTMSK_COMMON;
0666
0667 gintsts = dwc2_readl(hsotg, GINTSTS);
0668 gintmsk = dwc2_readl(hsotg, GINTMSK);
0669 gahbcfg = dwc2_readl(hsotg, GAHBCFG);
0670
0671
0672 if (gintsts & gintmsk_common)
0673 dev_dbg(hsotg->dev, "gintsts=%08x gintmsk=%08x\n",
0674 gintsts, gintmsk);
0675
0676 if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
0677 return gintsts & gintmsk & gintmsk_common;
0678 else
0679 return 0;
0680 }
0681
0682
0683
0684
0685
0686
0687
0688
0689 static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
0690 u32 gpwrdn)
0691 {
0692 u32 gpwrdn_tmp;
0693
0694
0695 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0696 gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
0697 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0698 udelay(5);
0699
0700
0701 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0702 gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
0703 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0704 udelay(5);
0705
0706
0707 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0708 gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
0709 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0710 udelay(5);
0711
0712
0713 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0714 gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
0715 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0716 udelay(5);
0717
0718
0719 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0720 gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
0721 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0722
0723
0724 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
0725 gpwrdn_tmp &= ~GPWRDN_PMUACTV;
0726 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
0727
0728 hsotg->hibernated = 0;
0729 hsotg->bus_suspended = 0;
0730
0731 if (gpwrdn & GPWRDN_IDSTS) {
0732 hsotg->op_state = OTG_STATE_B_PERIPHERAL;
0733 dwc2_core_init(hsotg, false);
0734 dwc2_enable_global_interrupts(hsotg);
0735 dwc2_hsotg_core_init_disconnected(hsotg, false);
0736 dwc2_hsotg_core_connect(hsotg);
0737 } else {
0738 hsotg->op_state = OTG_STATE_A_HOST;
0739
0740
0741 dwc2_core_init(hsotg, false);
0742 dwc2_enable_global_interrupts(hsotg);
0743 dwc2_hcd_start(hsotg);
0744 }
0745 }
0746
0747
0748
0749
0750
0751
0752
0753 static int dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
0754 {
0755 u32 gpwrdn;
0756 int linestate;
0757 int ret = 0;
0758
0759 gpwrdn = dwc2_readl(hsotg, GPWRDN);
0760
0761 dwc2_writel(hsotg, gpwrdn, GPWRDN);
0762 linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
0763 dev_dbg(hsotg->dev,
0764 "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
0765 gpwrdn);
0766
0767 if ((gpwrdn & GPWRDN_DISCONN_DET) &&
0768 (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
0769 dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
0770
0771
0772
0773
0774 dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
0775 } else if ((gpwrdn & GPWRDN_LNSTSCHG) &&
0776 (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
0777 dev_dbg(hsotg->dev, "%s: GPWRDN_LNSTSCHG\n", __func__);
0778 if (hsotg->hw_params.hibernation &&
0779 hsotg->hibernated) {
0780 if (gpwrdn & GPWRDN_IDSTS) {
0781 ret = dwc2_exit_hibernation(hsotg, 0, 0, 0);
0782 if (ret)
0783 dev_err(hsotg->dev,
0784 "exit hibernation failed.\n");
0785 call_gadget(hsotg, resume);
0786 } else {
0787 ret = dwc2_exit_hibernation(hsotg, 1, 0, 1);
0788 if (ret)
0789 dev_err(hsotg->dev,
0790 "exit hibernation failed.\n");
0791 }
0792 }
0793 } else if ((gpwrdn & GPWRDN_RST_DET) &&
0794 (gpwrdn & GPWRDN_RST_DET_MSK)) {
0795 dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
0796 if (!linestate) {
0797 ret = dwc2_exit_hibernation(hsotg, 0, 1, 0);
0798 if (ret)
0799 dev_err(hsotg->dev,
0800 "exit hibernation failed.\n");
0801 }
0802 } else if ((gpwrdn & GPWRDN_STS_CHGINT) &&
0803 (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
0804 dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
0805
0806
0807
0808
0809
0810
0811 dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
0812 }
0813
0814 return ret;
0815 }
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830 irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
0831 {
0832 struct dwc2_hsotg *hsotg = dev;
0833 u32 gintsts;
0834 irqreturn_t retval = IRQ_NONE;
0835
0836 spin_lock(&hsotg->lock);
0837
0838 if (!dwc2_is_controller_alive(hsotg)) {
0839 dev_warn(hsotg->dev, "Controller is dead\n");
0840 goto out;
0841 }
0842
0843
0844 if (dwc2_is_device_mode(hsotg))
0845 hsotg->frame_number = (dwc2_readl(hsotg, DSTS)
0846 & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
0847 else
0848 hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
0849 & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
0850
0851 gintsts = dwc2_read_common_intr(hsotg);
0852 if (gintsts & ~GINTSTS_PRTINT)
0853 retval = IRQ_HANDLED;
0854
0855
0856 if (hsotg->hibernated) {
0857 dwc2_handle_gpwrdn_intr(hsotg);
0858 retval = IRQ_HANDLED;
0859 goto out;
0860 }
0861
0862 if (gintsts & GINTSTS_MODEMIS)
0863 dwc2_handle_mode_mismatch_intr(hsotg);
0864 if (gintsts & GINTSTS_OTGINT)
0865 dwc2_handle_otg_intr(hsotg);
0866 if (gintsts & GINTSTS_CONIDSTSCHNG)
0867 dwc2_handle_conn_id_status_change_intr(hsotg);
0868 if (gintsts & GINTSTS_DISCONNINT)
0869 dwc2_handle_disconnect_intr(hsotg);
0870 if (gintsts & GINTSTS_SESSREQINT)
0871 dwc2_handle_session_req_intr(hsotg);
0872 if (gintsts & GINTSTS_WKUPINT)
0873 dwc2_handle_wakeup_detected_intr(hsotg);
0874 if (gintsts & GINTSTS_USBSUSP)
0875 dwc2_handle_usb_suspend_intr(hsotg);
0876 if (gintsts & GINTSTS_LPMTRANRCVD)
0877 dwc2_handle_lpm_intr(hsotg);
0878
0879 if (gintsts & GINTSTS_PRTINT) {
0880
0881
0882
0883
0884 if (dwc2_is_device_mode(hsotg)) {
0885 dev_dbg(hsotg->dev,
0886 " --Port interrupt received in Device mode--\n");
0887 dwc2_handle_usb_port_intr(hsotg);
0888 retval = IRQ_HANDLED;
0889 }
0890 }
0891
0892 out:
0893 spin_unlock(&hsotg->lock);
0894 return retval;
0895 }