summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch
diff options
context:
space:
mode:
authorSergey Lapin <slapin@ossfans.org>2009-10-13 17:30:38 +0400
committerSergey Lapin <slapin@ossfans.org>2009-10-13 17:30:38 +0400
commitc9d89f888ec69245c56358b454f37cffd8bb87ac (patch)
tree10d3aefa0fc1c74baeccbc456ce16e0d42816f17 /recipes/linux/linux-omap-2.6.31/usb/0015-musb-Add-context-save-and-restore-support.patch
parent43653cf44fc541bd55cb094392444a7faa7bb3be (diff)
parent925dea6086bd5f7479eda0226f32bcd46ba025a1 (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.patch422
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
+