RE: [PATCH 1/7] usb: musb: Add context save and restore support

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

 



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

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux