On Fri, Mar 14, 2014 at 12:48:18PM +0800, Li Jun wrote: > From: Li Jun <b47624@xxxxxxxxxxxxx> > > Use a more general way to read and write otgsc register. > > Signed-off-by: Li Jun <b47624@xxxxxxxxxxxxx> > --- > > Changes for v2: > Use one API for otgsc regiter write, and add mask as input parameter > for otgsc register target bits read. > > drivers/usb/chipidea/core.c | 16 ++++++++++------ > drivers/usb/chipidea/otg.c | 39 ++++++++++++++++++++++++++++++--------- > drivers/usb/chipidea/otg.h | 18 ++---------------- > drivers/usb/chipidea/udc.c | 17 ++++++++++------- > 4 files changed, 52 insertions(+), 38 deletions(-) > > diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c > index ca6831c..bc9dcab 100644 > --- a/drivers/usb/chipidea/core.c > +++ b/drivers/usb/chipidea/core.c > @@ -360,7 +360,7 @@ static irqreturn_t ci_irq(int irq, void *data) > u32 otgsc = 0; > > if (ci->is_otg) > - otgsc = hw_read(ci, OP_OTGSC, ~0); > + otgsc = hw_read_otgsc_bits(ci, ~0); > > /* > * Handle id change interrupt, it indicates device/host function > @@ -368,7 +368,8 @@ static irqreturn_t ci_irq(int irq, void *data) > */ > if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) { > ci->id_event = true; > - ci_clear_otg_interrupt(ci, OTGSC_IDIS); > + /* Clear ID change irq status */ > + hw_set_otgsc_bits(ci, OTGSC_IDIS, 0); > disable_irq_nosync(ci->irq); > queue_work(ci->wq, &ci->work); > return IRQ_HANDLED; > @@ -380,7 +381,8 @@ static irqreturn_t ci_irq(int irq, void *data) > */ > if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) { > ci->b_sess_valid_event = true; > - ci_clear_otg_interrupt(ci, OTGSC_BSVIS); > + /* Clear BSV irq */ > + hw_set_otgsc_bits(ci, OTGSC_BSVIS, 0); > disable_irq_nosync(ci->irq); > queue_work(ci->wq, &ci->work); > return IRQ_HANDLED; > @@ -502,8 +504,9 @@ static void ci_get_otg_capable(struct ci_hdrc *ci) > == (DCCPARAMS_DC | DCCPARAMS_HC)); > if (ci->is_otg) { > dev_dbg(ci->dev, "It is OTG capable controller\n"); > - ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS); > - ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS); > + /* Disable and clear all OTG irq */ > + hw_set_otgsc_bits(ci, > + OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS, 0); > } > } > > @@ -617,7 +620,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) > */ > mdelay(2); > ci->role = ci_otg_role(ci); > - ci_enable_otg_interrupt(ci, OTGSC_IDIE); > + /* Enable ID change irq */ > + hw_set_otgsc_bits(ci, OTGSC_IDIE, OTGSC_IDIE); > } else { > /* > * If the controller is not OTG capable, but support > diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c > index 39bd7ec..e20101f 100644 > --- a/drivers/usb/chipidea/otg.c > +++ b/drivers/usb/chipidea/otg.c > @@ -24,13 +24,38 @@ > #include "otg.h" > > /** > + * hw_read_otgsc_bits returns otgsc register bits value. > + * bits: target bits to be read. > + * This function returns register content > + */ > +u32 hw_read_otgsc_bits(struct ci_hdrc *ci, u32 bits) > +{ > + return hw_read(ci, OP_OTGSC, bits); > +} > + Using the name hw_read_otgsc please, the usage of this API is the same of hw_read, just the mask fixed. > +/** > + * hw_set_otgsc_bits updates target bits of OTGSC register. > + * - bits: the target bits to be updated. > + * - val: the target value to be achieved of those bits. > + * note: for any bits within OTGSC_INT_STATUS_BITS, > + * to set them to be 0(clear irq status), > + * just set val to be 0 like other bits. > + */ > +void hw_set_otgsc_bits(struct ci_hdrc *ci, u32 bits, u32 val) > +{ > + u32 otg_int_clear_bits = bits & ~val & OTGSC_INT_STATUS_BITS; > + > + hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, > + val | otg_int_clear_bits); > +} > + Sorry, it is too complicated. I just want the hw_write_otgsc is the same usage with hw_write, write to "0" is really write to 0, write to "1" is really write to "1". The reason we introduce hw_write_otgsc is just wants the user's life to be easier, they doesn't need to consider the OTGSC_INT_STATUS_BITS is cleared unexpected. Peter > +/** > * ci_otg_role - pick role based on ID pin state > * @ci: the controller > */ > enum ci_role ci_otg_role(struct ci_hdrc *ci) > { > - u32 sts = hw_read(ci, OP_OTGSC, ~0); > - enum ci_role role = sts & OTGSC_ID > + enum ci_role role = hw_read_otgsc_bits(ci, OTGSC_ID) > ? CI_ROLE_GADGET > : CI_ROLE_HOST; > > @@ -39,14 +64,10 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci) > > void ci_handle_vbus_change(struct ci_hdrc *ci) > { > - u32 otgsc; > - > if (!ci->is_otg) > return; > > - otgsc = hw_read(ci, OP_OTGSC, ~0); > - > - if (otgsc & OTGSC_BSV) > + if (hw_read_otgsc_bits(ci, OTGSC_BSV)) > usb_gadget_vbus_connect(&ci->gadget); > else > usb_gadget_vbus_disconnect(&ci->gadget); > @@ -115,6 +136,6 @@ void ci_hdrc_otg_destroy(struct ci_hdrc *ci) > flush_workqueue(ci->wq); > destroy_workqueue(ci->wq); > } > - ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS); > - ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS); > + /* Disable all OTG irq and clear status */ > + hw_set_otgsc_bits(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS, 0); > } > diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h > index 449bee0..149a457 100644 > --- a/drivers/usb/chipidea/otg.h > +++ b/drivers/usb/chipidea/otg.h > @@ -11,22 +11,8 @@ > #ifndef __DRIVERS_USB_CHIPIDEA_OTG_H > #define __DRIVERS_USB_CHIPIDEA_OTG_H > > -static inline void ci_clear_otg_interrupt(struct ci_hdrc *ci, u32 bits) > -{ > - /* Only clear request bits */ > - hw_write(ci, OP_OTGSC, OTGSC_INT_STATUS_BITS, bits); > -} > - > -static inline void ci_enable_otg_interrupt(struct ci_hdrc *ci, u32 bits) > -{ > - hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, bits); > -} > - > -static inline void ci_disable_otg_interrupt(struct ci_hdrc *ci, u32 bits) > -{ > - hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, 0); > -} > - > +u32 hw_read_otgsc_bits(struct ci_hdrc *ci, u32 bits); > +void hw_set_otgsc_bits(struct ci_hdrc *ci, u32 bits, u32 val); > int ci_hdrc_otg_init(struct ci_hdrc *ci); > void ci_hdrc_otg_destroy(struct ci_hdrc *ci); > enum ci_role ci_otg_role(struct ci_hdrc *ci); > diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c > index 7739c64..3bc28d4 100644 > --- a/drivers/usb/chipidea/udc.c > +++ b/drivers/usb/chipidea/udc.c > @@ -1844,8 +1844,10 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci) > static int udc_id_switch_for_device(struct ci_hdrc *ci) > { > if (ci->is_otg) { > - ci_clear_otg_interrupt(ci, OTGSC_BSVIS); > - ci_enable_otg_interrupt(ci, OTGSC_BSVIE); > + /* Clear BSV irq */ > + hw_set_otgsc_bits(ci, OTGSC_BSVIS, 0); > + /* Enable BSV irq */ > + hw_set_otgsc_bits(ci, OTGSC_BSVIE, OTGSC_BSVIE); > } > > return 0; > @@ -1853,11 +1855,12 @@ static int udc_id_switch_for_device(struct ci_hdrc *ci) > > static void udc_id_switch_for_host(struct ci_hdrc *ci) > { > - if (ci->is_otg) { > - /* host doesn't care B_SESSION_VALID event */ > - ci_clear_otg_interrupt(ci, OTGSC_BSVIS); > - ci_disable_otg_interrupt(ci, OTGSC_BSVIE); > - } > + /* > + * host doesn't care B_SESSION_VALID event > + * so clear and disbale BSV irq > + */ > + if (ci->is_otg) > + hw_set_otgsc_bits(ci, OTGSC_BSVIE | OTGSC_BSVIS, 0); > } > > /** > -- > 1.7.9.5 > > -- 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