xref: /openbmc/linux/drivers/dma/sa11x0-dma.c (revision 50437bff7f7374f86837986f66e15e73a364f894)
16365beadSRussell King /*
26365beadSRussell King  * SA11x0 DMAengine support
36365beadSRussell King  *
46365beadSRussell King  * Copyright (C) 2012 Russell King
56365beadSRussell King  *   Derived in part from arch/arm/mach-sa1100/dma.c,
66365beadSRussell King  *   Copyright (C) 2000, 2001 by Nicolas Pitre
76365beadSRussell King  *
86365beadSRussell King  * This program is free software; you can redistribute it and/or modify
96365beadSRussell King  * it under the terms of the GNU General Public License version 2 as
106365beadSRussell King  * published by the Free Software Foundation.
116365beadSRussell King  */
126365beadSRussell King #include <linux/sched.h>
136365beadSRussell King #include <linux/device.h>
146365beadSRussell King #include <linux/dmaengine.h>
156365beadSRussell King #include <linux/init.h>
166365beadSRussell King #include <linux/interrupt.h>
176365beadSRussell King #include <linux/kernel.h>
186365beadSRussell King #include <linux/module.h>
196365beadSRussell King #include <linux/platform_device.h>
206365beadSRussell King #include <linux/sa11x0-dma.h>
216365beadSRussell King #include <linux/slab.h>
226365beadSRussell King #include <linux/spinlock.h>
236365beadSRussell King 
24*50437bffSRussell King #include "virt-dma.h"
25*50437bffSRussell King 
266365beadSRussell King #define NR_PHY_CHAN	6
276365beadSRussell King #define DMA_ALIGN	3
286365beadSRussell King #define DMA_MAX_SIZE	0x1fff
296365beadSRussell King #define DMA_CHUNK_SIZE	0x1000
306365beadSRussell King 
316365beadSRussell King #define DMA_DDAR	0x00
326365beadSRussell King #define DMA_DCSR_S	0x04
336365beadSRussell King #define DMA_DCSR_C	0x08
346365beadSRussell King #define DMA_DCSR_R	0x0c
356365beadSRussell King #define DMA_DBSA	0x10
366365beadSRussell King #define DMA_DBTA	0x14
376365beadSRussell King #define DMA_DBSB	0x18
386365beadSRussell King #define DMA_DBTB	0x1c
396365beadSRussell King #define DMA_SIZE	0x20
406365beadSRussell King 
416365beadSRussell King #define DCSR_RUN	(1 << 0)
426365beadSRussell King #define DCSR_IE		(1 << 1)
436365beadSRussell King #define DCSR_ERROR	(1 << 2)
446365beadSRussell King #define DCSR_DONEA	(1 << 3)
456365beadSRussell King #define DCSR_STRTA	(1 << 4)
466365beadSRussell King #define DCSR_DONEB	(1 << 5)
476365beadSRussell King #define DCSR_STRTB	(1 << 6)
486365beadSRussell King #define DCSR_BIU	(1 << 7)
496365beadSRussell King 
506365beadSRussell King #define DDAR_RW		(1 << 0)	/* 0 = W, 1 = R */
516365beadSRussell King #define DDAR_E		(1 << 1)	/* 0 = LE, 1 = BE */
526365beadSRussell King #define DDAR_BS		(1 << 2)	/* 0 = BS4, 1 = BS8 */
536365beadSRussell King #define DDAR_DW		(1 << 3)	/* 0 = 8b, 1 = 16b */
546365beadSRussell King #define DDAR_Ser0UDCTr	(0x0 << 4)
556365beadSRussell King #define DDAR_Ser0UDCRc	(0x1 << 4)
566365beadSRussell King #define DDAR_Ser1SDLCTr	(0x2 << 4)
576365beadSRussell King #define DDAR_Ser1SDLCRc	(0x3 << 4)
586365beadSRussell King #define DDAR_Ser1UARTTr	(0x4 << 4)
596365beadSRussell King #define DDAR_Ser1UARTRc	(0x5 << 4)
606365beadSRussell King #define DDAR_Ser2ICPTr	(0x6 << 4)
616365beadSRussell King #define DDAR_Ser2ICPRc	(0x7 << 4)
626365beadSRussell King #define DDAR_Ser3UARTTr	(0x8 << 4)
636365beadSRussell King #define DDAR_Ser3UARTRc	(0x9 << 4)
646365beadSRussell King #define DDAR_Ser4MCP0Tr	(0xa << 4)
656365beadSRussell King #define DDAR_Ser4MCP0Rc	(0xb << 4)
666365beadSRussell King #define DDAR_Ser4MCP1Tr	(0xc << 4)
676365beadSRussell King #define DDAR_Ser4MCP1Rc	(0xd << 4)
686365beadSRussell King #define DDAR_Ser4SSPTr	(0xe << 4)
696365beadSRussell King #define DDAR_Ser4SSPRc	(0xf << 4)
706365beadSRussell King 
716365beadSRussell King struct sa11x0_dma_sg {
726365beadSRussell King 	u32			addr;
736365beadSRussell King 	u32			len;
746365beadSRussell King };
756365beadSRussell King 
766365beadSRussell King struct sa11x0_dma_desc {
77*50437bffSRussell King 	struct virt_dma_desc	vd;
78*50437bffSRussell King 
796365beadSRussell King 	u32			ddar;
806365beadSRussell King 	size_t			size;
816365beadSRussell King 
826365beadSRussell King 	unsigned		sglen;
836365beadSRussell King 	struct sa11x0_dma_sg	sg[0];
846365beadSRussell King };
856365beadSRussell King 
866365beadSRussell King struct sa11x0_dma_phy;
876365beadSRussell King 
886365beadSRussell King struct sa11x0_dma_chan {
89*50437bffSRussell King 	struct virt_dma_chan	vc;
906365beadSRussell King 
91*50437bffSRussell King 	/* protected by c->vc.lock */
926365beadSRussell King 	struct sa11x0_dma_phy	*phy;
936365beadSRussell King 	enum dma_status		status;
946365beadSRussell King 
956365beadSRussell King 	/* protected by d->lock */
966365beadSRussell King 	struct list_head	node;
976365beadSRussell King 
986365beadSRussell King 	u32			ddar;
996365beadSRussell King 	const char		*name;
1006365beadSRussell King };
1016365beadSRussell King 
1026365beadSRussell King struct sa11x0_dma_phy {
1036365beadSRussell King 	void __iomem		*base;
1046365beadSRussell King 	struct sa11x0_dma_dev	*dev;
1056365beadSRussell King 	unsigned		num;
1066365beadSRussell King 
1076365beadSRussell King 	struct sa11x0_dma_chan	*vchan;
1086365beadSRussell King 
109*50437bffSRussell King 	/* Protected by c->vc.lock */
1106365beadSRussell King 	unsigned		sg_load;
1116365beadSRussell King 	struct sa11x0_dma_desc	*txd_load;
1126365beadSRussell King 	unsigned		sg_done;
1136365beadSRussell King 	struct sa11x0_dma_desc	*txd_done;
1146365beadSRussell King #ifdef CONFIG_PM_SLEEP
1156365beadSRussell King 	u32			dbs[2];
1166365beadSRussell King 	u32			dbt[2];
1176365beadSRussell King 	u32			dcsr;
1186365beadSRussell King #endif
1196365beadSRussell King };
1206365beadSRussell King 
1216365beadSRussell King struct sa11x0_dma_dev {
1226365beadSRussell King 	struct dma_device	slave;
1236365beadSRussell King 	void __iomem		*base;
1246365beadSRussell King 	spinlock_t		lock;
1256365beadSRussell King 	struct tasklet_struct	task;
1266365beadSRussell King 	struct list_head	chan_pending;
1276365beadSRussell King 	struct sa11x0_dma_phy	phy[NR_PHY_CHAN];
1286365beadSRussell King };
1296365beadSRussell King 
1306365beadSRussell King static struct sa11x0_dma_chan *to_sa11x0_dma_chan(struct dma_chan *chan)
1316365beadSRussell King {
132*50437bffSRussell King 	return container_of(chan, struct sa11x0_dma_chan, vc.chan);
1336365beadSRussell King }
1346365beadSRussell King 
1356365beadSRussell King static struct sa11x0_dma_dev *to_sa11x0_dma(struct dma_device *dmadev)
1366365beadSRussell King {
1376365beadSRussell King 	return container_of(dmadev, struct sa11x0_dma_dev, slave);
1386365beadSRussell King }
1396365beadSRussell King 
1406365beadSRussell King static struct sa11x0_dma_desc *sa11x0_dma_next_desc(struct sa11x0_dma_chan *c)
1416365beadSRussell King {
142*50437bffSRussell King 	struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
1436365beadSRussell King 
144*50437bffSRussell King 	return vd ? container_of(vd, struct sa11x0_dma_desc, vd) : NULL;
145*50437bffSRussell King }
146*50437bffSRussell King 
147*50437bffSRussell King static void sa11x0_dma_free_desc(struct virt_dma_desc *vd)
148*50437bffSRussell King {
149*50437bffSRussell King 	kfree(container_of(vd, struct sa11x0_dma_desc, vd));
1506365beadSRussell King }
1516365beadSRussell King 
1526365beadSRussell King static void sa11x0_dma_start_desc(struct sa11x0_dma_phy *p, struct sa11x0_dma_desc *txd)
1536365beadSRussell King {
154*50437bffSRussell King 	list_del(&txd->vd.node);
1556365beadSRussell King 	p->txd_load = txd;
1566365beadSRussell King 	p->sg_load = 0;
1576365beadSRussell King 
1586365beadSRussell King 	dev_vdbg(p->dev->slave.dev, "pchan %u: txd %p[%x]: starting: DDAR:%x\n",
159*50437bffSRussell King 		p->num, &txd->vd, txd->vd.tx.cookie, txd->ddar);
1606365beadSRussell King }
1616365beadSRussell King 
1626365beadSRussell King static void noinline sa11x0_dma_start_sg(struct sa11x0_dma_phy *p,
1636365beadSRussell King 	struct sa11x0_dma_chan *c)
1646365beadSRussell King {
1656365beadSRussell King 	struct sa11x0_dma_desc *txd = p->txd_load;
1666365beadSRussell King 	struct sa11x0_dma_sg *sg;
1676365beadSRussell King 	void __iomem *base = p->base;
1686365beadSRussell King 	unsigned dbsx, dbtx;
1696365beadSRussell King 	u32 dcsr;
1706365beadSRussell King 
1716365beadSRussell King 	if (!txd)
1726365beadSRussell King 		return;
1736365beadSRussell King 
1746365beadSRussell King 	dcsr = readl_relaxed(base + DMA_DCSR_R);
1756365beadSRussell King 
1766365beadSRussell King 	/* Don't try to load the next transfer if both buffers are started */
1776365beadSRussell King 	if ((dcsr & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB))
1786365beadSRussell King 		return;
1796365beadSRussell King 
1806365beadSRussell King 	if (p->sg_load == txd->sglen) {
1816365beadSRussell King 		struct sa11x0_dma_desc *txn = sa11x0_dma_next_desc(c);
1826365beadSRussell King 
1836365beadSRussell King 		/*
1846365beadSRussell King 		 * We have reached the end of the current descriptor.
1856365beadSRussell King 		 * Peek at the next descriptor, and if compatible with
1866365beadSRussell King 		 * the current, start processing it.
1876365beadSRussell King 		 */
1886365beadSRussell King 		if (txn && txn->ddar == txd->ddar) {
1896365beadSRussell King 			txd = txn;
1906365beadSRussell King 			sa11x0_dma_start_desc(p, txn);
1916365beadSRussell King 		} else {
1926365beadSRussell King 			p->txd_load = NULL;
1936365beadSRussell King 			return;
1946365beadSRussell King 		}
1956365beadSRussell King 	}
1966365beadSRussell King 
1976365beadSRussell King 	sg = &txd->sg[p->sg_load++];
1986365beadSRussell King 
1996365beadSRussell King 	/* Select buffer to load according to channel status */
2006365beadSRussell King 	if (((dcsr & (DCSR_BIU | DCSR_STRTB)) == (DCSR_BIU | DCSR_STRTB)) ||
2016365beadSRussell King 	    ((dcsr & (DCSR_BIU | DCSR_STRTA)) == 0)) {
2026365beadSRussell King 		dbsx = DMA_DBSA;
2036365beadSRussell King 		dbtx = DMA_DBTA;
2046365beadSRussell King 		dcsr = DCSR_STRTA | DCSR_IE | DCSR_RUN;
2056365beadSRussell King 	} else {
2066365beadSRussell King 		dbsx = DMA_DBSB;
2076365beadSRussell King 		dbtx = DMA_DBTB;
2086365beadSRussell King 		dcsr = DCSR_STRTB | DCSR_IE | DCSR_RUN;
2096365beadSRussell King 	}
2106365beadSRussell King 
2116365beadSRussell King 	writel_relaxed(sg->addr, base + dbsx);
2126365beadSRussell King 	writel_relaxed(sg->len, base + dbtx);
2136365beadSRussell King 	writel(dcsr, base + DMA_DCSR_S);
2146365beadSRussell King 
2156365beadSRussell King 	dev_dbg(p->dev->slave.dev, "pchan %u: load: DCSR:%02x DBS%c:%08x DBT%c:%08x\n",
2166365beadSRussell King 		p->num, dcsr,
2176365beadSRussell King 		'A' + (dbsx == DMA_DBSB), sg->addr,
2186365beadSRussell King 		'A' + (dbtx == DMA_DBTB), sg->len);
2196365beadSRussell King }
2206365beadSRussell King 
2216365beadSRussell King static void noinline sa11x0_dma_complete(struct sa11x0_dma_phy *p,
2226365beadSRussell King 	struct sa11x0_dma_chan *c)
2236365beadSRussell King {
2246365beadSRussell King 	struct sa11x0_dma_desc *txd = p->txd_done;
2256365beadSRussell King 
2266365beadSRussell King 	if (++p->sg_done == txd->sglen) {
227*50437bffSRussell King 		vchan_cookie_complete(&txd->vd);
2286365beadSRussell King 
2296365beadSRussell King 		p->sg_done = 0;
2306365beadSRussell King 		p->txd_done = p->txd_load;
2316365beadSRussell King 
232*50437bffSRussell King 		if (!p->txd_done)
233*50437bffSRussell King 			tasklet_schedule(&p->dev->task);
2346365beadSRussell King 	}
2356365beadSRussell King 
2366365beadSRussell King 	sa11x0_dma_start_sg(p, c);
2376365beadSRussell King }
2386365beadSRussell King 
2396365beadSRussell King static irqreturn_t sa11x0_dma_irq(int irq, void *dev_id)
2406365beadSRussell King {
2416365beadSRussell King 	struct sa11x0_dma_phy *p = dev_id;
2426365beadSRussell King 	struct sa11x0_dma_dev *d = p->dev;
2436365beadSRussell King 	struct sa11x0_dma_chan *c;
2446365beadSRussell King 	u32 dcsr;
2456365beadSRussell King 
2466365beadSRussell King 	dcsr = readl_relaxed(p->base + DMA_DCSR_R);
2476365beadSRussell King 	if (!(dcsr & (DCSR_ERROR | DCSR_DONEA | DCSR_DONEB)))
2486365beadSRussell King 		return IRQ_NONE;
2496365beadSRussell King 
2506365beadSRussell King 	/* Clear reported status bits */
2516365beadSRussell King 	writel_relaxed(dcsr & (DCSR_ERROR | DCSR_DONEA | DCSR_DONEB),
2526365beadSRussell King 		p->base + DMA_DCSR_C);
2536365beadSRussell King 
2546365beadSRussell King 	dev_dbg(d->slave.dev, "pchan %u: irq: DCSR:%02x\n", p->num, dcsr);
2556365beadSRussell King 
2566365beadSRussell King 	if (dcsr & DCSR_ERROR) {
2576365beadSRussell King 		dev_err(d->slave.dev, "pchan %u: error. DCSR:%02x DDAR:%08x DBSA:%08x DBTA:%08x DBSB:%08x DBTB:%08x\n",
2586365beadSRussell King 			p->num, dcsr,
2596365beadSRussell King 			readl_relaxed(p->base + DMA_DDAR),
2606365beadSRussell King 			readl_relaxed(p->base + DMA_DBSA),
2616365beadSRussell King 			readl_relaxed(p->base + DMA_DBTA),
2626365beadSRussell King 			readl_relaxed(p->base + DMA_DBSB),
2636365beadSRussell King 			readl_relaxed(p->base + DMA_DBTB));
2646365beadSRussell King 	}
2656365beadSRussell King 
2666365beadSRussell King 	c = p->vchan;
2676365beadSRussell King 	if (c) {
2686365beadSRussell King 		unsigned long flags;
2696365beadSRussell King 
270*50437bffSRussell King 		spin_lock_irqsave(&c->vc.lock, flags);
2716365beadSRussell King 		/*
2726365beadSRussell King 		 * Now that we're holding the lock, check that the vchan
2736365beadSRussell King 		 * really is associated with this pchan before touching the
2746365beadSRussell King 		 * hardware.  This should always succeed, because we won't
2756365beadSRussell King 		 * change p->vchan or c->phy while the channel is actively
2766365beadSRussell King 		 * transferring.
2776365beadSRussell King 		 */
2786365beadSRussell King 		if (c->phy == p) {
2796365beadSRussell King 			if (dcsr & DCSR_DONEA)
2806365beadSRussell King 				sa11x0_dma_complete(p, c);
2816365beadSRussell King 			if (dcsr & DCSR_DONEB)
2826365beadSRussell King 				sa11x0_dma_complete(p, c);
2836365beadSRussell King 		}
284*50437bffSRussell King 		spin_unlock_irqrestore(&c->vc.lock, flags);
2856365beadSRussell King 	}
2866365beadSRussell King 
2876365beadSRussell King 	return IRQ_HANDLED;
2886365beadSRussell King }
2896365beadSRussell King 
2906365beadSRussell King static void sa11x0_dma_start_txd(struct sa11x0_dma_chan *c)
2916365beadSRussell King {
2926365beadSRussell King 	struct sa11x0_dma_desc *txd = sa11x0_dma_next_desc(c);
2936365beadSRussell King 
2946365beadSRussell King 	/* If the issued list is empty, we have no further txds to process */
2956365beadSRussell King 	if (txd) {
2966365beadSRussell King 		struct sa11x0_dma_phy *p = c->phy;
2976365beadSRussell King 
2986365beadSRussell King 		sa11x0_dma_start_desc(p, txd);
2996365beadSRussell King 		p->txd_done = txd;
3006365beadSRussell King 		p->sg_done = 0;
3016365beadSRussell King 
3026365beadSRussell King 		/* The channel should not have any transfers started */
3036365beadSRussell King 		WARN_ON(readl_relaxed(p->base + DMA_DCSR_R) &
3046365beadSRussell King 				      (DCSR_STRTA | DCSR_STRTB));
3056365beadSRussell King 
3066365beadSRussell King 		/* Clear the run and start bits before changing DDAR */
3076365beadSRussell King 		writel_relaxed(DCSR_RUN | DCSR_STRTA | DCSR_STRTB,
3086365beadSRussell King 			       p->base + DMA_DCSR_C);
3096365beadSRussell King 		writel_relaxed(txd->ddar, p->base + DMA_DDAR);
3106365beadSRussell King 
3116365beadSRussell King 		/* Try to start both buffers */
3126365beadSRussell King 		sa11x0_dma_start_sg(p, c);
3136365beadSRussell King 		sa11x0_dma_start_sg(p, c);
3146365beadSRussell King 	}
3156365beadSRussell King }
3166365beadSRussell King 
3176365beadSRussell King static void sa11x0_dma_tasklet(unsigned long arg)
3186365beadSRussell King {
3196365beadSRussell King 	struct sa11x0_dma_dev *d = (struct sa11x0_dma_dev *)arg;
3206365beadSRussell King 	struct sa11x0_dma_phy *p;
3216365beadSRussell King 	struct sa11x0_dma_chan *c;
3226365beadSRussell King 	unsigned pch, pch_alloc = 0;
3236365beadSRussell King 
3246365beadSRussell King 	dev_dbg(d->slave.dev, "tasklet enter\n");
3256365beadSRussell King 
326*50437bffSRussell King 	list_for_each_entry(c, &d->slave.channels, vc.chan.device_node) {
327*50437bffSRussell King 		spin_lock_irq(&c->vc.lock);
3286365beadSRussell King 		p = c->phy;
329*50437bffSRussell King 		if (p && !p->txd_done) {
3306365beadSRussell King 			sa11x0_dma_start_txd(c);
3316365beadSRussell King 			if (!p->txd_done) {
3326365beadSRussell King 				/* No current txd associated with this channel */
3336365beadSRussell King 				dev_dbg(d->slave.dev, "pchan %u: free\n", p->num);
3346365beadSRussell King 
3356365beadSRussell King 				/* Mark this channel free */
3366365beadSRussell King 				c->phy = NULL;
3376365beadSRussell King 				p->vchan = NULL;
3386365beadSRussell King 			}
3396365beadSRussell King 		}
340*50437bffSRussell King 		spin_unlock_irq(&c->vc.lock);
3416365beadSRussell King 	}
3426365beadSRussell King 
3436365beadSRussell King 	spin_lock_irq(&d->lock);
3446365beadSRussell King 	for (pch = 0; pch < NR_PHY_CHAN; pch++) {
3456365beadSRussell King 		p = &d->phy[pch];
3466365beadSRussell King 
3476365beadSRussell King 		if (p->vchan == NULL && !list_empty(&d->chan_pending)) {
3486365beadSRussell King 			c = list_first_entry(&d->chan_pending,
3496365beadSRussell King 				struct sa11x0_dma_chan, node);
3506365beadSRussell King 			list_del_init(&c->node);
3516365beadSRussell King 
3526365beadSRussell King 			pch_alloc |= 1 << pch;
3536365beadSRussell King 
3546365beadSRussell King 			/* Mark this channel allocated */
3556365beadSRussell King 			p->vchan = c;
3566365beadSRussell King 
357*50437bffSRussell King 			dev_dbg(d->slave.dev, "pchan %u: alloc vchan %p\n", pch, &c->vc);
3586365beadSRussell King 		}
3596365beadSRussell King 	}
3606365beadSRussell King 	spin_unlock_irq(&d->lock);
3616365beadSRussell King 
3626365beadSRussell King 	for (pch = 0; pch < NR_PHY_CHAN; pch++) {
3636365beadSRussell King 		if (pch_alloc & (1 << pch)) {
3646365beadSRussell King 			p = &d->phy[pch];
3656365beadSRussell King 			c = p->vchan;
3666365beadSRussell King 
367*50437bffSRussell King 			spin_lock_irq(&c->vc.lock);
3686365beadSRussell King 			c->phy = p;
3696365beadSRussell King 
3706365beadSRussell King 			sa11x0_dma_start_txd(c);
371*50437bffSRussell King 			spin_unlock_irq(&c->vc.lock);
3726365beadSRussell King 		}
3736365beadSRussell King 	}
3746365beadSRussell King 
3756365beadSRussell King 	dev_dbg(d->slave.dev, "tasklet exit\n");
3766365beadSRussell King }
3776365beadSRussell King 
3786365beadSRussell King 
3796365beadSRussell King static int sa11x0_dma_alloc_chan_resources(struct dma_chan *chan)
3806365beadSRussell King {
3816365beadSRussell King 	return 0;
3826365beadSRussell King }
3836365beadSRussell King 
3846365beadSRussell King static void sa11x0_dma_free_chan_resources(struct dma_chan *chan)
3856365beadSRussell King {
3866365beadSRussell King 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
3876365beadSRussell King 	struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
3886365beadSRussell King 	unsigned long flags;
3896365beadSRussell King 
390*50437bffSRussell King 	spin_lock_irqsave(&d->lock, flags);
3916365beadSRussell King 	list_del_init(&c->node);
392*50437bffSRussell King 	spin_unlock_irqrestore(&d->lock, flags);
3936365beadSRussell King 
394*50437bffSRussell King 	vchan_free_chan_resources(&c->vc);
3956365beadSRussell King }
3966365beadSRussell King 
3976365beadSRussell King static dma_addr_t sa11x0_dma_pos(struct sa11x0_dma_phy *p)
3986365beadSRussell King {
3996365beadSRussell King 	unsigned reg;
4006365beadSRussell King 	u32 dcsr;
4016365beadSRussell King 
4026365beadSRussell King 	dcsr = readl_relaxed(p->base + DMA_DCSR_R);
4036365beadSRussell King 
4046365beadSRussell King 	if ((dcsr & (DCSR_BIU | DCSR_STRTA)) == DCSR_STRTA ||
4056365beadSRussell King 	    (dcsr & (DCSR_BIU | DCSR_STRTB)) == DCSR_BIU)
4066365beadSRussell King 		reg = DMA_DBSA;
4076365beadSRussell King 	else
4086365beadSRussell King 		reg = DMA_DBSB;
4096365beadSRussell King 
4106365beadSRussell King 	return readl_relaxed(p->base + reg);
4116365beadSRussell King }
4126365beadSRussell King 
4136365beadSRussell King static enum dma_status sa11x0_dma_tx_status(struct dma_chan *chan,
4146365beadSRussell King 	dma_cookie_t cookie, struct dma_tx_state *state)
4156365beadSRussell King {
4166365beadSRussell King 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
4176365beadSRussell King 	struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
4186365beadSRussell King 	struct sa11x0_dma_phy *p;
4196365beadSRussell King 	struct sa11x0_dma_desc *txd;
4206365beadSRussell King 	unsigned long flags;
4216365beadSRussell King 	enum dma_status ret;
4226365beadSRussell King 	size_t bytes = 0;
4236365beadSRussell King 
424*50437bffSRussell King 	ret = dma_cookie_status(&c->vc.chan, cookie, state);
425*50437bffSRussell King 	if (ret == DMA_SUCCESS)
4266365beadSRussell King 		return ret;
4276365beadSRussell King 
428*50437bffSRussell King 	spin_lock_irqsave(&c->vc.lock, flags);
4296365beadSRussell King 	p = c->phy;
4306365beadSRussell King 	ret = c->status;
4316365beadSRussell King 	if (p) {
4326365beadSRussell King 		dma_addr_t addr = sa11x0_dma_pos(p);
4336365beadSRussell King 
4346365beadSRussell King 		dev_vdbg(d->slave.dev, "tx_status: addr:%x\n", addr);
4356365beadSRussell King 
4366365beadSRussell King 		txd = p->txd_done;
4376365beadSRussell King 		if (txd) {
4386365beadSRussell King 			unsigned i;
4396365beadSRussell King 
4406365beadSRussell King 			for (i = 0; i < txd->sglen; i++) {
4416365beadSRussell King 				dev_vdbg(d->slave.dev, "tx_status: [%u] %x+%x\n",
4426365beadSRussell King 					i, txd->sg[i].addr, txd->sg[i].len);
4436365beadSRussell King 				if (addr >= txd->sg[i].addr &&
4446365beadSRussell King 				    addr < txd->sg[i].addr + txd->sg[i].len) {
4456365beadSRussell King 					unsigned len;
4466365beadSRussell King 
4476365beadSRussell King 					len = txd->sg[i].len -
4486365beadSRussell King 						(addr - txd->sg[i].addr);
4496365beadSRussell King 					dev_vdbg(d->slave.dev, "tx_status: [%u] +%x\n",
4506365beadSRussell King 						i, len);
4516365beadSRussell King 					bytes += len;
4526365beadSRussell King 					i++;
4536365beadSRussell King 					break;
4546365beadSRussell King 				}
4556365beadSRussell King 			}
4566365beadSRussell King 			for (; i < txd->sglen; i++) {
4576365beadSRussell King 				dev_vdbg(d->slave.dev, "tx_status: [%u] %x+%x ++\n",
4586365beadSRussell King 					i, txd->sg[i].addr, txd->sg[i].len);
4596365beadSRussell King 				bytes += txd->sg[i].len;
4606365beadSRussell King 			}
4616365beadSRussell King 		}
4626365beadSRussell King 		if (txd != p->txd_load && p->txd_load)
4636365beadSRussell King 			bytes += p->txd_load->size;
4646365beadSRussell King 	}
465*50437bffSRussell King 	list_for_each_entry(txd, &c->vc.desc_issued, vd.node) {
4666365beadSRussell King 		bytes += txd->size;
4676365beadSRussell King 	}
468*50437bffSRussell King 	spin_unlock_irqrestore(&c->vc.lock, flags);
4696365beadSRussell King 
470*50437bffSRussell King 	if (state)
471*50437bffSRussell King 		state->residue = bytes;
4726365beadSRussell King 
4736365beadSRussell King 	dev_vdbg(d->slave.dev, "tx_status: bytes 0x%zx\n", bytes);
4746365beadSRussell King 
4756365beadSRussell King 	return ret;
4766365beadSRussell King }
4776365beadSRussell King 
4786365beadSRussell King /*
4796365beadSRussell King  * Move pending txds to the issued list, and re-init pending list.
4806365beadSRussell King  * If not already pending, add this channel to the list of pending
4816365beadSRussell King  * channels and trigger the tasklet to run.
4826365beadSRussell King  */
4836365beadSRussell King static void sa11x0_dma_issue_pending(struct dma_chan *chan)
4846365beadSRussell King {
4856365beadSRussell King 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
4866365beadSRussell King 	struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
4876365beadSRussell King 	unsigned long flags;
4886365beadSRussell King 
489*50437bffSRussell King 	spin_lock_irqsave(&c->vc.lock, flags);
490*50437bffSRussell King 	if (vchan_issue_pending(&c->vc)) {
491*50437bffSRussell King 		if (!c->phy) {
4926365beadSRussell King 			spin_lock(&d->lock);
493*50437bffSRussell King 			if (list_empty(&c->node)) {
4946365beadSRussell King 				list_add_tail(&c->node, &d->chan_pending);
4956365beadSRussell King 				tasklet_schedule(&d->task);
496*50437bffSRussell King 				dev_dbg(d->slave.dev, "vchan %p: issued\n", &c->vc);
4976365beadSRussell King 			}
4986365beadSRussell King 			spin_unlock(&d->lock);
4996365beadSRussell King 		}
500*50437bffSRussell King 	} else
501*50437bffSRussell King 		dev_dbg(d->slave.dev, "vchan %p: nothing to issue\n", &c->vc);
502*50437bffSRussell King 	spin_unlock_irqrestore(&c->vc.lock, flags);
5036365beadSRussell King }
5046365beadSRussell King 
5056365beadSRussell King static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
5066365beadSRussell King 	struct dma_chan *chan, struct scatterlist *sg, unsigned int sglen,
507d9d54540SRussell King 	enum dma_transfer_direction dir, unsigned long flags, void *context)
5086365beadSRussell King {
5096365beadSRussell King 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
5106365beadSRussell King 	struct sa11x0_dma_desc *txd;
5116365beadSRussell King 	struct scatterlist *sgent;
5126365beadSRussell King 	unsigned i, j = sglen;
5136365beadSRussell King 	size_t size = 0;
5146365beadSRussell King 
5156365beadSRussell King 	/* SA11x0 channels can only operate in their native direction */
5166365beadSRussell King 	if (dir != (c->ddar & DDAR_RW ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV)) {
5176365beadSRussell King 		dev_err(chan->device->dev, "vchan %p: bad DMA direction: DDAR:%08x dir:%u\n",
518*50437bffSRussell King 			&c->vc, c->ddar, dir);
5196365beadSRussell King 		return NULL;
5206365beadSRussell King 	}
5216365beadSRussell King 
5226365beadSRussell King 	/* Do not allow zero-sized txds */
5236365beadSRussell King 	if (sglen == 0)
5246365beadSRussell King 		return NULL;
5256365beadSRussell King 
5266365beadSRussell King 	for_each_sg(sg, sgent, sglen, i) {
5276365beadSRussell King 		dma_addr_t addr = sg_dma_address(sgent);
5286365beadSRussell King 		unsigned int len = sg_dma_len(sgent);
5296365beadSRussell King 
5306365beadSRussell King 		if (len > DMA_MAX_SIZE)
5316365beadSRussell King 			j += DIV_ROUND_UP(len, DMA_MAX_SIZE & ~DMA_ALIGN) - 1;
5326365beadSRussell King 		if (addr & DMA_ALIGN) {
5336365beadSRussell King 			dev_dbg(chan->device->dev, "vchan %p: bad buffer alignment: %08x\n",
534*50437bffSRussell King 				&c->vc, addr);
5356365beadSRussell King 			return NULL;
5366365beadSRussell King 		}
5376365beadSRussell King 	}
5386365beadSRussell King 
5396365beadSRussell King 	txd = kzalloc(sizeof(*txd) + j * sizeof(txd->sg[0]), GFP_ATOMIC);
5406365beadSRussell King 	if (!txd) {
541*50437bffSRussell King 		dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc);
5426365beadSRussell King 		return NULL;
5436365beadSRussell King 	}
5446365beadSRussell King 
5456365beadSRussell King 	j = 0;
5466365beadSRussell King 	for_each_sg(sg, sgent, sglen, i) {
5476365beadSRussell King 		dma_addr_t addr = sg_dma_address(sgent);
5486365beadSRussell King 		unsigned len = sg_dma_len(sgent);
5496365beadSRussell King 
5506365beadSRussell King 		size += len;
5516365beadSRussell King 
5526365beadSRussell King 		do {
5536365beadSRussell King 			unsigned tlen = len;
5546365beadSRussell King 
5556365beadSRussell King 			/*
5566365beadSRussell King 			 * Check whether the transfer will fit.  If not, try
5576365beadSRussell King 			 * to split the transfer up such that we end up with
5586365beadSRussell King 			 * equal chunks - but make sure that we preserve the
5596365beadSRussell King 			 * alignment.  This avoids small segments.
5606365beadSRussell King 			 */
5616365beadSRussell King 			if (tlen > DMA_MAX_SIZE) {
5626365beadSRussell King 				unsigned mult = DIV_ROUND_UP(tlen,
5636365beadSRussell King 					DMA_MAX_SIZE & ~DMA_ALIGN);
5646365beadSRussell King 
5656365beadSRussell King 				tlen = (tlen / mult) & ~DMA_ALIGN;
5666365beadSRussell King 			}
5676365beadSRussell King 
5686365beadSRussell King 			txd->sg[j].addr = addr;
5696365beadSRussell King 			txd->sg[j].len = tlen;
5706365beadSRussell King 
5716365beadSRussell King 			addr += tlen;
5726365beadSRussell King 			len -= tlen;
5736365beadSRussell King 			j++;
5746365beadSRussell King 		} while (len);
5756365beadSRussell King 	}
5766365beadSRussell King 
5776365beadSRussell King 	txd->ddar = c->ddar;
5786365beadSRussell King 	txd->size = size;
5796365beadSRussell King 	txd->sglen = j;
5806365beadSRussell King 
5816365beadSRussell King 	dev_dbg(chan->device->dev, "vchan %p: txd %p: size %u nr %u\n",
582*50437bffSRussell King 		&c->vc, &txd->vd, txd->size, txd->sglen);
5836365beadSRussell King 
584*50437bffSRussell King 	return vchan_tx_prep(&c->vc, &txd->vd, flags);
5856365beadSRussell King }
5866365beadSRussell King 
5876365beadSRussell King static int sa11x0_dma_slave_config(struct sa11x0_dma_chan *c, struct dma_slave_config *cfg)
5886365beadSRussell King {
5896365beadSRussell King 	u32 ddar = c->ddar & ((0xf << 4) | DDAR_RW);
5906365beadSRussell King 	dma_addr_t addr;
5916365beadSRussell King 	enum dma_slave_buswidth width;
5926365beadSRussell King 	u32 maxburst;
5936365beadSRussell King 
5946365beadSRussell King 	if (ddar & DDAR_RW) {
5956365beadSRussell King 		addr = cfg->src_addr;
5966365beadSRussell King 		width = cfg->src_addr_width;
5976365beadSRussell King 		maxburst = cfg->src_maxburst;
5986365beadSRussell King 	} else {
5996365beadSRussell King 		addr = cfg->dst_addr;
6006365beadSRussell King 		width = cfg->dst_addr_width;
6016365beadSRussell King 		maxburst = cfg->dst_maxburst;
6026365beadSRussell King 	}
6036365beadSRussell King 
6046365beadSRussell King 	if ((width != DMA_SLAVE_BUSWIDTH_1_BYTE &&
6056365beadSRussell King 	     width != DMA_SLAVE_BUSWIDTH_2_BYTES) ||
6066365beadSRussell King 	    (maxburst != 4 && maxburst != 8))
6076365beadSRussell King 		return -EINVAL;
6086365beadSRussell King 
6096365beadSRussell King 	if (width == DMA_SLAVE_BUSWIDTH_2_BYTES)
6106365beadSRussell King 		ddar |= DDAR_DW;
6116365beadSRussell King 	if (maxburst == 8)
6126365beadSRussell King 		ddar |= DDAR_BS;
6136365beadSRussell King 
614*50437bffSRussell King 	dev_dbg(c->vc.chan.device->dev, "vchan %p: dma_slave_config addr %x width %u burst %u\n",
615*50437bffSRussell King 		&c->vc, addr, width, maxburst);
6166365beadSRussell King 
6176365beadSRussell King 	c->ddar = ddar | (addr & 0xf0000000) | (addr & 0x003ffffc) << 6;
6186365beadSRussell King 
6196365beadSRussell King 	return 0;
6206365beadSRussell King }
6216365beadSRussell King 
6226365beadSRussell King static int sa11x0_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
6236365beadSRussell King 	unsigned long arg)
6246365beadSRussell King {
6256365beadSRussell King 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
6266365beadSRussell King 	struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device);
6276365beadSRussell King 	struct sa11x0_dma_phy *p;
6286365beadSRussell King 	LIST_HEAD(head);
6296365beadSRussell King 	unsigned long flags;
6306365beadSRussell King 	int ret;
6316365beadSRussell King 
6326365beadSRussell King 	switch (cmd) {
6336365beadSRussell King 	case DMA_SLAVE_CONFIG:
6346365beadSRussell King 		return sa11x0_dma_slave_config(c, (struct dma_slave_config *)arg);
6356365beadSRussell King 
6366365beadSRussell King 	case DMA_TERMINATE_ALL:
637*50437bffSRussell King 		dev_dbg(d->slave.dev, "vchan %p: terminate all\n", &c->vc);
6386365beadSRussell King 		/* Clear the tx descriptor lists */
639*50437bffSRussell King 		spin_lock_irqsave(&c->vc.lock, flags);
640*50437bffSRussell King 		vchan_get_all_descriptors(&c->vc, &head);
6416365beadSRussell King 
6426365beadSRussell King 		p = c->phy;
6436365beadSRussell King 		if (p) {
6446365beadSRussell King 			dev_dbg(d->slave.dev, "pchan %u: terminating\n", p->num);
6456365beadSRussell King 			/* vchan is assigned to a pchan - stop the channel */
6466365beadSRussell King 			writel(DCSR_RUN | DCSR_IE |
6476365beadSRussell King 				DCSR_STRTA | DCSR_DONEA |
6486365beadSRussell King 				DCSR_STRTB | DCSR_DONEB,
6496365beadSRussell King 				p->base + DMA_DCSR_C);
6506365beadSRussell King 
6516365beadSRussell King 			if (p->txd_load) {
6526365beadSRussell King 				if (p->txd_load != p->txd_done)
653*50437bffSRussell King 					list_add_tail(&p->txd_load->vd.node, &head);
6546365beadSRussell King 				p->txd_load = NULL;
6556365beadSRussell King 			}
6566365beadSRussell King 			if (p->txd_done) {
657*50437bffSRussell King 				list_add_tail(&p->txd_done->vd.node, &head);
6586365beadSRussell King 				p->txd_done = NULL;
6596365beadSRussell King 			}
6606365beadSRussell King 			c->phy = NULL;
6616365beadSRussell King 			spin_lock(&d->lock);
6626365beadSRussell King 			p->vchan = NULL;
6636365beadSRussell King 			spin_unlock(&d->lock);
6646365beadSRussell King 			tasklet_schedule(&d->task);
6656365beadSRussell King 		}
666*50437bffSRussell King 		spin_unlock_irqrestore(&c->vc.lock, flags);
667*50437bffSRussell King 		vchan_dma_desc_free_list(&c->vc, &head);
6686365beadSRussell King 		ret = 0;
6696365beadSRussell King 		break;
6706365beadSRussell King 
6716365beadSRussell King 	case DMA_PAUSE:
672*50437bffSRussell King 		dev_dbg(d->slave.dev, "vchan %p: pause\n", &c->vc);
673*50437bffSRussell King 		spin_lock_irqsave(&c->vc.lock, flags);
6746365beadSRussell King 		if (c->status == DMA_IN_PROGRESS) {
6756365beadSRussell King 			c->status = DMA_PAUSED;
6766365beadSRussell King 
6776365beadSRussell King 			p = c->phy;
6786365beadSRussell King 			if (p) {
6796365beadSRussell King 				writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C);
6806365beadSRussell King 			} else {
6816365beadSRussell King 				spin_lock(&d->lock);
6826365beadSRussell King 				list_del_init(&c->node);
6836365beadSRussell King 				spin_unlock(&d->lock);
6846365beadSRussell King 			}
6856365beadSRussell King 		}
686*50437bffSRussell King 		spin_unlock_irqrestore(&c->vc.lock, flags);
6876365beadSRussell King 		ret = 0;
6886365beadSRussell King 		break;
6896365beadSRussell King 
6906365beadSRussell King 	case DMA_RESUME:
691*50437bffSRussell King 		dev_dbg(d->slave.dev, "vchan %p: resume\n", &c->vc);
692*50437bffSRussell King 		spin_lock_irqsave(&c->vc.lock, flags);
6936365beadSRussell King 		if (c->status == DMA_PAUSED) {
6946365beadSRussell King 			c->status = DMA_IN_PROGRESS;
6956365beadSRussell King 
6966365beadSRussell King 			p = c->phy;
6976365beadSRussell King 			if (p) {
6986365beadSRussell King 				writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_S);
699*50437bffSRussell King 			} else if (!list_empty(&c->vc.desc_issued)) {
7006365beadSRussell King 				spin_lock(&d->lock);
7016365beadSRussell King 				list_add_tail(&c->node, &d->chan_pending);
7026365beadSRussell King 				spin_unlock(&d->lock);
7036365beadSRussell King 			}
7046365beadSRussell King 		}
705*50437bffSRussell King 		spin_unlock_irqrestore(&c->vc.lock, flags);
7066365beadSRussell King 		ret = 0;
7076365beadSRussell King 		break;
7086365beadSRussell King 
7096365beadSRussell King 	default:
7106365beadSRussell King 		ret = -ENXIO;
7116365beadSRussell King 		break;
7126365beadSRussell King 	}
7136365beadSRussell King 
7146365beadSRussell King 	return ret;
7156365beadSRussell King }
7166365beadSRussell King 
7176365beadSRussell King struct sa11x0_dma_channel_desc {
7186365beadSRussell King 	u32 ddar;
7196365beadSRussell King 	const char *name;
7206365beadSRussell King };
7216365beadSRussell King 
7226365beadSRussell King #define CD(d1, d2) { .ddar = DDAR_##d1 | d2, .name = #d1 }
7236365beadSRussell King static const struct sa11x0_dma_channel_desc chan_desc[] = {
7246365beadSRussell King 	CD(Ser0UDCTr, 0),
7256365beadSRussell King 	CD(Ser0UDCRc, DDAR_RW),
7266365beadSRussell King 	CD(Ser1SDLCTr, 0),
7276365beadSRussell King 	CD(Ser1SDLCRc, DDAR_RW),
7286365beadSRussell King 	CD(Ser1UARTTr, 0),
7296365beadSRussell King 	CD(Ser1UARTRc, DDAR_RW),
7306365beadSRussell King 	CD(Ser2ICPTr, 0),
7316365beadSRussell King 	CD(Ser2ICPRc, DDAR_RW),
7326365beadSRussell King 	CD(Ser3UARTTr, 0),
7336365beadSRussell King 	CD(Ser3UARTRc, DDAR_RW),
7346365beadSRussell King 	CD(Ser4MCP0Tr, 0),
7356365beadSRussell King 	CD(Ser4MCP0Rc, DDAR_RW),
7366365beadSRussell King 	CD(Ser4MCP1Tr, 0),
7376365beadSRussell King 	CD(Ser4MCP1Rc, DDAR_RW),
7386365beadSRussell King 	CD(Ser4SSPTr, 0),
7396365beadSRussell King 	CD(Ser4SSPRc, DDAR_RW),
7406365beadSRussell King };
7416365beadSRussell King 
7426365beadSRussell King static int __devinit sa11x0_dma_init_dmadev(struct dma_device *dmadev,
7436365beadSRussell King 	struct device *dev)
7446365beadSRussell King {
7456365beadSRussell King 	unsigned i;
7466365beadSRussell King 
7476365beadSRussell King 	dmadev->chancnt = ARRAY_SIZE(chan_desc);
7486365beadSRussell King 	INIT_LIST_HEAD(&dmadev->channels);
7496365beadSRussell King 	dmadev->dev = dev;
7506365beadSRussell King 	dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_chan_resources;
7516365beadSRussell King 	dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources;
7526365beadSRussell King 	dmadev->device_control = sa11x0_dma_control;
7536365beadSRussell King 	dmadev->device_tx_status = sa11x0_dma_tx_status;
7546365beadSRussell King 	dmadev->device_issue_pending = sa11x0_dma_issue_pending;
7556365beadSRussell King 
7566365beadSRussell King 	for (i = 0; i < dmadev->chancnt; i++) {
7576365beadSRussell King 		struct sa11x0_dma_chan *c;
7586365beadSRussell King 
7596365beadSRussell King 		c = kzalloc(sizeof(*c), GFP_KERNEL);
7606365beadSRussell King 		if (!c) {
7616365beadSRussell King 			dev_err(dev, "no memory for channel %u\n", i);
7626365beadSRussell King 			return -ENOMEM;
7636365beadSRussell King 		}
7646365beadSRussell King 
7656365beadSRussell King 		c->status = DMA_IN_PROGRESS;
7666365beadSRussell King 		c->ddar = chan_desc[i].ddar;
7676365beadSRussell King 		c->name = chan_desc[i].name;
7686365beadSRussell King 		INIT_LIST_HEAD(&c->node);
769*50437bffSRussell King 
770*50437bffSRussell King 		c->vc.desc_free = sa11x0_dma_free_desc;
771*50437bffSRussell King 		vchan_init(&c->vc, dmadev);
7726365beadSRussell King 	}
7736365beadSRussell King 
7746365beadSRussell King 	return dma_async_device_register(dmadev);
7756365beadSRussell King }
7766365beadSRussell King 
7776365beadSRussell King static int sa11x0_dma_request_irq(struct platform_device *pdev, int nr,
7786365beadSRussell King 	void *data)
7796365beadSRussell King {
7806365beadSRussell King 	int irq = platform_get_irq(pdev, nr);
7816365beadSRussell King 
7826365beadSRussell King 	if (irq <= 0)
7836365beadSRussell King 		return -ENXIO;
7846365beadSRussell King 
7856365beadSRussell King 	return request_irq(irq, sa11x0_dma_irq, 0, dev_name(&pdev->dev), data);
7866365beadSRussell King }
7876365beadSRussell King 
7886365beadSRussell King static void sa11x0_dma_free_irq(struct platform_device *pdev, int nr,
7896365beadSRussell King 	void *data)
7906365beadSRussell King {
7916365beadSRussell King 	int irq = platform_get_irq(pdev, nr);
7926365beadSRussell King 	if (irq > 0)
7936365beadSRussell King 		free_irq(irq, data);
7946365beadSRussell King }
7956365beadSRussell King 
7966365beadSRussell King static void sa11x0_dma_free_channels(struct dma_device *dmadev)
7976365beadSRussell King {
7986365beadSRussell King 	struct sa11x0_dma_chan *c, *cn;
7996365beadSRussell King 
800*50437bffSRussell King 	list_for_each_entry_safe(c, cn, &dmadev->channels, vc.chan.device_node) {
801*50437bffSRussell King 		list_del(&c->vc.chan.device_node);
802*50437bffSRussell King 		tasklet_kill(&c->vc.task);
8036365beadSRussell King 		kfree(c);
8046365beadSRussell King 	}
8056365beadSRussell King }
8066365beadSRussell King 
8076365beadSRussell King static int __devinit sa11x0_dma_probe(struct platform_device *pdev)
8086365beadSRussell King {
8096365beadSRussell King 	struct sa11x0_dma_dev *d;
8106365beadSRussell King 	struct resource *res;
8116365beadSRussell King 	unsigned i;
8126365beadSRussell King 	int ret;
8136365beadSRussell King 
8146365beadSRussell King 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8156365beadSRussell King 	if (!res)
8166365beadSRussell King 		return -ENXIO;
8176365beadSRussell King 
8186365beadSRussell King 	d = kzalloc(sizeof(*d), GFP_KERNEL);
8196365beadSRussell King 	if (!d) {
8206365beadSRussell King 		ret = -ENOMEM;
8216365beadSRussell King 		goto err_alloc;
8226365beadSRussell King 	}
8236365beadSRussell King 
8246365beadSRussell King 	spin_lock_init(&d->lock);
8256365beadSRussell King 	INIT_LIST_HEAD(&d->chan_pending);
8266365beadSRussell King 
8276365beadSRussell King 	d->base = ioremap(res->start, resource_size(res));
8286365beadSRussell King 	if (!d->base) {
8296365beadSRussell King 		ret = -ENOMEM;
8306365beadSRussell King 		goto err_ioremap;
8316365beadSRussell King 	}
8326365beadSRussell King 
8336365beadSRussell King 	tasklet_init(&d->task, sa11x0_dma_tasklet, (unsigned long)d);
8346365beadSRussell King 
8356365beadSRussell King 	for (i = 0; i < NR_PHY_CHAN; i++) {
8366365beadSRussell King 		struct sa11x0_dma_phy *p = &d->phy[i];
8376365beadSRussell King 
8386365beadSRussell King 		p->dev = d;
8396365beadSRussell King 		p->num = i;
8406365beadSRussell King 		p->base = d->base + i * DMA_SIZE;
8416365beadSRussell King 		writel_relaxed(DCSR_RUN | DCSR_IE | DCSR_ERROR |
8426365beadSRussell King 			DCSR_DONEA | DCSR_STRTA | DCSR_DONEB | DCSR_STRTB,
8436365beadSRussell King 			p->base + DMA_DCSR_C);
8446365beadSRussell King 		writel_relaxed(0, p->base + DMA_DDAR);
8456365beadSRussell King 
8466365beadSRussell King 		ret = sa11x0_dma_request_irq(pdev, i, p);
8476365beadSRussell King 		if (ret) {
8486365beadSRussell King 			while (i) {
8496365beadSRussell King 				i--;
8506365beadSRussell King 				sa11x0_dma_free_irq(pdev, i, &d->phy[i]);
8516365beadSRussell King 			}
8526365beadSRussell King 			goto err_irq;
8536365beadSRussell King 		}
8546365beadSRussell King 	}
8556365beadSRussell King 
8566365beadSRussell King 	dma_cap_set(DMA_SLAVE, d->slave.cap_mask);
8576365beadSRussell King 	d->slave.device_prep_slave_sg = sa11x0_dma_prep_slave_sg;
8586365beadSRussell King 	ret = sa11x0_dma_init_dmadev(&d->slave, &pdev->dev);
8596365beadSRussell King 	if (ret) {
8606365beadSRussell King 		dev_warn(d->slave.dev, "failed to register slave async device: %d\n",
8616365beadSRussell King 			ret);
8626365beadSRussell King 		goto err_slave_reg;
8636365beadSRussell King 	}
8646365beadSRussell King 
8656365beadSRussell King 	platform_set_drvdata(pdev, d);
8666365beadSRussell King 	return 0;
8676365beadSRussell King 
8686365beadSRussell King  err_slave_reg:
8696365beadSRussell King 	sa11x0_dma_free_channels(&d->slave);
8706365beadSRussell King 	for (i = 0; i < NR_PHY_CHAN; i++)
8716365beadSRussell King 		sa11x0_dma_free_irq(pdev, i, &d->phy[i]);
8726365beadSRussell King  err_irq:
8736365beadSRussell King 	tasklet_kill(&d->task);
8746365beadSRussell King 	iounmap(d->base);
8756365beadSRussell King  err_ioremap:
8766365beadSRussell King 	kfree(d);
8776365beadSRussell King  err_alloc:
8786365beadSRussell King 	return ret;
8796365beadSRussell King }
8806365beadSRussell King 
8816365beadSRussell King static int __devexit sa11x0_dma_remove(struct platform_device *pdev)
8826365beadSRussell King {
8836365beadSRussell King 	struct sa11x0_dma_dev *d = platform_get_drvdata(pdev);
8846365beadSRussell King 	unsigned pch;
8856365beadSRussell King 
8866365beadSRussell King 	dma_async_device_unregister(&d->slave);
8876365beadSRussell King 
8886365beadSRussell King 	sa11x0_dma_free_channels(&d->slave);
8896365beadSRussell King 	for (pch = 0; pch < NR_PHY_CHAN; pch++)
8906365beadSRussell King 		sa11x0_dma_free_irq(pdev, pch, &d->phy[pch]);
8916365beadSRussell King 	tasklet_kill(&d->task);
8926365beadSRussell King 	iounmap(d->base);
8936365beadSRussell King 	kfree(d);
8946365beadSRussell King 
8956365beadSRussell King 	return 0;
8966365beadSRussell King }
8976365beadSRussell King 
8986365beadSRussell King #ifdef CONFIG_PM_SLEEP
8996365beadSRussell King static int sa11x0_dma_suspend(struct device *dev)
9006365beadSRussell King {
9016365beadSRussell King 	struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
9026365beadSRussell King 	unsigned pch;
9036365beadSRussell King 
9046365beadSRussell King 	for (pch = 0; pch < NR_PHY_CHAN; pch++) {
9056365beadSRussell King 		struct sa11x0_dma_phy *p = &d->phy[pch];
9066365beadSRussell King 		u32 dcsr, saved_dcsr;
9076365beadSRussell King 
9086365beadSRussell King 		dcsr = saved_dcsr = readl_relaxed(p->base + DMA_DCSR_R);
9096365beadSRussell King 		if (dcsr & DCSR_RUN) {
9106365beadSRussell King 			writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C);
9116365beadSRussell King 			dcsr = readl_relaxed(p->base + DMA_DCSR_R);
9126365beadSRussell King 		}
9136365beadSRussell King 
9146365beadSRussell King 		saved_dcsr &= DCSR_RUN | DCSR_IE;
9156365beadSRussell King 		if (dcsr & DCSR_BIU) {
9166365beadSRussell King 			p->dbs[0] = readl_relaxed(p->base + DMA_DBSB);
9176365beadSRussell King 			p->dbt[0] = readl_relaxed(p->base + DMA_DBTB);
9186365beadSRussell King 			p->dbs[1] = readl_relaxed(p->base + DMA_DBSA);
9196365beadSRussell King 			p->dbt[1] = readl_relaxed(p->base + DMA_DBTA);
9206365beadSRussell King 			saved_dcsr |= (dcsr & DCSR_STRTA ? DCSR_STRTB : 0) |
9216365beadSRussell King 				      (dcsr & DCSR_STRTB ? DCSR_STRTA : 0);
9226365beadSRussell King 		} else {
9236365beadSRussell King 			p->dbs[0] = readl_relaxed(p->base + DMA_DBSA);
9246365beadSRussell King 			p->dbt[0] = readl_relaxed(p->base + DMA_DBTA);
9256365beadSRussell King 			p->dbs[1] = readl_relaxed(p->base + DMA_DBSB);
9266365beadSRussell King 			p->dbt[1] = readl_relaxed(p->base + DMA_DBTB);
9276365beadSRussell King 			saved_dcsr |= dcsr & (DCSR_STRTA | DCSR_STRTB);
9286365beadSRussell King 		}
9296365beadSRussell King 		p->dcsr = saved_dcsr;
9306365beadSRussell King 
9316365beadSRussell King 		writel(DCSR_STRTA | DCSR_STRTB, p->base + DMA_DCSR_C);
9326365beadSRussell King 	}
9336365beadSRussell King 
9346365beadSRussell King 	return 0;
9356365beadSRussell King }
9366365beadSRussell King 
9376365beadSRussell King static int sa11x0_dma_resume(struct device *dev)
9386365beadSRussell King {
9396365beadSRussell King 	struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
9406365beadSRussell King 	unsigned pch;
9416365beadSRussell King 
9426365beadSRussell King 	for (pch = 0; pch < NR_PHY_CHAN; pch++) {
9436365beadSRussell King 		struct sa11x0_dma_phy *p = &d->phy[pch];
9446365beadSRussell King 		struct sa11x0_dma_desc *txd = NULL;
9456365beadSRussell King 		u32 dcsr = readl_relaxed(p->base + DMA_DCSR_R);
9466365beadSRussell King 
9476365beadSRussell King 		WARN_ON(dcsr & (DCSR_BIU | DCSR_STRTA | DCSR_STRTB | DCSR_RUN));
9486365beadSRussell King 
9496365beadSRussell King 		if (p->txd_done)
9506365beadSRussell King 			txd = p->txd_done;
9516365beadSRussell King 		else if (p->txd_load)
9526365beadSRussell King 			txd = p->txd_load;
9536365beadSRussell King 
9546365beadSRussell King 		if (!txd)
9556365beadSRussell King 			continue;
9566365beadSRussell King 
9576365beadSRussell King 		writel_relaxed(txd->ddar, p->base + DMA_DDAR);
9586365beadSRussell King 
9596365beadSRussell King 		writel_relaxed(p->dbs[0], p->base + DMA_DBSA);
9606365beadSRussell King 		writel_relaxed(p->dbt[0], p->base + DMA_DBTA);
9616365beadSRussell King 		writel_relaxed(p->dbs[1], p->base + DMA_DBSB);
9626365beadSRussell King 		writel_relaxed(p->dbt[1], p->base + DMA_DBTB);
9636365beadSRussell King 		writel_relaxed(p->dcsr, p->base + DMA_DCSR_S);
9646365beadSRussell King 	}
9656365beadSRussell King 
9666365beadSRussell King 	return 0;
9676365beadSRussell King }
9686365beadSRussell King #endif
9696365beadSRussell King 
9706365beadSRussell King static const struct dev_pm_ops sa11x0_dma_pm_ops = {
9716365beadSRussell King 	.suspend_noirq = sa11x0_dma_suspend,
9726365beadSRussell King 	.resume_noirq = sa11x0_dma_resume,
9736365beadSRussell King 	.freeze_noirq = sa11x0_dma_suspend,
9746365beadSRussell King 	.thaw_noirq = sa11x0_dma_resume,
9756365beadSRussell King 	.poweroff_noirq = sa11x0_dma_suspend,
9766365beadSRussell King 	.restore_noirq = sa11x0_dma_resume,
9776365beadSRussell King };
9786365beadSRussell King 
9796365beadSRussell King static struct platform_driver sa11x0_dma_driver = {
9806365beadSRussell King 	.driver = {
9816365beadSRussell King 		.name	= "sa11x0-dma",
9826365beadSRussell King 		.owner	= THIS_MODULE,
9836365beadSRussell King 		.pm	= &sa11x0_dma_pm_ops,
9846365beadSRussell King 	},
9856365beadSRussell King 	.probe		= sa11x0_dma_probe,
9866365beadSRussell King 	.remove		= __devexit_p(sa11x0_dma_remove),
9876365beadSRussell King };
9886365beadSRussell King 
9896365beadSRussell King bool sa11x0_dma_filter_fn(struct dma_chan *chan, void *param)
9906365beadSRussell King {
9916365beadSRussell King 	if (chan->device->dev->driver == &sa11x0_dma_driver.driver) {
9926365beadSRussell King 		struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
9936365beadSRussell King 		const char *p = param;
9946365beadSRussell King 
9956365beadSRussell King 		return !strcmp(c->name, p);
9966365beadSRussell King 	}
9976365beadSRussell King 	return false;
9986365beadSRussell King }
9996365beadSRussell King EXPORT_SYMBOL(sa11x0_dma_filter_fn);
10006365beadSRussell King 
10016365beadSRussell King static int __init sa11x0_dma_init(void)
10026365beadSRussell King {
10036365beadSRussell King 	return platform_driver_register(&sa11x0_dma_driver);
10046365beadSRussell King }
10056365beadSRussell King subsys_initcall(sa11x0_dma_init);
10066365beadSRussell King 
10076365beadSRussell King static void __exit sa11x0_dma_exit(void)
10086365beadSRussell King {
10096365beadSRussell King 	platform_driver_unregister(&sa11x0_dma_driver);
10106365beadSRussell King }
10116365beadSRussell King module_exit(sa11x0_dma_exit);
10126365beadSRussell King 
10136365beadSRussell King MODULE_AUTHOR("Russell King");
10146365beadSRussell King MODULE_DESCRIPTION("SA-11x0 DMA driver");
10156365beadSRussell King MODULE_LICENSE("GPL v2");
10166365beadSRussell King MODULE_ALIAS("platform:sa11x0-dma");
1017