Felipe, > -----Original Message----- > From: linux-usb-owner@xxxxxxxxxxxxxxx [mailto:linux-usb- > owner@xxxxxxxxxxxxxxx] On Behalf Of Felipe Balbi > Sent: Thursday, January 21, 2010 7:04 PM > To: Greg KH > Cc: Linux USB Mailing List; Linux OMAP Mailing List; Gupta, Ajay Kumar; > Gadiyar, Anand; Felipe Balbi > Subject: [PATCH 1/7] usb: musb: Add context save and restore support > > From: Ajay Kumar Gupta <ajay.gupta@xxxxxx> > > Adding support for MUSB register save and restore during system > suspend and resume. > > Changes: > - Added musb_save/restore_context() functions > - Added platform specific musb_platform_save/restore_context() > to handle platform specific jobs. > - Maintaining BlackFin compatibility by adding read/write > functions for registers which are not available in BlackFin > > Tested system suspend and resume on OMAP3EVM board. > > Signed-off-by: Anand Gadiyar <gadiyar@xxxxxx> > Signed-off-by: Ajay Kumar Gupta <ajay.gupta@xxxxxx> > Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> > --- > drivers/usb/musb/musb_core.c | 146 > ++++++++++++++++++++++++++++++++++++++++++ > drivers/usb/musb/musb_core.h | 39 +++++++++++ > drivers/usb/musb/musb_regs.h | 90 ++++++++++++++++++++++++++ > drivers/usb/musb/omap2430.c | 16 +++++ > 4 files changed, 291 insertions(+), 0 deletions(-) > > diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c > index 074d380..2c53da7 100644 > --- a/drivers/usb/musb/musb_core.c > +++ b/drivers/usb/musb/musb_core.c > @@ -2167,6 +2167,148 @@ static int __exit musb_remove(struct > platform_device *pdev) > > #ifdef CONFIG_PM > > +static struct musb_context_registers musb_context; > + > +void musb_save_context(struct musb *musb) > +{ > + int i; > + void __iomem *musb_base = musb->mregs; > + > + if (is_host_enabled(musb)) { > + musb_context.frame = musb_readw(musb_base, MUSB_FRAME); > + musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE); > + } > + musb_context.power = musb_readb(musb_base, MUSB_POWER); > + musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); > + musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); > + musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); > + musb_context.index = musb_readb(musb_base, MUSB_INDEX); > + musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL); > + > + for (i = 0; i < MUSB_C_NUM_EPS; ++i) { > + musb_writeb(musb_base, MUSB_INDEX, i); > + musb_context.index_regs[i].txmaxp = > + musb_readw(musb_base, 0x10 + MUSB_TXMAXP); > + musb_context.index_regs[i].txcsr = > + musb_readw(musb_base, 0x10 + MUSB_TXCSR); > + musb_context.index_regs[i].rxmaxp = > + musb_readw(musb_base, 0x10 + MUSB_RXMAXP); > + musb_context.index_regs[i].rxcsr = > + musb_readw(musb_base, 0x10 + MUSB_RXCSR); > + > + if (musb->dyn_fifo) { dyn_fifo should be declared under struct musb. Otherwise it will give compilation errors. > + musb_context.index_regs[i].txfifoadd = > + musb_read_txfifoadd(musb_base); > + musb_context.index_regs[i].rxfifoadd = > + musb_read_rxfifoadd(musb_base); > + musb_context.index_regs[i].txfifosz = > + musb_read_txfifosz(musb_base); > + musb_context.index_regs[i].rxfifosz = > + musb_read_rxfifosz(musb_base); > + } > + if (is_host_enabled(musb)) { > + musb_context.index_regs[i].txtype = > + musb_readb(musb_base, 0x10 + MUSB_TXTYPE); > + musb_context.index_regs[i].txinterval = > + musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL); > + musb_context.index_regs[i].rxtype = > + musb_readb(musb_base, 0x10 + MUSB_RXTYPE); > + musb_context.index_regs[i].rxinterval = > + musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL); > + > + musb_context.index_regs[i].txfunaddr = > + musb_read_txfunaddr(musb_base, i); > + musb_context.index_regs[i].txhubaddr = > + musb_read_txhubaddr(musb_base, i); > + musb_context.index_regs[i].txhubport = > + musb_read_txhubport(musb_base, i); > + > + musb_context.index_regs[i].rxfunaddr = > + musb_read_rxfunaddr(musb_base, i); > + musb_context.index_regs[i].rxhubaddr = > + musb_read_rxhubaddr(musb_base, i); > + musb_context.index_regs[i].rxhubport = > + musb_read_rxhubport(musb_base, i); > + } > + } > + > + musb_writeb(musb_base, MUSB_INDEX, musb_context.index); > + > + musb_platform_save_context(&musb_context); > +} > + > +void musb_restore_context(struct musb *musb) > +{ > + int i; > + void __iomem *musb_base = musb->mregs; > + void __iomem *ep_target_regs; > + > + musb_platform_restore_context(&musb_context); > + > + if (is_host_enabled(musb)) { > + musb_writew(musb_base, MUSB_FRAME, musb_context.frame); > + musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode); > + } > + musb_writeb(musb_base, MUSB_POWER, musb_context.power); > + musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe); > + musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe); > + musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe); > + musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl); > + > + for (i = 0; i < MUSB_C_NUM_EPS; ++i) { > + musb_writeb(musb_base, MUSB_INDEX, i); > + musb_writew(musb_base, 0x10 + MUSB_TXMAXP, > + musb_context.index_regs[i].txmaxp); > + musb_writew(musb_base, 0x10 + MUSB_TXCSR, > + musb_context.index_regs[i].txcsr); > + musb_writew(musb_base, 0x10 + MUSB_RXMAXP, > + musb_context.index_regs[i].rxmaxp); > + musb_writew(musb_base, 0x10 + MUSB_RXCSR, > + musb_context.index_regs[i].rxcsr); > + > + if (musb->dyn_fifo) { > + musb_write_txfifosz(musb_base, > + musb_context.index_regs[i].txfifosz); > + musb_write_rxfifosz(musb_base, > + musb_context.index_regs[i].rxfifosz); > + musb_write_txfifoadd(musb_base, > + musb_context.index_regs[i].txfifoadd); > + musb_write_rxfifoadd(musb_base, > + musb_context.index_regs[i].rxfifoadd); > + } > + > + if (is_host_enabled(musb)) { > + musb_writeb(musb_base, 0x10 + MUSB_TXTYPE, > + musb_context.index_regs[i].txtype); > + musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL, > + musb_context.index_regs[i].txinterval); > + musb_writeb(musb_base, 0x10 + MUSB_RXTYPE, > + musb_context.index_regs[i].rxtype); > + musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL, > + > + musb_context.index_regs[i].rxinterval); > + musb_write_txfunaddr(musb_base, i, > + musb_context.index_regs[i].txfunaddr); > + musb_write_txhubaddr(musb_base, i, > + musb_context.index_regs[i].txhubaddr); > + musb_write_txhubport(musb_base, i, > + musb_context.index_regs[i].txhubport); > + > + ep_target_regs = > + musb_read_target_reg_base(i, musb_base); > + > + musb_write_rxfunaddr(ep_target_regs, > + musb_context.index_regs[i].rxfunaddr); > + musb_write_rxhubaddr(ep_target_regs, > + musb_context.index_regs[i].rxhubaddr); > + musb_write_rxhubport(ep_target_regs, > + musb_context.index_regs[i].rxhubport); > + } > + } > + > + musb_writeb(musb_base, MUSB_INDEX, musb_context.index); > +} > + > static int musb_suspend(struct device *dev) > { > struct platform_device *pdev = to_platform_device(dev); > @@ -2188,6 +2330,8 @@ static int musb_suspend(struct device *dev) > */ > } > > + musb_save_context(musb); > + > if (musb->set_clock) > musb->set_clock(musb->clock, 0); > else > @@ -2209,6 +2353,8 @@ static int musb_resume_noirq(struct device *dev) > else > clk_enable(musb->clock); > > + musb_restore_context(musb); > + > /* for static cmos like DaVinci, register values were preserved > * unless for some reason the whole soc powered down or the USB > * module got reset through the PSC (vs just being disabled). > diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h > index eaa0114..3d66c3e 100644 > --- a/drivers/usb/musb/musb_core.h > +++ b/drivers/usb/musb/musb_core.h > @@ -454,6 +454,45 @@ struct musb { > #endif > }; > > +#ifdef CONFIG_PM > +struct musb_csr_regs { > + /* FIFO registers */ > + u16 txmaxp, txcsr, rxmaxp, rxcsr; > + u16 rxfifoadd, txfifoadd; > + u8 txtype, txinterval, rxtype, rxinterval; > + u8 rxfifosz, txfifosz; > + u8 txfunaddr, txhubaddr, txhubport; > + u8 rxfunaddr, rxhubaddr, rxhubport; > +}; > + > +struct musb_context_registers { > + > +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) > + u32 otg_sysconfig, otg_forcestandby; > +#endif > + u8 power; > + u16 intrtxe, intrrxe; > + u8 intrusbe; > + u16 frame; > + u8 index, testmode; > + > + u8 devctl, misc; > + > + struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; > +}; > + > +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) > +extern void musb_platform_save_context(struct musb_context_registers > + *musb_context); > +extern void musb_platform_restore_context(struct musb_context_registers > + *musb_context); > +#else > +#define musb_platform_save_context(x) do {} while (0) > +#define musb_platform_restore_context(x) do {} while (0) > +#endif > + > +#endif > + > static inline void musb_set_vbus(struct musb *musb, int is_on) > { > musb->board_set_vbus(musb, is_on); > diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h > index 9a8621a..895fb05 100644 > --- a/drivers/usb/musb/musb_regs.h > +++ b/drivers/usb/musb/musb_regs.h > @@ -326,6 +326,26 @@ static inline void musb_write_rxfifoadd(void __iomem > *mbase, u16 c_off) > musb_writew(mbase, MUSB_RXFIFOADD, c_off); > } > > +static inline u8 musb_read_txfifosz(void __iomem *mbase) > +{ > + return musb_readb(mbase, MUSB_TXFIFOSZ); > +} > + > +static inline u16 musb_read_txfifoadd(void __iomem *mbase) > +{ > + return musb_readw(mbase, MUSB_TXFIFOADD); > +} > + > +static inline u8 musb_read_rxfifosz(void __iomem *mbase) > +{ > + return musb_readb(mbase, MUSB_RXFIFOSZ); > +} > + > +static inline u16 musb_read_rxfifoadd(void __iomem *mbase) > +{ > + return musb_readw(mbase, MUSB_RXFIFOADD); > +} > + > static inline u8 musb_read_configdata(void __iomem *mbase) > { > musb_writeb(mbase, MUSB_INDEX, 0); > @@ -381,6 +401,36 @@ static inline void musb_write_txhubport(void __iomem > *mbase, u8 epnum, > qh_h_port_reg); > } > > +static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) > +{ > + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, > MUSB_RXFUNCADDR)); > +} > + > +static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) > +{ > + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR)); > +} > + > +static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) > +{ > + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT)); > +} > + > +static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) > +{ > + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, > MUSB_TXFUNCADDR)); > +} > + > +static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) > +{ > + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR)); > +} > + > +static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum) > +{ > + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT)); > +} > + > #else /* CONFIG_BLACKFIN */ > > #define USB_BASE USB_FADDR > @@ -460,6 +510,22 @@ static inline void musb_write_rxfifoadd(void __iomem > *mbase, u16 c_off) > { > } > > +static inline u8 musb_read_txfifosz(void __iomem *mbase) > +{ > +} > + > +static inline u16 musb_read_txfifoadd(void __iomem *mbase) > +{ > +} > + > +static inline u8 musb_read_rxfifosz(void __iomem *mbase) > +{ > +} > + > +static inline u16 musb_read_rxfifoadd(void __iomem *mbase) > +{ > +} > + > static inline u8 musb_read_configdata(void __iomem *mbase) > { > return 0; > @@ -505,6 +571,30 @@ static inline void musb_write_txhubport(void __iomem > *mbase, u8 epnum, > { > } > > +static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) > +{ > +} > + > +static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) > +{ > +} > + > +static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) > +{ > +} > + > +static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) > +{ > +} > + > +static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) > +{ > +} > + > +static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum) > +{ > +} > + > #endif /* CONFIG_BLACKFIN */ > > #endif /* __MUSB_REGS_H__ */ > diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c > index 83beeac..15a3f27 100644 > --- a/drivers/usb/musb/omap2430.c > +++ b/drivers/usb/musb/omap2430.c > @@ -255,6 +255,22 @@ int __init musb_platform_init(struct musb *musb) > return 0; > } > > +#ifdef CONFIG_PM > +void musb_platform_save_context(struct musb_context_registers > + *musb_context) > +{ > + musb_context->otg_sysconfig = omap_readl(OTG_SYSCONFIG); > + musb_context->otg_forcestandby = omap_readl(OTG_FORCESTDBY); > +} > + > +void musb_platform_restore_context(struct musb_context_registers > + *musb_context) > +{ > + omap_writel(musb_context->otg_sysconfig, OTG_SYSCONFIG); > + omap_writel(musb_context->otg_forcestandby, OTG_FORCESTDBY); > +} > +#endif > + > int musb_platform_suspend(struct musb *musb) > { > u32 l; > -- > 1.6.6.rc0 > > -- > 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 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html