Commit 8c73aff6 authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by Greg Kroah-Hartman

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: default avatarYoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Acked-by: default avatarDavid Brownell <david-b@pacbell.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 9da0068a
...@@ -220,6 +220,16 @@ config USB_M66592 ...@@ -220,6 +220,16 @@ config USB_M66592
default USB_GADGET default USB_GADGET
select USB_GADGET_SELECTED select USB_GADGET_SELECTED
config SUPERH_BUILT_IN_M66592
boolean "Enable SuperH built-in USB like the M66592"
depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
help
SH7722 has USB like the M66592.
The transfer rate is very slow when use "Ethernet Gadget".
However, this problem is improved if change a value of
NET_IP_ALIGN to 4.
config USB_GADGET_GOKU config USB_GADGET_GOKU
boolean "Toshiba TC86C001 'Goku-S'" boolean "Toshiba TC86C001 'Goku-S'"
depends on PCI depends on PCI
......
...@@ -36,9 +36,14 @@ MODULE_DESCRIPTION("M66592 USB gadget driver"); ...@@ -36,9 +36,14 @@ MODULE_DESCRIPTION("M66592 USB gadget driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yoshihiro Shimoda"); MODULE_AUTHOR("Yoshihiro Shimoda");
#define DRIVER_VERSION "29 May 2007" #define DRIVER_VERSION "18 Oct 2007"
/* module parameters */ /* 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; static unsigned short clock = M66592_XTAL24;
module_param(clock, ushort, 0644); module_param(clock, ushort, 0644);
MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
...@@ -56,6 +61,7 @@ static unsigned short irq_sense = M66592_INTL; ...@@ -56,6 +61,7 @@ static unsigned short irq_sense = M66592_INTL;
module_param(irq_sense, ushort, 0644); module_param(irq_sense, ushort, 0644);
MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 " MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
"(default=2)"); "(default=2)");
#endif
static const char udc_name[] = "m66592_udc"; static const char udc_name[] = "m66592_udc";
static const char *m66592_ep_name[] = { static const char *m66592_ep_name[] = {
...@@ -360,6 +366,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ...@@ -360,6 +366,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
ep->fifosel = M66592_D0FIFOSEL; ep->fifosel = M66592_D0FIFOSEL;
ep->fifoctr = M66592_D0FIFOCTR; ep->fifoctr = M66592_D0FIFOCTR;
ep->fifotrn = M66592_D0FIFOTRN; ep->fifotrn = M66592_D0FIFOTRN;
#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
} else if (m66592->num_dma == 1) { } else if (m66592->num_dma == 1) {
m66592->num_dma++; m66592->num_dma++;
ep->use_dma = 1; ep->use_dma = 1;
...@@ -367,6 +374,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ...@@ -367,6 +374,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
ep->fifosel = M66592_D1FIFOSEL; ep->fifosel = M66592_D1FIFOSEL;
ep->fifoctr = M66592_D1FIFOCTR; ep->fifoctr = M66592_D1FIFOCTR;
ep->fifotrn = M66592_D1FIFOTRN; ep->fifotrn = M66592_D1FIFOTRN;
#endif
} else { } else {
ep->use_dma = 0; ep->use_dma = 0;
ep->fifoaddr = M66592_CFIFO; ep->fifoaddr = M66592_CFIFO;
...@@ -611,6 +619,28 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req) ...@@ -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) static void init_controller(struct m66592 *m66592)
{ {
m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND), m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
...@@ -636,9 +666,13 @@ static void init_controller(struct m66592 *m66592) ...@@ -636,9 +666,13 @@ static void init_controller(struct m66592 *m66592)
m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
M66592_DMA0CFG); M66592_DMA0CFG);
} }
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
static void disable_controller(struct m66592 *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); m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
udelay(1); udelay(1);
m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG); m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
...@@ -646,15 +680,20 @@ static void disable_controller(struct m66592 *m66592) ...@@ -646,15 +680,20 @@ static void disable_controller(struct m66592 *m66592)
m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG); m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
udelay(1); udelay(1);
m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG); m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
#endif
} }
static void m66592_start_xclock(struct m66592 *m66592) static void m66592_start_xclock(struct m66592 *m66592)
{ {
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
usbf_start_clock();
#else
u16 tmp; u16 tmp;
tmp = m66592_read(m66592, M66592_SYSCFG); tmp = m66592_read(m66592, M66592_SYSCFG);
if (!(tmp & M66592_XCKE)) if (!(tmp & M66592_XCKE))
m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
#endif
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -1142,6 +1181,19 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) ...@@ -1142,6 +1181,19 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
intsts0 = m66592_read(m66592, M66592_INTSTS0); intsts0 = m66592_read(m66592, M66592_INTSTS0);
intenb0 = m66592_read(m66592, M66592_INTENB0); 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); savepipe = m66592_read(m66592, M66592_CFIFOSEL);
mask0 = intsts0 & intenb0; mask0 = intsts0 & intenb0;
...@@ -1485,6 +1537,7 @@ static int __exit m66592_remove(struct platform_device *pdev) ...@@ -1485,6 +1537,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
iounmap(m66592->reg); iounmap(m66592->reg);
free_irq(platform_get_irq(pdev, 0), m66592); free_irq(platform_get_irq(pdev, 0), m66592);
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
usbf_stop_clock();
kfree(m66592); kfree(m66592);
return 0; return 0;
} }
......
...@@ -72,6 +72,11 @@ ...@@ -72,6 +72,11 @@
#define M66592_P_TST_J 0x0001 /* PERI TEST J */ #define M66592_P_TST_J 0x0001 /* PERI TEST J */
#define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */ #define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
#define M66592_CFBCFG 0x0A
#define M66592_D0FBCFG 0x0C
#define M66592_LITTLE 0x0100 /* b8: Little endian mode */
#else
#define M66592_PINCFG 0x0A #define M66592_PINCFG 0x0A
#define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */ #define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */
#define M66592_BIGEND 0x0100 /* b8: Big endian mode */ #define M66592_BIGEND 0x0100 /* b8: Big endian mode */
...@@ -91,6 +96,7 @@ ...@@ -91,6 +96,7 @@
#define M66592_PKTM 0x0020 /* b5: Packet mode */ #define M66592_PKTM 0x0020 /* b5: Packet mode */
#define M66592_DENDE 0x0010 /* b4: Dend enable */ #define M66592_DENDE 0x0010 /* b4: Dend enable */
#define M66592_OBUS 0x0004 /* b2: OUTbus mode */ #define M66592_OBUS 0x0004 /* b2: OUTbus mode */
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
#define M66592_CFIFO 0x10 #define M66592_CFIFO 0x10
#define M66592_D0FIFO 0x14 #define M66592_D0FIFO 0x14
...@@ -103,9 +109,13 @@ ...@@ -103,9 +109,13 @@
#define M66592_REW 0x4000 /* b14: Buffer rewind */ #define M66592_REW 0x4000 /* b14: Buffer rewind */
#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */ #define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */
#define M66592_DREQE 0x1000 /* b12: DREQ output enable */ #define M66592_DREQE 0x1000 /* b12: DREQ output enable */
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
#define M66592_MBW 0x0800 /* b11: Maximum bit width for FIFO */
#else
#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO */ #define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO */
#define M66592_MBW_8 0x0000 /* 8bit */ #define M66592_MBW_8 0x0000 /* 8bit */
#define M66592_MBW_16 0x0400 /* 16bit */ #define M66592_MBW_16 0x0400 /* 16bit */
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */ #define M66592_TRENB 0x0200 /* b9: Transaction counter enable */
#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */ #define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */
#define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */ #define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */
...@@ -530,8 +540,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592, ...@@ -530,8 +540,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592,
{ {
unsigned long fifoaddr = (unsigned long)m66592->reg + offset; unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
len = (len + 3) / 4;
insl(fifoaddr, buf, len);
#else
len = (len + 1) / 2; len = (len + 1) / 2;
insw(fifoaddr, buf, len); insw(fifoaddr, buf, len);
#endif
} }
static inline void m66592_write(struct m66592 *m66592, u16 val, static inline void m66592_write(struct m66592 *m66592, u16 val,
...@@ -545,6 +560,24 @@ static inline void m66592_write_fifo(struct m66592 *m66592, ...@@ -545,6 +560,24 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
void *buf, unsigned long len) void *buf, unsigned long len)
{ {
unsigned long fifoaddr = (unsigned long)m66592->reg + offset; unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
unsigned long count;
unsigned char *pb;
int i;
count = len / 4;
outsl(fifoaddr, buf, count);
if (len & 0x00000003) {
pb = buf + count * 4;
for (i = 0; i < (len & 0x00000003); i++) {
if (m66592_read(m66592, M66592_CFBCFG)) /* little */
outb(pb[i], fifoaddr + (3 - i));
else
outb(pb[i], fifoaddr + i);
}
}
#else
unsigned long odd = len & 0x0001; unsigned long odd = len & 0x0001;
len = len / 2; len = len / 2;
...@@ -553,6 +586,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592, ...@@ -553,6 +586,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
unsigned char *p = buf + len*2; unsigned char *p = buf + len*2;
outb(*p, fifoaddr); outb(*p, fifoaddr);
} }
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
} }
static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, static 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,6 +604,26 @@ static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
#define m66592_bset(m66592, val, offset) \ #define m66592_bset(m66592, val, offset) \
m66592_mdfy(m66592, val, 0, offset) m66592_mdfy(m66592, val, 0, offset)
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
#include <asm/io.h>
#define MSTPCR2 0xA4150038 /* for SH7722 */
#define MSTPCR2_USB 0x00000800
static inline void usbf_start_clock(void)
{
ctrl_outl(ctrl_inl(MSTPCR2) & ~MSTPCR2_USB, MSTPCR2);
}
static inline void usbf_stop_clock(void)
{
ctrl_outl(ctrl_inl(MSTPCR2) | MSTPCR2_USB, MSTPCR2);
}
#else
#define usbf_start_clock(x)
#define usbf_stop_clock(x)
#endif /* if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
#endif /* ifndef __M66592_UDC_H__ */ #endif /* ifndef __M66592_UDC_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment