xref: /openbsd-src/sys/dev/usb/dwc2/dwc2_coreintr.c (revision da56e3f05039b286a5ba51464f5f884589fc13c2)
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