On Tue, Nov 20, 2012 at 02:44:35PM +0200, Alexander Shishkin wrote: > Peter Chen <peter.chen@xxxxxxxxxxxxx> writes: > > > diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h > > index d738603..d32f932 100644 > > --- a/drivers/usb/chipidea/ci.h > > +++ b/drivers/usb/chipidea/ci.h > > @@ -139,6 +139,7 @@ struct ci13xxx { > > enum ci_role role; > > bool is_otg; > > struct work_struct work; > > + struct delayed_work dwork; > > struct workqueue_struct *wq; > > > > struct dma_pool *qh_pool; > > @@ -164,6 +165,11 @@ struct ci13xxx { > > bool global_phy; > > struct usb_phy *transceiver; > > struct usb_hcd *hcd; > > + /* events handled at ci_role_work */ > > +#define ID 0 > > +#define B_SESS_VALID 1 > > + unsigned long events; > > I would still like bools or ints here. events will be as parameter for set_bit, for function set_bit it is define like below: set_bit(unsigned int nr, volatile unsigned long *addr) > > > > /* Controller register map */ > > static uintptr_t ci_regs_nolpm[] = { > > @@ -264,25 +265,131 @@ static enum ci_role ci_otg_role(struct ci13xxx *ci) > > return role; > > } > > > > +#define CI_WAIT_VBUS_STABLE_TIMEOUT 500 > > /** > > - * ci_role_work - perform role changing based on ID pin > > - * @work: work struct > > + * ci_wait_vbus_stable > > + * When usb role switches, we need to turn on/off internal vbus > > + * regulaor, sometimes, the real vbus value may not lower fast > > + * enough due to capacitance, and we do want the vbus lower > > + * than 0.8v if it is device mode, and higher than 4.4v, if it > > + * is host mode. > > + * > > + * @low: true, Wait vbus lower than OTGSC_BSV > > + * : false, Wait vbus higher than OTGSC_AVV > > */ > > -static void ci_role_work(struct work_struct *work) > > +static void ci_wait_vbus_stable(struct ci13xxx *ci, bool low) > > +{ > > + unsigned long timeout; > > + u32 otgsc = hw_read(ci, OP_OTGSC, ~0); > > + > > + timeout = jiffies + CI_WAIT_VBUS_STABLE_TIMEOUT; > > + > > + if (low) { > > + while (otgsc & OTGSC_BSV) { > > + if (time_after(jiffies, timeout)) { > > + dev_err(ci->dev, "wait vbus lower than\ > > + OTGSC_BSV timeout!\n"); > > + return; > > + } > > + msleep(20); > > + otgsc = hw_read(ci, OP_OTGSC, ~0); > > + } > > + } else { > > + while (!(otgsc & OTGSC_AVV)) { > > + if (time_after(jiffies, timeout)) { > > + dev_err(ci->dev, "wait vbus higher than\ > > + OTGSC_AVV timeout!\n"); > > + return; > > + } > > + msleep(20); > > + otgsc = hw_read(ci, OP_OTGSC, ~0); > > + } > > + > > + } > > +} > > How about > > static int hw_wait_reg(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask, > unsigned long timeout) > { > unsigned long elapse = jiffies + timeout; > > while (hw_read(ci, reg, mask)) { > if (time_after(jiffies, elapse)) { > dev_err(ci->dev, "timeout waiting for %08x in %d\n", > mask, reg); > return -ETIMEDOUT; > } > msleep(20); > } > > return 0; > } > > and then also checking if we timed out or everything's fine. I can use this API, how can this API consolidate both of the case (<OTGSC_BSV and >OTGSC_AVV)? > > Regards, > -- > Alex > -- > 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 > -- 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