* [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* Re: [PATCH] OMAP: MUSB HOST support on 2430SDP
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-24 19:02 ` [PATCH] " Kevin Hilman
1 sibling, 2 replies; 6+ messages in thread
From: Kevin Hilman @ 2007-05-22 22:47 UTC (permalink / raw)
To: Pandita, Vikram; +Cc: linux-omap-open-source
On Mon, 2007-05-21 at 12:58 +0530, Pandita, Vikram wrote:
> Fix Mentor controller DMA for OMAP2430/3430
>
> Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
> Signed-off-by: Nishant Kamat <nskamat@ti.com>
Vikram,
These patches are line-wrapped. Can you resend without the wraps.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH] OMAP: MUSB HOST support on 2430SDP
2007-05-22 22:47 ` Kevin Hilman
@ 2007-05-22 23:28 ` Syed Mohammed, Khasim
2007-05-23 6:11 ` [RESUBMIT PATCH] " Pandita, Vikram
1 sibling, 0 replies; 6+ messages in thread
From: Syed Mohammed, Khasim @ 2007-05-22 23:28 UTC (permalink / raw)
To: Kevin Hilman, Pandita, Vikram; +Cc: linux-omap-open-source
Vikram,
>
>These patches are line-wrapped. Can you resend without the wraps.
>
Here is how we do it for OUTLOOK.
In OUTLOOK, Tools > Options > Mail Format > International Options "deselect the check box for Auto select encoding for outgoing messages".
Select Preferred encoding for outgoing messages as Western European (ISO).
Regards,
Khasim
_______________________________________________
>-----Original Message-----
>From: linux-omap-open-source-bounces+x0khasim=ti.com@linux.omap.com
>[mailto:linux-omap-open-source-bounces+x0khasim=ti.com@linux.omap.com] On
>Behalf Of Kevin Hilman
>Sent: Tuesday, May 22, 2007 5:47 PM
>To: Pandita, Vikram
>Cc: linux-omap-open-source@linux.omap.com
>Subject: Re: [PATCH] OMAP: MUSB HOST support on 2430SDP
>
>On Mon, 2007-05-21 at 12:58 +0530, Pandita, Vikram wrote:
>> Fix Mentor controller DMA for OMAP2430/3430
>>
>> Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
>> Signed-off-by: Nishant Kamat <nskamat@ti.com>
>
>Vikram,
>
>These patches are line-wrapped. Can you resend without the wraps.
>
>Thanks,
>
>Kevin
>
>_______________________________________________
>Linux-omap-open-source mailing list
>Linux-omap-open-source@linux.omap.com
>http://linux.omap.com/mailman/listinfo/linux-omap-open-source
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RESUBMIT PATCH] OMAP: MUSB HOST support on 2430SDP
2007-05-22 22:47 ` Kevin Hilman
2007-05-22 23:28 ` Syed Mohammed, Khasim
@ 2007-05-23 6:11 ` Pandita, Vikram
2007-05-25 22:02 ` Tony Lindgren
1 sibling, 1 reply; 6+ messages in thread
From: Pandita, Vikram @ 2007-05-23 6:11 UTC (permalink / raw)
To: linux-omap-open-source
All
[Resubmitting patch after removal of line wrap]
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:45:49.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:45:49.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:45:49.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:45:49.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:45:49.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:45:49.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
* Re: [PATCH] OMAP: MUSB HOST support on 2430SDP
2007-05-21 7:28 [PATCH] OMAP: MUSB HOST support on 2430SDP Pandita, Vikram
2007-05-22 22:47 ` Kevin Hilman
@ 2007-05-24 19:02 ` Kevin Hilman
1 sibling, 0 replies; 6+ messages in thread
From: Kevin Hilman @ 2007-05-24 19:02 UTC (permalink / raw)
To: Pandita, Vikram; +Cc: linux-omap-open-source
Pandita, Vikram wrote:
> Fix Mentor controller DMA for OMAP2430/3430
>
> Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
> Signed-off-by: Nishant Kamat <nskamat@ti.com>
>
With this patch, plus the plat_uds.c patch, I confirm that MUSB host is working on the 2430SDP.
Acked-by: Kevin Hilman <khilman@mvista.com>
^ 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