1 /* $OpenBSD: dwc2_coreintr.c,v 1.14 2022/09/08 19:32:54 mglocker Exp $ */
2 /* $NetBSD: dwc2_coreintr.c,v 1.8 2014/04/04 05:40:57 skrll Exp $ */
3
4 /*
5 * core_intr.c - DesignWare HS OTG Controller common interrupt handling
6 *
7 * Copyright (C) 2004-2013 Synopsys, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions, and the following disclaimer,
14 * without modification.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The names of the above-listed copyright holders may not be used
19 * to endorse or promote products derived from this software without
20 * specific prior written permission.
21 *
22 * ALTERNATIVELY, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") as published by the Free Software
24 * Foundation; either version 2 of the License, or (at your option) any
25 * later version.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
28 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * This file contains the common interrupt handlers
42 */
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/mutex.h>
47 #include <sys/pool.h>
48 #include <sys/timeout.h>
49
50 #include <lib/libkern/libkern.h>
51
52 #include <machine/bus.h>
53
54 #include <dev/usb/usb.h>
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdivar.h>
57 #include <dev/usb/usb_mem.h>
58
59 #include <dev/usb/dwc2/dwc2.h>
60 #include <dev/usb/dwc2/dwc2var.h>
61
62 #include <dev/usb/dwc2/dwc2_core.h>
63 #include <dev/usb/dwc2/dwc2_hcd.h>
64
dwc2_op_state_str(struct dwc2_hsotg * hsotg)65 STATIC const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
66 {
67 switch (hsotg->op_state) {
68 case OTG_STATE_A_HOST:
69 return "a_host";
70 case OTG_STATE_A_SUSPEND:
71 return "a_suspend";
72 case OTG_STATE_A_PERIPHERAL:
73 return "a_peripheral";
74 case OTG_STATE_B_PERIPHERAL:
75 return "b_peripheral";
76 case OTG_STATE_B_HOST:
77 return "b_host";
78 default:
79 return "unknown";
80 }
81 }
82
83 /**
84 * dwc2_handle_usb_port_intr - handles OTG PRTINT interrupts.
85 * When the PRTINT interrupt fires, there are certain status bits in the Host
86 * Port that needs to get cleared.
87 *
88 * @hsotg: Programming view of DWC_otg controller
89 */
dwc2_handle_usb_port_intr(struct dwc2_hsotg * hsotg)90 STATIC void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
91 {
92 u32 hprt0 = dwc2_readl(hsotg, HPRT0);
93
94 if (hprt0 & HPRT0_ENACHG) {
95 hprt0 &= ~HPRT0_ENA;
96 dwc2_writel(hsotg, hprt0, HPRT0);
97 }
98 }
99
100 /**
101 * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
102 *
103 * @hsotg: Programming view of DWC_otg controller
104 */
dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg * hsotg)105 STATIC void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
106 {
107 /* Clear interrupt */
108 dwc2_writel(hsotg, GINTSTS_MODEMIS, GINTSTS);
109
110 dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
111 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
112 }
113
114 /**
115 * dwc2_handle_otg_intr() - Handles the OTG Interrupts. It reads the OTG
116 * Interrupt Register (GOTGINT) to determine what interrupt has occurred.
117 *
118 * @hsotg: Programming view of DWC_otg controller
119 */
dwc2_handle_otg_intr(struct dwc2_hsotg * hsotg)120 STATIC void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
121 {
122 u32 gotgint;
123 u32 gotgctl;
124 u32 gintmsk;
125
126 gotgint = dwc2_readl(hsotg, GOTGINT);
127 gotgctl = dwc2_readl(hsotg, GOTGCTL);
128 dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
129 dwc2_op_state_str(hsotg));
130
131 if (gotgint & GOTGINT_SES_END_DET) {
132 dev_dbg(hsotg->dev,
133 " ++OTG Interrupt: Session End Detected++ (%s)\n",
134 dwc2_op_state_str(hsotg));
135 gotgctl = dwc2_readl(hsotg, GOTGCTL);
136
137 if (dwc2_is_device_mode(hsotg))
138 dwc2_hsotg_disconnect(hsotg);
139
140 if (hsotg->op_state == OTG_STATE_B_HOST) {
141 hsotg->op_state = OTG_STATE_B_PERIPHERAL;
142 } else {
143 /*
144 * If not B_HOST and Device HNP still set, HNP did
145 * not succeed!
146 */
147 if (gotgctl & GOTGCTL_DEVHNPEN) {
148 dev_dbg(hsotg->dev, "Session End Detected\n");
149 dev_err(hsotg->dev,
150 "Device Not Connected/Responding!\n");
151 }
152
153 /*
154 * If Session End Detected the B-Cable has been
155 * disconnected
156 */
157 /* Reset to a clean state */
158 hsotg->lx_state = DWC2_L0;
159 }
160
161 gotgctl = dwc2_readl(hsotg, GOTGCTL);
162 gotgctl &= ~GOTGCTL_DEVHNPEN;
163 dwc2_writel(hsotg, gotgctl, GOTGCTL);
164 }
165
166 if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
167 dev_dbg(hsotg->dev,
168 " ++OTG Interrupt: Session Request Success Status Change++\n");
169 gotgctl = dwc2_readl(hsotg, GOTGCTL);
170 if (gotgctl & GOTGCTL_SESREQSCS) {
171 if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
172 hsotg->params.i2c_enable) {
173 hsotg->srp_success = 1;
174 } else {
175 /* Clear Session Request */
176 gotgctl = dwc2_readl(hsotg, GOTGCTL);
177 gotgctl &= ~GOTGCTL_SESREQ;
178 dwc2_writel(hsotg, gotgctl, GOTGCTL);
179 }
180 }
181 }
182
183 if (gotgint & GOTGINT_HST_NEG_SUC_STS_CHNG) {
184 /*
185 * Print statements during the HNP interrupt handling
186 * can cause it to fail
187 */
188 gotgctl = dwc2_readl(hsotg, GOTGCTL);
189 /*
190 * WA for 3.00a- HW is not setting cur_mode, even sometimes
191 * this does not help
192 */
193 if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)
194 udelay(100);
195 if (gotgctl & GOTGCTL_HSTNEGSCS) {
196 if (dwc2_is_host_mode(hsotg)) {
197 hsotg->op_state = OTG_STATE_B_HOST;
198 /*
199 * Need to disable SOF interrupt immediately.
200 * When switching from device to host, the PCD
201 * interrupt handler won't handle the interrupt
202 * if host mode is already set. The HCD
203 * interrupt handler won't get called if the
204 * HCD state is HALT. This means that the
205 * interrupt does not get handled and Linux
206 * complains loudly.
207 */
208 gintmsk = dwc2_readl(hsotg, GINTMSK);
209 gintmsk &= ~GINTSTS_SOF;
210 dwc2_writel(hsotg, gintmsk, GINTMSK);
211
212 /*
213 * Call callback function with spin lock
214 * released
215 */
216 spin_unlock(&hsotg->lock);
217
218 /* Initialize the Core for Host mode */
219 dwc2_hcd_start(hsotg);
220 spin_lock(&hsotg->lock);
221 hsotg->op_state = OTG_STATE_B_HOST;
222 }
223 } else {
224 gotgctl = dwc2_readl(hsotg, GOTGCTL);
225 gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
226 dwc2_writel(hsotg, gotgctl, GOTGCTL);
227 dev_dbg(hsotg->dev, "HNP Failed\n");
228 dev_err(hsotg->dev,
229 "Device Not Connected/Responding\n");
230 }
231 }
232
233 if (gotgint & GOTGINT_HST_NEG_DET) {
234 /*
235 * The disconnect interrupt is set at the same time as
236 * Host Negotiation Detected. During the mode switch all
237 * interrupts are cleared so the disconnect interrupt
238 * handler will not get executed.
239 */
240 dev_dbg(hsotg->dev,
241 " ++OTG Interrupt: Host Negotiation Detected++ (%s)\n",
242 (dwc2_is_host_mode(hsotg) ? "Host" : "Device"));
243 if (dwc2_is_device_mode(hsotg)) {
244 dev_dbg(hsotg->dev, "a_suspend->a_peripheral (%d)\n",
245 hsotg->op_state);
246 spin_unlock(&hsotg->lock);
247 dwc2_hcd_disconnect(hsotg, false);
248 spin_lock(&hsotg->lock);
249 hsotg->op_state = OTG_STATE_A_PERIPHERAL;
250 } else {
251 /* Need to disable SOF interrupt immediately */
252 gintmsk = dwc2_readl(hsotg, GINTMSK);
253 gintmsk &= ~GINTSTS_SOF;
254 dwc2_writel(hsotg, gintmsk, GINTMSK);
255 spin_unlock(&hsotg->lock);
256 dwc2_hcd_start(hsotg);
257 spin_lock(&hsotg->lock);
258 hsotg->op_state = OTG_STATE_A_HOST;
259 }
260 }
261
262 if (gotgint & GOTGINT_A_DEV_TOUT_CHG)
263 dev_dbg(hsotg->dev,
264 " ++OTG Interrupt: A-Device Timeout Change++\n");
265 if (gotgint & GOTGINT_DBNCE_DONE)
266 dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
267
268 /* Clear GOTGINT */
269 dwc2_writel(hsotg, gotgint, GOTGINT);
270 }
271
272 /**
273 * dwc2_handle_conn_id_status_change_intr() - Handles the Connector ID Status
274 * Change Interrupt
275 *
276 * @hsotg: Programming view of DWC_otg controller
277 *
278 * Reads the OTG Interrupt Register (GOTCTL) to determine whether this is a
279 * Device to Host Mode transition or a Host to Device Mode transition. This only
280 * occurs when the cable is connected/removed from the PHY connector.
281 */
dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg * hsotg)282 STATIC void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
283 {
284 u32 gintmsk;
285
286 /* Clear interrupt */
287 dwc2_writel(hsotg, GINTSTS_CONIDSTSCHNG, GINTSTS);
288
289 /* Need to disable SOF interrupt immediately */
290 gintmsk = dwc2_readl(hsotg, GINTMSK);
291 gintmsk &= ~GINTSTS_SOF;
292 dwc2_writel(hsotg, gintmsk, GINTMSK);
293
294 dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++ (%s)\n",
295 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
296
297 /*
298 * Need to schedule a work, as there are possible DELAY function calls.
299 */
300 if (hsotg->wq_otg)
301 task_add(hsotg->wq_otg, &hsotg->wf_otg);
302 }
303
304 /**
305 * dwc2_handle_session_req_intr() - This interrupt indicates that a device is
306 * initiating the Session Request Protocol to request the host to turn on bus
307 * power so a new session can begin
308 *
309 * @hsotg: Programming view of DWC_otg controller
310 *
311 * This handler responds by turning on bus power. If the DWC_otg controller is
312 * in low power mode, this handler brings the controller out of low power mode
313 * before turning on bus power.
314 */
dwc2_handle_session_req_intr(struct dwc2_hsotg * hsotg)315 STATIC void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
316 {
317 int ret;
318 u32 hprt0;
319
320 /* Clear interrupt */
321 dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
322
323 dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
324 hsotg->lx_state);
325
326 if (dwc2_is_device_mode(hsotg)) {
327 if (hsotg->lx_state == DWC2_L2) {
328 if (hsotg->in_ppd) {
329 ret = dwc2_exit_partial_power_down(hsotg, 0,
330 true);
331 if (ret)
332 dev_err(hsotg->dev,
333 "exit power_down failed\n");
334 }
335
336 /* Exit gadget mode clock gating. */
337 if (hsotg->params.power_down ==
338 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
339 dwc2_gadget_exit_clock_gating(hsotg, 0);
340 }
341
342 /*
343 * Report disconnect if there is any previous session
344 * established
345 */
346 dwc2_hsotg_disconnect(hsotg);
347 } else {
348 /* Turn on the port power bit. */
349 hprt0 = dwc2_read_hprt0(hsotg);
350 hprt0 |= HPRT0_PWR;
351 dwc2_writel(hsotg, hprt0, HPRT0);
352 /* Connect hcd after port power is set. */
353 dwc2_hcd_connect(hsotg);
354 }
355 }
356
357 /**
358 * dwc2_wakeup_from_lpm_l1 - Exit the device from LPM L1 state
359 *
360 * @hsotg: Programming view of DWC_otg controller
361 *
362 */
dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg * hsotg)363 static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
364 {
365 u32 glpmcfg;
366 u32 i = 0;
367
368 if (hsotg->lx_state != DWC2_L1) {
369 dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
370 return;
371 }
372
373 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
374 if (dwc2_is_device_mode(hsotg)) {
375 dev_dbg(hsotg->dev, "Exit from L1 state\n");
376 glpmcfg &= ~GLPMCFG_ENBLSLPM;
377 glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
378 dwc2_writel(hsotg, glpmcfg, GLPMCFG);
379
380 do {
381 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
382
383 if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
384 GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
385 break;
386
387 udelay(1);
388 } while (++i < 200);
389
390 if (i == 200) {
391 dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
392 return;
393 }
394 dwc2_gadget_init_lpm(hsotg);
395 } else {
396 /* TODO */
397 dev_err(hsotg->dev, "Host side LPM is not supported.\n");
398 return;
399 }
400
401 /* Change to L0 state */
402 hsotg->lx_state = DWC2_L0;
403
404 /* Inform gadget to exit from L1 */
405 call_gadget(hsotg, resume);
406 }
407
408 /*
409 * This interrupt indicates that the DWC_otg controller has detected a
410 * resume or remote wakeup sequence. If the DWC_otg controller is in
411 * low power mode, the handler must brings the controller out of low
412 * power mode. The controller automatically begins resume signaling.
413 * The handler schedules a time to stop resume signaling.
414 */
dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg * hsotg)415 STATIC void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
416 {
417 int ret;
418
419 /* Clear interrupt */
420 dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
421
422 dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
423 dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
424
425 if (hsotg->lx_state == DWC2_L1) {
426 dwc2_wakeup_from_lpm_l1(hsotg);
427 return;
428 }
429
430 if (dwc2_is_device_mode(hsotg)) {
431 dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
432 dwc2_readl(hsotg, DSTS));
433 if (hsotg->lx_state == DWC2_L2) {
434 if (hsotg->in_ppd) {
435 u32 dctl = dwc2_readl(hsotg, DCTL);
436 /* Clear Remote Wakeup Signaling */
437 dctl &= ~DCTL_RMTWKUPSIG;
438 dwc2_writel(hsotg, dctl, DCTL);
439 ret = dwc2_exit_partial_power_down(hsotg, 1,
440 true);
441 if (ret)
442 dev_err(hsotg->dev,
443 "exit partial_power_down failed\n");
444 call_gadget(hsotg, resume);
445 }
446
447 /* Exit gadget mode clock gating. */
448 if (hsotg->params.power_down ==
449 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
450 dwc2_gadget_exit_clock_gating(hsotg, 0);
451 } else {
452 /* Change to L0 state */
453 hsotg->lx_state = DWC2_L0;
454 }
455 } else {
456 if (hsotg->lx_state == DWC2_L2) {
457 if (hsotg->in_ppd) {
458 ret = dwc2_exit_partial_power_down(hsotg, 1,
459 true);
460 if (ret)
461 dev_err(hsotg->dev,
462 "exit partial_power_down failed\n");
463 }
464
465 if (hsotg->params.power_down ==
466 DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
467 dwc2_host_exit_clock_gating(hsotg, 1);
468
469 /*
470 * If we've got this quirk then the PHY is stuck upon
471 * wakeup. Assert reset. This will propagate out and
472 * eventually we'll re-enumerate the device. Not great
473 * but the best we can do. We can't call phy_reset()
474 * at interrupt time but there's no hurry, so we'll
475 * schedule it for later.
476 */
477 if (hsotg->reset_phy_on_wake)
478 dwc2_host_schedule_phy_reset(hsotg);
479
480 timeout_add_msec(&hsotg->wkp_timer, 71);
481 } else {
482 /* Change to L0 state */
483 hsotg->lx_state = DWC2_L0;
484 }
485 }
486 }
487
488 /*
489 * This interrupt indicates that a device has been disconnected from the
490 * root port
491 */
dwc2_handle_disconnect_intr(struct dwc2_hsotg * hsotg)492 STATIC void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
493 {
494 dwc2_writel(hsotg, GINTSTS_DISCONNINT, GINTSTS);
495
496 dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
497 dwc2_is_host_mode(hsotg) ? "Host" : "Device",
498 dwc2_op_state_str(hsotg));
499
500 if (hsotg->op_state == OTG_STATE_A_HOST)
501 dwc2_hcd_disconnect(hsotg, false);
502 }
503
504 /*
505 * This interrupt indicates that SUSPEND state has been detected on the USB.
506 *
507 * For HNP the USB Suspend interrupt signals the change from "a_peripheral"
508 * to "a_host".
509 *
510 * When power management is enabled the core will be put in low power mode.
511 */
dwc2_handle_usb_suspend_intr(struct dwc2_hsotg * hsotg)512 STATIC void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
513 {
514 u32 dsts;
515 int ret;
516
517 /* Clear interrupt */
518 dwc2_writel(hsotg, GINTSTS_USBSUSP, GINTSTS);
519
520 dev_dbg(hsotg->dev, "USB SUSPEND\n");
521
522 if (dwc2_is_device_mode(hsotg)) {
523 /*
524 * Check the Device status register to determine if the Suspend
525 * state is active
526 */
527 dsts = dwc2_readl(hsotg, DSTS);
528 dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
529 dev_dbg(hsotg->dev,
530 "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d HWCFG4.Hibernation=%d\n",
531 !!(dsts & DSTS_SUSPSTS),
532 hsotg->hw_params.power_optimized,
533 hsotg->hw_params.hibernation);
534
535 /* Ignore suspend request before enumeration */
536 if (!dwc2_is_device_connected(hsotg)) {
537 dev_dbg(hsotg->dev,
538 "ignore suspend request before enumeration\n");
539 return;
540 }
541 if (dsts & DSTS_SUSPSTS) {
542 switch (hsotg->params.power_down) {
543 case DWC2_POWER_DOWN_PARAM_PARTIAL:
544 ret = dwc2_enter_partial_power_down(hsotg);
545 if (ret)
546 dev_err(hsotg->dev,
547 "enter partial_power_down failed\n");
548
549 udelay(100);
550
551 /* Ask phy to be suspended */
552 #if 0
553 if (!IS_ERR_OR_NULL(hsotg->uphy))
554 usb_phy_set_suspend(hsotg->uphy, true);
555 #endif
556 break;
557 case DWC2_POWER_DOWN_PARAM_HIBERNATION:
558 ret = dwc2_enter_hibernation(hsotg, 0);
559 if (ret)
560 dev_err(hsotg->dev,
561 "enter hibernation failed\n");
562 break;
563 case DWC2_POWER_DOWN_PARAM_NONE:
564 /*
565 * If neither hibernation nor partial power down are supported,
566 * clock gating is used to save power.
567 */
568 if (!hsotg->params.no_clock_gating)
569 dwc2_gadget_enter_clock_gating(hsotg);
570 }
571
572 /*
573 * Change to L2 (suspend) state before releasing
574 * spinlock
575 */
576 hsotg->lx_state = DWC2_L2;
577
578 /* Call gadget suspend callback */
579 call_gadget(hsotg, suspend);
580 }
581 } else {
582 if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
583 dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
584
585 /* Change to L2 (suspend) state */
586 hsotg->lx_state = DWC2_L2;
587 /* Clear the a_peripheral flag, back to a_host */
588 spin_unlock(&hsotg->lock);
589 dwc2_hcd_start(hsotg);
590 spin_lock(&hsotg->lock);
591 hsotg->op_state = OTG_STATE_A_HOST;
592 }
593 }
594 }
595
596 /**
597 * dwc2_handle_lpm_intr - GINTSTS_LPMTRANRCVD Interrupt handler
598 *
599 * @hsotg: Programming view of DWC_otg controller
600 *
601 */
dwc2_handle_lpm_intr(struct dwc2_hsotg * hsotg)602 static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
603 {
604 u32 glpmcfg;
605 u32 pcgcctl;
606 u32 hird;
607 u32 hird_thres;
608 u32 hird_thres_en;
609 u32 enslpm;
610
611 /* Clear interrupt */
612 dwc2_writel(hsotg, GINTSTS_LPMTRANRCVD, GINTSTS);
613
614 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
615
616 if (!(glpmcfg & GLPMCFG_LPMCAP)) {
617 dev_err(hsotg->dev, "Unexpected LPM interrupt\n");
618 return;
619 }
620
621 hird = (glpmcfg & GLPMCFG_HIRD_MASK) >> GLPMCFG_HIRD_SHIFT;
622 hird_thres = (glpmcfg & GLPMCFG_HIRD_THRES_MASK &
623 ~GLPMCFG_HIRD_THRES_EN) >> GLPMCFG_HIRD_THRES_SHIFT;
624 hird_thres_en = glpmcfg & GLPMCFG_HIRD_THRES_EN;
625 enslpm = glpmcfg & GLPMCFG_ENBLSLPM;
626
627 if (dwc2_is_device_mode(hsotg)) {
628 dev_dbg(hsotg->dev, "HIRD_THRES_EN = %d\n", hird_thres_en);
629
630 if (hird_thres_en && hird >= hird_thres) {
631 dev_dbg(hsotg->dev, "L1 with utmi_l1_suspend_n\n");
632 } else if (enslpm) {
633 dev_dbg(hsotg->dev, "L1 with utmi_sleep_n\n");
634 } else {
635 dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n");
636
637 pcgcctl = dwc2_readl(hsotg, PCGCTL);
638 pcgcctl |= PCGCTL_ENBL_SLEEP_GATING;
639 dwc2_writel(hsotg, pcgcctl, PCGCTL);
640 }
641 /**
642 * Examine prt_sleep_sts after TL1TokenTetry period max (10 us)
643 */
644 udelay(10);
645
646 glpmcfg = dwc2_readl(hsotg, GLPMCFG);
647
648 if (glpmcfg & GLPMCFG_SLPSTS) {
649 /* Save the current state */
650 hsotg->lx_state = DWC2_L1;
651 dev_dbg(hsotg->dev,
652 "Core is in L1 sleep glpmcfg=%08x\n", glpmcfg);
653
654 /* Inform gadget that we are in L1 state */
655 call_gadget(hsotg, suspend);
656 }
657 }
658 }
659
660 #define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \
661 GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT | \
662 GINTSTS_MODEMIS | GINTSTS_DISCONNINT | \
663 GINTSTS_USBSUSP | GINTSTS_PRTINT | \
664 GINTSTS_LPMTRANRCVD)
665
666 /*
667 * This function returns the Core Interrupt register
668 */
dwc2_read_common_intr(struct dwc2_hsotg * hsotg)669 STATIC u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
670 {
671 u32 gintsts;
672 u32 gintmsk;
673 u32 gahbcfg;
674 u32 gintmsk_common = GINTMSK_COMMON;
675
676 gintsts = dwc2_readl(hsotg, GINTSTS);
677 gintmsk = dwc2_readl(hsotg, GINTMSK);
678 gahbcfg = dwc2_readl(hsotg, GAHBCFG);
679
680 /* If any common interrupts set */
681 if (gintsts & gintmsk_common)
682 dev_dbg(hsotg->dev, "gintsts=%08x gintmsk=%08x\n",
683 gintsts, gintmsk);
684
685 if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
686 return gintsts & gintmsk & gintmsk_common;
687 else
688 return 0;
689 }
690
691 /**
692 * dwc_handle_gpwrdn_disc_det() - Handles the gpwrdn disconnect detect.
693 * Exits hibernation without restoring registers.
694 *
695 * @hsotg: Programming view of DWC_otg controller
696 * @gpwrdn: GPWRDN register
697 */
dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg * hsotg,u32 gpwrdn)698 static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
699 u32 gpwrdn)
700 {
701 u32 gpwrdn_tmp;
702
703 /* Switch-on voltage to the core */
704 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
705 gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
706 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
707 udelay(5);
708
709 /* Reset core */
710 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
711 gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
712 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
713 udelay(5);
714
715 /* Disable Power Down Clamp */
716 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
717 gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
718 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
719 udelay(5);
720
721 /* Deassert reset core */
722 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
723 gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
724 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
725 udelay(5);
726
727 /* Disable PMU interrupt */
728 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
729 gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
730 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
731
732 /* De-assert Wakeup Logic */
733 gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
734 gpwrdn_tmp &= ~GPWRDN_PMUACTV;
735 dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
736
737 hsotg->hibernated = 0;
738 hsotg->bus_suspended = 0;
739
740 if (gpwrdn & GPWRDN_IDSTS) {
741 hsotg->op_state = OTG_STATE_B_PERIPHERAL;
742 dwc2_core_init(hsotg, false);
743 dwc2_enable_global_interrupts(hsotg);
744 dwc2_hsotg_core_init_disconnected(hsotg, false);
745 dwc2_hsotg_core_connect(hsotg);
746 } else {
747 hsotg->op_state = OTG_STATE_A_HOST;
748
749 /* Initialize the Core for Host mode */
750 dwc2_core_init(hsotg, false);
751 dwc2_enable_global_interrupts(hsotg);
752 dwc2_hcd_start(hsotg);
753 }
754 }
755
756 /*
757 * GPWRDN interrupt handler.
758 *
759 * The GPWRDN interrupts are those that occur in both Host and
760 * Device mode while core is in hibernated state.
761 */
dwc2_handle_gpwrdn_intr(struct dwc2_hsotg * hsotg)762 static int dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
763 {
764 u32 gpwrdn;
765 int linestate;
766 int ret = 0;
767
768 gpwrdn = dwc2_readl(hsotg, GPWRDN);
769 /* clear all interrupt */
770 dwc2_writel(hsotg, gpwrdn, GPWRDN);
771 linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
772 dev_dbg(hsotg->dev,
773 "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
774 gpwrdn);
775
776 if ((gpwrdn & GPWRDN_DISCONN_DET) &&
777 (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
778 dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
779 /*
780 * Call disconnect detect function to exit from
781 * hibernation
782 */
783 dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
784 } else if ((gpwrdn & GPWRDN_LNSTSCHG) &&
785 (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
786 dev_dbg(hsotg->dev, "%s: GPWRDN_LNSTSCHG\n", __func__);
787 if (hsotg->hw_params.hibernation &&
788 hsotg->hibernated) {
789 if (gpwrdn & GPWRDN_IDSTS) {
790 ret = dwc2_exit_hibernation(hsotg, 0, 0, 0);
791 if (ret)
792 dev_err(hsotg->dev,
793 "exit hibernation failed.\n");
794 call_gadget(hsotg, resume);
795 } else {
796 ret = dwc2_exit_hibernation(hsotg, 1, 0, 1);
797 if (ret)
798 dev_err(hsotg->dev,
799 "exit hibernation failed.\n");
800 }
801 }
802 } else if ((gpwrdn & GPWRDN_RST_DET) &&
803 (gpwrdn & GPWRDN_RST_DET_MSK)) {
804 dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
805 if (!linestate) {
806 ret = dwc2_exit_hibernation(hsotg, 0, 1, 0);
807 if (ret)
808 dev_err(hsotg->dev,
809 "exit hibernation failed.\n");
810 }
811 } else if ((gpwrdn & GPWRDN_STS_CHGINT) &&
812 (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
813 dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
814 /*
815 * As GPWRDN_STS_CHGINT exit from hibernation flow is
816 * the same as in GPWRDN_DISCONN_DET flow. Call
817 * disconnect detect helper function to exit from
818 * hibernation.
819 */
820 dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
821 }
822
823 return ret;
824 }
825
826 /*
827 * Common interrupt handler
828 *
829 * The common interrupts are those that occur in both Host and Device mode.
830 * This handler handles the following interrupts:
831 * - Mode Mismatch Interrupt
832 * - OTG Interrupt
833 * - Connector ID Status Change Interrupt
834 * - Disconnect Interrupt
835 * - Session Request Interrupt
836 * - Resume / Remote Wakeup Detected Interrupt
837 * - Suspend Interrupt
838 */
dwc2_handle_common_intr(void * dev)839 irqreturn_t dwc2_handle_common_intr(void *dev)
840 {
841 struct dwc2_hsotg *hsotg = dev;
842 u32 gintsts;
843 irqreturn_t retval = IRQ_NONE;
844
845 spin_lock(&hsotg->lock);
846
847 if (!dwc2_is_controller_alive(hsotg)) {
848 dev_warn(hsotg->dev, "Controller is dead\n");
849 goto out;
850 }
851
852 /* Reading current frame number value in device or host modes. */
853 if (dwc2_is_device_mode(hsotg))
854 hsotg->frame_number = (dwc2_readl(hsotg, DSTS)
855 & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
856 else
857 hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
858 & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
859
860 gintsts = dwc2_read_common_intr(hsotg);
861 if (gintsts & ~GINTSTS_PRTINT)
862 retval = IRQ_HANDLED;
863
864 /* In case of hibernated state gintsts must not work */
865 if (hsotg->hibernated) {
866 dwc2_handle_gpwrdn_intr(hsotg);
867 retval = IRQ_HANDLED;
868 goto out;
869 }
870
871 if (gintsts & GINTSTS_MODEMIS)
872 dwc2_handle_mode_mismatch_intr(hsotg);
873 if (gintsts & GINTSTS_OTGINT)
874 dwc2_handle_otg_intr(hsotg);
875 if (gintsts & GINTSTS_CONIDSTSCHNG)
876 dwc2_handle_conn_id_status_change_intr(hsotg);
877 if (gintsts & GINTSTS_DISCONNINT)
878 dwc2_handle_disconnect_intr(hsotg);
879 if (gintsts & GINTSTS_SESSREQINT)
880 dwc2_handle_session_req_intr(hsotg);
881 if (gintsts & GINTSTS_WKUPINT)
882 dwc2_handle_wakeup_detected_intr(hsotg);
883 if (gintsts & GINTSTS_USBSUSP)
884 dwc2_handle_usb_suspend_intr(hsotg);
885 if (gintsts & GINTSTS_LPMTRANRCVD)
886 dwc2_handle_lpm_intr(hsotg);
887
888 if (gintsts & GINTSTS_PRTINT) {
889 /*
890 * The port interrupt occurs while in device mode with HPRT0
891 * Port Enable/Disable
892 */
893 if (dwc2_is_device_mode(hsotg)) {
894 dev_dbg(hsotg->dev,
895 " --Port interrupt received in Device mode--\n");
896 dwc2_handle_usb_port_intr(hsotg);
897 retval = IRQ_HANDLED;
898 }
899 }
900
901 out:
902 spin_unlock(&hsotg->lock);
903 return retval;
904 }
905