public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] OMAP: MUSB HOST support on 2430SDP
@ 2007-05-21  7:28 Pandita, Vikram
  2007-05-22 22:47 ` Kevin Hilman
  2007-05-24 19:02 ` [PATCH] " Kevin Hilman
  0 siblings, 2 replies; 6+ messages in thread
From: Pandita, Vikram @ 2007-05-21  7:28 UTC (permalink / raw)
  To: linux-omap-open-source


Fix Mentor controller DMA for OMAP2430/3430

Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
Signed-off-by: Nishant Kamat <nskamat@ti.com>

---
 musb_gadget.c |   24 +++
 musb_host.c   |   39 ------
 musbdefs.h    |    3
 musbhsdma.c   |  377 +++++++++++++++---------------
 omap2430.c    |  124 ++++++++++++++-----
 omap2430.h    |   42 +++++-
 6 files changed, 363 insertions(+), 246 deletions(-)
---
diff -purN -X ./dontdiff a/drivers/usb/musb/musbdefs.h
b/drivers/usb/musb/musbdefs.h
--- a/drivers/usb/musb/musbdefs.h	2007-05-21 12:32:53.000000000
+0530
+++ b/drivers/usb/musb/musbdefs.h	2007-05-21 11:37:51.000000000
+0530
@@ -206,7 +206,8 @@ enum musb_g_ep0_state {
  * directly with the "flat" model, or after setting up an index
register.
  */
 
-#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430)
+#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) || \
+				     defined(CONFIG_ARCH_OMAP3430)
 /* REVISIT indexed access seemed to
  * misbehave (on DaVinci) for at least peripheral IN ...
  */
diff -purN -X ./dontdiff a/drivers/usb/musb/musb_gadget.c
b/drivers/usb/musb/musb_gadget.c
--- a/drivers/usb/musb/musb_gadget.c	2007-05-21 12:32:53.000000000
+0530
+++ b/drivers/usb/musb/musb_gadget.c	2007-05-21 11:37:51.000000000
+0530
@@ -159,12 +159,24 @@ __acquires(ep->musb->Lock)
 static void nuke(struct musb_ep *ep, const int status)
 {
 	struct musb_request	*req = NULL;
+	void __iomem *epio = ep->pThis->aLocalEnd[ep->bEndNumber].regs;
 
 	ep->busy = 1;
 
 	if (is_dma_capable() && ep->dma) {
 		struct dma_controller	*c = ep->pThis->pDmaController;
 		int value;
+		if (ep->is_in) {
+			musb_writew(epio, MGC_O_HDRC_TXCSR,
+					0 | MGC_M_TXCSR_FLUSHFIFO);
+			musb_writew(epio, MGC_O_HDRC_TXCSR,
+					0 | MGC_M_TXCSR_FLUSHFIFO);
+		} else {
+			musb_writew(epio, MGC_O_HDRC_RXCSR,
+					0 | MGC_M_RXCSR_FLUSHFIFO);
+			musb_writew(epio, MGC_O_HDRC_RXCSR,
+					0 | MGC_M_RXCSR_FLUSHFIFO);
+		}
 
 		value = c->channel_abort(ep->dma);
 		DBG(value ? 1 : 6, "%s: abort DMA --> %d\n", ep->name,
value);
@@ -454,12 +466,12 @@ void musb_g_tx(struct musb *musb, u8 bEn
 				musb_writew(epio, MGC_O_HDRC_TXCSR,
wCsrVal);
 				/* ensure writebuffer is empty */
 				wCsrVal = musb_readw(epio,
MGC_O_HDRC_TXCSR);
+				pRequest->actual +=
pEnd->dma->dwActualLength;
 				DBG(4, "TXCSR%d %04x, dma off, "
 						"len %Zd, req %p\n",
 					bEnd, wCsrVal,
 					pEnd->dma->dwActualLength,
 					pRequest);
-				pRequest->actual +=
pEnd->dma->dwActualLength;
 			}
 
 			if (is_dma || pRequest->actual ==
pRequest->length) {
@@ -475,8 +487,9 @@ void musb_g_tx(struct musb *musb, u8 bEn
 							== 0)
 #ifdef CONFIG_USB_INVENTRA_DMA
 					|| (is_dma &&
-						(pRequest->actual
-							<
pEnd->wPacketSize))
+						((!dma->bDesiredMode) ||

+						    (pRequest->actual & 
+						    (pEnd->wPacketSize -
1))))
 #endif
 				) {
 					/* on dma completion, fifo may
not
@@ -489,6 +502,7 @@ void musb_g_tx(struct musb *musb, u8 bEn
 					musb_writew(epio,
MGC_O_HDRC_TXCSR,
 							MGC_M_TXCSR_MODE
 							|
MGC_M_TXCSR_TXPKTRDY);
+					pRequest->zero = 0;
 				}
 
 				/* ... or if not, then complete it */
@@ -1143,6 +1157,8 @@ static int musb_gadget_queue(struct usb_
 
 	if (!ep || !req)
 		return -EINVAL;
+	if (!req->buf)
+		return -ENODATA;
 
 	pEnd = to_musb_ep(ep);
 	musb = pEnd->pThis;
@@ -1275,6 +1291,8 @@ int musb_gadget_set_halt(struct usb_ep *
 	struct musb_request	*pRequest = NULL;
 	int			status = 0;
 
+	if (!ep)
+		return -EINVAL;
 	pBase = musb->pRegs;
 
 	spin_lock_irqsave(&musb->Lock, flags);
diff -purN -X ./dontdiff a/drivers/usb/musb/musb_host.c
b/drivers/usb/musb/musb_host.c
--- a/drivers/usb/musb/musb_host.c	2007-05-21 12:32:53.000000000
+0530
+++ b/drivers/usb/musb/musb_host.c	2007-05-21 11:37:51.000000000
+0530
@@ -435,21 +435,6 @@ musb_advance_schedule(struct musb *pThis
 		qh = pEnd->out_qh;
 	qh = musb_giveback(qh, urb, 0);
 
-#ifdef CONFIG_USB_INVENTRA_DMA
-	/* REVISIT udelay reportedly works around issues in unmodified
-	 * Mentor RTL before v1.5, where it doesn't disable the pull-up
-	 * resisters in high speed mode.  That causes signal reflection
-	 * and errors because inter packet IDLE time vanishes.
-	 *
-	 * Yes, this delay makes DMA-OUT a bit slower than PIO.  But
-	 * without it, some devices are unusable.  But there seem to be
-	 * other issues too, at least on DaVinci; the delay improves
-	 * some full speed cases, and being DMA-coupled is strange...
-	 */
-	if (is_dma_capable() && !is_in && pEnd->tx_channel)
-		udelay(15);	/* 10 usec ~= 1x 512byte packet */
-#endif
-
 	if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
 		DBG(4, "... next ep%d %cX urb %p\n",
 				pEnd->bLocalEnd, is_in ? 'R' : 'T',
@@ -498,6 +483,9 @@ static u8 musb_host_packet_rx(struct mus
 
 	// MGC_SelectEnd(pBase, bEnd);
 	wRxCount = musb_readw(epio, MGC_O_HDRC_RXCOUNT);
+	DBG(3, "RX%d count %d, buffer %p len %d/%d\n", bEnd, wRxCount,
+			pUrb->transfer_buffer, qh->offset,
+			pUrb->transfer_buffer_length);
 
 	/* unload FIFO */
 	if (usb_pipeisoc(nPipe)) {
@@ -1271,20 +1259,6 @@ void musb_host_tx(struct musb *pThis, u8
 
 	/* REVISIT this looks wrong... */
 	if (!status || dma || usb_pipeisoc(nPipe)) {
-
-#ifdef CONFIG_USB_INVENTRA_DMA
-		/* mode 0 or last short packet)
-		 * REVISIT how about ZLP?
-		 */
-		if ((dma->bDesiredMode == 0)
-				|| (dma->dwActualLength
-					& (qh->maxpacket - 1))) {
-			/* Send out the packet first ... */
-			MGC_SelectEnd(pBase, bEnd);
-			musb_writew(epio, MGC_O_HDRC_TXCSR,
-					MGC_M_TXCSR_TXPKTRDY);
-		}
-#endif
 		if (dma)
 			wLength = dma->dwActualLength;
 		else
@@ -1542,11 +1516,9 @@ void musb_host_rx(struct musb *pThis, u8
 		musb_writew(pEnd->regs, MGC_O_HDRC_RXCSR, wVal);
 
 #ifdef CONFIG_USB_INVENTRA_DMA
-		pUrb->actual_length += xfer_len;
-		qh->offset += xfer_len;
-
 		/* bDone if pUrb buffer is full or short packet is recd
*/
-		bDone = (pUrb->actual_length >=
pUrb->transfer_buffer_length)
+		bDone = ((pUrb->actual_length + xfer_len) >=
+				pUrb->transfer_buffer_length)
 			|| (dma->dwActualLength & (qh->maxpacket - 1));
 
 		/* send IN token for next packet, without AUTOREQ */
@@ -1969,6 +1941,7 @@ static int musb_cleanup_urb(struct urb *
 			| MGC_M_TXCSR_H_RXSTALL
 			| MGC_M_TXCSR_H_NAKTIMEOUT
 			| MGC_M_TXCSR_H_ERROR
+			| MGC_M_TXCSR_TXPKTRDY
 			);
 		musb_writew(epio, MGC_O_HDRC_TXCSR, csr);
 		/* REVISIT may need to clear FLUSHFIFO ... */
diff -purN -X ./dontdiff a/drivers/usb/musb/musbhsdma.c
b/drivers/usb/musb/musbhsdma.c
--- a/drivers/usb/musb/musbhsdma.c	2007-05-21 12:32:53.000000000
+0530
+++ b/drivers/usb/musb/musbhsdma.c	2007-05-21 11:37:51.000000000
+0530
@@ -1,6 +1,6 @@
 /******************************************************************
  * Copyright 2005 Mentor Graphics Corporation
- * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2005-2007 by Texas Instruments
  *
  * This file is part of the Inventra Controller Driver for Linux.
  *
@@ -32,88 +32,108 @@
  ******************************************************************/
 
 /*
- * Interface to Mentor's DMA engine
+ * Implementation for the DMA controller within the MUSBMHDRC.
  */
 
+#include <linux/device.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
-
 #include "musbdefs.h"
 
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#include "omap2430.h"
+#endif
 
-/****************************** CONSTANTS
********************************/
-
-#define MGC_O_HSDMA_BASE    0x200
-#define MGC_O_HSDMA_INTR    0x200
-
-#define MGC_O_HSDMA_CONTROL 4
-#define MGC_O_HSDMA_ADDRESS 8
-#define MGC_O_HSDMA_COUNT   0xc
+#define MGC_O_HSDMA_BASE		0x200
+#define MGC_O_HSDMA_INTR		(MGC_O_HSDMA_BASE + 0)
+#define MGC_O_HSDMA_CONTROL		0x4
+#define MGC_O_HSDMA_ADDRESS		0x8
+#define MGC_O_HSDMA_COUNT		0xc
 
 #define MGC_HSDMA_CHANNEL_OFFSET(_bChannel, _bOffset)		\
 		(MGC_O_HSDMA_BASE + (_bChannel << 4) + _bOffset)
 
 /* control register (16-bit): */
-#define MGC_S_HSDMA_ENABLE	0
-#define MGC_S_HSDMA_TRANSMIT	1
-#define MGC_S_HSDMA_MODE1	2
-#define MGC_S_HSDMA_IRQENABLE	3
-#define MGC_S_HSDMA_ENDPOINT	4
-#define MGC_S_HSDMA_BUSERROR	8
-#define MGC_S_HSDMA_BURSTMODE	9
-#define MGC_M_HSDMA_BURSTMODE	(3 << MGC_S_HSDMA_BURSTMODE)
-#define MGC_HSDMA_BURSTMODE_UNSPEC  0
-#define MGC_HSDMA_BURSTMODE_INCR4   1
-#define MGC_HSDMA_BURSTMODE_INCR8   2
-#define MGC_HSDMA_BURSTMODE_INCR16  3
-
-#define MGC_HSDMA_CHANNELS 8
-
-/******************************* Types
********************************/
-
-struct hsdma_channel {
-	struct dma_channel Channel;
-	struct hsdma *pController;
-	u32 dwStartAddress;
-	u32 dwCount;
-	u8 bIndex;
-	u8 bEnd;
-	u8 bTransmit;
+#define MGC_S_HSDMA_ENABLE		0
+#define MGC_S_HSDMA_TRANSMIT		1
+#define MGC_S_HSDMA_MODE1		2
+#define MGC_S_HSDMA_IRQENABLE		3
+#define MGC_S_HSDMA_ENDPOINT		4
+#define MGC_S_HSDMA_BUSERROR		8
+#define MGC_S_HSDMA_BURSTMODE		9
+#define MGC_M_HSDMA_BURSTMODE		(3 << MGC_S_HSDMA_BURSTMODE)
+#define MGC_HSDMA_BURSTMODE_UNSPEC	0
+#define MGC_HSDMA_BURSTMODE_INCR4	1
+#define MGC_HSDMA_BURSTMODE_INCR8	2
+#define MGC_HSDMA_BURSTMODE_INCR16	3
+
+#define MGC_HSDMA_CHANNELS		8
+
+struct musb_dma_controller;
+
+struct musb_dma_channel {
+	struct dma_channel		Channel;
+	struct musb_dma_controller	*pController;
+	u32				dwStartAddress;
+	u32				dwCount;
+	u16				wMaxPacketSize;
+	u8				bIndex;
+	u8				bEnd;
+	u8				bTransmit;
 };
 
-struct hsdma {
-	struct dma_controller Controller;
-	struct hsdma_channel aChannel[MGC_HSDMA_CHANNELS];
-	void *pDmaPrivate;
-	void __iomem *pCoreBase;
-	u8 bChannelCount;
-	u8 bmUsedChannels;
+struct musb_dma_controller {
+	struct dma_controller		Controller;
+	struct musb_dma_channel		aChannel[MGC_HSDMA_CHANNELS];
+	void 				*pDmaPrivate;
+	void __iomem 			*pCoreBase;
+	u8 				bChannelCount;
+	u8 				bmUsedChannels;
+	u8				irq;
 };
 
-/****************************** FUNCTIONS
********************************/
-
-static int hsdma_start(struct dma_controller *c)
+static int dma_controller_start(struct dma_controller *c)
 {
 	/* nothing to do */
 	return 0;
 }
 
-static int hsdma_stop(struct dma_controller *c)
+static void dma_channel_release(struct dma_channel *pChannel);
+
+static int dma_controller_stop(struct dma_controller *c)
 {
-	/* nothing to do */
+	struct musb_dma_controller *pController =
+		container_of(c, struct musb_dma_controller, Controller);
+	struct musb *pThis = (struct musb *) pController->pDmaPrivate;
+	struct dma_channel *pChannel;
+	u8 bBit;
+
+	if (pController->bmUsedChannels != 0) {
+		dev_err(pThis->controller,
+			"Stopping DMA controller while channel
active\n");
+
+		for (bBit = 0; bBit < MGC_HSDMA_CHANNELS; bBit++) {
+			if (pController->bmUsedChannels & (1 << bBit)) {
+				pChannel =
&(pController->aChannel[bBit].Channel);
+				dma_channel_release(pChannel);
+
+				if (!pController->bmUsedChannels)
+					break;
+			}
+		}
+	}
 	return 0;
 }
 
-static struct dma_channel *
-hsdma_channel_alloc(struct dma_controller *c,
-		struct musb_hw_ep *hw_ep,
-		u8 bTransmit)
+static struct dma_channel* dma_channel_allocate(struct dma_controller
*c,
+				struct musb_hw_ep *hw_ep, u8 bTransmit)
 {
 	u8 bBit;
 	struct dma_channel *pChannel = NULL;
-	struct hsdma_channel *pImplChannel = NULL;
-	struct hsdma *pController;
+	struct musb_dma_channel *pImplChannel = NULL;
+	struct musb_dma_controller *pController =
+			container_of(c, struct musb_dma_controller,
Controller);
 
-	pController = container_of(c, struct hsdma, Controller);
 	for (bBit = 0; bBit < MGC_HSDMA_CHANNELS; bBit++) {
 		if (!(pController->bmUsedChannels & (1 << bBit))) {
 			pController->bmUsedChannels |= (1 << bBit);
@@ -135,48 +155,33 @@ hsdma_channel_alloc(struct dma_controlle
 	return pChannel;
 }
 
-static void hsdma_channel_release(struct dma_channel *pChannel)
+static void dma_channel_release(struct dma_channel *pChannel)
 {
-	struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
+	struct musb_dma_channel *pImplChannel =
+		(struct musb_dma_channel *) pChannel->pPrivateData;
 
-	pImplChannel->pController->bmUsedChannels &=
-	    ~(1 << pImplChannel->bIndex);
-	pChannel->bStatus = MGC_DMA_STATUS_FREE;
-}
-
-static void clear_state(struct dma_channel *pChannel)
-{
-	struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
-	struct hsdma *pController = pImplChannel->pController;
-	u8 *pBase = pController->pCoreBase;
-	u8 bChannel = pImplChannel->bIndex;
-
-	musb_writew(pBase,
-		    MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_CONTROL),
-		    0);
-	musb_writel(pBase,
-		    MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_ADDRESS),
-		    0);
-	musb_writel(pBase,
-		    MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_COUNT),
-		    0);
-
-	pChannel->dwActualLength = 0L;
+	pChannel->dwActualLength = 0;
 	pImplChannel->dwStartAddress = 0;
 	pImplChannel->dwCount = 0;
+
+	pImplChannel->pController->bmUsedChannels &=
+		~(1 << pImplChannel->bIndex);
+
+	pChannel->bStatus = MGC_DMA_STATUS_UNKNOWN;
 }
 
-static u8 configure_channel(struct dma_channel *pChannel,
-				  u16 wPacketSize, u8 bMode,
-				  dma_addr_t dma_addr, u32 dwLength)
+static void configure_channel(struct dma_channel *pChannel,
+				u16 wPacketSize, u8 bMode,
+				dma_addr_t dma_addr, u32 dwLength)
 {
-	struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
-	struct hsdma *pController = pImplChannel->pController;
+	struct musb_dma_channel *pImplChannel =
+		(struct musb_dma_channel *) pChannel->pPrivateData;
+	struct musb_dma_controller *pController =
pImplChannel->pController;
 	u8 *pBase = pController->pCoreBase;
 	u8 bChannel = pImplChannel->bIndex;
 	u16 wCsr = 0;
 
-	DBG(2, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
+	DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
 	    pChannel, wPacketSize, dma_addr, dwLength, bMode);
 
 	if (bMode) {
@@ -213,45 +218,32 @@ static u8 configure_channel(struct dma_c
 	musb_writew(pBase,
 		    MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_CONTROL),
 		    wCsr);
-
-	return TRUE;
 }
 
-static int hsdma_channel_program(struct dma_channel * pChannel,
-				  u16 wPacketSize, u8 bMode,
-				  dma_addr_t dma_addr, u32 dwLength)
-{
-	struct hsdma_channel *pImplChannel = pChannel->pPrivateData;
-
-	DBG(2, "pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
-	       wPacketSize, dma_addr, dwLength, bMode);
+static int dma_channel_program(struct dma_channel * pChannel,
+				u16 wPacketSize, u8 bMode,
+				dma_addr_t dma_addr, u32 dwLength)
+{
+	struct musb_dma_channel *pImplChannel =
+			(struct musb_dma_channel *)
pChannel->pPrivateData;
+
+	DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
+		pImplChannel->bEnd,
+		pImplChannel->bTransmit ? "Tx" : "Rx",
+		wPacketSize, dma_addr, dwLength, bMode);
 
-	BUG_ON(pChannel->bStatus != MGC_DMA_STATUS_FREE);
+	BUG_ON(pChannel->bStatus == MGC_DMA_STATUS_UNKNOWN ||
+		pChannel->bStatus == MGC_DMA_STATUS_BUSY);
 
-	pChannel->dwActualLength = 0L;
+	pChannel->dwActualLength = 0;
 	pImplChannel->dwStartAddress = dma_addr;
 	pImplChannel->dwCount = dwLength;
-
+	pImplChannel->wMaxPacketSize = wPacketSize;
 	pChannel->bStatus = MGC_DMA_STATUS_BUSY;
 
 	if ((bMode == 1) && (dwLength >= wPacketSize)) {
-
-#if 0
-		/* mode 1 sends an extra IN token at the end of
-		 * full packet transfer in host Rx
-		 */
-		if (dwLength % wPacketSize == 0)
-			dwLength -= wPacketSize;
-
-		/* mode 1 doesn't give an interrupt on short packet */
-		configure_channel(pChannel, wPacketSize, 1, dma_addr,
-				  dwLength & ~(wPacketSize - 1));
-		/* the rest (<= pkt_size) will be transferred in mode 0
*/
-#endif
-
 		configure_channel(pChannel, wPacketSize, 1, dma_addr,
 				  dwLength);
-
 	} else
 		configure_channel(pChannel, wPacketSize, 0, dma_addr,
 				  dwLength);
@@ -259,32 +251,70 @@ static int hsdma_channel_program(struct 
 	return TRUE;
 }
 
-// REVISIT...
-static int hsdma_channel_abort(struct dma_channel *pChannel)
+static int dma_channel_abort(struct dma_channel *pChannel)
 {
-	clear_state(pChannel);
-	pChannel->bStatus = MGC_DMA_STATUS_FREE;
+	struct musb_dma_channel *pImplChannel =
+		(struct musb_dma_channel *) pChannel->pPrivateData;
+	u8 bChannel = pImplChannel->bIndex;
+	u8 *pBase = pImplChannel->pController->pCoreBase;
+	u16 csr;
+
+	if (pChannel->bStatus == MGC_DMA_STATUS_BUSY) {
+		if (pImplChannel->bTransmit) {
+
+			csr = musb_readw(pBase, 
+
MGC_END_OFFSET(pImplChannel->bEnd,MGC_O_HDRC_TXCSR));
+			csr &= ~(MGC_M_TXCSR_AUTOSET |
+				 MGC_M_TXCSR_DMAENAB |
+				 MGC_M_TXCSR_DMAMODE);
+			musb_writew(pBase, 
+
MGC_END_OFFSET(pImplChannel->bEnd,MGC_O_HDRC_TXCSR), 
+					csr);
+		}
+		else {
+			csr = musb_readw(pBase, 
+
MGC_END_OFFSET(pImplChannel->bEnd,MGC_O_HDRC_RXCSR));
+			csr &= ~(MGC_M_RXCSR_AUTOCLEAR |
+				 MGC_M_RXCSR_DMAENAB |
+				 MGC_M_RXCSR_DMAMODE);
+			musb_writew(pBase, 
+
MGC_END_OFFSET(pImplChannel->bEnd,MGC_O_HDRC_RXCSR), 
+					csr);
+		}
+
+		musb_writew(pBase,
+		   MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_CONTROL), 0);
+		musb_writel(pBase,
+		   MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_ADDRESS), 0);
+		musb_writel(pBase,
+		   MGC_HSDMA_CHANNEL_OFFSET(bChannel,
MGC_O_HSDMA_COUNT), 0);
+
+		pChannel->bStatus = MGC_DMA_STATUS_FREE;
+	}
 	return 0;
 }
 
-static irqreturn_t hsdma_irq(int irq, void *pPrivateData)
+static irqreturn_t dma_controller_irq(int irq, void *pPrivateData)
 {
+	struct musb_dma_controller *pController =
+		(struct musb_dma_controller *)pPrivateData;
+	struct musb_dma_channel *pImplChannel;
+	u8 *pBase = pController->pCoreBase;
+	struct dma_channel *pChannel;
 	u8 bChannel;
 	u16 wCsr;
 	u32 dwAddress;
-	struct hsdma_channel *pImplChannel;
-	struct hsdma *pController = pPrivateData;
-	u8 *pBase = pController->pCoreBase;
-	struct dma_channel *pChannel;
-	u8 bIntr = musb_readb(pBase, MGC_O_HSDMA_INTR);
+	u8 bIntr;
+	irqreturn_t retval = IRQ_NONE;
 
+	bIntr = musb_readb(pBase, MGC_O_HSDMA_INTR);
 	if (!bIntr)
-		return IRQ_NONE;
+		goto done;
 
 	for (bChannel = 0; bChannel < MGC_HSDMA_CHANNELS; bChannel++) {
 		if (bIntr & (1 << bChannel)) {
-
-			pImplChannel = &pController->aChannel[bChannel];
+			pImplChannel = (struct musb_dma_channel *)
+
&(pController->aChannel[bChannel]);
 			pChannel = &pImplChannel->Channel;
 
 			wCsr = musb_readw(pBase,
@@ -296,8 +326,8 @@ static irqreturn_t hsdma_irq(int irq, vo
 				    MGC_DMA_STATUS_BUS_ABORT;
 			} else {
 				dwAddress = musb_readl(pBase,
-
MGC_HSDMA_CHANNEL_OFFSET
-						       (bChannel,
+
MGC_HSDMA_CHANNEL_OFFSET(
+							bChannel,
 
MGC_O_HSDMA_ADDRESS));
 				pChannel->dwActualLength =
 				    dwAddress -
pImplChannel->dwStartAddress;
@@ -309,55 +339,57 @@ static irqreturn_t hsdma_irq(int irq, vo
 				    (pChannel->dwActualLength <
 					pImplChannel->dwCount) ?
 					"=> reconfig 0": "=> complete");
-#if 0
-				if (pChannel->dwActualLength <
-				    pImplChannel->dwCount) {
-					/* mode 1 sends an extra IN
request if
-					the last packet is a complete
packet */
-					u16 newcsr =
MGC_ReadCsr16(pBase,
-
MGC_O_HDRC_RXCSR,
-
pImplChannel->bEnd);
-					newcsr &=
~(MGC_M_RXCSR_H_AUTOREQ |
-
MGC_M_RXCSR_H_REQPKT);
-					MGC_WriteCsr16(pBase,
MGC_O_HDRC_RXCSR,
-
pImplChannel->bEnd,
-
MGC_M_RXCSR_H_WZC_BITS |
-								newcsr);
-
-					configure_channel(pChannel,
-
pImplChannel->wMaxPacketSize,
-						0, dwAddress,
-						pImplChannel->dwCount -
-
pChannel->dwActualLength);
-				}
-				else
-#endif
-				{
-					pChannel->bStatus =
MGC_DMA_STATUS_FREE;
-					/* completed */
+
+				u8 devctl = musb_readb(pBase,
+						MGC_O_HDRC_DEVCTL);
+
+				pChannel->bStatus = MGC_DMA_STATUS_FREE;
+
+				/* completed */
+				if ((devctl & MGC_M_DEVCTL_HM)
+				    && (pImplChannel->bTransmit)
+				    && ((pChannel->bDesiredMode == 0)
+					|| (pChannel->dwActualLength &
+
(pImplChannel->wMaxPacketSize - 1)))
+				   ) {
+					/* Send out the packet */
+					MGC_SelectEnd(pBase,
+						pImplChannel->bEnd);
+					musb_writew(pBase, 
+
MGC_END_OFFSET(pImplChannel->bEnd,MGC_O_HDRC_TXCSR), 
+						MGC_M_TXCSR_TXPKTRDY);
+				} else
 					musb_dma_completion(
 
pController->pDmaPrivate,
 						pImplChannel->bEnd,
 
pImplChannel->bTransmit);
-				}
 			}
 		}
 	}
-	return IRQ_HANDLED;
+	retval = IRQ_HANDLED;
+done:
+	return retval;
 }
 
-void dma_controller_destroy(struct dma_controller *pController)
+void dma_controller_destroy(struct dma_controller *c)
 {
-	struct hsdma *pHsController = pController->pPrivateData;
+	struct musb_dma_controller *pController =
+		(struct musb_dma_controller *) c->pPrivateData;
 
-	pHsController->Controller.pPrivateData = NULL;
-	kfree(pHsController);
+	if (!pController)
+		return;
+
+	if (pController->irq)
+		free_irq(pController->irq, c);
+
+	kfree(pController);
+	c->pPrivateData = NULL;
 }
 
 struct dma_controller *__init
 dma_controller_create(struct musb *pThis, void __iomem *pCoreBase)
 {
-	struct hsdma *pController;
+	struct musb_dma_controller *pController;
 	struct device *dev = pThis->controller;
 	struct platform_device *pdev = to_platform_device(dev);
 	int irq = platform_get_irq(pdev, 1);
@@ -367,7 +399,8 @@ dma_controller_create(struct musb *pThis
 		return NULL;
 	}
 
-	if (!(pController = kzalloc(sizeof *pController, GFP_KERNEL)))
+	if (!(pController = kzalloc(sizeof(struct musb_dma_controller),
+				GFP_KERNEL)))
 		return NULL;
 
 	pController->bChannelCount = MGC_HSDMA_CHANNELS;
@@ -375,19 +408,21 @@ dma_controller_create(struct musb *pThis
 	pController->pCoreBase = pCoreBase;
 
 	pController->Controller.pPrivateData = pController;
-	pController->Controller.start = hsdma_start;
-	pController->Controller.stop = hsdma_stop;
-	pController->Controller.channel_alloc = hsdma_channel_alloc;
-	pController->Controller.channel_release = hsdma_channel_release;
-	pController->Controller.channel_program = hsdma_channel_program;
-	pController->Controller.channel_abort = hsdma_channel_abort;
+	pController->Controller.start = dma_controller_start;
+	pController->Controller.stop = dma_controller_stop;
+	pController->Controller.channel_alloc = dma_channel_allocate;
+	pController->Controller.channel_release = dma_channel_release;
+	pController->Controller.channel_program = dma_channel_program;
+	pController->Controller.channel_abort = dma_channel_abort;
 
-	if (request_irq(irq, hsdma_irq, IRQF_DISABLED,
+	if (request_irq(irq, dma_controller_irq, IRQF_DISABLED,
 			pThis->controller->bus_id,
&pController->Controller)) {
 		dev_err(dev, "request_irq %d failed!\n", irq);
-		kfree(pController);
+		dma_controller_destroy(&pController->Controller);
 		return NULL;
 	}
 
+	pController->irq = irq;
+
 	return &pController->Controller;
 }
diff -purN -X ./dontdiff a/drivers/usb/musb/omap2430.c
b/drivers/usb/musb/omap2430.c
--- a/drivers/usb/musb/omap2430.c	2007-05-21 12:32:53.000000000
+0530
+++ b/drivers/usb/musb/omap2430.c	2007-05-21 11:37:51.000000000
+0530
@@ -36,68 +36,134 @@
 #include "musbdefs.h"
 #include "omap2430.h"
 
+#ifdef CONFIG_ARCH_OMAP3430
+#define	get_cpu_rev()	2
+#endif
 
-static int dma_off;
 
 void musb_platform_enable(struct musb *musb)
 {
-	if (is_dma_capable() && dma_off)
-		printk(KERN_WARNING "%s %s: dma not reactivated\n",
-				__FILE__, __FUNCTION__);
-	else
-		dma_off = 1;
 }
-
 void musb_platform_disable(struct musb *musb)
 {
-	if (is_dma_capable()) {
-		printk(KERN_WARNING "%s %s: dma still active\n",
-				__FILE__, __FUNCTION__);
-		dma_off = 1;
-	}
 }
-
 static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
 {
 }
 
 static void omap_set_vbus(struct musb *musb, int is_on)
 {
-	WARN_ON(is_on && is_peripheral_active(musb));
-	return omap_vbus_power(musb, is_on, 0);
+	u8		devctl;
+	/* HDRC controls CPEN, but beware current surges during device
+	 * connect.  They can trigger transient overcurrent conditions
+	 * that must be ignored.
+	 */
+
+	devctl = musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL);
+
+	if (is_on) {
+		musb->is_active = 1;
+		musb->xceiv.default_a = 1;
+		musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
+		devctl |= MGC_M_DEVCTL_SESSION;
+
+		MUSB_HST_MODE(musb);
+	} else {
+		musb->is_active = 0;
+
+		/* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
+		 * jumping right to B_IDLE...
+		 */
+
+		musb->xceiv.default_a = 0;
+		musb->xceiv.state = OTG_STATE_B_IDLE;
+		devctl &= ~MGC_M_DEVCTL_SESSION;
+
+		MUSB_DEV_MODE(musb);
+	}
+	musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, devctl);
+
+	DBG(1, "VBUS %s, devctl %02x "
+		/* otg %3x conf %08x prcm %08x */ "\n",
+		otg_state_string(musb),
+		musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL));
+}
+static int omap_set_power(struct otg_transceiver *x, unsigned mA)
+{
+	return 0;
 }
 
+int musb_platform_resume(struct musb *musb);
+
 int __init musb_platform_init(struct musb *musb)
 {
-	/* Erratum - reset value of STP has pull-down.
-	   Change it to pull-up. */
+#if defined(CONFIG_ARCH_OMAP2430)
 	omap_cfg_reg(AE5_2430_USB0HS_STP);
-
-	/* start clock */
+	/* get the clock */
 	musb->clock = clk_get((struct device *)musb->controller,
"usbhs_ick");
-	clk_enable(musb->clock);
+#else
+	musb->clock = clk_get((struct device *)musb->controller,
"hsusb_ick");
+#endif
+	if(IS_ERR(musb->clock))
+        	return PTR_ERR(musb->clock);
+
+	musb_platform_resume(musb);
 
-	omap_writel(omap_readl(OTG_INTERFSEL) | (1<<0), OTG_INTERFSEL);
-	omap_writel(omap_readl(OTG_SYSCONFIG) |
-		    ((1 << 12) | (1 << 3) | (1 << 2)),
-		    OTG_SYSCONFIG);
+	OTG_INTERFSEL_REG |= ULPI_12PIN;
 
 	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
 			"sysstatus 0x%x, intrfsel 0x%x, simenable
0x%x\n",
-			omap_readl(OTG_REVISION),
omap_readl(OTG_SYSCONFIG),
-			omap_readl(OTG_SYSSTATUS),
omap_readl(OTG_INTERFSEL),
-			omap_readl(OTG_SIMENABLE));
+			OTG_REVISION_REG, OTG_SYSCONFIG_REG,
OTG_SYSSTATUS_REG,
+			OTG_INTERFSEL_REG, OTG_SIMENABLE_REG);
 
-	musb->board_set_vbus = omap_set_vbus;
 	omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
 
+
+	if (is_host_enabled(musb))
+		musb->board_set_vbus = omap_set_vbus;
+	if (is_peripheral_enabled(musb))
+		musb->xceiv.set_power = omap_set_power;
+
 	return 0;
 }
 
+int musb_platform_suspend(struct musb *musb)
+{
+	/* in any role */
+	OTG_FORCESTDBY_REG &= ~ENABLEFORCE; /* disable MSTANDBY */
+	OTG_SYSCONFIG_REG &= FORCESTDBY;	/* enable force standby
*/
+	OTG_SYSCONFIG_REG &= ~AUTOIDLE;		/* disable auto idle */
+	OTG_SYSCONFIG_REG |= SMARTIDLE;		/* enable smart idle */
+	OTG_FORCESTDBY_REG |= ENABLEFORCE; /* enable MSTANDBY */
+	OTG_SYSCONFIG_REG |= AUTOIDLE;		/* enable auto idle */
+
+	clk_disable(musb->clock);
+	return 0;
+}
+
+int musb_platform_resume(struct musb *musb)
+{
+	clk_enable(musb->clock);
+
+	OTG_FORCESTDBY_REG &= ~ENABLEFORCE; /* disable MSTANDBY */
+	OTG_SYSCONFIG_REG |= SMARTSTDBY;	/* enable smart standby
*/
+	OTG_SYSCONFIG_REG &= ~AUTOIDLE;		/* disable auto idle */
+	OTG_SYSCONFIG_REG |= SMARTIDLE;		/* enable smart idle */
+	OTG_SYSCONFIG_REG |= AUTOIDLE;		/* enable auto idle */
+
+	return 0;
+}
+
+
 int musb_platform_exit(struct musb *musb)
 {
+
 	omap_vbus_power(musb, 0 /*off*/, 1);
-	clk_disable(musb->clock);
+
+	musb_platform_suspend(musb);
+
+	clk_put(musb->clock);
+	musb->clock = 0;
 
 	return 0;
 }
diff -purN -X ./dontdiff a/drivers/usb/musb/omap2430.h
b/drivers/usb/musb/omap2430.h
--- a/drivers/usb/musb/omap2430.h	2007-05-21 12:32:53.000000000
+0530
+++ b/drivers/usb/musb/omap2430.h	2007-05-21 11:37:51.000000000
+0530
@@ -10,21 +10,45 @@
 #ifndef __MUSB_OMAP243X_H__
 #define __MUSB_OMAP243X_H__
 
-#ifdef CONFIG_ARCH_OMAP2430
-
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#include <asm/arch/hardware.h>
 #include <asm/arch/usb.h>
-
 /*
  * OMAP2430-specific definitions
  */
 
 #define MENTOR_BASE_OFFSET	0
-#define HS_OTG(offset)		(OMAP243X_HS_BASE + (offset))
-#define OTG_REVISION		HS_OTG(0x400)
-#define OTG_SYSCONFIG		HS_OTG(0x404)
-#define OTG_SYSSTATUS		HS_OTG(0x408)
-#define OTG_INTERFSEL		HS_OTG(0x40c)
-#define OTG_SIMENABLE		HS_OTG(0x410)
+#if	defined(CONFIG_ARCH_OMAP2430)
+#define	OMAP_HSOTG_BASE		(OMAP243X_HS_BASE)
+#elif	defined(CONFIG_ARCH_OMAP3430)
+#define	OMAP_HSOTG_BASE		(HS_BASE)
+#endif
+#define OMAP_HSOTG(offset)	__REG32(OMAP_HSOTG_BASE + 0x400 +
(offset))
+#define OTG_REVISION_REG	OMAP_HSOTG(0x0)
+#define OTG_SYSCONFIG_REG	OMAP_HSOTG(0x4)
+#	define	MIDLEMODE	12	/* bit position */
+#	define	FORCESTDBY		(0 << MIDLEMODE)
+#	define	NOSTDBY			(1 << MIDLEMODE)
+#	define	SMARTSTDBY		(2 << MIDLEMODE)
+#	define	SIDLEMODE		3	/* bit position */
+#	define	FORCEIDLE		(0 << SIDLEMODE)
+#	define	NOIDLE			(1 << SIDLEMODE)
+#	define	SMARTIDLE		(2 << SIDLEMODE)
+#	define	ENABLEWAKEUP		(1 << 2)
+#	define	SOFTRST			(1 << 1)
+#	define	AUTOIDLE		(1 << 0)
+#define OTG_SYSSTATUS_REG	OMAP_HSOTG(0x8)
+#	define	RESETDONE		(1 << 0)
+#define OTG_INTERFSEL_REG	OMAP_HSOTG(0xc)
+#	define	EXTCP			(1 << 2)
+#	define	PHYSEL		0	/* bit position */
+#	define	UTMI_8BIT		(0 << PHYSEL)
+#	define	ULPI_12PIN		(1 << PHYSEL)
+#	define	ULPI_8PIN		(2 << PHYSEL)
+#define OTG_SIMENABLE_REG     	OMAP_HSOTG(0x10)
+#	define	TM1			(1 << 0)
+#define OTG_FORCESTDBY_REG	OMAP_HSOTG(0x14)
+#	define	ENABLEFORCE		(1 << 0)
 
 #endif	/* CONFIG_ARCH_OMAP2430 */

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-05-25 22:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-21  7:28 [PATCH] OMAP: MUSB HOST support on 2430SDP Pandita, Vikram
2007-05-22 22:47 ` Kevin Hilman
2007-05-22 23:28   ` Syed Mohammed, Khasim
2007-05-23  6:11   ` [RESUBMIT PATCH] " Pandita, Vikram
2007-05-25 22:02     ` Tony Lindgren
2007-05-24 19:02 ` [PATCH] " Kevin Hilman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox