--- zzzz-none-000/linux-2.6.28.10/drivers/usb/musb/davinci.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/drivers/usb/musb/davinci.c 2010-03-30 18:41:51.000000000 +0000 @@ -30,17 +30,18 @@ #include #include #include -#include +#include #include #include +#include #include #include #include "musb_core.h" -#ifdef CONFIG_MACH_DAVINCI_EVM -#define GPIO_nVBUS_DRV 87 +#if defined(CONFIG_MACH_DAVINCI_EVM) || defined(CONFIG_MACH_DAVINCI_DM6467_EVM) +#include #endif #include "davinci.h" @@ -56,8 +57,17 @@ static inline void phy_on(void) { /* start the on-chip PHY and its PLL */ - __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON, - (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); + if (cpu_is_davinci_dm644x()) + __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON, + IO_ADDRESS(USBPHY_CTL_PADDR)); + + else if (cpu_is_davinci_dm355()) + __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON + | USBPHY_DATAPOL, IO_ADDRESS(USBPHY_CTL_PADDR)); + + else if (cpu_is_davinci_dm6467()) + __raw_writel(0, IO_ADDRESS(USBPHY_CTL_PADDR)); + while ((__raw_readl((void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)) & USBPHY_PHYCLKGD) == 0) @@ -67,8 +77,12 @@ static inline void phy_off(void) { /* powerdown the on-chip PHY and its oscillator */ - __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)); + if (cpu_is_davinci_dm644x() || cpu_is_davinci_dm355()) + __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, + (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); + + else if (cpu_is_davinci_dm6467()) + __raw_writel(USBPHY_PHYPDWN, IO_ADDRESS(USBPHY_CTL_PADDR)); } static int dma_off = 1; @@ -87,8 +101,12 @@ musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp); tmp |= old; - val = ~MUSB_INTR_SOF; + if( is_intr_sched() ) + val = ~0x0; + else + val = ~MUSB_INTR_SOF; tmp |= ((val & 0x01ff) << DAVINCI_USB_USBINT_SHIFT); + musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp); if (is_dma_capable() && !dma_off) @@ -121,7 +139,7 @@ musb_writel(musb->ctrl_base, DAVINCI_USB_EOI_REG, 0); if (is_dma_capable() && !dma_off) - WARNING("dma still active\n"); + WARN("dma still active\n"); } @@ -138,19 +156,28 @@ /* VBUS SWITCHING IS BOARD-SPECIFIC */ -#ifdef CONFIG_MACH_DAVINCI_EVM +#if defined(CONFIG_MACH_DAVINCI_EVM) || defined(CONFIG_MACH_DAVINCI_DM6467_EVM) +#ifndef CONFIG_MACH_DAVINCI_EVM_OTG + +static inline void davinci_i2c_drvvbus(int is_on) +{ + if (machine_is_davinci_evm()) + davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on); + else if (machine_is_davinci_dm6467_evm()) + davinci_i2c_expander_op(0x3a, USB_FB_DM646X, !is_on); +} /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice * to satisfy the 100msec A_WAIT_VRISE timeout... */ -static void evm_deferred_drvvbus(struct work_struct *ignored) +static void evm_deferred_drvvbus(void *_musb) { - gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); - vbus_state = !vbus_state; + davinci_i2c_drvvbus(vbus_state); } -static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); +DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus, 0); +#endif /* modified board */ #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) @@ -160,18 +187,24 @@ if (vbus_state == is_on) return; - vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ + vbus_state = is_on; /* 0/1 vs "-1 == unknown/init" */ -#ifdef CONFIG_MACH_DAVINCI_EVM - if (machine_is_davinci_evm()) { +#if defined(CONFIG_MACH_DAVINCI_EVM) || defined(CONFIG_MACH_DAVINCI_DM6467_EVM) + if (machine_is_davinci_evm() || machine_is_davinci_dm6467_evm()) { +#ifdef CONFIG_USB_MUSB_OTG + /* modified EVM board switching VBUS with GPIO(6) not I2C + * NOTE: PINMUX0.RGB888 (bit23) must be clear + */ + gpio_set_value(GPIO(6), is_on); + immediate = 1; +#else if (immediate) - gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); + davinci_i2c_drvvbus(is_on); else schedule_work(&evm_vbus_work); +#endif } #endif - if (immediate) - vbus_state = is_on; } static void davinci_set_vbus(struct musb *musb, int is_on) @@ -243,7 +276,7 @@ spin_unlock_irqrestore(&musb->lock, flags); } -static irqreturn_t davinci_interrupt(int irq, void *__hci) +static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r) { unsigned long flags; irqreturn_t retval = IRQ_NONE; @@ -287,6 +320,7 @@ >> DAVINCI_USB_TXINT_SHIFT; musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK) >> DAVINCI_USB_USBINT_SHIFT; + musb->int_regs = r; /* DRVVBUS irqs are the only proxy we have (a very poor one!) for * DaVinci's missing ID change IRQ. We need an ID change IRQ to @@ -317,7 +351,7 @@ musb->int_usb &= ~MUSB_INTR_VBUSERROR; musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); - WARNING("VBUS error workaround (delay coming)\n"); + WARN("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { musb->is_active = 1; MUSB_HST_MODE(musb); @@ -349,6 +383,8 @@ /* irq stays asserted until EOI is written */ musb_writel(tibase, DAVINCI_USB_EOI_REG, 0); + musb->int_regs = NULL; + /* poll for ID change */ if (is_otg_enabled(musb) && musb->xceiv.state == OTG_STATE_B_IDLE) @@ -364,24 +400,26 @@ return IRQ_HANDLED; } +void musb_platform_set_mode(struct musb *musb, u8 musb_mode) +{ + WARN("FIXME: %p not implemented\n", __func__); +} + int __init musb_platform_init(struct musb *musb) { void __iomem *tibase = musb->ctrl_base; - u32 revision; + u32 revision, phystatus; + int status; musb->mregs += DAVINCI_BASE_OFFSET; -#if 0 - /* REVISIT there's something odd about clocking, this - * didn't appear do the job ... - */ - musb->clock = clk_get(pDevice, "usb"); + + musb->clock = clk_get(NULL, "USBCLK"); if (IS_ERR(musb->clock)) return PTR_ERR(musb->clock); status = clk_enable(musb->clock); if (status < 0) return -ENODEV; -#endif /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); @@ -391,9 +429,38 @@ if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); +#if defined(CONFIG_MACH_DAVINCI_EVM) || defined(CONFIG_MACH_DAVINCI_DM6467_EVM) + evm_vbus_work.data = musb; +#ifdef CONFIG_USB_MUSB_OTG + { + u32 tmp; + + /* clear EMACEN to enble OTG GPIO 16 for VBus power control */ + /* Set GPIO Direction */ + tmp = davinci_readl(DVEVM_GPIO45_DIR & ~DVEVM_GPIO45_DIR_OUT); + davinci_writel(tmp, DVEVM_GPIO45_DIR); + + davinci_cfg_reg(DM644X_GPIO3V); + } +#endif +#endif musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); + if (machine_is_davinci_dm355_evm()) { + /* + * On DM355 EVM USB_ID toggle is controlled via GPIO2 output + */ + if (is_peripheral_enabled(musb)) + gpio_direction_output(2, 0); + else + gpio_direction_output(2, 1); + + /* Clear DRVVBUS_OVERRIDE */ + davinci_writel(davinci_readl(DM355_DEEPSLEEP_PADDR) & + 0xfffffff0, DM355_DEEPSLEEP_PADDR); + } + /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); @@ -402,6 +469,17 @@ msleep(5); + if (cpu_is_davinci_dm6467()) { + phystatus = davinci_readl(USBPHY_CTL_PADDR); + if (is_host_enabled(musb)) + davinci_writel(phystatus | USBPHY_SESSION_VBUS | + USBPHY_NDATAPOL, USBPHY_CTL_PADDR); + else + davinci_writel(phystatus | USBPHY_SESSION_VBUS | + USBPHY_NDATAPOL | USBPHY_PERI_USBID, + USBPHY_CTL_PADDR); + } + /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", revision, __raw_readl((void __force __iomem *) @@ -414,6 +492,12 @@ int musb_platform_exit(struct musb *musb) { +#if defined(CONFIG_MACH_DAVINCI_EVM) && defined(CONFIG_USB_MUSB_OTG) + /* Set EMACEN to enable OTG GPIO 16 for Emac control */ + /* Set GPIO Direction */ + davinci_cfg_reg(DM644X_EMACEN); +#endif + if (is_host_enabled(musb)) del_timer_sync(&otg_workaround);