*/
#include <linux/module.h>
-#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
return davinci_vbus_power(musb, is_on, 0);
}
-static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r)
+static irqreturn_t davinci_interrupt(int irq, void *__hci)
{
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
>> DAVINCI_USB_TXINT_SHIFT;
musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK)
>> DAVINCI_USB_USBINT_SHIFT;
- musb->int_regs = r;
/* treat DRVVBUS irq like an ID change IRQ (for now) */
if (tmp & (1 << (8 + DAVINCI_USB_USBINT_SHIFT))) {
/* irq stays asserted until EOI is written */
musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
- musb->int_regs = NULL;
spin_unlock_irqrestore(&musb->Lock, flags);
/* REVISIT we sometimes get unhandled IRQs
*/
pThis->bSetAddress = FALSE;
pThis->ackpend = MGC_M_CSR0_P_SVDRXPKTRDY;
- if (req->wLength == 0)
+ if (req->wLength == 0) {
+ if (req->bRequestType & USB_DIR_IN)
+ pThis->ackpend |= MGC_M_CSR0_TXPKTRDY;
pThis->ep0_state = MGC_END0_STAGE_ACKWAIT;
- else if (req->bRequestType & USB_DIR_IN) {
+ } else if (req->bRequestType & USB_DIR_IN) {
pThis->ep0_state = MGC_END0_STAGE_TX;
musb_writew(regs, MGC_O_HDRC_CSR0, MGC_M_CSR0_P_SVDRXPKTRDY);
while ((musb_readw(regs, MGC_O_HDRC_CSR0)
ep->busy = 1;
spin_unlock(&musb->Lock);
- if (is_dma_capable() && req->mapped) {
- dma_unmap_single(musb->controller,
- req->request.dma,
- req->request.length,
- req->bTx
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- req->request.dma = DMA_ADDR_INVALID;
- req->mapped = 0;
+ if (is_dma_capable()) {
+ if (req->mapped) {
+ dma_unmap_single(musb->controller,
+ req->request.dma,
+ req->request.length,
+ req->bTx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ req->request.dma = DMA_ADDR_INVALID;
+ req->mapped = 0;
+ } else
+ dma_sync_single_for_cpu(musb->controller,
+ req->request.dma,
+ req->request.length,
+ req->bTx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
}
if (pRequest->status == 0)
DBG(5, "%s done request %p, %d/%d\n",
{
struct musb_ep *pEnd;
struct musb_request *pRequest;
- struct musb *pThis;
+ struct musb *musb;
int status = 0;
unsigned long lockflags;
return -EINVAL;
pEnd = to_musb_ep(ep);
- pThis = pEnd->pThis;
+ musb = pEnd->pThis;
pRequest = to_musb_request(req);
- pRequest->musb = pThis;
+ pRequest->musb = musb;
if (pRequest->ep != pEnd)
return -EINVAL;
pRequest->bEnd = pEnd->bEndNumber;
pRequest->bTx = pEnd->is_in;
- if (is_dma_capable()
- && pRequest->request.dma == DMA_ADDR_INVALID
- && pRequest->request.length >= MIN_DMA_REQUEST
- && pEnd->dma) {
- pRequest->request.dma = dma_map_single(pThis->controller,
- pRequest->request.buf,
- pRequest->request.length,
- pRequest->bTx
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- pRequest->mapped = 1;
+ if (is_dma_capable() && pEnd->dma) {
+ if (pRequest->request.dma == DMA_ADDR_INVALID) {
+ pRequest->request.dma = dma_map_single(
+ musb->controller,
+ pRequest->request.buf,
+ pRequest->request.length,
+ pRequest->bTx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ pRequest->mapped = 1;
+ } else {
+ dma_sync_single_for_device(musb->controller,
+ pRequest->request.dma,
+ pRequest->request.length,
+ pRequest->bTx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ pRequest->mapped = 0;
+ }
} else if (!req->buf) {
return -ENODATA;
} else
pRequest->mapped = 0;
- spin_lock_irqsave(&pThis->Lock, lockflags);
+ spin_lock_irqsave(&musb->Lock, lockflags);
/* don't queue if the ep is down */
if (!pEnd->desc) {
/* it this is the head of the queue, start i/o ... */
if (!pEnd->busy && &pRequest->request.list == pEnd->req_list.next)
- musb_ep_restart(pThis, pRequest);
+ musb_ep_restart(musb, pRequest);
cleanup:
- spin_unlock_irqrestore(&pThis->Lock, lockflags);
+ spin_unlock_irqrestore(&musb->Lock, lockflags);
return status;
}
/* later things are modified based on usage */
struct list_head req_list;
+ /* true if lock must be dropped but req_list may not be advanced */
u8 busy;
};
******************************************************************/
#include <linux/module.h>
-#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
);
spin_unlock(&musb->Lock);
- usb_hcd_giveback_urb(musb_to_hcd(musb), urb, musb->int_regs);
+ usb_hcd_giveback_urb(musb_to_hcd(musb), urb);
spin_lock(&musb->Lock);
}
}
if (unlikely(dma_channel_status(dma) == MGC_DMA_STATUS_BUSY)) {
- /* SHOULD NEVER HAPPEN */
- ERR("RX%d dma busy\n", bEnd);
+ /* SHOULD NEVER HAPPEN ... but at least DaVinci has done it */
+ ERR("RX%d dma busy, csr %04x\n", bEnd, wRxCsrVal);
goto finish;
}
}
#endif
if (dma && (wRxCsrVal & MGC_M_RXCSR_DMAENAB)) {
+ xfer_len = dma->dwActualLength;
+
+ wVal &= ~(MGC_M_RXCSR_DMAENAB
+ | MGC_M_RXCSR_H_AUTOREQ
+ | MGC_M_RXCSR_AUTOCLEAR
+ | MGC_M_RXCSR_RXPKTRDY);
+ musb_writew(pEnd->regs, MGC_O_HDRC_RXCSR, wVal);
#ifdef CONFIG_USB_INVENTRA_DMA
- xfer_len = dma->dwActualLength;
pUrb->actual_length += xfer_len;
qh->offset += xfer_len;
bDone = (pUrb->actual_length >= pUrb->transfer_buffer_length)
|| (dma->dwActualLength & (qh->maxpacket - 1));
- wVal &= ~(MGC_M_RXCSR_DMAENAB
- | MGC_M_RXCSR_H_AUTOREQ
- | MGC_M_RXCSR_AUTOCLEAR
- | MGC_M_RXCSR_RXPKTRDY);
-
- MGC_WriteCsr16(pBase, MGC_O_HDRC_RXCSR, bEnd, wVal);
- MGC_WriteCsr16(pBase, MGC_O_HDRC_RXCSR, bEnd, wVal);
-
/* send IN token for next packet, without AUTOREQ */
if (!bDone) {
wVal |= MGC_M_RXCSR_H_REQPKT;
MGC_ReadCsr16(pBase, MGC_O_HDRC_RXCOUNT, bEnd));
#else
bDone = TRUE;
- xfer_len = dma->dwActualLength;
#endif
} else if (pUrb->status == -EINPROGRESS) {
/* if no errors, be sure a packet is ready for unloading */
int idle;
int wBestDiff;
int nBestEnd, nEnd;
- struct musb_hw_ep *hw_ep;
+ struct musb_hw_ep *hw_ep = NULL;
struct list_head *head = NULL;
/* use fixed hardware for control and bulk */
code = sprintf(buffer,
"TUSB6010: devconf %08x, phy enable %08x drive %08x"
"\n\totg %03x timer %08x"
- "\n\tprcm conf %08x mgmt %08x; intmask %08x"
+ "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
"\n",
musb_readl(pThis->ctrl_base, TUSB_DEV_CONF),
musb_readl(pThis->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
musb_readl(pThis->ctrl_base, TUSB_DEV_OTG_TIMER),
musb_readl(pThis->ctrl_base, TUSB_PRCM_CONF),
musb_readl(pThis->ctrl_base, TUSB_PRCM_MNGMT),
+ musb_readl(pThis->ctrl_base, TUSB_INT_SRC),
musb_readl(pThis->ctrl_base, TUSB_INT_MASK));
if (code <= 0)
goto done;
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
#include <linux/usb/musb.h>
struct musb;
#include "otg.h"
-/* REVISIT tune this */
-#define MIN_DMA_REQUEST 1 /* use PIO below this xfer size */
-
#ifdef CONFIG_USB_MUSB_OTG
struct musb {
spinlock_t Lock;
struct clk *clock;
- irqreturn_t (*isr)(int, void *, struct pt_regs *);
+ irqreturn_t (*isr)(int, void *);
struct work_struct irq_work;
#ifdef CONFIG_USB_MUSB_HDRC_HCD
u8 int_usb;
u16 int_rx;
u16 int_tx;
- struct pt_regs *int_regs;
struct otg_transceiver xceiv;
*
*/
#include <linux/module.h>
-#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
*/
#include <linux/module.h>
-#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
musb_writeb(regs, MGC_O_HDRC_POWER, MGC_M_POWER_ISOUPDATE
| MGC_M_POWER_SOFTCONN
| MGC_M_POWER_HSENAB
+ /* ENSUSPEND wedges tusb */
// | MGC_M_POWER_ENSUSPEND
);
devctl = musb_readb(regs, MGC_O_HDRC_DEVCTL);
devctl &= ~MGC_M_DEVCTL_SESSION;
- if (is_otg_enabled(pThis)) {
+ if (is_otg_enabled(musb)) {
/* session started after:
* (a) ID-grounded irq, host mode;
* (b) vbus present/connect IRQ, peripheral mode;
else
devctl |= MGC_M_DEVCTL_SESSION;
- } else if (is_host_enabled(pThis)) {
+ } else if (is_host_enabled(musb)) {
/* assume ID pin is hard-wired to ground */
devctl |= MGC_M_DEVCTL_SESSION;
#ifdef CONFIG_ARCH_OMAP243X
-static irqreturn_t generic_interrupt(int irq, void *__hci, struct pt_regs *r)
+static irqreturn_t generic_interrupt(int irq, void *__hci)
{
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
musb->int_usb = musb_readb(musb->pRegs, MGC_O_HDRC_INTRUSB);
musb->int_tx = musb_readw(musb->pRegs, MGC_O_HDRC_INTRTX);
musb->int_rx = musb_readw(musb->pRegs, MGC_O_HDRC_INTRRX);
- musb->int_regs = r;
if (musb->int_usb || musb->int_tx || musb->int_rx)
retval = musb_interrupt(musb);
if (is_dma_capable() && musb->pDmaController) {
struct dma_controller *c = musb->pDmaController;
-//
(void) c->stop(c->pPrivateData);
dma_controller_factory.destroy(c);
}
bad_config:
#endif
default:
- dev_dbg(dev, "incompatible Kconfig role setting\n");
+ dev_err(dev, "incompatible Kconfig role setting\n");
return -EINVAL;
}
INIT_WORK(&pThis->irq_work, musb_irq_work, pThis);
#ifdef CONFIG_SYSFS
- device_create_file(dev, &dev_attr_mode);
- device_create_file(dev, &dev_attr_cable);
+ status = device_create_file(dev, &dev_attr_mode);
+ status = device_create_file(dev, &dev_attr_cable);
+ status = 0;
#endif
return status;
* bridge to a platform device; this driver then suffices.
*/
+#ifndef CONFIG_USB_INVENTRA_FIFO
+static u64 *orig_dma_mask;
+#endif
+
static int __devinit musb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
return -ENOMEM;
}
+#ifndef CONFIG_USB_INVENTRA_FIFO
+ /* clobbered by use_dma=n */
+ orig_dma_mask = dev->dma_mask;
+#endif
return musb_init_controller(dev, irq, base);
}
static int __devexit musb_remove(struct platform_device *pdev)
{
struct musb *musb = dev_to_musb(&pdev->dev);
+ void __iomem *ctrl_base = musb->ctrl_base;
/* this gets called on rmmod.
* - Host mode: host may still be active
usb_remove_hcd(musb_to_hcd(musb));
#endif
musb_free(musb);
+ iounmap(ctrl_base);
device_init_wakeup(&pdev->dev, 0);
+#ifndef CONFIG_USB_INVENTRA_FIFO
+ dev->dma_mask = orig_dma_mask;
+#endif
return 0;
}
* at most mA current to be drawn from VBUS during a Default-B session
* (that is, while VBUS exceeds 4.4V). In Default-A (including pure host
* mode), or low power Default-B sessions, something else supplies power.
+ * Caller must take care of locking.
*/
static int tusb_set_power(struct otg_transceiver *x, unsigned mA)
{
* (to be fixed in rev3 silicon) ... symptoms include disconnect
* or looping suspend/resume cycles
*/
-static void tusb_set_clock_source(struct musb *musb, int mode)
+static void tusb_set_clock_source(struct musb *musb, unsigned mode)
{
void __iomem *base = musb->ctrl_base;
u32 reg;
reg = musb_readl(base, TUSB_PRCM_CONF);
reg &= ~TUSB_PRCM_CONF_SYS_CLKSEL(0x3);
+ /* 0 = refclk (clkin, XI)
+ * 1 = PHY 60 MHz (internal PLL)
+ * 2 = not supported
+ * 3 = NOR clock (huh?)
+ */
if (mode > 0)
reg |= TUSB_PRCM_CONF_SYS_CLKSEL(mode & 0x3);
musb_writel(base, TUSB_PRCM_CONF, reg);
+
+ // FIXME tusb6010_platform_retime(mode == 0);
}
/*
}
}
-static irqreturn_t tusb_interrupt(int irq, void *__hci, struct pt_regs *r)
+static irqreturn_t tusb_interrupt(int irq, void *__hci)
{
struct musb *musb = __hci;
void __iomem *base = musb->ctrl_base;
int_src = musb_readl(base, TUSB_INT_SRC) & ~TUSB_INT_SRC_RESERVED_BITS;
DBG(3, "TUSB IRQ %08x\n", int_src);
- musb->int_regs = r;
musb->int_usb = (u8) int_src;
/* Acknowledge wake-up source interrupts */
musb_writel(base, TUSB_INT_SRC_CLEAR,
int_src & ~TUSB_INT_MASK_RESERVED_BITS);
- musb->int_regs = NULL;
musb_platform_try_idle(musb);
spin_unlock_irqrestore(&musb->Lock, flags);
return TUSB_REV_MAJOR(musb_readl(base, TUSB_INT_CTRL_REV));
}
-static int tusb_start(struct musb *musb)
+static int __devinit tusb_start(struct musb *musb)
{
void __iomem *base = musb->ctrl_base;
- int ret = -1;
+ int ret = 0;
unsigned long flags;
u32 reg;
ret = musb->board_set_power(1);
if (ret != 0) {
printk(KERN_ERR "tusb: Cannot enable TUSB6010\n");
- goto err;
+ return ret;
}
spin_lock_irqsave(&musb->Lock, flags);
return 0;
err:
+ spin_unlock_irqrestore(&musb->Lock, flags);
+
if (musb->board_set_power)
musb->board_set_power(0);