split hw glue layer to its own platform_device, which is a parent of musb-hdrc platform_device. we can now handle suspend/resume, PM, clocks and context save/restore in a better and local fashion which won't touch other archs. NYET-Signed-off-by: Felipe Balbi <balbi@xxxxxx> --- arch/arm/mach-omap2/usb-musb.c | 2 +- arch/arm/plat-omap/include/plat/usb.h | 1 + drivers/usb/musb/Makefile | 41 ++---- drivers/usb/musb/musb_core.c | 239 +------------------------------- drivers/usb/musb/musb_core.h | 46 ++++-- drivers/usb/musb/omap2430.c | 252 ++++++++++++++++++++++----------- 6 files changed, 210 insertions(+), 371 deletions(-) diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 33a5cde..2ce9b71 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -74,7 +74,7 @@ static struct musb_hdrc_platform_data musb_plat = { static u64 musb_dmamask = DMA_BIT_MASK(32); static struct platform_device musb_device = { - .name = "musb_hdrc", + .name = "omap-musb-hdrc", .id = -1, .dev = { .dma_mask = &musb_dmamask, diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 2a9427c..ba622a8 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -69,6 +69,7 @@ struct omap_musb_board_data { u8 mode; u16 power; unsigned extvbus:1; + struct musb_hdrc_platform_data *musb; }; enum musb_interface {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI}; diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 9705f71..99d5a7f 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -2,37 +2,7 @@ # for USB OTG silicon based on Mentor Graphics INVENTRA designs # -musb_hdrc-objs := musb_core.o - -obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o - -ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y) - musb_hdrc-objs += davinci.o -endif - -ifeq ($(CONFIG_USB_TUSB6010),y) - musb_hdrc-objs += tusb6010.o -endif - -ifeq ($(CONFIG_ARCH_OMAP2430),y) - musb_hdrc-objs += omap2430.o -endif - -ifeq ($(CONFIG_ARCH_OMAP3430),y) - musb_hdrc-objs += omap2430.o -endif - -ifeq ($(CONFIG_ARCH_OMAP4),y) - musb_hdrc-objs += omap2430.o -endif - -ifeq ($(CONFIG_BF54x),y) - musb_hdrc-objs += blackfin.o -endif - -ifeq ($(CONFIG_BF52x),y) - musb_hdrc-objs += blackfin.o -endif +musb_hdrc-objs = musb_core.o ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y) musb_hdrc-objs += musb_gadget_ep0.o musb_gadget.o @@ -46,6 +16,15 @@ ifeq ($(CONFIG_DEBUG_FS),y) musb_hdrc-objs += musb_debugfs.o endif +obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o +obj-$(CONFIG_ARCH_DAVINCI_DMx) += davinci.o +obj-$(CONFIG_USB_TUSB6010) += tusb6010.o +obj-$(CONFIG_ARCH_OMAP2430) += omap2430.o +obj-$(CONFIG_ARCH_OMAP3430) += omap2430.o +obj-$(CONFIG_ARCH_OMAP4) += omap2430.o +obj-$(CONFIG_BF54x) += blackfin.o +obj-$(CONFIG_BF52x) += blackfin.o + # the kconfig must guarantee that only one of the # possible I/O schemes will be enabled at a time ... # PIO only, or DMA (several potential schemes). diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 540c766..976345c5 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -984,7 +984,6 @@ void musb_start(struct musb *musb) if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) musb->is_active = 1; } - musb_platform_enable(musb); musb_writeb(regs, MUSB_DEVCTL, devctl); } @@ -1019,7 +1018,6 @@ static void musb_generic_disable(struct musb *musb) void musb_stop(struct musb *musb) { /* stop IRQs, timers, ... */ - musb_platform_disable(musb); musb_generic_disable(musb); DBG(3, "HDRC disabled\n"); @@ -1033,22 +1031,6 @@ void musb_stop(struct musb *musb) musb_platform_try_idle(musb, 0); } -static void musb_shutdown(struct platform_device *pdev) -{ - struct musb *musb = dev_to_musb(&pdev->dev); - unsigned long flags; - - spin_lock_irqsave(&musb->lock, flags); - musb_platform_disable(musb); - musb_generic_disable(musb); - if (musb->clock) - clk_put(musb->clock); - spin_unlock_irqrestore(&musb->lock, flags); - - /* FIXME power down */ -} - - /*-------------------------------------------------------------------------*/ /* @@ -2022,13 +2004,9 @@ bad_config: * isp1504, non-OTG, etc) mostly hooking up through ULPI. */ musb->isr = generic_interrupt; - status = musb_platform_init(musb, plat->board_data); - if (status < 0) - goto fail2; - if (!musb->isr) { status = -ENODEV; - goto fail3; + goto fail2; } if (!musb->xceiv->io_ops) { @@ -2051,7 +2029,6 @@ bad_config: dev->dma_mask = NULL; /* be sure interrupts are disabled before connecting ISR */ - musb_platform_disable(musb); musb_generic_disable(musb); /* setup musb parts of the core (especially endpoints) */ @@ -2172,7 +2149,6 @@ fail4: fail3: if (musb->irq_wake) device_init_wakeup(dev, 0); - musb_platform_exit(musb); fail2: if (musb->clock) @@ -2240,13 +2216,11 @@ static int __exit musb_remove(struct platform_device *pdev) * - OTG mode: both roles are deactivated (or never-activated) */ musb_exit_debugfs(musb); - musb_shutdown(pdev); #ifdef CONFIG_USB_MUSB_HDRC_HCD if (musb->board_mode == MUSB_HOST) usb_remove_hcd(musb_to_hcd(musb)); #endif musb_writeb(musb->mregs, MUSB_DEVCTL, 0); - musb_platform_exit(musb); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); musb_free(musb); @@ -2258,224 +2232,13 @@ static int __exit musb_remove(struct platform_device *pdev) return 0; } -#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.busctl = musb_read_ulpi_buscontrol(musb->mregs); - } - 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) { - 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, &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, &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_write_ulpi_buscontrol(musb->mregs, musb_context.busctl); - } - 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); - unsigned long flags; - struct musb *musb = dev_to_musb(&pdev->dev); - - if (!musb->clock) - return 0; - - spin_lock_irqsave(&musb->lock, flags); - - if (is_peripheral_active(musb)) { - /* FIXME force disconnect unless we know USB will wake - * the system up quickly enough to respond ... - */ - } else if (is_host_active(musb)) { - /* we know all the children are suspended; sometimes - * they will even be wakeup-enabled. - */ - } - - musb_save_context(musb); - - if (musb->set_clock) - musb->set_clock(musb->clock, 0); - else - clk_disable(musb->clock); - spin_unlock_irqrestore(&musb->lock, flags); - return 0; -} - -static int musb_resume_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct musb *musb = dev_to_musb(&pdev->dev); - - if (!musb->clock) - return 0; - - if (musb->set_clock) - musb->set_clock(musb->clock, 1); - 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). - */ - return 0; -} - -static const struct dev_pm_ops musb_dev_pm_ops = { - .suspend = musb_suspend, - .resume_noirq = musb_resume_noirq, -}; - -#define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) -#else -#define MUSB_DEV_PM_OPS NULL -#endif - static struct platform_driver musb_driver = { .driver = { .name = (char *)musb_driver_name, .bus = &platform_bus_type, .owner = THIS_MODULE, - .pm = MUSB_DEV_PM_OPS, }, .remove = __exit_p(musb_remove), - .shutdown = musb_shutdown, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 91d6779..0918eb2 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -323,6 +323,14 @@ static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep) #endif } +struct musb_hdrc_ops { + int (*get_vbus_status)(struct musb *); + int (*set_mode)(struct musb *, u8); + + void (*try_idle)(struct musb *, unsigned long); + void (*set_vbus)(struct musb *, int); +}; + /* * struct musb - Driver instance data. */ @@ -334,6 +342,8 @@ struct musb { struct work_struct irq_work; u16 hwvers; + struct musb_hdrc_ops *ops; + /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ #define MUSB_PORT_STAT_RESUME (1 << 31) @@ -596,23 +606,29 @@ extern void musb_platform_disable(struct musb *musb); extern void musb_hnp_stop(struct musb *musb); -extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode); +static inline int musb_platform_set_mode(struct musb *musb, u8 mode) +{ + if (!musb->ops || !musb->ops->set_mode) + return 0; -#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \ - defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ - defined(CONFIG_ARCH_OMAP4) -extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); -#else -#define musb_platform_try_idle(x, y) do {} while (0) -#endif + return musb->ops->set_mode(musb, mode); +} -#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) -extern int musb_platform_get_vbus_status(struct musb *musb); -#else -#define musb_platform_get_vbus_status(x) 0 -#endif +static inline int musb_platform_get_vbus_status(struct musb *musb) +{ + if (!musb->ops || !musb->ops->get_vbus_status) + return 0; -extern int __init musb_platform_init(struct musb *musb, void *board_data); -extern int musb_platform_exit(struct musb *musb); + return musb->ops->get_vbus_status(musb); +} + +static inline void musb_platform_try_idle(struct musb *musb, + unsigned long timeout) +{ + if (!musb->ops || !musb->ops->try_idle) + return; + + musb->ops->try_idle(musb, timeout); +} #endif /* __MUSB_CORE_H__ */ diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2111a24..23c9a1f 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 by Texas Instruments + * Copyright (C) 2005-2010 by Texas Instruments * Some code has been taken from tusb6010.c * Copyrights for that are attributable to: * Copyright (C) 2006 Nokia Corporation @@ -29,13 +29,14 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/list.h> +#include <linux/platform_device.h> #include <linux/clk.h> #include <linux/io.h> +#include <plat/usb.h> #include "musb_core.h" #include "omap2430.h" - static struct timer_list musb_idle_timer; static void musb_do_idle(unsigned long _musb) @@ -98,7 +99,7 @@ static void musb_do_idle(unsigned long _musb) } -void musb_platform_try_idle(struct musb *musb, unsigned long timeout) +static void omap_musb_try_idle(struct musb *musb, unsigned long timeout) { unsigned long default_timeout = jiffies + msecs_to_jiffies(3); static unsigned long last_timer; @@ -131,12 +132,6 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) mod_timer(&musb_idle_timer, timeout); } -void musb_platform_enable(struct musb *musb) -{ -} -void musb_platform_disable(struct musb *musb) -{ -} static void omap_set_vbus(struct musb *musb, int is_on) { u8 devctl; @@ -175,36 +170,60 @@ static void omap_set_vbus(struct musb *musb, int is_on) musb_readb(musb->mregs, MUSB_DEVCTL)); } -static int musb_platform_resume(struct musb *musb); +#ifdef CONFIG_PM +void musb_platform_save_context(struct musb *musb, + struct musb_context_registers *musb_context) +{ + musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG); + musb_context->otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY); +} -int musb_platform_set_mode(struct musb *musb, u8 musb_mode) +void musb_platform_restore_context(struct musb *musb, + struct musb_context_registers *musb_context) { - u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig); + musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby); +} +#endif - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); +static struct musb_hdrc_ops omap_musb_ops = { + .try_idle = omap_musb_try_idle, + .set_vbus = omap_set_vbus, +}; - return 0; -} +struct omap_musb { + spinlock_t lock; + struct clk *clk; + void __iomem *base; +}; -int __init musb_platform_init(struct musb *musb, void *board_data) +static int __init omap_musb_probe(struct platform_device *pdev) { - u32 l; - struct omap_musb_board_data *data = board_data; + struct omap_musb *omap; + struct omap_musb_board_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *musb_data = pdata->musb; + struct platform_device *musb; + struct clk *clk; + long l; + int ret = -ENOMEM; + + omap = kzalloc(sizeof(*omap), GFP_KERNEL); + if (!omap) { + dev_err(&pdev->dev, "not enough memory\n"); + goto err0; + } - /* We require some kind of external transceiver, hooked - * up through ULPI. TWL4030-family PMICs include one, - * which needs a driver, drivers aren't always needed. - */ - musb->xceiv = otg_get_transceiver(); - if (!musb->xceiv) { - pr_err("HS USB OTG: no transceiver configured\n"); - return -ENODEV; + clk = clk_get(&pdev->dev, "ick"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "can't get clock\n"); + ret = PTR_ERR(clk); + goto err1; } - musb_platform_resume(musb); + omap->clk = clk; + spin_lock_init(&omap->lock); - l = musb_readl(musb->mregs, OTG_SYSCONFIG); + l = musb_readl(omap->base, OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ l &= ~NOSTDBY; /* remove possible nostdby */ l |= SMARTSTDBY; /* enable smart standby */ @@ -217,11 +236,11 @@ int __init musb_platform_init(struct musb *musb, void *board_data) */ if (!cpu_is_omap3430()) l |= AUTOIDLE; /* enable auto idle */ - musb_writel(musb->mregs, OTG_SYSCONFIG, l); + musb_writel(omap->base, OTG_SYSCONFIG, l); - l = musb_readl(musb->mregs, OTG_INTERFSEL); + l = musb_readl(omap->base, OTG_INTERFSEL); - if (data->interface_type == MUSB_INTERFACE_UTMI) { + if (pdata->interface_type == MUSB_INTERFACE_UTMI) { /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ l &= ~ULPI_12PIN; /* Disable ULPI */ l |= UTMI_8BIT; /* Enable UTMI */ @@ -229,96 +248,157 @@ int __init musb_platform_init(struct musb *musb, void *board_data) l |= ULPI_12PIN; } - musb_writel(musb->mregs, OTG_INTERFSEL, l); + musb_writel(omap->base, OTG_INTERFSEL, l); - pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " - "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", - musb_readl(musb->mregs, OTG_REVISION), - musb_readl(musb->mregs, OTG_SYSCONFIG), - musb_readl(musb->mregs, OTG_SYSSTATUS), - musb_readl(musb->mregs, OTG_INTERFSEL), - musb_readl(musb->mregs, OTG_SIMENABLE)); + ret = clk_enable(clk); + if (ret) { + dev_err(&pdev->dev, "failed to enabled clock\n"); + goto err2; + } - if (is_host_enabled(musb)) - musb->board_set_vbus = omap_set_vbus; + musb = platform_device_alloc("musb-hdrc", -1); + if (!musb) { + dev_err(&pdev->dev, "can't allocate musb-hdrc pdev\n"); + goto err3; + } + + musb->dev.parent = &pdev->dev; + platform_set_drvdata(pdev, omap); + + ret = platform_device_add_data(musb, musb_data, sizeof(*musb_data)); + if (ret) { + dev_err(&pdev->dev, "failed to add pdata\n"); + goto err4; + } + + ret = platform_device_register(musb); + if (ret) { + dev_err(&pdev->dev, "failed to register musb-hdrc pdev\n"); + goto err4; + } setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); + dev_dbg(&pdev->dev, "Rev: 0x%x, SYSCONFIG 0x%02x, " + "SYSSTATUS 0x%x, INTRSEL 0x%x, SIMENABLE 0x%x\n", + musb_readl(omap->base, OTG_REVISION), + musb_readl(omap->base, OTG_SYSCONFIG), + musb_readl(omap->base, OTG_SYSSTATUS), + musb_readl(omap->base, OTG_INTERFSEL), + musb_readl(omap->base, OTG_SIMENABLE)); + return 0; -} -#ifdef CONFIG_PM -void musb_platform_save_context(struct musb *musb, - struct musb_context_registers *musb_context) -{ - musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG); - musb_context->otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY); +err4: + platform_device_put(musb); + +err3: + clk_disable(clk); + +err2: + clk_put(clk); + +err1: + kfree(omap); + +err0: + return ret; } -void musb_platform_restore_context(struct musb *musb, - struct musb_context_registers *musb_context) +static int __exit omap_musb_remove(struct platform_device *pdev) { - musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig); - musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby); + struct omap_musb *omap = platform_get_drvdata(pdev); + + clk_disable(omap->clk); + clk_put(omap->clk); + kfree(omap); + + return 0; } -#endif -static int musb_platform_suspend(struct musb *musb) +#ifdef CONFIG_PM +static int omap_musb_suspend(struct platform_device *pdev, pm_message_t state) { - u32 l; + struct omap_musb *omap = platform_get_drvdata(pdev); + unsigned long flags; + unsigned long l; - if (!musb->clock) - return 0; + spin_lock_irqsave(&omap->lock, flags); - /* in any role */ - l = musb_readl(musb->mregs, OTG_FORCESTDBY); + l = musb_readl(omap->base, OTG_FORCESTDBY); l |= ENABLEFORCE; /* enable MSTANDBY */ - musb_writel(musb->mregs, OTG_FORCESTDBY, l); + musb_writel(omap->base, OTG_FORCESTDBY, l); - l = musb_readl(musb->mregs, OTG_SYSCONFIG); + l = musb_readl(omap->base, OTG_SYSCONFIG); l |= ENABLEWAKEUP; /* enable wakeup */ - musb_writel(musb->mregs, OTG_SYSCONFIG, l); + musb_writel(omap->base, OTG_SYSCONFIG, l); - otg_set_suspend(musb->xceiv, 1); + /* save context here */ - if (musb->set_clock) - musb->set_clock(musb->clock, 0); - else - clk_disable(musb->clock); + clk_disable(omap->clk); + + spin_unlock_irqrestore(&omap->lock, flags); return 0; } -static int musb_platform_resume(struct musb *musb) +static int omap_musb_resume(struct platform_device *pdev) { - u32 l; + struct omap_musb *omap = platform_get_drvdata(pdev); + unsigned long flags; + unsigned long l; + int ret; - if (!musb->clock) - return 0; + spin_lock_irqsave(&omap->lock, flags); - otg_set_suspend(musb->xceiv, 0); + ret = clk_enable(omap->clk); + if (ret) { + dev_err(&pdev->dev, "could not enable clk\n"); + goto out; + } - if (musb->set_clock) - musb->set_clock(musb->clock, 1); - else - clk_enable(musb->clock); + /* restore context here */ - l = musb_readl(musb->mregs, OTG_SYSCONFIG); + l = musb_readl(omap->base, OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ - musb_writel(musb->mregs, OTG_SYSCONFIG, l); + musb_writel(omap->base, OTG_SYSCONFIG, l); - l = musb_readl(musb->mregs, OTG_FORCESTDBY); + l = musb_readl(omap->base, OTG_FORCESTDBY); l &= ~ENABLEFORCE; /* disable MSTANDBY */ - musb_writel(musb->mregs, OTG_FORCESTDBY, l); + musb_writel(omap->base, OTG_FORCESTDBY, l); - return 0; +out: + spin_unlock_irqrestore(&omap->lock, flags); + + return ret; } +#else +#define omap_musb_suspend NULL +#define omap_musb_resume NULL +#endif +static struct platform_driver omap_musb_driver = { + .remove = __exit_p(omap_musb_remove), + .suspend = omap_musb_suspend, + .resume = omap_musb_resume, + .driver = { + .name = "omap-musb-hdrc", + }, +}; -int musb_platform_exit(struct musb *musb) -{ +MODULE_DESCRIPTION("OMAP MUSB Glue Layer"); +MODULE_AUTHOR("Felipe Balbi <balbi@xxxxxx>"); +MODULE_LICENSE("GPL v2"); - musb_platform_suspend(musb); +static int __init omap_musb_init(void) +{ + return platform_driver_probe(&omap_musb_driver, omap_musb_probe); +} +module_init(omap_musb_init); - return 0; +static void __exit omap_musb_exit(void) +{ + platform_driver_unregister(&omap_musb_driver); } +module_exit(omap_musb_exit); + -- 1.7.3.rc0.35.g8ac8c -- 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