Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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
+54 −1
Original line number Diff line number Diff line
@@ -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;
}
+54 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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
@@ -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 */
@@ -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,
@@ -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;
@@ -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,
@@ -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__ */