Skip to content

Commit

Permalink
USB: m66592-udc: Add support for SH7722 USBF
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yoshihiro Shimoda authored and Greg Kroah-Hartman committed Feb 1, 2008
1 parent 9da0068 commit 8c73aff
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 1 deletion.
10 changes: 10 additions & 0 deletions drivers/usb/gadget/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,16 @@ config USB_M66592
default USB_GADGET
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
boolean "Toshiba TC86C001 'Goku-S'"
depends on PCI
Expand Down
55 changes: 54 additions & 1 deletion drivers/usb/gadget/m66592-udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand All @@ -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[] = {
Expand Down Expand Up @@ -360,13 +366,15 @@ 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;
ep->fifoaddr = M66592_D1FIFO;
ep->fifosel = M66592_D1FIFOSEL;
ep->fifoctr = M66592_D1FIFOCTR;
ep->fifotrn = M66592_D1FIFOTRN;
#endif
} else {
ep->use_dma = 0;
ep->fifoaddr = M66592_CFIFO;
Expand Down Expand Up @@ -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),
Expand All @@ -636,25 +666,34 @@ 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);
udelay(1);
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
}

/*-------------------------------------------------------------------------*/
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
54 changes: 54 additions & 0 deletions drivers/usb/gadget/m66592-udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@
#define M66592_P_TST_J 0x0001 /* PERI TEST J */
#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_LDRV 0x8000 /* b15: Drive Current Adjust */
#define M66592_BIGEND 0x0100 /* b8: Big endian mode */
Expand All @@ -91,6 +96,7 @@
#define M66592_PKTM 0x0020 /* b5: Packet mode */
#define M66592_DENDE 0x0010 /* b4: Dend enable */
#define M66592_OBUS 0x0004 /* b2: OUTbus mode */
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */

#define M66592_CFIFO 0x10
#define M66592_D0FIFO 0x14
Expand All @@ -103,9 +109,13 @@
#define M66592_REW 0x4000 /* b14: Buffer rewind */
#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */
#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_8 0x0000 /* 8bit */
#define M66592_MBW_16 0x0400 /* 16bit */
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */
#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */
#define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */
Expand Down Expand Up @@ -530,8 +540,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592,
{
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;
insw(fifoaddr, buf, len);
#endif
}

static inline void m66592_write(struct m66592 *m66592, u16 val,
Expand All @@ -545,6 +560,24 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
void *buf, unsigned long len)
{
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;

len = len / 2;
Expand All @@ -553,6 +586,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
unsigned char *p = buf + len*2;
outb(*p, fifoaddr);
}
#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
}

static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
Expand All @@ -570,6 +604,26 @@ static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
#define m66592_bset(m66592, val, 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__ */


0 comments on commit 8c73aff

Please sign in to comment.