aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/core.c
diff options
context:
space:
mode:
authorJohn Youn <John.Youn@synopsys.com>2015-12-17 14:17:12 -0500
committerFelipe Balbi <balbi@ti.com>2015-12-22 13:00:34 -0500
commit09c96980dc723462ed2eeacc945fed5bcb278f85 (patch)
tree8b19af92cd27f36b967683b9a5f29753646f29d7 /drivers/usb/dwc2/core.c
parent263b7fb557f797d9d4d1dcf93fb6bb2efc3f1d46 (diff)
usb: dwc2: Add functions to set and clear force mode
Added functions to set force mode for host and device. These functions will check the current mode and only force if needed thus avoiding unnecessary force mode delays. However clearing the mode is currently done unconditionally and with the delay in place. This is needed during the connector ID status change interrupt in order to ensure that the mode has changed properly. This preserves the old behavior only for this case. The warning comment about this is moved into the clear mode condition. Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc2/core.c')
-rw-r--r--drivers/usb/dwc2/core.c149
1 files changed, 125 insertions, 24 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 3b55635c878c..436e7d1ef3c8 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -520,6 +520,114 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
520} 520}
521 521
522/* 522/*
523 * Force the mode of the controller.
524 *
525 * Forcing the mode is needed for two cases:
526 *
527 * 1) If the dr_mode is set to either HOST or PERIPHERAL we force the
528 * controller to stay in a particular mode regardless of ID pin
529 * changes. We do this usually after a core reset.
530 *
531 * 2) During probe we want to read reset values of the hw
532 * configuration registers that are only available in either host or
533 * device mode. We may need to force the mode if the current mode does
534 * not allow us to access the register in the mode that we want.
535 *
536 * In either case it only makes sense to force the mode if the
537 * controller hardware is OTG capable.
538 *
539 * Checks are done in this function to determine whether doing a force
540 * would be valid or not.
541 *
542 * If a force is done, it requires a 25ms delay to take effect.
543 *
544 * Returns true if the mode was forced.
545 */
546static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
547{
548 u32 gusbcfg;
549 u32 set;
550 u32 clear;
551
552 dev_dbg(hsotg->dev, "Forcing mode to %s\n", host ? "host" : "device");
553
554 /*
555 * Force mode has no effect if the hardware is not OTG.
556 */
557 if (!dwc2_hw_is_otg(hsotg))
558 return false;
559
560 /*
561 * If dr_mode is either peripheral or host only, there is no
562 * need to ever force the mode to the opposite mode.
563 */
564 if (WARN_ON(host && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL))
565 return false;
566
567 if (WARN_ON(!host && hsotg->dr_mode == USB_DR_MODE_HOST))
568 return false;
569
570 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
571
572 set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE;
573 clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE;
574
575 /*
576 * If the force mode bit is already set, don't set it.
577 */
578 if ((gusbcfg & set) && !(gusbcfg & clear))
579 return false;
580
581 gusbcfg &= ~clear;
582 gusbcfg |= set;
583 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
584
585 msleep(25);
586 return true;
587}
588
589/*
590 * Clears the force mode bits.
591 */
592static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
593{
594 u32 gusbcfg;
595
596 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
597 gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
598 gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
599 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
600
601 /*
602 * NOTE: This long sleep is _very_ important, otherwise the core will
603 * not stay in host mode after a connector ID change!
604 */
605 usleep_range(150000, 160000);
606}
607
608/*
609 * Sets or clears force mode based on the dr_mode parameter.
610 */
611void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
612{
613 switch (hsotg->dr_mode) {
614 case USB_DR_MODE_HOST:
615 dwc2_force_mode(hsotg, true);
616 break;
617 case USB_DR_MODE_PERIPHERAL:
618 dwc2_force_mode(hsotg, false);
619 break;
620 case USB_DR_MODE_OTG:
621 dwc2_clear_force_mode(hsotg);
622 break;
623 default:
624 dev_warn(hsotg->dev, "%s() Invalid dr_mode=%d\n",
625 __func__, hsotg->dr_mode);
626 break;
627 }
628}
629
630/*
523 * Do core a soft reset of the core. Be careful with this because it 631 * Do core a soft reset of the core. Be careful with this because it
524 * resets all the internal state machines of the core. 632 * resets all the internal state machines of the core.
525 * 633 *
@@ -529,35 +637,12 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
529int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg) 637int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg)
530{ 638{
531 int retval; 639 int retval;
532 u32 gusbcfg;
533 640
534 retval = dwc2_core_reset(hsotg); 641 retval = dwc2_core_reset(hsotg);
535 if (retval) 642 if (retval)
536 return retval; 643 return retval;
537 644
538 if (hsotg->dr_mode == USB_DR_MODE_HOST) { 645 dwc2_force_dr_mode(hsotg);
539 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
540 gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
541 gusbcfg |= GUSBCFG_FORCEHOSTMODE;
542 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
543 } else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
544 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
545 gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
546 gusbcfg |= GUSBCFG_FORCEDEVMODE;
547 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
548 } else if (hsotg->dr_mode == USB_DR_MODE_OTG) {
549 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
550 gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
551 gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
552 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
553 }
554
555 /*
556 * NOTE: This long sleep is _very_ important, otherwise the core will
557 * not stay in host mode after a connector ID change!
558 */
559 usleep_range(150000, 160000);
560
561 return 0; 646 return 0;
562} 647}
563 648
@@ -3117,6 +3202,22 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
3117 dwc2_set_param_hibernation(hsotg, params->hibernation); 3202 dwc2_set_param_hibernation(hsotg, params->hibernation);
3118} 3203}
3119 3204
3205/*
3206 * Forces either host or device mode if the controller is not
3207 * currently in that mode.
3208 *
3209 * Returns true if the mode was forced.
3210 */
3211static bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host)
3212{
3213 if (host && dwc2_is_host_mode(hsotg))
3214 return false;
3215 else if (!host && dwc2_is_device_mode(hsotg))
3216 return false;
3217
3218 return dwc2_force_mode(hsotg, host);
3219}
3220
3120/** 3221/**
3121 * During device initialization, read various hardware configuration 3222 * During device initialization, read various hardware configuration
3122 * registers and interpret the contents. 3223 * registers and interpret the contents.