From 8c73aff6d3b772e5f373d78bc34fd47b10b35fef Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 22 Nov 2007 21:00:30 +0900 Subject: USB: m66592-udc: Add support for SH7722 USBF Add support for SuperH SH7722 USB Function. M66592 is similar to SH7722 USBF. It can support SH7722 USBF by changing several M66592 code. Signed-off-by: Yoshihiro Shimoda Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/m66592-udc.c | 55 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget/m66592-udc.c') diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index ebc5536a..154007a 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -36,9 +36,14 @@ MODULE_DESCRIPTION("M66592 USB gadget driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yoshihiro Shimoda"); -#define DRIVER_VERSION "29 May 2007" +#define DRIVER_VERSION "18 Oct 2007" /* module parameters */ +#if defined(CONFIG_SUPERH_BUILT_IN_M66592) +static unsigned short endian = M66592_LITTLE; +module_param(endian, ushort, 0644); +MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)"); +#else static unsigned short clock = M66592_XTAL24; module_param(clock, ushort, 0644); MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " @@ -56,6 +61,7 @@ static unsigned short irq_sense = M66592_INTL; module_param(irq_sense, ushort, 0644); MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 " "(default=2)"); +#endif static const char udc_name[] = "m66592_udc"; static const char *m66592_ep_name[] = { @@ -360,6 +366,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ep->fifosel = M66592_D0FIFOSEL; ep->fifoctr = M66592_D0FIFOCTR; ep->fifotrn = M66592_D0FIFOTRN; +#if !defined(CONFIG_SUPERH_BUILT_IN_M66592) } else if (m66592->num_dma == 1) { m66592->num_dma++; ep->use_dma = 1; @@ -367,6 +374,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ep->fifosel = M66592_D1FIFOSEL; ep->fifoctr = M66592_D1FIFOCTR; ep->fifotrn = M66592_D1FIFOTRN; +#endif } else { ep->use_dma = 0; ep->fifoaddr = M66592_CFIFO; @@ -611,6 +619,28 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req) } } +#if defined(CONFIG_SUPERH_BUILT_IN_M66592) +static void init_controller(struct m66592 *m66592) +{ + usbf_start_clock(); + m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ + m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG); + m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); + m66592_bset(m66592, M66592_USBE, M66592_SYSCFG); + + /* This is a workaound for SH7722 2nd cut */ + m66592_bset(m66592, 0x8000, M66592_DVSTCTR); + m66592_bset(m66592, 0x1000, M66592_TESTMODE); + m66592_bclr(m66592, 0x8000, M66592_DVSTCTR); + + m66592_bset(m66592, M66592_INTL, M66592_INTENB1); + + m66592_write(m66592, 0, M66592_CFBCFG); + m66592_write(m66592, 0, M66592_D0FBCFG); + m66592_bset(m66592, endian, M66592_CFBCFG); + m66592_bset(m66592, endian, M66592_D0FBCFG); +} +#else /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ static void init_controller(struct m66592 *m66592) { m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND), @@ -636,9 +666,13 @@ static void init_controller(struct m66592 *m66592) m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, M66592_DMA0CFG); } +#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ static void disable_controller(struct m66592 *m66592) { +#if defined(CONFIG_SUPERH_BUILT_IN_M66592) + usbf_stop_clock(); +#else m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG); udelay(1); m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG); @@ -646,15 +680,20 @@ static void disable_controller(struct m66592 *m66592) m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG); udelay(1); m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG); +#endif } static void m66592_start_xclock(struct m66592 *m66592) { +#if defined(CONFIG_SUPERH_BUILT_IN_M66592) + usbf_start_clock(); +#else u16 tmp; tmp = m66592_read(m66592, M66592_SYSCFG); if (!(tmp & M66592_XCKE)) m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); +#endif } /*-------------------------------------------------------------------------*/ @@ -1142,6 +1181,19 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) intsts0 = m66592_read(m66592, M66592_INTSTS0); intenb0 = m66592_read(m66592, M66592_INTENB0); +#if defined(CONFIG_SUPERH_BUILT_IN_M66592) + if (!intsts0 && !intenb0) { + /* + * When USB clock stops, it cannot read register. Even if a + * clock stops, the interrupt occurs. So this driver turn on + * a clock by this timing and do re-reading of register. + */ + m66592_start_xclock(m66592); + intsts0 = m66592_read(m66592, M66592_INTSTS0); + intenb0 = m66592_read(m66592, M66592_INTENB0); + } +#endif + savepipe = m66592_read(m66592, M66592_CFIFOSEL); mask0 = intsts0 & intenb0; @@ -1485,6 +1537,7 @@ static int __exit m66592_remove(struct platform_device *pdev) iounmap(m66592->reg); free_irq(platform_get_irq(pdev, 0), m66592); m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); + usbf_stop_clock(); kfree(m66592); return 0; } -- cgit v1.1