summaryrefslogtreecommitdiff
path: root/arch/mips/alchemy/common/dbdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/alchemy/common/dbdma.c')
-rw-r--r--arch/mips/alchemy/common/dbdma.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 19d5642c16d9..6c2c2010bbae 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -30,12 +30,13 @@
*
*/
+#include <linux/dma-map-ops.h> /* for dma_default_coherent */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/module.h>
+#include <linux/export.h>
#include <linux/syscore_ops.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -261,7 +262,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
au1x_dma_chan_t *cp;
/*
- * We do the intialization on the first channel allocation.
+ * We do the initialization on the first channel allocation.
* We have to wait because of the interrupt handler initialization
* which can't be done successfully during board set up.
*/
@@ -341,7 +342,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
(dtp->dev_flags & DEV_FLAGS_SYNC))
i |= DDMA_CFG_SYNC;
cp->ddma_cfg = i;
- au_sync();
+ wmb(); /* drain writebuffer */
/*
* Return a non-zero value that can be used to find the channel
@@ -411,8 +412,8 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
* and if we try that first we are likely to not waste larger
* slabs of memory.
*/
- desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t),
- GFP_KERNEL|GFP_DMA);
+ desc_base = (u32)kmalloc_array(entries, sizeof(au1x_ddma_desc_t),
+ GFP_KERNEL|GFP_DMA);
if (desc_base == 0)
return 0;
@@ -574,7 +575,7 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
dp++;
}
- /* Make last descrptor point to the first. */
+ /* Make last descriptor point to the first. */
dp--;
dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base));
ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;
@@ -623,17 +624,18 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
/*
- * There is an errata on the Au1200/Au1550 parts that could result
- * in "stale" data being DMA'ed. It has to do with the snoop logic on
- * the cache eviction buffer. DMA_NONCOHERENT is on by default for
- * these parts. If it is fixed in the future, these dma_cache_inv will
- * just be nothing more than empty macros. See io.h.
+ * There is an erratum on certain Au1200/Au1550 revisions that could
+ * result in "stale" data being DMA'ed. It has to do with the snoop
+ * logic on the cache eviction buffer. dma_default_coherent is set
+ * to false on these parts.
*/
- dma_cache_wback_inv((unsigned long)buf, nbytes);
+ if (!dma_default_coherent)
+ dma_cache_wback_inv(KSEG0ADDR(buf), nbytes);
dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
- au_sync();
+ wmb(); /* drain writebuffer */
dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
ctp->chan_ptr->ddma_dbell = 0;
+ wmb(); /* force doorbell write out to dma engine */
/* Get next descriptor pointer. */
ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
@@ -685,17 +687,18 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
#endif
/*
- * There is an errata on the Au1200/Au1550 parts that could result in
- * "stale" data being DMA'ed. It has to do with the snoop logic on the
- * cache eviction buffer. DMA_NONCOHERENT is on by default for these
- * parts. If it is fixed in the future, these dma_cache_inv will just
- * be nothing more than empty macros. See io.h.
+ * There is an erratum on certain Au1200/Au1550 revisions that could
+ * result in "stale" data being DMA'ed. It has to do with the snoop
+ * logic on the cache eviction buffer. dma_default_coherent is set
+ * to false on these parts.
*/
- dma_cache_inv((unsigned long)buf, nbytes);
+ if (!dma_default_coherent)
+ dma_cache_inv(KSEG0ADDR(buf), nbytes);
dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
- au_sync();
+ wmb(); /* drain writebuffer */
dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
ctp->chan_ptr->ddma_dbell = 0;
+ wmb(); /* force doorbell write out to dma engine */
/* Get next descriptor pointer. */
ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
@@ -760,7 +763,7 @@ void au1xxx_dbdma_stop(u32 chanid)
cp = ctp->chan_ptr;
cp->ddma_cfg &= ~DDMA_CFG_EN; /* Disable channel */
- au_sync();
+ wmb(); /* drain writebuffer */
while (!(cp->ddma_stat & DDMA_STAT_H)) {
udelay(1);
halt_timeout++;
@@ -771,7 +774,7 @@ void au1xxx_dbdma_stop(u32 chanid)
}
/* clear current desc valid and doorbell */
cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
- au_sync();
+ wmb(); /* drain writebuffer */
}
EXPORT_SYMBOL(au1xxx_dbdma_stop);
@@ -789,9 +792,9 @@ void au1xxx_dbdma_start(u32 chanid)
cp = ctp->chan_ptr;
cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */
- au_sync();
+ wmb(); /* drain writebuffer */
cp->ddma_dbell = 0;
- au_sync();
+ wmb(); /* drain writebuffer */
}
EXPORT_SYMBOL(au1xxx_dbdma_start);
@@ -832,7 +835,7 @@ u32 au1xxx_get_dma_residue(u32 chanid)
/* This is only valid if the channel is stopped. */
rv = cp->ddma_bytecnt;
- au_sync();
+ wmb(); /* drain writebuffer */
return rv;
}
@@ -868,7 +871,7 @@ static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
au1x_dma_chan_t *cp;
intstat = dbdma_gptr->ddma_intstat;
- au_sync();
+ wmb(); /* drain writebuffer */
chan_index = __ffs(intstat);
ctp = chan_tab_ptr[chan_index];
@@ -877,7 +880,7 @@ static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
/* Reset interrupt. */
cp->ddma_irq = 0;
- au_sync();
+ wmb(); /* drain writebuffer */
if (ctp->chan_callback)
ctp->chan_callback(irq, ctp->chan_callparam);
@@ -964,7 +967,7 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
dp->dscr_source1 = dscr->dscr_source1;
dp->dscr_cmd1 = dscr->dscr_cmd1;
nbytes = dscr->dscr_cmd1;
- /* Allow the caller to specifiy if an interrupt is generated */
+ /* Allow the caller to specify if an interrupt is generated */
dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V;
ctp->chan_ptr->ddma_dbell = 0;
@@ -979,7 +982,7 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
static unsigned long alchemy_dbdma_pm_data[NUM_DBDMA_CHANS + 1][6];
-static int alchemy_dbdma_suspend(void)
+static int alchemy_dbdma_suspend(void *data)
{
int i;
void __iomem *addr;
@@ -1016,7 +1019,7 @@ static int alchemy_dbdma_suspend(void)
return 0;
}
-static void alchemy_dbdma_resume(void)
+static void alchemy_dbdma_resume(void *data)
{
int i;
void __iomem *addr;
@@ -1041,16 +1044,20 @@ static void alchemy_dbdma_resume(void)
}
}
-static struct syscore_ops alchemy_dbdma_syscore_ops = {
+static const struct syscore_ops alchemy_dbdma_syscore_ops = {
.suspend = alchemy_dbdma_suspend,
.resume = alchemy_dbdma_resume,
};
+static struct syscore alchemy_dbdma_syscore = {
+ .ops = &alchemy_dbdma_syscore_ops,
+};
+
static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
{
int ret;
- dbdev_tab = kzalloc(sizeof(dbdev_tab_t) * DBDEV_TAB_SIZE, GFP_KERNEL);
+ dbdev_tab = kcalloc(DBDEV_TAB_SIZE, sizeof(dbdev_tab_t), GFP_KERNEL);
if (!dbdev_tab)
return -ENOMEM;
@@ -1061,14 +1068,14 @@ static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
dbdma_gptr->ddma_config = 0;
dbdma_gptr->ddma_throttle = 0;
dbdma_gptr->ddma_inten = 0xffff;
- au_sync();
+ wmb(); /* drain writebuffer */
ret = request_irq(irq, dbdma_interrupt, 0, "dbdma", (void *)dbdma_gptr);
if (ret)
printk(KERN_ERR "Cannot grab DBDMA interrupt!\n");
else {
dbdma_initialized = 1;
- register_syscore_ops(&alchemy_dbdma_syscore_ops);
+ register_syscore(&alchemy_dbdma_syscore);
}
return ret;