Re: [PATCH 1/1] usb: chipidea: host: add .bus_suspend quirk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Dec 29, 2014 at 10:44:28AM -0500, Alan Stern wrote:
> On Mon, 29 Dec 2014, Peter Chen wrote:
> 
> > For chipidea, its resume sequence is not-EHCI compatible, see
> > below description for FPR at portsc. So in order to send SoF in
> > time for remote wakeup sequence(within 3ms), the RUN/STOP bit must
> > be set before the resume signal is ended.
> > 
> > Force Port Resume - RW. Default = 0b.
> > 1= Resume detected/driven on port.
> > 0=No resume (K-state) detected/driven on port.
> > Host mode:
> > Software sets this bit to one to drive resume signaling. The Controller sets this bit to '1' if
> > a J-to-K transition is detected while the port is in the Suspend state. When this bit
> > transitions to a '1' because a J-to-K transition is detected, the Port Change Detect bit in
> > the USBSTS register is also set to '1'. This bit will automatically change to '0' after the
> > resume sequence is complete. This behavior is different from EHCI where the controller
> > driver is required to set this bit to a '0' after the resume duration is timed in the driver.
> > Note that when the controller owns the port, the resume sequence follows the defined
> > 
> > sequence documented in the USB Specification Revision 2.0. The resume signaling
> > (Full-speed 'K') is driven on the port as long as this bit remains a '1'. This bit will remain
> > a '1' until the port has switched to idle. Writing a '0' has no affect because the port
> > controller will time the resume operation, clear the bit and the port control state switches
> > to HS or FS idle.
> > This field is '0' if Port Power(PP) is '0' in host mode.
> > 
> > This bit is not-EHCI compatible.
> 
> If you really want to do this, go ahead.  But see below.
> 

Any other solutions for this (Let the SoF send in time within 3ms after resume
signal has ended)?

> > Signed-off-by: Peter Chen <peter.chen@xxxxxxxxxxxxx>
> > ---
> >  drivers/usb/chipidea/host.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 47 insertions(+)
> > 
> > diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> > index 48731d0..4f2fd3b 100644
> > --- a/drivers/usb/chipidea/host.c
> > +++ b/drivers/usb/chipidea/host.c
> > @@ -33,6 +33,7 @@
> >  #include "host.h"
> >  
> >  static struct hc_driver __read_mostly ci_ehci_hc_driver;
> > +static int (*orig_bus_suspend)(struct usb_hcd *hcd);
> >  
> >  struct ehci_ci_priv {
> >  	struct regulator *reg_vbus;
> > @@ -158,6 +159,50 @@ void ci_hdrc_host_destroy(struct ci_hdrc *ci)
> >  		host_stop(ci);
> >  }
> >  
> > +static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
> > +{
> > +	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> > +	int port;
> > +	u32 tmp;
> > +
> > +	int ret = orig_bus_suspend(hcd);
> > +
> > +	if (ret)
> > +		return ret;
> > +
> > +	port = HCS_N_PORTS(ehci->hcs_params);
> > +	while (port--) {
> > +		u32 __iomem *reg = &ehci->regs->port_status[port];
> > +		u32 portsc = ehci_readl(ehci, reg);
> > +
> > +		if ((portsc & PORT_CONNECT) &&
> > +			hcd->self.root_hub->do_remote_wakeup) {
> 
> This is not the right test.  You want to know whether remote wakeup is 
> enabled for any downstream devices, not whether it is enabled for the 
> root hub.
> 
> It would be simpler to get rid of this test, and always turn on the
> CMD_RUN bit.
> 

What I had thought was:
- There is device on the root hub.
- If the user wants to enable downstream device's remote wakeup, he must
enable root hub's as well

Yes, it is not the right test, I will use simpler, and only add
connection judgement.

> > +			/*
> > +			 * For chipidea, the resume signal will be ended
> > +			 * automatically, so for remote wakeup case, the
> > +			 * usbcmd.rs may not be set before the resume has
> > +			 * ended if other resume paths consumes too much
> > +			 * time (~23ms-24ms), in that case, the SOF will not
> > +			 * send out within 3ms after resume ends, then the
> > +			 * device will enter suspend again.
> > +			 */
> > +			ehci_dbg(ehci, "Remote wakeup is enabled for device\n");
> > +
> > +			tmp = ehci_readl(ehci, &ehci->regs->command);
> > +			tmp |= CMD_RUN;
> > +			ehci_writel(ehci, tmp, &ehci->regs->command);
> 
> At this point, the bus isn't suspended any more.  It is running.
> 

The bus state is 'J' since the portsc.suspendM = 1, so the bus is
suspended, correct?

> > +			/*
> > +			 * It needs a short delay between set RUNSTOP
> > +			 * and set PHCD.
> > +			 */
> > +			udelay(125);
> 
> Wouldn't it be better to do a sleep instead of a delay?
> 

Sure, will change to usleep_range.

> > +			break;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  int ci_hdrc_host_init(struct ci_hdrc *ci)
> >  {
> >  	struct ci_role_driver *rdrv;
> > @@ -176,6 +221,8 @@ int ci_hdrc_host_init(struct ci_hdrc *ci)
> >  	ci->roles[CI_ROLE_HOST] = rdrv;
> >  
> >  	ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
> > +	orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
> > +	ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
> >  
> >  	return 0;
> >  }
> 
> Alan Stern
> 

-- 

Best Regards,
Peter Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux