core_intr.c 22.9 KB
Newer Older
1
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
/*
 * core_intr.c - DesignWare HS OTG Controller common interrupt handling
 *
 * Copyright (C) 2004-2013 Synopsys, Inc.
 */

/*
 * This file contains the common interrupt handlers
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/usb.h>

#include <linux/usb/hcd.h>
#include <linux/usb/ch11.h>

#include "core.h"
#include "hcd.h"

static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
{
	switch (hsotg->op_state) {
	case OTG_STATE_A_HOST:
		return "a_host";
	case OTG_STATE_A_SUSPEND:
		return "a_suspend";
	case OTG_STATE_A_PERIPHERAL:
		return "a_peripheral";
	case OTG_STATE_B_PERIPHERAL:
		return "b_peripheral";
	case OTG_STATE_B_HOST:
		return "b_host";
	default:
		return "unknown";
	}
}

45 46 47 48 49 50 51 52 53
/**
 * dwc2_handle_usb_port_intr - handles OTG PRTINT interrupts.
 * When the PRTINT interrupt fires, there are certain status bits in the Host
 * Port that needs to get cleared.
 *
 * @hsotg: Programming view of DWC_otg controller
 */
static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
{
54
	u32 hprt0 = dwc2_readl(hsotg, HPRT0);
55 56 57

	if (hprt0 & HPRT0_ENACHG) {
		hprt0 &= ~HPRT0_ENA;
58
		dwc2_writel(hsotg, hprt0, HPRT0);
59 60 61
	}
}

62 63 64 65 66 67 68 69
/**
 * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message
 *
 * @hsotg: Programming view of DWC_otg controller
 */
static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
{
	/* Clear interrupt */
70
	dwc2_writel(hsotg, GINTSTS_MODEMIS, GINTSTS);
71 72 73

	dev_warn(hsotg->dev, "Mode Mismatch Interrupt: currently in %s mode\n",
		 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
74 75 76 77 78 79 80 81 82 83 84 85 86 87
}

/**
 * dwc2_handle_otg_intr() - Handles the OTG Interrupts. It reads the OTG
 * Interrupt Register (GOTGINT) to determine what interrupt has occurred.
 *
 * @hsotg: Programming view of DWC_otg controller
 */
static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
{
	u32 gotgint;
	u32 gotgctl;
	u32 gintmsk;

88 89
	gotgint = dwc2_readl(hsotg, GOTGINT);
	gotgctl = dwc2_readl(hsotg, GOTGCTL);
90 91 92 93 94 95 96
	dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
		dwc2_op_state_str(hsotg));

	if (gotgint & GOTGINT_SES_END_DET) {
		dev_dbg(hsotg->dev,
			" ++OTG Interrupt: Session End Detected++ (%s)\n",
			dwc2_op_state_str(hsotg));
97
		gotgctl = dwc2_readl(hsotg, GOTGCTL);
98

99
		if (dwc2_is_device_mode(hsotg))
100
			dwc2_hsotg_disconnect(hsotg);
101

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
		if (hsotg->op_state == OTG_STATE_B_HOST) {
			hsotg->op_state = OTG_STATE_B_PERIPHERAL;
		} else {
			/*
			 * If not B_HOST and Device HNP still set, HNP did
			 * not succeed!
			 */
			if (gotgctl & GOTGCTL_DEVHNPEN) {
				dev_dbg(hsotg->dev, "Session End Detected\n");
				dev_err(hsotg->dev,
					"Device Not Connected/Responding!\n");
			}

			/*
			 * If Session End Detected the B-Cable has been
			 * disconnected
			 */
			/* Reset to a clean state */
			hsotg->lx_state = DWC2_L0;
		}

123
		gotgctl = dwc2_readl(hsotg, GOTGCTL);
124
		gotgctl &= ~GOTGCTL_DEVHNPEN;
125
		dwc2_writel(hsotg, gotgctl, GOTGCTL);
126 127 128 129 130
	}

	if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
		dev_dbg(hsotg->dev,
			" ++OTG Interrupt: Session Request Success Status Change++\n");
131
		gotgctl = dwc2_readl(hsotg, GOTGCTL);
132
		if (gotgctl & GOTGCTL_SESREQSCS) {
133
			if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
134
			    hsotg->params.i2c_enable) {
135 136 137
				hsotg->srp_success = 1;
			} else {
				/* Clear Session Request */
138
				gotgctl = dwc2_readl(hsotg, GOTGCTL);
139
				gotgctl &= ~GOTGCTL_SESREQ;
140
				dwc2_writel(hsotg, gotgctl, GOTGCTL);
141 142 143 144 145 146 147 148 149
			}
		}
	}

	if (gotgint & GOTGINT_HST_NEG_SUC_STS_CHNG) {
		/*
		 * Print statements during the HNP interrupt handling
		 * can cause it to fail
		 */
150
		gotgctl = dwc2_readl(hsotg, GOTGCTL);
151 152 153 154
		/*
		 * WA for 3.00a- HW is not setting cur_mode, even sometimes
		 * this does not help
		 */
155
		if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)
156 157 158 159 160 161 162 163 164 165 166 167 168 169
			udelay(100);
		if (gotgctl & GOTGCTL_HSTNEGSCS) {
			if (dwc2_is_host_mode(hsotg)) {
				hsotg->op_state = OTG_STATE_B_HOST;
				/*
				 * Need to disable SOF interrupt immediately.
				 * When switching from device to host, the PCD
				 * interrupt handler won't handle the interrupt
				 * if host mode is already set. The HCD
				 * interrupt handler won't get called if the
				 * HCD state is HALT. This means that the
				 * interrupt does not get handled and Linux
				 * complains loudly.
				 */
170
				gintmsk = dwc2_readl(hsotg, GINTMSK);
171
				gintmsk &= ~GINTSTS_SOF;
172
				dwc2_writel(hsotg, gintmsk, GINTMSK);
173 174 175 176 177 178 179 180 181 182 183 184 185

				/*
				 * Call callback function with spin lock
				 * released
				 */
				spin_unlock(&hsotg->lock);

				/* Initialize the Core for Host mode */
				dwc2_hcd_start(hsotg);
				spin_lock(&hsotg->lock);
				hsotg->op_state = OTG_STATE_B_HOST;
			}
		} else {
186
			gotgctl = dwc2_readl(hsotg, GOTGCTL);
187
			gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
188
			dwc2_writel(hsotg, gotgctl, GOTGCTL);
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
			dev_dbg(hsotg->dev, "HNP Failed\n");
			dev_err(hsotg->dev,
				"Device Not Connected/Responding\n");
		}
	}

	if (gotgint & GOTGINT_HST_NEG_DET) {
		/*
		 * The disconnect interrupt is set at the same time as
		 * Host Negotiation Detected. During the mode switch all
		 * interrupts are cleared so the disconnect interrupt
		 * handler will not get executed.
		 */
		dev_dbg(hsotg->dev,
			" ++OTG Interrupt: Host Negotiation Detected++ (%s)\n",
			(dwc2_is_host_mode(hsotg) ? "Host" : "Device"));
		if (dwc2_is_device_mode(hsotg)) {
			dev_dbg(hsotg->dev, "a_suspend->a_peripheral (%d)\n",
				hsotg->op_state);
			spin_unlock(&hsotg->lock);
209
			dwc2_hcd_disconnect(hsotg, false);
210 211 212 213
			spin_lock(&hsotg->lock);
			hsotg->op_state = OTG_STATE_A_PERIPHERAL;
		} else {
			/* Need to disable SOF interrupt immediately */
214
			gintmsk = dwc2_readl(hsotg, GINTMSK);
215
			gintmsk &= ~GINTSTS_SOF;
216
			dwc2_writel(hsotg, gintmsk, GINTMSK);
217 218 219 220 221 222 223 224 225 226 227 228 229 230
			spin_unlock(&hsotg->lock);
			dwc2_hcd_start(hsotg);
			spin_lock(&hsotg->lock);
			hsotg->op_state = OTG_STATE_A_HOST;
		}
	}

	if (gotgint & GOTGINT_A_DEV_TOUT_CHG)
		dev_dbg(hsotg->dev,
			" ++OTG Interrupt: A-Device Timeout Change++\n");
	if (gotgint & GOTGINT_DBNCE_DONE)
		dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");

	/* Clear GOTGINT */
231
	dwc2_writel(hsotg, gotgint, GOTGINT);
232 233 234 235 236 237 238 239 240 241 242 243 244 245
}

/**
 * dwc2_handle_conn_id_status_change_intr() - Handles the Connector ID Status
 * Change Interrupt
 *
 * @hsotg: Programming view of DWC_otg controller
 *
 * Reads the OTG Interrupt Register (GOTCTL) to determine whether this is a
 * Device to Host Mode transition or a Host to Device Mode transition. This only
 * occurs when the cable is connected/removed from the PHY connector.
 */
static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
{
246 247 248
	u32 gintmsk;

	/* Clear interrupt */
249
	dwc2_writel(hsotg, GINTSTS_CONIDSTSCHNG, GINTSTS);
250 251

	/* Need to disable SOF interrupt immediately */
252
	gintmsk = dwc2_readl(hsotg, GINTMSK);
253
	gintmsk &= ~GINTSTS_SOF;
254
	dwc2_writel(hsotg, gintmsk, GINTMSK);
255 256 257 258 259 260 261

	dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
		dwc2_is_host_mode(hsotg) ? "Host" : "Device");

	/*
	 * Need to schedule a work, as there are possible DELAY function calls.
	 */
262
	if (hsotg->wq_otg)
263
		queue_work(hsotg->wq_otg, &hsotg->wf_otg);
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
}

/**
 * dwc2_handle_session_req_intr() - This interrupt indicates that a device is
 * initiating the Session Request Protocol to request the host to turn on bus
 * power so a new session can begin
 *
 * @hsotg: Programming view of DWC_otg controller
 *
 * This handler responds by turning on bus power. If the DWC_otg controller is
 * in low power mode, this handler brings the controller out of low power mode
 * before turning on bus power.
 */
static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
{
279
	int ret;
280
	u32 hprt0;
281

282
	/* Clear interrupt */
283
	dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
284

285
	dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
286
		hsotg->lx_state);
287

288
	if (dwc2_is_device_mode(hsotg)) {
289 290 291 292 293 294 295 296 297 298 299 300 301
		if (hsotg->lx_state == DWC2_L2) {
			if (hsotg->in_ppd) {
				ret = dwc2_exit_partial_power_down(hsotg, 0,
								   true);
				if (ret)
					dev_err(hsotg->dev,
						"exit power_down failed\n");
			}

			/* Exit gadget mode clock gating. */
			if (hsotg->params.power_down ==
			    DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
				dwc2_gadget_exit_clock_gating(hsotg, 0);
302 303 304 305 306 307
		}

		/*
		 * Report disconnect if there is any previous session
		 * established
		 */
308
		dwc2_hsotg_disconnect(hsotg);
309 310 311 312 313 314 315
	} else {
		/* Turn on the port power bit. */
		hprt0 = dwc2_read_hprt0(hsotg);
		hprt0 |= HPRT0_PWR;
		dwc2_writel(hsotg, hprt0, HPRT0);
		/* Connect hcd after port power is set. */
		dwc2_hcd_connect(hsotg);
316
	}
317 318
}

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
/**
 * dwc2_wakeup_from_lpm_l1 - Exit the device from LPM L1 state
 *
 * @hsotg: Programming view of DWC_otg controller
 *
 */
static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
{
	u32 glpmcfg;
	u32 i = 0;

	if (hsotg->lx_state != DWC2_L1) {
		dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
		return;
	}

335
	glpmcfg = dwc2_readl(hsotg, GLPMCFG);
336 337 338 339
	if (dwc2_is_device_mode(hsotg)) {
		dev_dbg(hsotg->dev, "Exit from L1 state\n");
		glpmcfg &= ~GLPMCFG_ENBLSLPM;
		glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
340
		dwc2_writel(hsotg, glpmcfg, GLPMCFG);
341 342

		do {
343
			glpmcfg = dwc2_readl(hsotg, GLPMCFG);
344 345 346 347 348 349 350 351 352 353 354 355

			if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
					 GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
				break;

			udelay(1);
		} while (++i < 200);

		if (i == 200) {
			dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
			return;
		}
356
		dwc2_gadget_init_lpm(hsotg);
357 358 359 360 361 362 363 364
	} else {
		/* TODO */
		dev_err(hsotg->dev, "Host side LPM is not supported.\n");
		return;
	}

	/* Change to L0 state */
	hsotg->lx_state = DWC2_L0;
365 366 367

	/* Inform gadget to exit from L1 */
	call_gadget(hsotg, resume);
368 369
}

370 371 372 373 374 375 376 377 378
/*
 * This interrupt indicates that the DWC_otg controller has detected a
 * resume or remote wakeup sequence. If the DWC_otg controller is in
 * low power mode, the handler must brings the controller out of low
 * power mode. The controller automatically begins resume signaling.
 * The handler schedules a time to stop resume signaling.
 */
static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
{
379
	int ret;
380 381

	/* Clear interrupt */
382
	dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
383

384 385 386
	dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
	dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);

387 388 389 390 391
	if (hsotg->lx_state == DWC2_L1) {
		dwc2_wakeup_from_lpm_l1(hsotg);
		return;
	}

392
	if (dwc2_is_device_mode(hsotg)) {
393
		dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
394
			dwc2_readl(hsotg, DSTS));
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
		if (hsotg->lx_state == DWC2_L2) {
			if (hsotg->in_ppd) {
				u32 dctl = dwc2_readl(hsotg, DCTL);
				/* Clear Remote Wakeup Signaling */
				dctl &= ~DCTL_RMTWKUPSIG;
				dwc2_writel(hsotg, dctl, DCTL);
				ret = dwc2_exit_partial_power_down(hsotg, 1,
								   true);
				if (ret)
					dev_err(hsotg->dev,
						"exit partial_power_down failed\n");
				call_gadget(hsotg, resume);
			}

			/* Exit gadget mode clock gating. */
			if (hsotg->params.power_down ==
			    DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
				dwc2_gadget_exit_clock_gating(hsotg, 0);
413 414 415
		} else {
			/* Change to L0 state */
			hsotg->lx_state = DWC2_L0;
416 417
		}
	} else {
418 419 420 421 422 423 424 425
		if (hsotg->lx_state == DWC2_L2) {
			if (hsotg->in_ppd) {
				ret = dwc2_exit_partial_power_down(hsotg, 1,
								   true);
				if (ret)
					dev_err(hsotg->dev,
						"exit partial_power_down failed\n");
			}
426

427 428 429 430
			if (hsotg->params.power_down ==
			    DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
				dwc2_host_exit_clock_gating(hsotg, 1);

431 432 433 434 435 436 437 438 439 440 441
			/*
			 * If we've got this quirk then the PHY is stuck upon
			 * wakeup.  Assert reset.  This will propagate out and
			 * eventually we'll re-enumerate the device.  Not great
			 * but the best we can do.  We can't call phy_reset()
			 * at interrupt time but there's no hurry, so we'll
			 * schedule it for later.
			 */
			if (hsotg->reset_phy_on_wake)
				dwc2_host_schedule_phy_reset(hsotg);

442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
			mod_timer(&hsotg->wkp_timer,
				  jiffies + msecs_to_jiffies(71));
		} else {
			/* Change to L0 state */
			hsotg->lx_state = DWC2_L0;
		}
	}
}

/*
 * This interrupt indicates that a device has been disconnected from the
 * root port
 */
static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
{
457
	dwc2_writel(hsotg, GINTSTS_DISCONNINT, GINTSTS);
458

459 460 461 462
	dev_dbg(hsotg->dev, "++Disconnect Detected Interrupt++ (%s) %s\n",
		dwc2_is_host_mode(hsotg) ? "Host" : "Device",
		dwc2_op_state_str(hsotg));

463
	if (hsotg->op_state == OTG_STATE_A_HOST)
464
		dwc2_hcd_disconnect(hsotg, false);
465 466 467 468 469 470 471 472 473 474 475 476 477
}

/*
 * This interrupt indicates that SUSPEND state has been detected on the USB.
 *
 * For HNP the USB Suspend interrupt signals the change from "a_peripheral"
 * to "a_host".
 *
 * When power management is enabled the core will be put in low power mode.
 */
static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
{
	u32 dsts;
478
	int ret;
479

480
	/* Clear interrupt */
481
	dwc2_writel(hsotg, GINTSTS_USBSUSP, GINTSTS);
482

483 484 485 486 487 488 489
	dev_dbg(hsotg->dev, "USB SUSPEND\n");

	if (dwc2_is_device_mode(hsotg)) {
		/*
		 * Check the Device status register to determine if the Suspend
		 * state is active
		 */
490
		dsts = dwc2_readl(hsotg, DSTS);
491
		dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
492
		dev_dbg(hsotg->dev,
493
			"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d HWCFG4.Hibernation=%d\n",
494
			!!(dsts & DSTS_SUSPSTS),
495 496 497 498 499 500 501 502 503 504
			hsotg->hw_params.power_optimized,
			hsotg->hw_params.hibernation);

		/* Ignore suspend request before enumeration */
		if (!dwc2_is_device_connected(hsotg)) {
			dev_dbg(hsotg->dev,
				"ignore suspend request before enumeration\n");
			return;
		}
		if (dsts & DSTS_SUSPSTS) {
505 506
			switch (hsotg->params.power_down) {
			case DWC2_POWER_DOWN_PARAM_PARTIAL:
507
				ret = dwc2_enter_partial_power_down(hsotg);
508 509 510 511
				if (ret)
					dev_err(hsotg->dev,
						"enter partial_power_down failed\n");

512 513 514 515 516
				udelay(100);

				/* Ask phy to be suspended */
				if (!IS_ERR_OR_NULL(hsotg->uphy))
					usb_phy_set_suspend(hsotg->uphy, true);
517 518
				break;
			case DWC2_POWER_DOWN_PARAM_HIBERNATION:
519
				ret = dwc2_enter_hibernation(hsotg, 0);
520
				if (ret)
521
					dev_err(hsotg->dev,
522
						"enter hibernation failed\n");
523 524
				break;
			case DWC2_POWER_DOWN_PARAM_NONE:
525
				/*
526
				 * If neither hibernation nor partial power down are supported,
527 528
				 * clock gating is used to save power.
				 */
529 530
				if (!hsotg->params.no_clock_gating)
					dwc2_gadget_enter_clock_gating(hsotg);
531
			}
532

533 534 535 536 537 538
			/*
			 * Change to L2 (suspend) state before releasing
			 * spinlock
			 */
			hsotg->lx_state = DWC2_L2;

539 540 541
			/* Call gadget suspend callback */
			call_gadget(hsotg, suspend);
		}
542 543 544 545
	} else {
		if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
			dev_dbg(hsotg->dev, "a_peripheral->a_host\n");

546 547
			/* Change to L2 (suspend) state */
			hsotg->lx_state = DWC2_L2;
548 549 550 551 552 553 554 555 556
			/* Clear the a_peripheral flag, back to a_host */
			spin_unlock(&hsotg->lock);
			dwc2_hcd_start(hsotg);
			spin_lock(&hsotg->lock);
			hsotg->op_state = OTG_STATE_A_HOST;
		}
	}
}

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
/**
 * dwc2_handle_lpm_intr - GINTSTS_LPMTRANRCVD Interrupt handler
 *
 * @hsotg: Programming view of DWC_otg controller
 *
 */
static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)
{
	u32 glpmcfg;
	u32 pcgcctl;
	u32 hird;
	u32 hird_thres;
	u32 hird_thres_en;
	u32 enslpm;

	/* Clear interrupt */
573
	dwc2_writel(hsotg, GINTSTS_LPMTRANRCVD, GINTSTS);
574

575
	glpmcfg = dwc2_readl(hsotg, GLPMCFG);
576 577 578 579 580 581 582 583 584 585

	if (!(glpmcfg & GLPMCFG_LPMCAP)) {
		dev_err(hsotg->dev, "Unexpected LPM interrupt\n");
		return;
	}

	hird = (glpmcfg & GLPMCFG_HIRD_MASK) >> GLPMCFG_HIRD_SHIFT;
	hird_thres = (glpmcfg & GLPMCFG_HIRD_THRES_MASK &
			~GLPMCFG_HIRD_THRES_EN) >> GLPMCFG_HIRD_THRES_SHIFT;
	hird_thres_en = glpmcfg & GLPMCFG_HIRD_THRES_EN;
586
	enslpm = glpmcfg & GLPMCFG_ENBLSLPM;
587 588 589 590 591 592 593 594 595 596 597

	if (dwc2_is_device_mode(hsotg)) {
		dev_dbg(hsotg->dev, "HIRD_THRES_EN = %d\n", hird_thres_en);

		if (hird_thres_en && hird >= hird_thres) {
			dev_dbg(hsotg->dev, "L1 with utmi_l1_suspend_n\n");
		} else if (enslpm) {
			dev_dbg(hsotg->dev, "L1 with utmi_sleep_n\n");
		} else {
			dev_dbg(hsotg->dev, "Entering Sleep with L1 Gating\n");

598
			pcgcctl = dwc2_readl(hsotg, PCGCTL);
599
			pcgcctl |= PCGCTL_ENBL_SLEEP_GATING;
600
			dwc2_writel(hsotg, pcgcctl, PCGCTL);
601 602 603 604 605 606
		}
		/**
		 * Examine prt_sleep_sts after TL1TokenTetry period max (10 us)
		 */
		udelay(10);

607
		glpmcfg = dwc2_readl(hsotg, GLPMCFG);
608 609 610 611 612 613

		if (glpmcfg & GLPMCFG_SLPSTS) {
			/* Save the current state */
			hsotg->lx_state = DWC2_L1;
			dev_dbg(hsotg->dev,
				"Core is in L1 sleep glpmcfg=%08x\n", glpmcfg);
614 615 616

			/* Inform gadget that we are in L1 state */
			call_gadget(hsotg, suspend);
617 618 619 620
		}
	}
}

621 622 623
#define GINTMSK_COMMON	(GINTSTS_WKUPINT | GINTSTS_SESSREQINT |		\
			 GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT |	\
			 GINTSTS_MODEMIS | GINTSTS_DISCONNINT |		\
624 625
			 GINTSTS_USBSUSP | GINTSTS_PRTINT |		\
			 GINTSTS_LPMTRANRCVD)
626 627 628 629 630 631 632 633 634 635 636

/*
 * This function returns the Core Interrupt register
 */
static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
{
	u32 gintsts;
	u32 gintmsk;
	u32 gahbcfg;
	u32 gintmsk_common = GINTMSK_COMMON;

637 638 639
	gintsts = dwc2_readl(hsotg, GINTSTS);
	gintmsk = dwc2_readl(hsotg, GINTMSK);
	gahbcfg = dwc2_readl(hsotg, GAHBCFG);
640 641 642 643 644 645 646 647 648 649 650 651

	/* If any common interrupts set */
	if (gintsts & gintmsk_common)
		dev_dbg(hsotg->dev, "gintsts=%08x  gintmsk=%08x\n",
			gintsts, gintmsk);

	if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
		return gintsts & gintmsk & gintmsk_common;
	else
		return 0;
}

652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
/**
 * dwc_handle_gpwrdn_disc_det() - Handles the gpwrdn disconnect detect.
 * Exits hibernation without restoring registers.
 *
 * @hsotg: Programming view of DWC_otg controller
 * @gpwrdn: GPWRDN register
 */
static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
					      u32 gpwrdn)
{
	u32 gpwrdn_tmp;

	/* Switch-on voltage to the core */
	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
	gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
	udelay(5);

	/* Reset core */
	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
	gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
	udelay(5);

	/* Disable Power Down Clamp */
	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
	gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
	udelay(5);

	/* Deassert reset core */
	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
	gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
	udelay(5);

	/* Disable PMU interrupt */
	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
	gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);

	/* De-assert Wakeup Logic */
	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
	gpwrdn_tmp &= ~GPWRDN_PMUACTV;
	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);

	hsotg->hibernated = 0;
	hsotg->bus_suspended = 0;

	if (gpwrdn & GPWRDN_IDSTS) {
		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
		dwc2_core_init(hsotg, false);
		dwc2_enable_global_interrupts(hsotg);
		dwc2_hsotg_core_init_disconnected(hsotg, false);
		dwc2_hsotg_core_connect(hsotg);
	} else {
		hsotg->op_state = OTG_STATE_A_HOST;

		/* Initialize the Core for Host mode */
		dwc2_core_init(hsotg, false);
		dwc2_enable_global_interrupts(hsotg);
		dwc2_hcd_start(hsotg);
	}
}

717 718 719 720 721 722
/*
 * GPWRDN interrupt handler.
 *
 * The GPWRDN interrupts are those that occur in both Host and
 * Device mode while core is in hibernated state.
 */
723
static int dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
724 725 726
{
	u32 gpwrdn;
	int linestate;
727
	int ret = 0;
728

729
	gpwrdn = dwc2_readl(hsotg, GPWRDN);
730
	/* clear all interrupt */
731
	dwc2_writel(hsotg, gpwrdn, GPWRDN);
732 733 734 735 736 737 738 739
	linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
	dev_dbg(hsotg->dev,
		"%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
		gpwrdn);

	if ((gpwrdn & GPWRDN_DISCONN_DET) &&
	    (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
		dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
740 741 742 743 744 745 746
		/*
		 * Call disconnect detect function to exit from
		 * hibernation
		 */
		dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
	} else if ((gpwrdn & GPWRDN_LNSTSCHG) &&
		   (gpwrdn & GPWRDN_LNSTSCHG_MSK) && linestate) {
747 748 749 750
		dev_dbg(hsotg->dev, "%s: GPWRDN_LNSTSCHG\n", __func__);
		if (hsotg->hw_params.hibernation &&
		    hsotg->hibernated) {
			if (gpwrdn & GPWRDN_IDSTS) {
751 752 753 754
				ret = dwc2_exit_hibernation(hsotg, 0, 0, 0);
				if (ret)
					dev_err(hsotg->dev,
						"exit hibernation failed.\n");
755 756
				call_gadget(hsotg, resume);
			} else {
757 758 759 760
				ret = dwc2_exit_hibernation(hsotg, 1, 0, 1);
				if (ret)
					dev_err(hsotg->dev,
						"exit hibernation failed.\n");
761 762
			}
		}
763 764
	} else if ((gpwrdn & GPWRDN_RST_DET) &&
		   (gpwrdn & GPWRDN_RST_DET_MSK)) {
765
		dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
766 767 768 769 770 771
		if (!linestate) {
			ret = dwc2_exit_hibernation(hsotg, 0, 1, 0);
			if (ret)
				dev_err(hsotg->dev,
					"exit hibernation failed.\n");
		}
772 773
	} else if ((gpwrdn & GPWRDN_STS_CHGINT) &&
		   (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
774
		dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
775 776 777 778 779 780 781
		/*
		 * As GPWRDN_STS_CHGINT exit from hibernation flow is
		 * the same as in GPWRDN_DISCONN_DET flow. Call
		 * disconnect detect helper function to exit from
		 * hibernation.
		 */
		dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
782
	}
783 784

	return ret;
785 786
}

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
/*
 * Common interrupt handler
 *
 * The common interrupts are those that occur in both Host and Device mode.
 * This handler handles the following interrupts:
 * - Mode Mismatch Interrupt
 * - OTG Interrupt
 * - Connector ID Status Change Interrupt
 * - Disconnect Interrupt
 * - Session Request Interrupt
 * - Resume / Remote Wakeup Detected Interrupt
 * - Suspend Interrupt
 */
irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
{
	struct dwc2_hsotg *hsotg = dev;
	u32 gintsts;
804
	irqreturn_t retval = IRQ_NONE;
805

806 807
	spin_lock(&hsotg->lock);

808 809
	if (!dwc2_is_controller_alive(hsotg)) {
		dev_warn(hsotg->dev, "Controller is dead\n");
810 811 812
		goto out;
	}

813 814
	/* Reading current frame number value in device or host modes. */
	if (dwc2_is_device_mode(hsotg))
815
		hsotg->frame_number = (dwc2_readl(hsotg, DSTS)
816 817
				       & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
	else
818
		hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
819 820
				       & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;

821 822
	gintsts = dwc2_read_common_intr(hsotg);
	if (gintsts & ~GINTSTS_PRTINT)
823
		retval = IRQ_HANDLED;
824

825 826 827 828 829 830 831
	/* In case of hibernated state gintsts must not work */
	if (hsotg->hibernated) {
		dwc2_handle_gpwrdn_intr(hsotg);
		retval = IRQ_HANDLED;
		goto out;
	}

832 833 834 835 836 837 838 839 840 841 842 843 844 845
	if (gintsts & GINTSTS_MODEMIS)
		dwc2_handle_mode_mismatch_intr(hsotg);
	if (gintsts & GINTSTS_OTGINT)
		dwc2_handle_otg_intr(hsotg);
	if (gintsts & GINTSTS_CONIDSTSCHNG)
		dwc2_handle_conn_id_status_change_intr(hsotg);
	if (gintsts & GINTSTS_DISCONNINT)
		dwc2_handle_disconnect_intr(hsotg);
	if (gintsts & GINTSTS_SESSREQINT)
		dwc2_handle_session_req_intr(hsotg);
	if (gintsts & GINTSTS_WKUPINT)
		dwc2_handle_wakeup_detected_intr(hsotg);
	if (gintsts & GINTSTS_USBSUSP)
		dwc2_handle_usb_suspend_intr(hsotg);
846 847
	if (gintsts & GINTSTS_LPMTRANRCVD)
		dwc2_handle_lpm_intr(hsotg);
848 849 850 851 852 853 854 855 856

	if (gintsts & GINTSTS_PRTINT) {
		/*
		 * The port interrupt occurs while in device mode with HPRT0
		 * Port Enable/Disable
		 */
		if (dwc2_is_device_mode(hsotg)) {
			dev_dbg(hsotg->dev,
				" --Port interrupt received in Device mode--\n");
857 858
			dwc2_handle_usb_port_intr(hsotg);
			retval = IRQ_HANDLED;
859 860 861 862
		}
	}

out:
863
	spin_unlock(&hsotg->lock);
864
	return retval;
865
}