power = musb_readb(musb->mregs, MUSB_POWER);
power &= ~MUSB_POWER_RESUME;
musb_dbg(musb, "root port resume stopped, power %02x", power);
musb_writeb(musb->mregs, MUSB_POWER, power);
/* NOTE: this doesn't necessarily put PHY into low power mode, *turningoffitsclock;that'safunctionofPHYintegrationand *MUSB_POWER_ENSUSPEND.PHYmayneedaclock(sigh)todetect *SE0changingtoconnect(J)orwakeup(K)states.
*/
power = musb_readb(mbase, MUSB_POWER); if (do_suspend) { int retries = 10000;
if (power & MUSB_POWER_RESUME) return -EBUSY;
if (!(power & MUSB_POWER_SUSPENDM)) {
power |= MUSB_POWER_SUSPENDM;
musb_writeb(mbase, MUSB_POWER, power);
/* Needed for OPT A tests */
power = musb_readb(mbase, MUSB_POWER); while (power & MUSB_POWER_SUSPENDM) {
power = musb_readb(mbase, MUSB_POWER); if (retries-- < 1) break;
}
}
musb_dbg(musb, "Root port suspended, power %02x", power);
if (musb_get_state(musb) == OTG_STATE_B_IDLE) {
musb_dbg(musb, "HNP: Returning from HNP; no hub reset from b_idle");
musb->port1_status &= ~USB_PORT_STAT_RESET; return;
}
if (!is_host_active(musb)) return;
/* NOTE: caller guarantees it will turn off the reset when *theappropriateamountoftimehaspassed
*/
power = musb_readb(mbase, MUSB_POWER); if (do_reset) { /* *IfRESUMEisset,wemustmakesureitstaysminimum20ms. *ThenwemustclearRESUMEandwaitabittoletmusbstart *generatingSOFs.Ifwedon'tdothis,OPTHSA6.8tests *failwith"Error!DidnotreceiveanSOFbeforesuspend *detected".
*/ if (power & MUSB_POWER_RESUME) { long remain = (unsignedlong) musb->rh_timer - jiffies;
if (musb->rh_timer > 0 && remain > 0) { /* take into account the minimum delay after resume */
schedule_delayed_work(
&musb->deassert_reset_work, remain); return;
}
musb_writeb(mbase, MUSB_POWER,
power & ~MUSB_POWER_RESUME);
/* Give the core 1 ms to clear MUSB_POWER_RESUME */
schedule_delayed_work(&musb->deassert_reset_work,
msecs_to_jiffies(1)); return;
}
power &= 0xf0;
musb_writeb(mbase, MUSB_POWER,
power | MUSB_POWER_RESET);
/* Caller may or may not hold musb->lock */ int musb_hub_status_data(struct usb_hcd *hcd, char *buf)
{ struct musb *musb = hcd_to_musb(hcd); int retval = 0;
/* called in_irq() via usb_hcd_poll_rh_status() */ if (musb->port1_status & 0xffff0000) {
*buf = 0x02;
retval = 1;
} return retval;
}
/* port change status is more interesting */
musb_dbg(musb, "port status %08x", musb->port1_status); break; case SetPortFeature: if ((wIndex & 0xff) != 1) goto error;
switch (wValue) { case USB_PORT_FEAT_POWER: /* NOTE: this controller has a strange state machine *thatinvolves"requestingsessions"accordingto *magicsideeffectsfromincompletely-described *rulesaboutstartup... * *Thiscalliswhatreallystartsthehostmode;be *verycarefulaboutsideeffectsifyoureorderany *initializationlogic,e.g.forOTG,orchangeany *logicrelatingtoVBUSpower-up.
*/ if (!hcd->self.is_b_host && musb_has_gadget(musb))
start_musb = true; break; case USB_PORT_FEAT_RESET:
musb_port_reset(musb, true); break; case USB_PORT_FEAT_SUSPEND:
musb_port_suspend(musb, true); break; case USB_PORT_FEAT_TEST: if (unlikely(is_host_active(musb))) goto error;
wIndex >>= 8; switch (wIndex) { case USB_TEST_J:
pr_debug("USB_TEST_J\n");
temp = MUSB_TEST_J; break; case USB_TEST_K:
pr_debug("USB_TEST_K\n");
temp = MUSB_TEST_K; break; case USB_TEST_SE0_NAK:
pr_debug("USB_TEST_SE0_NAK\n");
temp = MUSB_TEST_SE0_NAK; break; case USB_TEST_PACKET:
pr_debug("USB_TEST_PACKET\n");
temp = MUSB_TEST_PACKET;
musb_load_testpacket(musb); break; case USB_TEST_FORCE_ENABLE:
pr_debug("USB_TEST_FORCE_ENABLE\n");
temp = MUSB_TEST_FORCE_HOST
| MUSB_TEST_FORCE_HS;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.