#define EBUS_DMA_RESET_TIMEOUT 10000
-static void __ebus_dma_reset(struct ebus_dma_info *p)
+static void __ebus_dma_reset(struct ebus_dma_info *p, int no_drain)
{
int i;
u32 val = 0;
writel(EBDMA_CSR_RESET, p->regs + EBDMA_CSR);
+ udelay(1);
+
+ if (no_drain)
+ return;
for (i = EBUS_DMA_RESET_TIMEOUT; i > 0; i--) {
val = readl(p->regs + EBDMA_CSR);
{
struct ebus_dma_info *p = dev_id;
unsigned long flags;
- u32 csr;
+ u32 csr = 0;
spin_lock_irqsave(&p->lock, flags);
csr = readl(p->regs + EBDMA_CSR);
}
return IRQ_NONE;
+
}
int ebus_dma_register(struct ebus_dma_info *p)
{
+ u32 csr;
+
if (!p->regs)
return -EINVAL;
- if (p->flags & ~(EBUS_DMA_FLAG_USE_EBDMA_HANDLER))
+ if (p->flags & ~(EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
+ EBUS_DMA_FLAG_TCI_DISABLE))
return -EINVAL;
if ((p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) && !p->callback)
return -EINVAL;
if (!strlen(p->name))
return -EINVAL;
- __ebus_dma_reset(p);
+ __ebus_dma_reset(p, 1);
+
+ csr = EBDMA_CSR_BURST_SZ_16 | EBDMA_CSR_EN_CNT;
+
+ if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE)
+ csr |= EBDMA_CSR_TCI_DIS;
+
+ writel(csr, p->regs + EBDMA_CSR);
return 0;
}
void ebus_dma_prepare(struct ebus_dma_info *p, int write)
{
unsigned long flags;
+ u32 csr;
spin_lock_irqsave(&p->lock, flags);
- __ebus_dma_reset(p);
- writel(EBDMA_CSR_INT_EN |
- ((write) ? EBDMA_CSR_WRITE : 0) |
+ __ebus_dma_reset(p, 0);
+
+ csr = (EBDMA_CSR_INT_EN |
EBDMA_CSR_EN_CNT |
EBDMA_CSR_BURST_SZ_16 |
- EBDMA_CSR_EN_NEXT, p->regs + EBDMA_CSR);
+ EBDMA_CSR_EN_NEXT);
+
+ if (write)
+ csr |= EBDMA_CSR_WRITE;
+ if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE)
+ csr |= EBDMA_CSR_TCI_DIS;
+
+ writel(csr, p->regs + EBDMA_CSR);
+
spin_unlock_irqrestore(&p->lock, flags);
}
EXPORT_SYMBOL(ebus_dma_prepare);
void ebus_dma_enable(struct ebus_dma_info *p, int on)
{
unsigned long flags;
- u32 csr;
+ u32 orig_csr, csr;
spin_lock_irqsave(&p->lock, flags);
- csr = readl(p->regs + EBDMA_CSR);
+ orig_csr = csr = readl(p->regs + EBDMA_CSR);
if (on)
csr |= EBDMA_CSR_EN_DMA;
else
csr &= ~EBDMA_CSR_EN_DMA;
- writel(csr, p->regs + EBDMA_CSR);
+ if ((orig_csr & EBDMA_CSR_EN_DMA) !=
+ (csr & EBDMA_CSR_EN_DMA))
+ writel(csr, p->regs + EBDMA_CSR);
spin_unlock_irqrestore(&p->lock, flags);
}
EXPORT_SYMBOL(ebus_dma_enable);
sun_pci_dma_current.len,
sun_pci_dma_current.direction);
+ ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
+
if (ebus_dma_request(&sun_pci_fd_ebus_dma,
sun_pci_dma_current.addr,
sun_pci_dma_current.len))
BUG();
-
- ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
}
static void sun_pci_fd_disable_dma(void)
static void sun_pci_fd_set_dma_mode(int mode)
{
+ if (mode == DMA_MODE_WRITE)
+ sun_pci_dma_pending.direction = PCI_DMA_TODEVICE;
+ else
+ sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE;
+
ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
}
prom_getproperty(edev->prom_node, "status",
state, sizeof(state));
- if(!strncmp(state, "disabled", 8))
+ if (!strncmp(state, "disabled", 8))
return 0;
- /* XXX ioremap */
- sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start;
FLOPPY_IRQ = edev->irqs[0];
/* Make sure the high density bit is set, some systems
sun_pci_ebus_dev = ebus->self;
spin_lock_init(&sun_pci_fd_ebus_dma.lock);
+
/* XXX ioremap */
sun_pci_fd_ebus_dma.regs = edev->resource[1].start;
if (!sun_pci_fd_ebus_dma.regs)
return 0;
- sun_pci_fd_ebus_dma.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
+
+ sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
+ EBUS_DMA_FLAG_TCI_DISABLE);
sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
sun_pci_fd_ebus_dma.client_cookie = NULL;
sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
if (ebus_dma_register(&sun_pci_fd_ebus_dma))
return 0;
+ /* XXX ioremap */
+ sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start;
+
sun_fdops.fd_inb = sun_pci_fd_inb;
sun_fdops.fd_outb = sun_pci_fd_outb;