aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorYoshihiro Shimoda <shimoda.yoshihiro@renesas.com>2007-11-22 07:00:30 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:34:48 -0500
commit8c73aff6d3b772e5f373d78bc34fd47b10b35fef (patch)
treec6829760527dd59c27acf86b3f935b3659b2c6fa /drivers
parent9da0068a4964540d8d1caa8455fe193b544d846d (diff)
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 <shimoda.yoshihiro@renesas.com> Acked-by: David Brownell <david-b@pacbell.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/Kconfig10
-rw-r--r--drivers/usb/gadget/m66592-udc.c55
-rw-r--r--drivers/usb/gadget/m66592-udc.h54
3 files changed, 118 insertions, 1 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 77a3759d6fc7..e706882a8e6f 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -220,6 +220,16 @@ config USB_M66592
220 default USB_GADGET 220 default USB_GADGET
221 select USB_GADGET_SELECTED 221 select USB_GADGET_SELECTED
222 222
223config SUPERH_BUILT_IN_M66592
224 boolean "Enable SuperH built-in USB like the M66592"
225 depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
226 help
227 SH7722 has USB like the M66592.
228
229 The transfer rate is very slow when use "Ethernet Gadget".
230 However, this problem is improved if change a value of
231 NET_IP_ALIGN to 4.
232
223config USB_GADGET_GOKU 233config USB_GADGET_GOKU
224 boolean "Toshiba TC86C001 'Goku-S'" 234 boolean "Toshiba TC86C001 'Goku-S'"
225 depends on PCI 235 depends on PCI
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index ebc5536aa271..154007aa8d30 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");
36MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
37MODULE_AUTHOR("Yoshihiro Shimoda"); 37MODULE_AUTHOR("Yoshihiro Shimoda");
38 38
39#define DRIVER_VERSION "29 May 2007" 39#define DRIVER_VERSION "18 Oct 2007"
40 40
41/* module parameters */ 41/* module parameters */
42#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
43static unsigned short endian = M66592_LITTLE;
44module_param(endian, ushort, 0644);
45MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
46#else
42static unsigned short clock = M66592_XTAL24; 47static unsigned short clock = M66592_XTAL24;
43module_param(clock, ushort, 0644); 48module_param(clock, ushort, 0644);
44MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " 49MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
@@ -56,6 +61,7 @@ static unsigned short irq_sense = M66592_INTL;
56module_param(irq_sense, ushort, 0644); 61module_param(irq_sense, ushort, 0644);
57MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 " 62MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
58 "(default=2)"); 63 "(default=2)");
64#endif
59 65
60static const char udc_name[] = "m66592_udc"; 66static const char udc_name[] = "m66592_udc";
61static const char *m66592_ep_name[] = { 67static const char *m66592_ep_name[] = {
@@ -360,6 +366,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
360 ep->fifosel = M66592_D0FIFOSEL; 366 ep->fifosel = M66592_D0FIFOSEL;
361 ep->fifoctr = M66592_D0FIFOCTR; 367 ep->fifoctr = M66592_D0FIFOCTR;
362 ep->fifotrn = M66592_D0FIFOTRN; 368 ep->fifotrn = M66592_D0FIFOTRN;
369#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
363 } else if (m66592->num_dma == 1) { 370 } else if (m66592->num_dma == 1) {
364 m66592->num_dma++; 371 m66592->num_dma++;
365 ep->use_dma = 1; 372 ep->use_dma = 1;
@@ -367,6 +374,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
367 ep->fifosel = M66592_D1FIFOSEL; 374 ep->fifosel = M66592_D1FIFOSEL;
368 ep->fifoctr = M66592_D1FIFOCTR; 375 ep->fifoctr = M66592_D1FIFOCTR;
369 ep->fifotrn = M66592_D1FIFOTRN; 376 ep->fifotrn = M66592_D1FIFOTRN;
377#endif
370 } else { 378 } else {
371 ep->use_dma = 0; 379 ep->use_dma = 0;
372 ep->fifoaddr = M66592_CFIFO; 380 ep->fifoaddr = M66592_CFIFO;
@@ -611,6 +619,28 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
611 } 619 }
612} 620}
613 621
622#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
623static void init_controller(struct m66592 *m66592)
624{
625 usbf_start_clock();
626 m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
627 m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
628 m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
629 m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
630
631 /* This is a workaound for SH7722 2nd cut */
632 m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
633 m66592_bset(m66592, 0x1000, M66592_TESTMODE);
634 m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
635
636 m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
637
638 m66592_write(m66592, 0, M66592_CFBCFG);
639 m66592_write(m66592, 0, M66592_D0FBCFG);
640 m66592_bset(m66592, endian, M66592_CFBCFG);
641 m66592_bset(m66592, endian, M66592_D0FBCFG);
642}
643#else /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
614static void init_controller(struct m66592 *m66592) 644static void init_controller(struct m66592 *m66592)
615{ 645{
616 m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND), 646 m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
@@ -636,9 +666,13 @@ static void init_controller(struct m66592 *m66592)
636 m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, 666 m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
637 M66592_DMA0CFG); 667 M66592_DMA0CFG);
638} 668}
669#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
639 670
640static void disable_controller(struct m66592 *m66592) 671static void disable_controller(struct m66592 *m66592)
641{ 672{
673#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
674 usbf_stop_clock();
675#else
642 m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG); 676 m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
643 udelay(1); 677 udelay(1);
644 m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG); 678 m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
@@ -646,15 +680,20 @@ static void disable_controller(struct m66592 *m66592)
646 m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG); 680 m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
647 udelay(1); 681 udelay(1);
648 m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG); 682 m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
683#endif
649} 684}
650 685
651static void m66592_start_xclock(struct m66592 *m66592) 686static void m66592_start_xclock(struct m66592 *m66592)
652{ 687{
688#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
689 usbf_start_clock();
690#else
653 u16 tmp; 691 u16 tmp;
654 692
655 tmp = m66592_read(m66592, M66592_SYSCFG); 693 tmp = m66592_read(m66592, M66592_SYSCFG);
656 if (!(tmp & M66592_XCKE)) 694 if (!(tmp & M66592_XCKE))
657 m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); 695 m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
696#endif
658} 697}
659 698
660/*-------------------------------------------------------------------------*/ 699/*-------------------------------------------------------------------------*/
@@ -1142,6 +1181,19 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
1142 intsts0 = m66592_read(m66592, M66592_INTSTS0); 1181 intsts0 = m66592_read(m66592, M66592_INTSTS0);
1143 intenb0 = m66592_read(m66592, M66592_INTENB0); 1182 intenb0 = m66592_read(m66592, M66592_INTENB0);
1144 1183
1184#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
1185 if (!intsts0 && !intenb0) {
1186 /*
1187 * When USB clock stops, it cannot read register. Even if a
1188 * clock stops, the interrupt occurs. So this driver turn on
1189 * a clock by this timing and do re-reading of register.
1190 */
1191 m66592_start_xclock(m66592);
1192 intsts0 = m66592_read(m66592, M66592_INTSTS0);
1193 intenb0 = m66592_read(m66592, M66592_INTENB0);
1194 }
1195#endif
1196
1145 savepipe = m66592_read(m66592, M66592_CFIFOSEL); 1197 savepipe = m66592_read(m66592, M66592_CFIFOSEL);
1146 1198
1147 mask0 = intsts0 & intenb0; 1199 mask0 = intsts0 & intenb0;
@@ -1485,6 +1537,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
1485 iounmap(m66592->reg); 1537 iounmap(m66592->reg);
1486 free_irq(platform_get_irq(pdev, 0), m66592); 1538 free_irq(platform_get_irq(pdev, 0), m66592);
1487 m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); 1539 m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
1540 usbf_stop_clock();
1488 kfree(m66592); 1541 kfree(m66592);
1489 return 0; 1542 return 0;
1490} 1543}
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index bfa0c645f229..17b792b7f6bf 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -72,6 +72,11 @@
72#define M66592_P_TST_J 0x0001 /* PERI TEST J */ 72#define M66592_P_TST_J 0x0001 /* PERI TEST J */
73#define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */ 73#define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */
74 74
75#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
76#define M66592_CFBCFG 0x0A
77#define M66592_D0FBCFG 0x0C
78#define M66592_LITTLE 0x0100 /* b8: Little endian mode */
79#else
75#define M66592_PINCFG 0x0A 80#define M66592_PINCFG 0x0A
76#define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */ 81#define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */
77#define M66592_BIGEND 0x0100 /* b8: Big endian mode */ 82#define M66592_BIGEND 0x0100 /* b8: Big endian mode */
@@ -91,6 +96,7 @@
91#define M66592_PKTM 0x0020 /* b5: Packet mode */ 96#define M66592_PKTM 0x0020 /* b5: Packet mode */
92#define M66592_DENDE 0x0010 /* b4: Dend enable */ 97#define M66592_DENDE 0x0010 /* b4: Dend enable */
93#define M66592_OBUS 0x0004 /* b2: OUTbus mode */ 98#define M66592_OBUS 0x0004 /* b2: OUTbus mode */
99#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
94 100
95#define M66592_CFIFO 0x10 101#define M66592_CFIFO 0x10
96#define M66592_D0FIFO 0x14 102#define M66592_D0FIFO 0x14
@@ -103,9 +109,13 @@
103#define M66592_REW 0x4000 /* b14: Buffer rewind */ 109#define M66592_REW 0x4000 /* b14: Buffer rewind */
104#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */ 110#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */
105#define M66592_DREQE 0x1000 /* b12: DREQ output enable */ 111#define M66592_DREQE 0x1000 /* b12: DREQ output enable */
112#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
113#define M66592_MBW 0x0800 /* b11: Maximum bit width for FIFO */
114#else
106#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO */ 115#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO */
107#define M66592_MBW_8 0x0000 /* 8bit */ 116#define M66592_MBW_8 0x0000 /* 8bit */
108#define M66592_MBW_16 0x0400 /* 16bit */ 117#define M66592_MBW_16 0x0400 /* 16bit */
118#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
109#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */ 119#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */
110#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */ 120#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */
111#define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */ 121#define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */
@@ -530,8 +540,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592,
530{ 540{
531 unsigned long fifoaddr = (unsigned long)m66592->reg + offset; 541 unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
532 542
543#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
544 len = (len + 3) / 4;
545 insl(fifoaddr, buf, len);
546#else
533 len = (len + 1) / 2; 547 len = (len + 1) / 2;
534 insw(fifoaddr, buf, len); 548 insw(fifoaddr, buf, len);
549#endif
535} 550}
536 551
537static inline void m66592_write(struct m66592 *m66592, u16 val, 552static inline void m66592_write(struct m66592 *m66592, u16 val,
@@ -545,6 +560,24 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
545 void *buf, unsigned long len) 560 void *buf, unsigned long len)
546{ 561{
547 unsigned long fifoaddr = (unsigned long)m66592->reg + offset; 562 unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
563#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
564 unsigned long count;
565 unsigned char *pb;
566 int i;
567
568 count = len / 4;
569 outsl(fifoaddr, buf, count);
570
571 if (len & 0x00000003) {
572 pb = buf + count * 4;
573 for (i = 0; i < (len & 0x00000003); i++) {
574 if (m66592_read(m66592, M66592_CFBCFG)) /* little */
575 outb(pb[i], fifoaddr + (3 - i));
576 else
577 outb(pb[i], fifoaddr + i);
578 }
579 }
580#else
548 unsigned long odd = len & 0x0001; 581 unsigned long odd = len & 0x0001;
549 582
550 len = len / 2; 583 len = len / 2;
@@ -553,6 +586,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
553 unsigned char *p = buf + len*2; 586 unsigned char *p = buf + len*2;
554 outb(*p, fifoaddr); 587 outb(*p, fifoaddr);
555 } 588 }
589#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
556} 590}
557 591
558static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, 592static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
@@ -570,6 +604,26 @@ static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
570#define m66592_bset(m66592, val, offset) \ 604#define m66592_bset(m66592, val, offset) \
571 m66592_mdfy(m66592, val, 0, offset) 605 m66592_mdfy(m66592, val, 0, offset)
572 606
607#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
608#include <asm/io.h>
609#define MSTPCR2 0xA4150038 /* for SH7722 */
610#define MSTPCR2_USB 0x00000800
611
612static inline void usbf_start_clock(void)
613{
614 ctrl_outl(ctrl_inl(MSTPCR2) & ~MSTPCR2_USB, MSTPCR2);
615}
616
617static inline void usbf_stop_clock(void)
618{
619 ctrl_outl(ctrl_inl(MSTPCR2) | MSTPCR2_USB, MSTPCR2);
620}
621
622#else
623#define usbf_start_clock(x)
624#define usbf_stop_clock(x)
625#endif /* if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
626
573#endif /* ifndef __M66592_UDC_H__ */ 627#endif /* ifndef __M66592_UDC_H__ */
574 628
575 629