diff options
| author | Sergey Lapin <slapin@ossfans.org> | 2009-10-13 17:30:38 +0400 |
|---|---|---|
| committer | Sergey Lapin <slapin@ossfans.org> | 2009-10-13 17:30:38 +0400 |
| commit | c9d89f888ec69245c56358b454f37cffd8bb87ac (patch) | |
| tree | 10d3aefa0fc1c74baeccbc456ce16e0d42816f17 /recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch | |
| parent | 43653cf44fc541bd55cb094392444a7faa7bb3be (diff) | |
| parent | 925dea6086bd5f7479eda0226f32bcd46ba025a1 (diff) | |
Merge branch 'org.openembedded.dev' of git@git.openembedded.net:openembedded into org.openembedded.dev
Diffstat (limited to 'recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch')
| -rw-r--r-- | recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch b/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch new file mode 100644 index 0000000000..3bf368c79f --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch @@ -0,0 +1,422 @@ +From 2b65475db2df6c0b7ebb8960e77e3aaf27147bda Mon Sep 17 00:00:00 2001 +From: Ajay Kumar Gupta <ajay.gupta@ti.com> +Date: Thu, 3 Sep 2009 17:07:40 +0530 +Subject: [PATCH 15/16] musb: Add context save and restore support + +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@ti.com> +Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> +--- + drivers/usb/musb/musb_core.c | 157 +++++++++++++++++++++++++++++++++++++++++- + drivers/usb/musb/musb_core.h | 39 ++++++++++ + drivers/usb/musb/musb_regs.h | 90 ++++++++++++++++++++++++ + drivers/usb/musb/omap2430.c | 16 ++++ + 4 files changed, 300 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index f5ca435..0de19da 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -2165,20 +2165,169 @@ static int __devexit musb_remove(struct platform_device *pdev) + + #ifdef CONFIG_PM + ++static struct musb_context_registers musb_context; ++ ++void musb_save_context(void __iomem *musb_base) ++{ ++ int i; ++ ++ musb_platform_save_context(&musb_context); ++ ++ musb_context.faddr = musb_readb(musb_base, MUSB_FADDR); ++ musb_context.power = musb_readb(musb_base, MUSB_POWER); ++ musb_context.intrtx = musb_readw(musb_base, MUSB_INTRTX); ++ musb_context.intrrx = musb_readw(musb_base, MUSB_INTRRX); ++ musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); ++ musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); ++ musb_context.intrusb = musb_readb(musb_base, MUSB_INTRUSB); ++ musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); ++ musb_context.frame = musb_readw(musb_base, MUSB_FRAME); ++ musb_context.index = musb_readb(musb_base, MUSB_INDEX); ++ musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE); ++ 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); ++ musb_context.index_regs[i].rxcount = ++ musb_readw(musb_base, 0x10 + MUSB_RXCOUNT); ++ 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].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); ++ ++ 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); ++} ++ ++void musb_restore_context(void __iomem *musb_base) ++{ ++ int i; ++ void __iomem *ep_target_regs; ++ ++ musb_writeb(musb_base, MUSB_FADDR, musb_context.faddr); ++ musb_writeb(musb_base, MUSB_POWER, musb_context.power); ++ musb_writew(musb_base, MUSB_INTRTX, musb_context.intrtx); ++ musb_writew(musb_base, MUSB_INTRRX, musb_context.intrrx); ++ musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe); ++ musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe); ++ musb_writeb(musb_base, MUSB_INTRUSB, musb_context.intrusb); ++ musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe); ++ musb_writew(musb_base, MUSB_FRAME, musb_context.frame); ++ musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode); ++ 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); ++ musb_writew(musb_base, 0x10 + MUSB_RXCOUNT, ++ musb_context.index_regs[i].rxcount); ++ 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_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); ++ ++ 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); ++ ++ musb_platform_restore_context(&musb_context); ++} ++ + static int musb_suspend(struct platform_device *pdev, pm_message_t message) + { + unsigned long flags; + struct musb *musb = dev_to_musb(&pdev->dev); ++ u8 reg; + + if (!musb->clock) + return 0; + + spin_lock_irqsave(&musb->lock, flags); + ++ musb_save_context(musb->mregs); ++ + if (is_peripheral_active(musb)) { +- /* FIXME force disconnect unless we know USB will wake +- * the system up quickly enough to respond ... ++ /* System is entering into suspend where gadget would not be ++ * able to respond to host and thus it will be in an unknown ++ * state for host.Re-enumemation of gadget is required after ++ * resume to make the gadget functional thus doing a force ++ * disconnect. + */ ++ reg = musb_readb(musb->mregs, MUSB_POWER); ++ reg &= ~MUSB_POWER_SOFTCONN; ++ musb_writeb(musb->mregs, MUSB_POWER, reg); ++ + } else if (is_host_active(musb)) { + /* we know all the children are suspended; sometimes + * they will even be wakeup-enabled. +@@ -2205,6 +2354,8 @@ static int musb_resume_early(struct platform_device *pdev) + else + clk_enable(musb->clock); + ++ musb_restore_context(musb->mregs); ++ + /* 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). +@@ -2215,6 +2366,8 @@ static int musb_resume_early(struct platform_device *pdev) + #else + #define musb_suspend NULL + #define musb_resume_early NULL ++#define musb_save_context do {} while (0) ++#define musb_restore_context do {} while (0) + #endif + + static struct platform_driver musb_driver = { +diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h +index b0b4fbd..4568a8e 100644 +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -446,6 +446,45 @@ struct musb { + #endif + }; + ++#ifdef CONFIG_PM ++struct musb_csr_regs { ++ /* FIFO registers */ ++ u16 txmaxp, txcsr, rxmaxp, rxcsr, rxcount; ++ 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) ++ u32 otg_sysconfig, otg_forcestandby; ++#endif ++ u8 faddr, power; ++ u16 intrtx, intrrx, intrtxe, intrrxe; ++ u8 intrusb, 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 fbfd3fd..a8e19da 100644 +--- a/drivers/usb/musb/musb_regs.h ++++ b/drivers/usb/musb/musb_regs.h +@@ -321,6 +321,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); +@@ -376,6 +396,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 +@@ -464,6 +514,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; +@@ -509,6 +575,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 3487520..84af3b3 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.2.4 + |
