blob: a59c3c47286c66757ca2b41a84872d11b4656ea8 [file] [log] [blame]
Linus Walleije8689e62010-09-28 15:57:37 +02001/*
2 * Copyright (c) 2006 ARM Ltd.
3 * Copyright (c) 2010 ST-Ericsson SA
4 *
5 * Author: Peter Pearse <peter.pearse@arm.com>
6 * Author: Linus Walleij <linus.walleij@stericsson.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +000022 * The full GNU General Public License is in this distribution in the file
23 * called COPYING.
Linus Walleije8689e62010-09-28 15:57:37 +020024 *
25 * Documentation: ARM DDI 0196G == PL080
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +000026 * Documentation: ARM DDI 0218E == PL081
Linus Walleije8689e62010-09-28 15:57:37 +020027 *
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +000028 * PL080 & PL081 both have 16 sets of DMA signals that can be routed to any
29 * channel.
Linus Walleije8689e62010-09-28 15:57:37 +020030 *
31 * The PL080 has 8 channels available for simultaneous use, and the PL081
32 * has only two channels. So on these DMA controllers the number of channels
33 * and the number of incoming DMA signals are two totally different things.
34 * It is usually not possible to theoretically handle all physical signals,
35 * so a multiplexing scheme with possible denial of use is necessary.
36 *
37 * The PL080 has a dual bus master, PL081 has a single master.
38 *
39 * Memory to peripheral transfer may be visualized as
40 * Get data from memory to DMAC
41 * Until no data left
42 * On burst request from peripheral
43 * Destination burst from DMAC to peripheral
44 * Clear burst request
45 * Raise terminal count interrupt
46 *
47 * For peripherals with a FIFO:
48 * Source burst size == half the depth of the peripheral FIFO
49 * Destination burst size == the depth of the peripheral FIFO
50 *
51 * (Bursts are irrelevant for mem to mem transfers - there are no burst
52 * signals, the DMA controller will simply facilitate its AHB master.)
53 *
54 * ASSUMES default (little) endianness for DMA transfers
55 *
Russell King - ARM Linux9dc2c202011-01-03 22:33:06 +000056 * The PL08x has two flow control settings:
57 * - DMAC flow control: the transfer size defines the number of transfers
58 * which occur for the current LLI entry, and the DMAC raises TC at the
59 * end of every LLI entry. Observed behaviour shows the DMAC listening
60 * to both the BREQ and SREQ signals (contrary to documented),
61 * transferring data if either is active. The LBREQ and LSREQ signals
62 * are ignored.
63 *
64 * - Peripheral flow control: the transfer size is ignored (and should be
65 * zero). The data is transferred from the current LLI entry, until
66 * after the final transfer signalled by LBREQ or LSREQ. The DMAC
67 * will then move to the next LLI entry.
68 *
Linus Walleije8689e62010-09-28 15:57:37 +020069 * Global TODO:
70 * - Break out common code from arch/arm/mach-s3c64xx and share
71 */
Russell King - ARM Linux730404a2011-01-03 22:34:07 +000072#include <linux/amba/bus.h>
Linus Walleije8689e62010-09-28 15:57:37 +020073#include <linux/amba/pl08x.h>
74#include <linux/debugfs.h>
Viresh Kumar0c38d702011-08-05 15:32:28 +053075#include <linux/delay.h>
76#include <linux/device.h>
77#include <linux/dmaengine.h>
78#include <linux/dmapool.h>
79#include <linux/init.h>
80#include <linux/interrupt.h>
81#include <linux/module.h>
Viresh Kumarb7b60182011-08-05 15:32:33 +053082#include <linux/pm_runtime.h>
Linus Walleije8689e62010-09-28 15:57:37 +020083#include <linux/seq_file.h>
Viresh Kumar0c38d702011-08-05 15:32:28 +053084#include <linux/slab.h>
Linus Walleije8689e62010-09-28 15:57:37 +020085#include <asm/hardware/pl080.h>
Linus Walleije8689e62010-09-28 15:57:37 +020086
87#define DRIVER_NAME "pl08xdmac"
88
89/**
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +000090 * struct vendor_data - vendor-specific config parameters for PL08x derivatives
Linus Walleije8689e62010-09-28 15:57:37 +020091 * @channels: the number of channels available in this variant
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +000092 * @dualmaster: whether this version supports dual AHB masters or not.
Linus Walleije8689e62010-09-28 15:57:37 +020093 */
94struct vendor_data {
Linus Walleije8689e62010-09-28 15:57:37 +020095 u8 channels;
96 bool dualmaster;
97};
98
99/*
100 * PL08X private data structures
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +0000101 * An LLI struct - see PL08x TRM. Note that next uses bit[0] as a bus bit,
Russell King - ARM Linuxe25761d2011-01-03 22:37:52 +0000102 * start & end do not - their bus bit info is in cctl. Also note that these
103 * are fixed 32-bit quantities.
Linus Walleije8689e62010-09-28 15:57:37 +0200104 */
Russell King - ARM Linux7cb72ad2011-01-03 22:35:28 +0000105struct pl08x_lli {
Russell King - ARM Linuxe25761d2011-01-03 22:37:52 +0000106 u32 src;
107 u32 dst;
Russell King - ARM Linuxbfddfb42011-01-03 22:38:12 +0000108 u32 lli;
Linus Walleije8689e62010-09-28 15:57:37 +0200109 u32 cctl;
110};
111
112/**
113 * struct pl08x_driver_data - the local state holder for the PL08x
114 * @slave: slave engine for this instance
115 * @memcpy: memcpy engine for this instance
116 * @base: virtual memory base (remapped) for the PL08x
117 * @adev: the corresponding AMBA (PrimeCell) bus entry
118 * @vd: vendor data for this PL08x variant
119 * @pd: platform data passed in from the platform/machine
120 * @phy_chans: array of data for the physical channels
121 * @pool: a pool for the LLI descriptors
122 * @pool_ctr: counter of LLIs in the pool
Viresh Kumar3e27ee82011-08-05 15:32:27 +0530123 * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
124 * fetches
Russell King - ARM Linux30749cb2011-01-03 22:41:13 +0000125 * @mem_buses: set to indicate memory transfers on AHB2.
Linus Walleije8689e62010-09-28 15:57:37 +0200126 * @lock: a spinlock for this struct
127 */
128struct pl08x_driver_data {
129 struct dma_device slave;
130 struct dma_device memcpy;
131 void __iomem *base;
132 struct amba_device *adev;
Russell King - ARM Linuxf96ca9ec2011-01-03 22:35:08 +0000133 const struct vendor_data *vd;
Linus Walleije8689e62010-09-28 15:57:37 +0200134 struct pl08x_platform_data *pd;
135 struct pl08x_phy_chan *phy_chans;
136 struct dma_pool *pool;
137 int pool_ctr;
Russell King - ARM Linux30749cb2011-01-03 22:41:13 +0000138 u8 lli_buses;
139 u8 mem_buses;
Linus Walleije8689e62010-09-28 15:57:37 +0200140 spinlock_t lock;
141};
142
143/*
144 * PL08X specific defines
145 */
146
Linus Walleije8689e62010-09-28 15:57:37 +0200147/* Size (bytes) of each LLI buffer allocated for one transfer */
148# define PL08X_LLI_TSFR_SIZE 0x2000
149
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +0000150/* Maximum times we call dma_pool_alloc on this pool without freeing */
Russell King - ARM Linux7cb72ad2011-01-03 22:35:28 +0000151#define MAX_NUM_TSFR_LLIS (PL08X_LLI_TSFR_SIZE/sizeof(struct pl08x_lli))
Linus Walleije8689e62010-09-28 15:57:37 +0200152#define PL08X_ALIGN 8
153
154static inline struct pl08x_dma_chan *to_pl08x_chan(struct dma_chan *chan)
155{
156 return container_of(chan, struct pl08x_dma_chan, chan);
157}
158
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +0000159static inline struct pl08x_txd *to_pl08x_txd(struct dma_async_tx_descriptor *tx)
160{
161 return container_of(tx, struct pl08x_txd, tx);
162}
163
Linus Walleije8689e62010-09-28 15:57:37 +0200164/*
165 * Physical channel handling
166 */
167
168/* Whether a certain channel is busy or not */
169static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch)
170{
171 unsigned int val;
172
173 val = readl(ch->base + PL080_CH_CONFIG);
174 return val & PL080_CONFIG_ACTIVE;
175}
176
177/*
178 * Set the initial DMA register values i.e. those for the first LLI
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +0000179 * The next LLI pointer and the configuration interrupt bit have
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000180 * been set when the LLIs were constructed. Poke them into the hardware
181 * and start the transfer.
Linus Walleije8689e62010-09-28 15:57:37 +0200182 */
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000183static void pl08x_start_txd(struct pl08x_dma_chan *plchan,
184 struct pl08x_txd *txd)
Linus Walleije8689e62010-09-28 15:57:37 +0200185{
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000186 struct pl08x_driver_data *pl08x = plchan->host;
Linus Walleije8689e62010-09-28 15:57:37 +0200187 struct pl08x_phy_chan *phychan = plchan->phychan;
Russell King - ARM Linux19524d72011-01-03 22:39:13 +0000188 struct pl08x_lli *lli = &txd->llis_va[0];
Russell King - ARM Linux09b3c322011-01-03 22:39:53 +0000189 u32 val;
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000190
191 plchan->at = txd;
Linus Walleije8689e62010-09-28 15:57:37 +0200192
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000193 /* Wait for channel inactive */
194 while (pl08x_phy_channel_busy(phychan))
Russell King - ARM Linux19386b322011-01-03 22:36:29 +0000195 cpu_relax();
Linus Walleije8689e62010-09-28 15:57:37 +0200196
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000197 dev_vdbg(&pl08x->adev->dev,
198 "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
Russell King - ARM Linux19524d72011-01-03 22:39:13 +0000199 "clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n",
200 phychan->id, lli->src, lli->dst, lli->lli, lli->cctl,
Russell King - ARM Linux09b3c322011-01-03 22:39:53 +0000201 txd->ccfg);
Linus Walleije8689e62010-09-28 15:57:37 +0200202
Russell King - ARM Linux19524d72011-01-03 22:39:13 +0000203 writel(lli->src, phychan->base + PL080_CH_SRC_ADDR);
204 writel(lli->dst, phychan->base + PL080_CH_DST_ADDR);
205 writel(lli->lli, phychan->base + PL080_CH_LLI);
206 writel(lli->cctl, phychan->base + PL080_CH_CONTROL);
Russell King - ARM Linux09b3c322011-01-03 22:39:53 +0000207 writel(txd->ccfg, phychan->base + PL080_CH_CONFIG);
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +0000208
209 /* Enable the DMA channel */
210 /* Do not access config register until channel shows as disabled */
211 while (readl(pl08x->base + PL080_EN_CHAN) & (1 << phychan->id))
212 cpu_relax();
213
214 /* Do not access config register until channel shows as inactive */
215 val = readl(phychan->base + PL080_CH_CONFIG);
216 while ((val & PL080_CONFIG_ACTIVE) || (val & PL080_CONFIG_ENABLE))
217 val = readl(phychan->base + PL080_CH_CONFIG);
218
219 writel(val | PL080_CONFIG_ENABLE, phychan->base + PL080_CH_CONFIG);
Linus Walleije8689e62010-09-28 15:57:37 +0200220}
221
222/*
Russell King - ARM Linux81796612011-01-27 12:37:44 +0000223 * Pause the channel by setting the HALT bit.
Linus Walleije8689e62010-09-28 15:57:37 +0200224 *
Russell King - ARM Linux81796612011-01-27 12:37:44 +0000225 * For M->P transfers, pause the DMAC first and then stop the peripheral -
226 * the FIFO can only drain if the peripheral is still requesting data.
227 * (note: this can still timeout if the DMAC FIFO never drains of data.)
Linus Walleije8689e62010-09-28 15:57:37 +0200228 *
Russell King - ARM Linux81796612011-01-27 12:37:44 +0000229 * For P->M transfers, disable the peripheral first to stop it filling
230 * the DMAC FIFO, and then pause the DMAC.
Linus Walleije8689e62010-09-28 15:57:37 +0200231 */
232static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch)
233{
234 u32 val;
Russell King - ARM Linux81796612011-01-27 12:37:44 +0000235 int timeout;
Linus Walleije8689e62010-09-28 15:57:37 +0200236
237 /* Set the HALT bit and wait for the FIFO to drain */
238 val = readl(ch->base + PL080_CH_CONFIG);
239 val |= PL080_CONFIG_HALT;
240 writel(val, ch->base + PL080_CH_CONFIG);
241
242 /* Wait for channel inactive */
Russell King - ARM Linux81796612011-01-27 12:37:44 +0000243 for (timeout = 1000; timeout; timeout--) {
244 if (!pl08x_phy_channel_busy(ch))
245 break;
246 udelay(1);
247 }
248 if (pl08x_phy_channel_busy(ch))
249 pr_err("pl08x: channel%u timeout waiting for pause\n", ch->id);
Linus Walleije8689e62010-09-28 15:57:37 +0200250}
251
252static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
253{
254 u32 val;
255
256 /* Clear the HALT bit */
257 val = readl(ch->base + PL080_CH_CONFIG);
258 val &= ~PL080_CONFIG_HALT;
259 writel(val, ch->base + PL080_CH_CONFIG);
260}
261
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +0000262/*
263 * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
264 * clears any pending interrupt status. This should not be used for
265 * an on-going transfer, but as a method of shutting down a channel
266 * (eg, when it's no longer used) or terminating a transfer.
267 */
268static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x,
269 struct pl08x_phy_chan *ch)
Linus Walleije8689e62010-09-28 15:57:37 +0200270{
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +0000271 u32 val = readl(ch->base + PL080_CH_CONFIG);
Linus Walleije8689e62010-09-28 15:57:37 +0200272
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +0000273 val &= ~(PL080_CONFIG_ENABLE | PL080_CONFIG_ERR_IRQ_MASK |
274 PL080_CONFIG_TC_IRQ_MASK);
Linus Walleije8689e62010-09-28 15:57:37 +0200275
Linus Walleije8689e62010-09-28 15:57:37 +0200276 writel(val, ch->base + PL080_CH_CONFIG);
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +0000277
278 writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR);
279 writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR);
Linus Walleije8689e62010-09-28 15:57:37 +0200280}
281
282static inline u32 get_bytes_in_cctl(u32 cctl)
283{
284 /* The source width defines the number of bytes */
285 u32 bytes = cctl & PL080_CONTROL_TRANSFER_SIZE_MASK;
286
287 switch (cctl >> PL080_CONTROL_SWIDTH_SHIFT) {
288 case PL080_WIDTH_8BIT:
289 break;
290 case PL080_WIDTH_16BIT:
291 bytes *= 2;
292 break;
293 case PL080_WIDTH_32BIT:
294 bytes *= 4;
295 break;
296 }
297 return bytes;
298}
299
300/* The channel should be paused when calling this */
301static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
302{
303 struct pl08x_phy_chan *ch;
Linus Walleije8689e62010-09-28 15:57:37 +0200304 struct pl08x_txd *txd;
305 unsigned long flags;
Russell King - ARM Linuxcace6582011-01-03 22:37:31 +0000306 size_t bytes = 0;
Linus Walleije8689e62010-09-28 15:57:37 +0200307
308 spin_lock_irqsave(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +0200309 ch = plchan->phychan;
310 txd = plchan->at;
311
312 /*
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000313 * Follow the LLIs to get the number of remaining
314 * bytes in the currently active transaction.
Linus Walleije8689e62010-09-28 15:57:37 +0200315 */
316 if (ch && txd) {
Russell King - ARM Linux4c0df6a2011-01-03 22:36:50 +0000317 u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
Linus Walleije8689e62010-09-28 15:57:37 +0200318
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000319 /* First get the remaining bytes in the active transfer */
Linus Walleije8689e62010-09-28 15:57:37 +0200320 bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
321
322 if (clli) {
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000323 struct pl08x_lli *llis_va = txd->llis_va;
324 dma_addr_t llis_bus = txd->llis_bus;
325 int index;
Linus Walleije8689e62010-09-28 15:57:37 +0200326
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000327 BUG_ON(clli < llis_bus || clli >= llis_bus +
328 sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
Linus Walleije8689e62010-09-28 15:57:37 +0200329
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000330 /*
331 * Locate the next LLI - as this is an array,
332 * it's simple maths to find.
333 */
334 index = (clli - llis_bus) / sizeof(struct pl08x_lli);
335
336 for (; index < MAX_NUM_TSFR_LLIS; index++) {
337 bytes += get_bytes_in_cctl(llis_va[index].cctl);
338
Linus Walleije8689e62010-09-28 15:57:37 +0200339 /*
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +0000340 * A LLI pointer of 0 terminates the LLI list
Linus Walleije8689e62010-09-28 15:57:37 +0200341 */
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000342 if (!llis_va[index].lli)
343 break;
Linus Walleije8689e62010-09-28 15:57:37 +0200344 }
345 }
346 }
347
348 /* Sum up all queued transactions */
Russell King - ARM Linux15c17232011-01-03 22:44:36 +0000349 if (!list_empty(&plchan->pend_list)) {
Russell King - ARM Linuxdb9f1362011-01-03 22:38:32 +0000350 struct pl08x_txd *txdi;
Russell King - ARM Linux15c17232011-01-03 22:44:36 +0000351 list_for_each_entry(txdi, &plchan->pend_list, node) {
Linus Walleije8689e62010-09-28 15:57:37 +0200352 bytes += txdi->len;
353 }
Linus Walleije8689e62010-09-28 15:57:37 +0200354 }
355
356 spin_unlock_irqrestore(&plchan->lock, flags);
357
358 return bytes;
359}
360
361/*
362 * Allocate a physical channel for a virtual channel
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +0000363 *
364 * Try to locate a physical channel to be used for this transfer. If all
365 * are taken return NULL and the requester will have to cope by using
366 * some fallback PIO mode or retrying later.
Linus Walleije8689e62010-09-28 15:57:37 +0200367 */
368static struct pl08x_phy_chan *
369pl08x_get_phy_channel(struct pl08x_driver_data *pl08x,
370 struct pl08x_dma_chan *virt_chan)
371{
372 struct pl08x_phy_chan *ch = NULL;
373 unsigned long flags;
374 int i;
375
Linus Walleije8689e62010-09-28 15:57:37 +0200376 for (i = 0; i < pl08x->vd->channels; i++) {
377 ch = &pl08x->phy_chans[i];
378
379 spin_lock_irqsave(&ch->lock, flags);
380
381 if (!ch->serving) {
382 ch->serving = virt_chan;
383 ch->signal = -1;
384 spin_unlock_irqrestore(&ch->lock, flags);
385 break;
386 }
387
388 spin_unlock_irqrestore(&ch->lock, flags);
389 }
390
391 if (i == pl08x->vd->channels) {
392 /* No physical channel available, cope with it */
393 return NULL;
394 }
395
Viresh Kumarb7b60182011-08-05 15:32:33 +0530396 pm_runtime_get_sync(&pl08x->adev->dev);
Linus Walleije8689e62010-09-28 15:57:37 +0200397 return ch;
398}
399
400static inline void pl08x_put_phy_channel(struct pl08x_driver_data *pl08x,
401 struct pl08x_phy_chan *ch)
402{
403 unsigned long flags;
404
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +0000405 spin_lock_irqsave(&ch->lock, flags);
406
Linus Walleije8689e62010-09-28 15:57:37 +0200407 /* Stop the channel and clear its interrupts */
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +0000408 pl08x_terminate_phy_chan(pl08x, ch);
Linus Walleije8689e62010-09-28 15:57:37 +0200409
Viresh Kumarb7b60182011-08-05 15:32:33 +0530410 pm_runtime_put(&pl08x->adev->dev);
411
Linus Walleije8689e62010-09-28 15:57:37 +0200412 /* Mark it as free */
Linus Walleije8689e62010-09-28 15:57:37 +0200413 ch->serving = NULL;
414 spin_unlock_irqrestore(&ch->lock, flags);
415}
416
417/*
418 * LLI handling
419 */
420
421static inline unsigned int pl08x_get_bytes_for_cctl(unsigned int coded)
422{
423 switch (coded) {
424 case PL080_WIDTH_8BIT:
425 return 1;
426 case PL080_WIDTH_16BIT:
427 return 2;
428 case PL080_WIDTH_32BIT:
429 return 4;
430 default:
431 break;
432 }
433 BUG();
434 return 0;
435}
436
437static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
Russell King - ARM Linuxcace6582011-01-03 22:37:31 +0000438 size_t tsize)
Linus Walleije8689e62010-09-28 15:57:37 +0200439{
440 u32 retbits = cctl;
441
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +0000442 /* Remove all src, dst and transfer size bits */
Linus Walleije8689e62010-09-28 15:57:37 +0200443 retbits &= ~PL080_CONTROL_DWIDTH_MASK;
444 retbits &= ~PL080_CONTROL_SWIDTH_MASK;
445 retbits &= ~PL080_CONTROL_TRANSFER_SIZE_MASK;
446
447 /* Then set the bits according to the parameters */
448 switch (srcwidth) {
449 case 1:
450 retbits |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT;
451 break;
452 case 2:
453 retbits |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT;
454 break;
455 case 4:
456 retbits |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT;
457 break;
458 default:
459 BUG();
460 break;
461 }
462
463 switch (dstwidth) {
464 case 1:
465 retbits |= PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT;
466 break;
467 case 2:
468 retbits |= PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT;
469 break;
470 case 4:
471 retbits |= PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT;
472 break;
473 default:
474 BUG();
475 break;
476 }
477
478 retbits |= tsize << PL080_CONTROL_TRANSFER_SIZE_SHIFT;
479 return retbits;
480}
481
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000482struct pl08x_lli_build_data {
483 struct pl08x_txd *txd;
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000484 struct pl08x_bus_data srcbus;
485 struct pl08x_bus_data dstbus;
486 size_t remainder;
Russell King - ARM Linux25c94f72011-07-21 17:11:46 +0100487 u32 lli_bus;
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000488};
489
Linus Walleije8689e62010-09-28 15:57:37 +0200490/*
Viresh Kumar0532e6f2011-08-05 15:32:31 +0530491 * Autoselect a master bus to use for the transfer. Slave will be the chosen as
492 * victim in case src & dest are not similarly aligned. i.e. If after aligning
493 * masters address with width requirements of transfer (by sending few byte by
494 * byte data), slave is still not aligned, then its width will be reduced to
495 * BYTE.
496 * - prefers the destination bus if both available
Viresh Kumar036f05f2011-08-05 15:32:41 +0530497 * - prefers bus with fixed address (i.e. peripheral)
Linus Walleije8689e62010-09-28 15:57:37 +0200498 */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000499static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
500 struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
Linus Walleije8689e62010-09-28 15:57:37 +0200501{
502 if (!(cctl & PL080_CONTROL_DST_INCR)) {
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000503 *mbus = &bd->dstbus;
504 *sbus = &bd->srcbus;
Viresh Kumar036f05f2011-08-05 15:32:41 +0530505 } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
506 *mbus = &bd->srcbus;
507 *sbus = &bd->dstbus;
Linus Walleije8689e62010-09-28 15:57:37 +0200508 } else {
Viresh Kumar036f05f2011-08-05 15:32:41 +0530509 if (bd->dstbus.buswidth >= bd->srcbus.buswidth) {
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000510 *mbus = &bd->dstbus;
511 *sbus = &bd->srcbus;
Linus Walleije8689e62010-09-28 15:57:37 +0200512 } else {
Viresh Kumar036f05f2011-08-05 15:32:41 +0530513 *mbus = &bd->srcbus;
514 *sbus = &bd->dstbus;
Linus Walleije8689e62010-09-28 15:57:37 +0200515 }
516 }
517}
518
519/*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +0000520 * Fills in one LLI for a certain transfer descriptor and advance the counter
Linus Walleije8689e62010-09-28 15:57:37 +0200521 */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000522static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
523 int num_llis, int len, u32 cctl)
Linus Walleije8689e62010-09-28 15:57:37 +0200524{
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000525 struct pl08x_lli *llis_va = bd->txd->llis_va;
526 dma_addr_t llis_bus = bd->txd->llis_bus;
Linus Walleije8689e62010-09-28 15:57:37 +0200527
528 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
529
Russell King - ARM Linux30749cb2011-01-03 22:41:13 +0000530 llis_va[num_llis].cctl = cctl;
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000531 llis_va[num_llis].src = bd->srcbus.addr;
532 llis_va[num_llis].dst = bd->dstbus.addr;
Viresh Kumar3e27ee82011-08-05 15:32:27 +0530533 llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
534 sizeof(struct pl08x_lli);
Russell King - ARM Linux25c94f72011-07-21 17:11:46 +0100535 llis_va[num_llis].lli |= bd->lli_bus;
Linus Walleije8689e62010-09-28 15:57:37 +0200536
537 if (cctl & PL080_CONTROL_SRC_INCR)
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000538 bd->srcbus.addr += len;
Linus Walleije8689e62010-09-28 15:57:37 +0200539 if (cctl & PL080_CONTROL_DST_INCR)
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000540 bd->dstbus.addr += len;
Linus Walleije8689e62010-09-28 15:57:37 +0200541
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000542 BUG_ON(bd->remainder < len);
Russell King - ARM Linuxcace6582011-01-03 22:37:31 +0000543
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000544 bd->remainder -= len;
Linus Walleije8689e62010-09-28 15:57:37 +0200545}
546
Viresh Kumar03af5002011-08-05 15:32:39 +0530547static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
548 u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
549{
550 *cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
551 pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
552 (*total_bytes) += len;
553}
554
Linus Walleije8689e62010-09-28 15:57:37 +0200555/*
Linus Walleije8689e62010-09-28 15:57:37 +0200556 * This fills in the table of LLIs for the transfer descriptor
557 * Note that we assume we never have to change the burst sizes
558 * Return 0 for error
559 */
560static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
561 struct pl08x_txd *txd)
562{
Linus Walleije8689e62010-09-28 15:57:37 +0200563 struct pl08x_bus_data *mbus, *sbus;
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000564 struct pl08x_lli_build_data bd;
Linus Walleije8689e62010-09-28 15:57:37 +0200565 int num_llis = 0;
Viresh Kumar03af5002011-08-05 15:32:39 +0530566 u32 cctl, early_bytes = 0;
Viresh Kumar3e27ee82011-08-05 15:32:27 +0530567 size_t max_bytes_per_lli, total_bytes = 0;
Russell King - ARM Linux7cb72ad2011-01-03 22:35:28 +0000568 struct pl08x_lli *llis_va;
Linus Walleije8689e62010-09-28 15:57:37 +0200569
Viresh Kumar3e27ee82011-08-05 15:32:27 +0530570 txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
Linus Walleije8689e62010-09-28 15:57:37 +0200571 if (!txd->llis_va) {
572 dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__);
573 return 0;
574 }
575
576 pl08x->pool_ctr++;
577
Russell King - ARM Linux70b5ed62011-01-03 22:40:13 +0000578 /* Get the default CCTL */
579 cctl = txd->cctl;
Linus Walleije8689e62010-09-28 15:57:37 +0200580
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000581 bd.txd = txd;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +0000582 bd.srcbus.addr = txd->src_addr;
583 bd.dstbus.addr = txd->dst_addr;
Russell King - ARM Linux25c94f72011-07-21 17:11:46 +0100584 bd.lli_bus = (pl08x->lli_buses & PL08X_AHB2) ? PL080_LLI_LM_AHB2 : 0;
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000585
Linus Walleije8689e62010-09-28 15:57:37 +0200586 /* Find maximum width of the source bus */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000587 bd.srcbus.maxwidth =
Linus Walleije8689e62010-09-28 15:57:37 +0200588 pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_SWIDTH_MASK) >>
589 PL080_CONTROL_SWIDTH_SHIFT);
590
591 /* Find maximum width of the destination bus */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000592 bd.dstbus.maxwidth =
Linus Walleije8689e62010-09-28 15:57:37 +0200593 pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >>
594 PL080_CONTROL_DWIDTH_SHIFT);
595
596 /* Set up the bus widths to the maximum */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000597 bd.srcbus.buswidth = bd.srcbus.maxwidth;
598 bd.dstbus.buswidth = bd.dstbus.maxwidth;
Linus Walleije8689e62010-09-28 15:57:37 +0200599
Linus Walleije8689e62010-09-28 15:57:37 +0200600 /* We need to count this down to zero */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000601 bd.remainder = txd->len;
Linus Walleije8689e62010-09-28 15:57:37 +0200602
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000603 pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
Linus Walleije8689e62010-09-28 15:57:37 +0200604
Viresh Kumarfa6a9402011-08-05 15:32:38 +0530605 dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu\n",
Russell King - ARM Linuxfc74eb72011-07-21 17:12:06 +0100606 bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
607 bd.srcbus.buswidth,
608 bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
609 bd.dstbus.buswidth,
Viresh Kumarfa6a9402011-08-05 15:32:38 +0530610 bd.remainder);
Russell King - ARM Linuxfc74eb72011-07-21 17:12:06 +0100611 dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
612 mbus == &bd.srcbus ? "src" : "dst",
613 sbus == &bd.srcbus ? "src" : "dst");
614
Viresh Kumar03af5002011-08-05 15:32:39 +0530615 /*
Viresh Kumar0a235652011-08-05 15:32:42 +0530616 * Zero length is only allowed if all these requirements are met:
617 * - flow controller is peripheral.
618 * - src.addr is aligned to src.width
619 * - dst.addr is aligned to dst.width
620 *
621 * sg_len == 1 should be true, as there can be two cases here:
622 * - Memory addresses are contiguous and are not scattered. Here, Only
623 * one sg will be passed by user driver, with memory address and zero
624 * length. We pass this to controller and after the transfer it will
625 * receive the last burst request from peripheral and so transfer
626 * finishes.
627 *
628 * - Memory addresses are scattered and are not contiguous. Here,
629 * Obviously as DMA controller doesn't know when a lli's transfer gets
630 * over, it can't load next lli. So in this case, there has to be an
631 * assumption that only one lli is supported. Thus, we can't have
632 * scattered addresses.
633 */
634 if (!bd.remainder) {
635 u32 fc = (txd->ccfg & PL080_CONFIG_FLOW_CONTROL_MASK) >>
636 PL080_CONFIG_FLOW_CONTROL_SHIFT;
637 if (!((fc >= PL080_FLOW_SRC2DST_DST) &&
638 (fc <= PL080_FLOW_SRC2DST_SRC))) {
639 dev_err(&pl08x->adev->dev, "%s sg len can't be zero",
640 __func__);
641 return 0;
642 }
643
644 if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
645 (bd.srcbus.addr % bd.srcbus.buswidth)) {
646 dev_err(&pl08x->adev->dev,
647 "%s src & dst address must be aligned to src"
648 " & dst width if peripheral is flow controller",
649 __func__);
650 return 0;
651 }
652
653 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
654 bd.dstbus.buswidth, 0);
655 pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
656 }
657
658 /*
Viresh Kumar03af5002011-08-05 15:32:39 +0530659 * Send byte by byte for following cases
660 * - Less than a bus width available
661 * - until master bus is aligned
662 */
663 if (bd.remainder < mbus->buswidth)
664 early_bytes = bd.remainder;
665 else if ((mbus->addr) % (mbus->buswidth)) {
666 early_bytes = mbus->buswidth - (mbus->addr) % (mbus->buswidth);
667 if ((bd.remainder - early_bytes) < mbus->buswidth)
668 early_bytes = bd.remainder;
669 }
Linus Walleije8689e62010-09-28 15:57:37 +0200670
Viresh Kumar03af5002011-08-05 15:32:39 +0530671 if (early_bytes) {
672 dev_vdbg(&pl08x->adev->dev, "%s byte width LLIs "
673 "(remain 0x%08x)\n", __func__, bd.remainder);
674 prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
675 &total_bytes);
676 }
677
678 if (bd.remainder) {
Linus Walleije8689e62010-09-28 15:57:37 +0200679 /*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +0000680 * Master now aligned
Linus Walleije8689e62010-09-28 15:57:37 +0200681 * - if slave is not then we must set its width down
682 */
683 if (sbus->addr % sbus->buswidth) {
684 dev_dbg(&pl08x->adev->dev,
685 "%s set down bus width to one byte\n",
686 __func__);
687
688 sbus->buswidth = 1;
689 }
690
Viresh Kumarfa6a9402011-08-05 15:32:38 +0530691 /* Bytes transferred = tsize * src width, not MIN(buswidths) */
692 max_bytes_per_lli = bd.srcbus.buswidth *
693 PL080_CONTROL_TRANSFER_SIZE_MASK;
694
Linus Walleije8689e62010-09-28 15:57:37 +0200695 /*
696 * Make largest possible LLIs until less than one bus
697 * width left
698 */
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000699 while (bd.remainder > (mbus->buswidth - 1)) {
Viresh Kumare0719162011-08-05 15:32:40 +0530700 size_t lli_len, tsize, width;
Linus Walleije8689e62010-09-28 15:57:37 +0200701
702 /*
703 * If enough left try to send max possible,
704 * otherwise try to send the remainder
705 */
Viresh Kumar16a2e7d2011-08-05 15:32:37 +0530706 lli_len = min(bd.remainder, max_bytes_per_lli);
Viresh Kumare0719162011-08-05 15:32:40 +0530707
Linus Walleije8689e62010-09-28 15:57:37 +0200708 /*
Viresh Kumare0719162011-08-05 15:32:40 +0530709 * Check against maximum bus alignment: Calculate actual
Viresh Kumar16a2e7d2011-08-05 15:32:37 +0530710 * transfer size in relation to bus width and get a
Viresh Kumare0719162011-08-05 15:32:40 +0530711 * maximum remainder of the highest bus width - 1
Linus Walleije8689e62010-09-28 15:57:37 +0200712 */
Viresh Kumare0719162011-08-05 15:32:40 +0530713 width = max(mbus->buswidth, sbus->buswidth);
714 lli_len = (lli_len / width) * width;
715 tsize = lli_len / bd.srcbus.buswidth;
Linus Walleije8689e62010-09-28 15:57:37 +0200716
Viresh Kumar16a2e7d2011-08-05 15:32:37 +0530717 dev_vdbg(&pl08x->adev->dev,
718 "%s fill lli with single lli chunk of "
719 "size 0x%08zx (remainder 0x%08zx)\n",
720 __func__, lli_len, bd.remainder);
Linus Walleije8689e62010-09-28 15:57:37 +0200721
Viresh Kumar16a2e7d2011-08-05 15:32:37 +0530722 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
723 bd.dstbus.buswidth, tsize);
724 pl08x_fill_lli_for_desc(&bd, num_llis++, lli_len, cctl);
725 total_bytes += lli_len;
Linus Walleije8689e62010-09-28 15:57:37 +0200726 }
727
728 /*
729 * Send any odd bytes
730 */
Viresh Kumar03af5002011-08-05 15:32:39 +0530731 if (bd.remainder) {
Linus Walleije8689e62010-09-28 15:57:37 +0200732 dev_vdbg(&pl08x->adev->dev,
Viresh Kumar03af5002011-08-05 15:32:39 +0530733 "%s align with boundary, send odd bytes (remain %zu)\n",
Russell King - ARM Linux542361f2011-01-03 22:43:15 +0000734 __func__, bd.remainder);
Viresh Kumar03af5002011-08-05 15:32:39 +0530735 prep_byte_width_lli(&bd, &cctl, bd.remainder,
736 num_llis++, &total_bytes);
Linus Walleije8689e62010-09-28 15:57:37 +0200737 }
738 }
Viresh Kumar16a2e7d2011-08-05 15:32:37 +0530739
Linus Walleije8689e62010-09-28 15:57:37 +0200740 if (total_bytes != txd->len) {
741 dev_err(&pl08x->adev->dev,
Russell King - ARM Linuxcace6582011-01-03 22:37:31 +0000742 "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
Linus Walleije8689e62010-09-28 15:57:37 +0200743 __func__, total_bytes, txd->len);
744 return 0;
745 }
746
747 if (num_llis >= MAX_NUM_TSFR_LLIS) {
748 dev_err(&pl08x->adev->dev,
749 "%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
750 __func__, (u32) MAX_NUM_TSFR_LLIS);
751 return 0;
752 }
Linus Walleije8689e62010-09-28 15:57:37 +0200753
Russell King - ARM Linuxb58b6b52011-01-03 22:34:48 +0000754 llis_va = txd->llis_va;
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +0000755 /* The final LLI terminates the LLI. */
Russell King - ARM Linuxbfddfb42011-01-03 22:38:12 +0000756 llis_va[num_llis - 1].lli = 0;
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +0000757 /* The final LLI element shall also fire an interrupt. */
Russell King - ARM Linuxb58b6b52011-01-03 22:34:48 +0000758 llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN;
Linus Walleije8689e62010-09-28 15:57:37 +0200759
Linus Walleije8689e62010-09-28 15:57:37 +0200760#ifdef VERBOSE_DEBUG
761 {
762 int i;
763
Russell King - ARM Linuxfc74eb72011-07-21 17:12:06 +0100764 dev_vdbg(&pl08x->adev->dev,
765 "%-3s %-9s %-10s %-10s %-10s %s\n",
766 "lli", "", "csrc", "cdst", "clli", "cctl");
Linus Walleije8689e62010-09-28 15:57:37 +0200767 for (i = 0; i < num_llis; i++) {
768 dev_vdbg(&pl08x->adev->dev,
Russell King - ARM Linuxfc74eb72011-07-21 17:12:06 +0100769 "%3d @%p: 0x%08x 0x%08x 0x%08x 0x%08x\n",
770 i, &llis_va[i], llis_va[i].src,
771 llis_va[i].dst, llis_va[i].lli, llis_va[i].cctl
Linus Walleije8689e62010-09-28 15:57:37 +0200772 );
773 }
774 }
775#endif
776
777 return num_llis;
778}
779
780/* You should call this with the struct pl08x lock held */
781static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
782 struct pl08x_txd *txd)
783{
Linus Walleije8689e62010-09-28 15:57:37 +0200784 /* Free the LLI */
Russell King - ARM Linux56b61882011-01-03 22:37:10 +0000785 dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
Linus Walleije8689e62010-09-28 15:57:37 +0200786
787 pl08x->pool_ctr--;
788
789 kfree(txd);
790}
791
792static void pl08x_free_txd_list(struct pl08x_driver_data *pl08x,
793 struct pl08x_dma_chan *plchan)
794{
795 struct pl08x_txd *txdi = NULL;
796 struct pl08x_txd *next;
797
Russell King - ARM Linux15c17232011-01-03 22:44:36 +0000798 if (!list_empty(&plchan->pend_list)) {
Linus Walleije8689e62010-09-28 15:57:37 +0200799 list_for_each_entry_safe(txdi,
Russell King - ARM Linux15c17232011-01-03 22:44:36 +0000800 next, &plchan->pend_list, node) {
Linus Walleije8689e62010-09-28 15:57:37 +0200801 list_del(&txdi->node);
802 pl08x_free_txd(pl08x, txdi);
803 }
Linus Walleije8689e62010-09-28 15:57:37 +0200804 }
805}
806
807/*
808 * The DMA ENGINE API
809 */
810static int pl08x_alloc_chan_resources(struct dma_chan *chan)
811{
812 return 0;
813}
814
815static void pl08x_free_chan_resources(struct dma_chan *chan)
816{
817}
818
819/*
820 * This should be called with the channel plchan->lock held
821 */
822static int prep_phy_channel(struct pl08x_dma_chan *plchan,
823 struct pl08x_txd *txd)
824{
825 struct pl08x_driver_data *pl08x = plchan->host;
826 struct pl08x_phy_chan *ch;
827 int ret;
828
829 /* Check if we already have a channel */
830 if (plchan->phychan)
831 return 0;
832
833 ch = pl08x_get_phy_channel(pl08x, plchan);
834 if (!ch) {
835 /* No physical channel available, cope with it */
836 dev_dbg(&pl08x->adev->dev, "no physical channel available for xfer on %s\n", plchan->name);
837 return -EBUSY;
838 }
839
840 /*
841 * OK we have a physical channel: for memcpy() this is all we
842 * need, but for slaves the physical signals may be muxed!
843 * Can the platform allow us to use this channel?
844 */
Viresh Kumar16ca8102011-08-05 15:32:35 +0530845 if (plchan->slave && pl08x->pd->get_signal) {
Linus Walleije8689e62010-09-28 15:57:37 +0200846 ret = pl08x->pd->get_signal(plchan);
847 if (ret < 0) {
848 dev_dbg(&pl08x->adev->dev,
849 "unable to use physical channel %d for transfer on %s due to platform restrictions\n",
850 ch->id, plchan->name);
851 /* Release physical channel & return */
852 pl08x_put_phy_channel(pl08x, ch);
853 return -EBUSY;
854 }
855 ch->signal = ret;
Russell King - ARM Linux09b3c322011-01-03 22:39:53 +0000856
857 /* Assign the flow control signal to this channel */
858 if (txd->direction == DMA_TO_DEVICE)
859 txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT;
860 else if (txd->direction == DMA_FROM_DEVICE)
861 txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT;
Linus Walleije8689e62010-09-28 15:57:37 +0200862 }
863
864 dev_dbg(&pl08x->adev->dev, "allocated physical channel %d and signal %d for xfer on %s\n",
865 ch->id,
866 ch->signal,
867 plchan->name);
868
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +0000869 plchan->phychan_hold++;
Linus Walleije8689e62010-09-28 15:57:37 +0200870 plchan->phychan = ch;
871
872 return 0;
873}
874
Russell King - ARM Linux8c8cc2b2011-01-03 22:36:09 +0000875static void release_phy_channel(struct pl08x_dma_chan *plchan)
876{
877 struct pl08x_driver_data *pl08x = plchan->host;
878
879 if ((plchan->phychan->signal >= 0) && pl08x->pd->put_signal) {
880 pl08x->pd->put_signal(plchan);
881 plchan->phychan->signal = -1;
882 }
883 pl08x_put_phy_channel(pl08x, plchan->phychan);
884 plchan->phychan = NULL;
885}
886
Linus Walleije8689e62010-09-28 15:57:37 +0200887static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
888{
889 struct pl08x_dma_chan *plchan = to_pl08x_chan(tx->chan);
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +0000890 struct pl08x_txd *txd = to_pl08x_txd(tx);
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +0000891 unsigned long flags;
892
893 spin_lock_irqsave(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +0200894
Russell King - ARM Linux91aa5fa2011-01-03 22:31:04 +0000895 plchan->chan.cookie += 1;
896 if (plchan->chan.cookie < 0)
897 plchan->chan.cookie = 1;
898 tx->cookie = plchan->chan.cookie;
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +0000899
900 /* Put this onto the pending list */
901 list_add_tail(&txd->node, &plchan->pend_list);
902
903 /*
904 * If there was no physical channel available for this memcpy,
905 * stack the request up and indicate that the channel is waiting
906 * for a free physical channel.
907 */
908 if (!plchan->slave && !plchan->phychan) {
909 /* Do this memcpy whenever there is a channel ready */
910 plchan->state = PL08X_CHAN_WAITING;
911 plchan->waiting = txd;
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +0000912 } else {
913 plchan->phychan_hold--;
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +0000914 }
915
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +0000916 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +0200917
918 return tx->cookie;
919}
920
921static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt(
922 struct dma_chan *chan, unsigned long flags)
923{
924 struct dma_async_tx_descriptor *retval = NULL;
925
926 return retval;
927}
928
929/*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +0000930 * Code accessing dma_async_is_complete() in a tight loop may give problems.
931 * If slaves are relying on interrupts to signal completion this function
932 * must not be called with interrupts disabled.
Linus Walleije8689e62010-09-28 15:57:37 +0200933 */
Viresh Kumar3e27ee82011-08-05 15:32:27 +0530934static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
935 dma_cookie_t cookie, struct dma_tx_state *txstate)
Linus Walleije8689e62010-09-28 15:57:37 +0200936{
937 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
938 dma_cookie_t last_used;
939 dma_cookie_t last_complete;
940 enum dma_status ret;
941 u32 bytesleft = 0;
942
Russell King - ARM Linux91aa5fa2011-01-03 22:31:04 +0000943 last_used = plchan->chan.cookie;
Linus Walleije8689e62010-09-28 15:57:37 +0200944 last_complete = plchan->lc;
945
946 ret = dma_async_is_complete(cookie, last_complete, last_used);
947 if (ret == DMA_SUCCESS) {
948 dma_set_tx_state(txstate, last_complete, last_used, 0);
949 return ret;
950 }
951
952 /*
Linus Walleije8689e62010-09-28 15:57:37 +0200953 * This cookie not complete yet
954 */
Russell King - ARM Linux91aa5fa2011-01-03 22:31:04 +0000955 last_used = plchan->chan.cookie;
Linus Walleije8689e62010-09-28 15:57:37 +0200956 last_complete = plchan->lc;
957
958 /* Get number of bytes left in the active transactions and queue */
959 bytesleft = pl08x_getbytes_chan(plchan);
960
961 dma_set_tx_state(txstate, last_complete, last_used,
962 bytesleft);
963
964 if (plchan->state == PL08X_CHAN_PAUSED)
965 return DMA_PAUSED;
966
967 /* Whether waiting or running, we're in progress */
968 return DMA_IN_PROGRESS;
969}
970
971/* PrimeCell DMA extension */
972struct burst_table {
Russell King - ARM Linux760596c62011-07-21 17:14:08 +0100973 u32 burstwords;
Linus Walleije8689e62010-09-28 15:57:37 +0200974 u32 reg;
975};
976
977static const struct burst_table burst_sizes[] = {
978 {
979 .burstwords = 256,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +0100980 .reg = PL080_BSIZE_256,
Linus Walleije8689e62010-09-28 15:57:37 +0200981 },
982 {
983 .burstwords = 128,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +0100984 .reg = PL080_BSIZE_128,
Linus Walleije8689e62010-09-28 15:57:37 +0200985 },
986 {
987 .burstwords = 64,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +0100988 .reg = PL080_BSIZE_64,
Linus Walleije8689e62010-09-28 15:57:37 +0200989 },
990 {
991 .burstwords = 32,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +0100992 .reg = PL080_BSIZE_32,
Linus Walleije8689e62010-09-28 15:57:37 +0200993 },
994 {
995 .burstwords = 16,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +0100996 .reg = PL080_BSIZE_16,
Linus Walleije8689e62010-09-28 15:57:37 +0200997 },
998 {
999 .burstwords = 8,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +01001000 .reg = PL080_BSIZE_8,
Linus Walleije8689e62010-09-28 15:57:37 +02001001 },
1002 {
1003 .burstwords = 4,
Russell King - ARM Linux760596c62011-07-21 17:14:08 +01001004 .reg = PL080_BSIZE_4,
Linus Walleije8689e62010-09-28 15:57:37 +02001005 },
1006 {
Russell King - ARM Linux760596c62011-07-21 17:14:08 +01001007 .burstwords = 0,
1008 .reg = PL080_BSIZE_1,
Linus Walleije8689e62010-09-28 15:57:37 +02001009 },
1010};
1011
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001012/*
1013 * Given the source and destination available bus masks, select which
1014 * will be routed to each port. We try to have source and destination
1015 * on separate ports, but always respect the allowable settings.
1016 */
1017static u32 pl08x_select_bus(u8 src, u8 dst)
1018{
1019 u32 cctl = 0;
1020
1021 if (!(dst & PL08X_AHB1) || ((dst & PL08X_AHB2) && (src & PL08X_AHB1)))
1022 cctl |= PL080_CONTROL_DST_AHB2;
1023 if (!(src & PL08X_AHB1) || ((src & PL08X_AHB2) && !(dst & PL08X_AHB2)))
1024 cctl |= PL080_CONTROL_SRC_AHB2;
1025
1026 return cctl;
1027}
1028
Russell King - ARM Linuxf14c4262011-07-21 17:12:47 +01001029static u32 pl08x_cctl(u32 cctl)
1030{
1031 cctl &= ~(PL080_CONTROL_SRC_AHB2 | PL080_CONTROL_DST_AHB2 |
1032 PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR |
1033 PL080_CONTROL_PROT_MASK);
1034
1035 /* Access the cell in privileged mode, non-bufferable, non-cacheable */
1036 return cctl | PL080_CONTROL_PROT_SYS;
1037}
1038
Russell King - ARM Linuxaa88cda2011-07-21 17:13:28 +01001039static u32 pl08x_width(enum dma_slave_buswidth width)
1040{
1041 switch (width) {
1042 case DMA_SLAVE_BUSWIDTH_1_BYTE:
1043 return PL080_WIDTH_8BIT;
1044 case DMA_SLAVE_BUSWIDTH_2_BYTES:
1045 return PL080_WIDTH_16BIT;
1046 case DMA_SLAVE_BUSWIDTH_4_BYTES:
1047 return PL080_WIDTH_32BIT;
Vinod Koulf32807f2011-07-25 19:22:01 +05301048 default:
1049 return ~0;
Russell King - ARM Linuxaa88cda2011-07-21 17:13:28 +01001050 }
Russell King - ARM Linuxaa88cda2011-07-21 17:13:28 +01001051}
1052
Russell King - ARM Linux760596c62011-07-21 17:14:08 +01001053static u32 pl08x_burst(u32 maxburst)
1054{
1055 int i;
1056
1057 for (i = 0; i < ARRAY_SIZE(burst_sizes); i++)
1058 if (burst_sizes[i].burstwords <= maxburst)
1059 break;
1060
1061 return burst_sizes[i].reg;
1062}
1063
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001064static int dma_set_runtime_config(struct dma_chan *chan,
1065 struct dma_slave_config *config)
Linus Walleije8689e62010-09-28 15:57:37 +02001066{
1067 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1068 struct pl08x_driver_data *pl08x = plchan->host;
Linus Walleije8689e62010-09-28 15:57:37 +02001069 enum dma_slave_buswidth addr_width;
Russell King - ARM Linux760596c62011-07-21 17:14:08 +01001070 u32 width, burst, maxburst;
Linus Walleije8689e62010-09-28 15:57:37 +02001071 u32 cctl = 0;
Linus Walleije8689e62010-09-28 15:57:37 +02001072
Russell King - ARM Linuxb7f75862011-01-03 22:46:17 +00001073 if (!plchan->slave)
1074 return -EINVAL;
1075
Linus Walleije8689e62010-09-28 15:57:37 +02001076 /* Transfer direction */
1077 plchan->runtime_direction = config->direction;
1078 if (config->direction == DMA_TO_DEVICE) {
Linus Walleije8689e62010-09-28 15:57:37 +02001079 addr_width = config->dst_addr_width;
1080 maxburst = config->dst_maxburst;
1081 } else if (config->direction == DMA_FROM_DEVICE) {
Linus Walleije8689e62010-09-28 15:57:37 +02001082 addr_width = config->src_addr_width;
1083 maxburst = config->src_maxburst;
1084 } else {
1085 dev_err(&pl08x->adev->dev,
1086 "bad runtime_config: alien transfer direction\n");
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001087 return -EINVAL;
Linus Walleije8689e62010-09-28 15:57:37 +02001088 }
1089
Russell King - ARM Linuxaa88cda2011-07-21 17:13:28 +01001090 width = pl08x_width(addr_width);
1091 if (width == ~0) {
Linus Walleije8689e62010-09-28 15:57:37 +02001092 dev_err(&pl08x->adev->dev,
1093 "bad runtime_config: alien address width\n");
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001094 return -EINVAL;
Linus Walleije8689e62010-09-28 15:57:37 +02001095 }
1096
Russell King - ARM Linuxaa88cda2011-07-21 17:13:28 +01001097 cctl |= width << PL080_CONTROL_SWIDTH_SHIFT;
1098 cctl |= width << PL080_CONTROL_DWIDTH_SHIFT;
1099
Linus Walleije8689e62010-09-28 15:57:37 +02001100 /*
Russell King - ARM Linux4440aac2011-01-03 22:30:44 +00001101 * If this channel will only request single transfers, set this
1102 * down to ONE element. Also select one element if no maxburst
1103 * is specified.
Linus Walleije8689e62010-09-28 15:57:37 +02001104 */
Russell King - ARM Linux760596c62011-07-21 17:14:08 +01001105 if (plchan->cd->single)
1106 maxburst = 1;
1107
1108 burst = pl08x_burst(maxburst);
1109 cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT;
1110 cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT;
Linus Walleije8689e62010-09-28 15:57:37 +02001111
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001112 if (plchan->runtime_direction == DMA_FROM_DEVICE) {
1113 plchan->src_addr = config->src_addr;
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001114 plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR |
1115 pl08x_select_bus(plchan->cd->periph_buses,
1116 pl08x->mem_buses);
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001117 } else {
1118 plchan->dst_addr = config->dst_addr;
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001119 plchan->dst_cctl = pl08x_cctl(cctl) | PL080_CONTROL_SRC_INCR |
1120 pl08x_select_bus(pl08x->mem_buses,
1121 plchan->cd->periph_buses);
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001122 }
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001123
Linus Walleije8689e62010-09-28 15:57:37 +02001124 dev_dbg(&pl08x->adev->dev,
1125 "configured channel %s (%s) for %s, data width %d, "
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001126 "maxburst %d words, LE, CCTL=0x%08x\n",
Linus Walleije8689e62010-09-28 15:57:37 +02001127 dma_chan_name(chan), plchan->name,
1128 (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
1129 addr_width,
1130 maxburst,
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001131 cctl);
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001132
1133 return 0;
Linus Walleije8689e62010-09-28 15:57:37 +02001134}
1135
1136/*
1137 * Slave transactions callback to the slave device to allow
1138 * synchronization of slave DMA signals with the DMAC enable
1139 */
1140static void pl08x_issue_pending(struct dma_chan *chan)
1141{
1142 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
Linus Walleije8689e62010-09-28 15:57:37 +02001143 unsigned long flags;
1144
1145 spin_lock_irqsave(&plchan->lock, flags);
Russell King - ARM Linux9c0bb432011-01-03 22:32:05 +00001146 /* Something is already active, or we're waiting for a channel... */
1147 if (plchan->at || plchan->state == PL08X_CHAN_WAITING) {
1148 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001149 return;
Russell King - ARM Linux9c0bb432011-01-03 22:32:05 +00001150 }
Linus Walleije8689e62010-09-28 15:57:37 +02001151
1152 /* Take the first element in the queue and execute it */
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001153 if (!list_empty(&plchan->pend_list)) {
Linus Walleije8689e62010-09-28 15:57:37 +02001154 struct pl08x_txd *next;
1155
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001156 next = list_first_entry(&plchan->pend_list,
Linus Walleije8689e62010-09-28 15:57:37 +02001157 struct pl08x_txd,
1158 node);
1159 list_del(&next->node);
Linus Walleije8689e62010-09-28 15:57:37 +02001160 plchan->state = PL08X_CHAN_RUNNING;
1161
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +00001162 pl08x_start_txd(plchan, next);
Linus Walleije8689e62010-09-28 15:57:37 +02001163 }
1164
1165 spin_unlock_irqrestore(&plchan->lock, flags);
1166}
1167
1168static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
1169 struct pl08x_txd *txd)
1170{
Linus Walleije8689e62010-09-28 15:57:37 +02001171 struct pl08x_driver_data *pl08x = plchan->host;
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001172 unsigned long flags;
1173 int num_llis, ret;
Linus Walleije8689e62010-09-28 15:57:37 +02001174
1175 num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
Russell King - ARM Linuxdafa7312011-01-03 22:31:45 +00001176 if (!num_llis) {
1177 kfree(txd);
Linus Walleije8689e62010-09-28 15:57:37 +02001178 return -EINVAL;
Russell King - ARM Linuxdafa7312011-01-03 22:31:45 +00001179 }
Linus Walleije8689e62010-09-28 15:57:37 +02001180
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001181 spin_lock_irqsave(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001182
Linus Walleije8689e62010-09-28 15:57:37 +02001183 /*
1184 * See if we already have a physical channel allocated,
1185 * else this is the time to try to get one.
1186 */
1187 ret = prep_phy_channel(plchan, txd);
1188 if (ret) {
1189 /*
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +00001190 * No physical channel was available.
1191 *
1192 * memcpy transfers can be sorted out at submission time.
1193 *
1194 * Slave transfers may have been denied due to platform
1195 * channel muxing restrictions. Since there is no guarantee
1196 * that this will ever be resolved, and the signal must be
1197 * acquired AFTER acquiring the physical channel, we will let
1198 * them be NACK:ed with -EBUSY here. The drivers can retry
1199 * the prep() call if they are eager on doing this using DMA.
Linus Walleije8689e62010-09-28 15:57:37 +02001200 */
1201 if (plchan->slave) {
1202 pl08x_free_txd_list(pl08x, plchan);
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +00001203 pl08x_free_txd(pl08x, txd);
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001204 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001205 return -EBUSY;
1206 }
Linus Walleije8689e62010-09-28 15:57:37 +02001207 } else
1208 /*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001209 * Else we're all set, paused and ready to roll, status
1210 * will switch to PL08X_CHAN_RUNNING when we call
1211 * issue_pending(). If there is something running on the
1212 * channel already we don't change its state.
Linus Walleije8689e62010-09-28 15:57:37 +02001213 */
1214 if (plchan->state == PL08X_CHAN_IDLE)
1215 plchan->state = PL08X_CHAN_PAUSED;
1216
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001217 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001218
1219 return 0;
1220}
1221
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001222static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
1223 unsigned long flags)
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001224{
Viresh Kumarb201c112011-08-05 15:32:29 +05301225 struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001226
1227 if (txd) {
1228 dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001229 txd->tx.flags = flags;
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001230 txd->tx.tx_submit = pl08x_tx_submit;
1231 INIT_LIST_HEAD(&txd->node);
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001232
1233 /* Always enable error and terminal interrupts */
1234 txd->ccfg = PL080_CONFIG_ERR_IRQ_MASK |
1235 PL080_CONFIG_TC_IRQ_MASK;
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001236 }
1237 return txd;
1238}
1239
Linus Walleije8689e62010-09-28 15:57:37 +02001240/*
1241 * Initialize a descriptor to be used by memcpy submit
1242 */
1243static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
1244 struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
1245 size_t len, unsigned long flags)
1246{
1247 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1248 struct pl08x_driver_data *pl08x = plchan->host;
1249 struct pl08x_txd *txd;
1250 int ret;
1251
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001252 txd = pl08x_get_txd(plchan, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001253 if (!txd) {
1254 dev_err(&pl08x->adev->dev,
1255 "%s no memory for descriptor\n", __func__);
1256 return NULL;
1257 }
1258
Linus Walleije8689e62010-09-28 15:57:37 +02001259 txd->direction = DMA_NONE;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +00001260 txd->src_addr = src;
1261 txd->dst_addr = dest;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001262 txd->len = len;
Linus Walleije8689e62010-09-28 15:57:37 +02001263
1264 /* Set platform data for m2m */
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001265 txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001266 txd->cctl = pl08x->pd->memcpy_channel.cctl &
1267 ~(PL080_CONTROL_DST_AHB2 | PL080_CONTROL_SRC_AHB2);
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001268
Linus Walleije8689e62010-09-28 15:57:37 +02001269 /* Both to be incremented or the code will break */
Russell King - ARM Linux70b5ed62011-01-03 22:40:13 +00001270 txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001271
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001272 if (pl08x->vd->dualmaster)
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001273 txd->cctl |= pl08x_select_bus(pl08x->mem_buses,
1274 pl08x->mem_buses);
Linus Walleije8689e62010-09-28 15:57:37 +02001275
Linus Walleije8689e62010-09-28 15:57:37 +02001276 ret = pl08x_prep_channel_resources(plchan, txd);
1277 if (ret)
1278 return NULL;
Linus Walleije8689e62010-09-28 15:57:37 +02001279
1280 return &txd->tx;
1281}
1282
Russell King - ARM Linux3e2a0372011-01-03 22:32:46 +00001283static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
Linus Walleije8689e62010-09-28 15:57:37 +02001284 struct dma_chan *chan, struct scatterlist *sgl,
1285 unsigned int sg_len, enum dma_data_direction direction,
1286 unsigned long flags)
1287{
1288 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1289 struct pl08x_driver_data *pl08x = plchan->host;
1290 struct pl08x_txd *txd;
Viresh Kumar0a235652011-08-05 15:32:42 +05301291 int ret, tmp;
Linus Walleije8689e62010-09-28 15:57:37 +02001292
1293 /*
1294 * Current implementation ASSUMES only one sg
1295 */
1296 if (sg_len != 1) {
1297 dev_err(&pl08x->adev->dev, "%s prepared too long sglist\n",
1298 __func__);
1299 BUG();
1300 }
1301
1302 dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
1303 __func__, sgl->length, plchan->name);
1304
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001305 txd = pl08x_get_txd(plchan, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001306 if (!txd) {
1307 dev_err(&pl08x->adev->dev, "%s no txd\n", __func__);
1308 return NULL;
1309 }
1310
Linus Walleije8689e62010-09-28 15:57:37 +02001311 if (direction != plchan->runtime_direction)
1312 dev_err(&pl08x->adev->dev, "%s DMA setup does not match "
1313 "the direction configured for the PrimeCell\n",
1314 __func__);
1315
1316 /*
1317 * Set up addresses, the PrimeCell configured address
1318 * will take precedence since this may configure the
1319 * channel target address dynamically at runtime.
1320 */
1321 txd->direction = direction;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001322 txd->len = sgl->length;
1323
Linus Walleije8689e62010-09-28 15:57:37 +02001324 if (direction == DMA_TO_DEVICE) {
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001325 txd->cctl = plchan->dst_cctl;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +00001326 txd->src_addr = sgl->dma_address;
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001327 txd->dst_addr = plchan->dst_addr;
Linus Walleije8689e62010-09-28 15:57:37 +02001328 } else if (direction == DMA_FROM_DEVICE) {
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001329 txd->cctl = plchan->src_cctl;
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001330 txd->src_addr = plchan->src_addr;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +00001331 txd->dst_addr = sgl->dma_address;
Linus Walleije8689e62010-09-28 15:57:37 +02001332 } else {
1333 dev_err(&pl08x->adev->dev,
1334 "%s direction unsupported\n", __func__);
1335 return NULL;
1336 }
Linus Walleije8689e62010-09-28 15:57:37 +02001337
Viresh Kumar0a235652011-08-05 15:32:42 +05301338 if (plchan->cd->device_fc)
1339 tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
1340 PL080_FLOW_PER2MEM_PER;
1341 else
1342 tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
1343 PL080_FLOW_PER2MEM;
1344
1345 txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1346
Linus Walleije8689e62010-09-28 15:57:37 +02001347 ret = pl08x_prep_channel_resources(plchan, txd);
1348 if (ret)
1349 return NULL;
Linus Walleije8689e62010-09-28 15:57:37 +02001350
1351 return &txd->tx;
1352}
1353
1354static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1355 unsigned long arg)
1356{
1357 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1358 struct pl08x_driver_data *pl08x = plchan->host;
1359 unsigned long flags;
1360 int ret = 0;
1361
1362 /* Controls applicable to inactive channels */
1363 if (cmd == DMA_SLAVE_CONFIG) {
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001364 return dma_set_runtime_config(chan,
1365 (struct dma_slave_config *)arg);
Linus Walleije8689e62010-09-28 15:57:37 +02001366 }
1367
1368 /*
1369 * Anything succeeds on channels with no physical allocation and
1370 * no queued transfers.
1371 */
1372 spin_lock_irqsave(&plchan->lock, flags);
1373 if (!plchan->phychan && !plchan->at) {
1374 spin_unlock_irqrestore(&plchan->lock, flags);
1375 return 0;
1376 }
1377
1378 switch (cmd) {
1379 case DMA_TERMINATE_ALL:
1380 plchan->state = PL08X_CHAN_IDLE;
1381
1382 if (plchan->phychan) {
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +00001383 pl08x_terminate_phy_chan(pl08x, plchan->phychan);
Linus Walleije8689e62010-09-28 15:57:37 +02001384
1385 /*
1386 * Mark physical channel as free and free any slave
1387 * signal
1388 */
Russell King - ARM Linux8c8cc2b2011-01-03 22:36:09 +00001389 release_phy_channel(plchan);
Linus Walleije8689e62010-09-28 15:57:37 +02001390 }
Linus Walleije8689e62010-09-28 15:57:37 +02001391 /* Dequeue jobs and free LLIs */
1392 if (plchan->at) {
1393 pl08x_free_txd(pl08x, plchan->at);
1394 plchan->at = NULL;
1395 }
1396 /* Dequeue jobs not yet fired as well */
1397 pl08x_free_txd_list(pl08x, plchan);
1398 break;
1399 case DMA_PAUSE:
1400 pl08x_pause_phy_chan(plchan->phychan);
1401 plchan->state = PL08X_CHAN_PAUSED;
1402 break;
1403 case DMA_RESUME:
1404 pl08x_resume_phy_chan(plchan->phychan);
1405 plchan->state = PL08X_CHAN_RUNNING;
1406 break;
1407 default:
1408 /* Unknown command */
1409 ret = -ENXIO;
1410 break;
1411 }
1412
1413 spin_unlock_irqrestore(&plchan->lock, flags);
1414
1415 return ret;
1416}
1417
1418bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
1419{
1420 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1421 char *name = chan_id;
1422
1423 /* Check that the channel is not taken! */
1424 if (!strcmp(plchan->name, name))
1425 return true;
1426
1427 return false;
1428}
1429
1430/*
1431 * Just check that the device is there and active
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001432 * TODO: turn this bit on/off depending on the number of physical channels
1433 * actually used, if it is zero... well shut it off. That will save some
1434 * power. Cut the clock at the same time.
Linus Walleije8689e62010-09-28 15:57:37 +02001435 */
1436static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
1437{
Viresh Kumar48a59ef2011-08-05 15:32:34 +05301438 writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
Linus Walleije8689e62010-09-28 15:57:37 +02001439}
1440
Russell King - ARM Linux3d992e12011-01-03 22:44:16 +00001441static void pl08x_unmap_buffers(struct pl08x_txd *txd)
1442{
1443 struct device *dev = txd->tx.chan->device->dev;
1444
1445 if (!(txd->tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
1446 if (txd->tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
1447 dma_unmap_single(dev, txd->src_addr, txd->len,
1448 DMA_TO_DEVICE);
1449 else
1450 dma_unmap_page(dev, txd->src_addr, txd->len,
1451 DMA_TO_DEVICE);
1452 }
1453 if (!(txd->tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
1454 if (txd->tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
1455 dma_unmap_single(dev, txd->dst_addr, txd->len,
1456 DMA_FROM_DEVICE);
1457 else
1458 dma_unmap_page(dev, txd->dst_addr, txd->len,
1459 DMA_FROM_DEVICE);
1460 }
1461}
1462
Linus Walleije8689e62010-09-28 15:57:37 +02001463static void pl08x_tasklet(unsigned long data)
1464{
1465 struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data;
Linus Walleije8689e62010-09-28 15:57:37 +02001466 struct pl08x_driver_data *pl08x = plchan->host;
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001467 struct pl08x_txd *txd;
Russell King - ARM Linuxbf072af2011-01-03 22:31:24 +00001468 unsigned long flags;
Linus Walleije8689e62010-09-28 15:57:37 +02001469
Russell King - ARM Linuxbf072af2011-01-03 22:31:24 +00001470 spin_lock_irqsave(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001471
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001472 txd = plchan->at;
1473 plchan->at = NULL;
1474
1475 if (txd) {
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001476 /* Update last completed */
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001477 plchan->lc = txd->tx.cookie;
Linus Walleije8689e62010-09-28 15:57:37 +02001478 }
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +00001479
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001480 /* If a new descriptor is queued, set it up plchan->at is NULL here */
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001481 if (!list_empty(&plchan->pend_list)) {
Linus Walleije8689e62010-09-28 15:57:37 +02001482 struct pl08x_txd *next;
1483
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001484 next = list_first_entry(&plchan->pend_list,
Linus Walleije8689e62010-09-28 15:57:37 +02001485 struct pl08x_txd,
1486 node);
1487 list_del(&next->node);
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +00001488
1489 pl08x_start_txd(plchan, next);
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +00001490 } else if (plchan->phychan_hold) {
1491 /*
1492 * This channel is still in use - we have a new txd being
1493 * prepared and will soon be queued. Don't give up the
1494 * physical channel.
1495 */
Linus Walleije8689e62010-09-28 15:57:37 +02001496 } else {
1497 struct pl08x_dma_chan *waiting = NULL;
1498
1499 /*
1500 * No more jobs, so free up the physical channel
1501 * Free any allocated signal on slave transfers too
1502 */
Russell King - ARM Linux8c8cc2b2011-01-03 22:36:09 +00001503 release_phy_channel(plchan);
Linus Walleije8689e62010-09-28 15:57:37 +02001504 plchan->state = PL08X_CHAN_IDLE;
1505
1506 /*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001507 * And NOW before anyone else can grab that free:d up
1508 * physical channel, see if there is some memcpy pending
1509 * that seriously needs to start because of being stacked
1510 * up while we were choking the physical channels with data.
Linus Walleije8689e62010-09-28 15:57:37 +02001511 */
1512 list_for_each_entry(waiting, &pl08x->memcpy.channels,
1513 chan.device_node) {
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301514 if (waiting->state == PL08X_CHAN_WAITING &&
1515 waiting->waiting != NULL) {
Linus Walleije8689e62010-09-28 15:57:37 +02001516 int ret;
1517
1518 /* This should REALLY not fail now */
1519 ret = prep_phy_channel(waiting,
1520 waiting->waiting);
1521 BUG_ON(ret);
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +00001522 waiting->phychan_hold--;
Linus Walleije8689e62010-09-28 15:57:37 +02001523 waiting->state = PL08X_CHAN_RUNNING;
1524 waiting->waiting = NULL;
1525 pl08x_issue_pending(&waiting->chan);
1526 break;
1527 }
1528 }
1529 }
1530
Russell King - ARM Linuxbf072af2011-01-03 22:31:24 +00001531 spin_unlock_irqrestore(&plchan->lock, flags);
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001532
Russell King - ARM Linux3d992e12011-01-03 22:44:16 +00001533 if (txd) {
1534 dma_async_tx_callback callback = txd->tx.callback;
1535 void *callback_param = txd->tx.callback_param;
1536
1537 /* Don't try to unmap buffers on slave channels */
1538 if (!plchan->slave)
1539 pl08x_unmap_buffers(txd);
1540
1541 /* Free the descriptor */
1542 spin_lock_irqsave(&plchan->lock, flags);
1543 pl08x_free_txd(pl08x, txd);
1544 spin_unlock_irqrestore(&plchan->lock, flags);
1545
1546 /* Callback to signal completion */
1547 if (callback)
1548 callback(callback_param);
1549 }
Linus Walleije8689e62010-09-28 15:57:37 +02001550}
1551
1552static irqreturn_t pl08x_irq(int irq, void *dev)
1553{
1554 struct pl08x_driver_data *pl08x = dev;
Viresh Kumar28da2832011-08-05 15:32:36 +05301555 u32 mask = 0, err, tc, i;
Linus Walleije8689e62010-09-28 15:57:37 +02001556
Viresh Kumar28da2832011-08-05 15:32:36 +05301557 /* check & clear - ERR & TC interrupts */
1558 err = readl(pl08x->base + PL080_ERR_STATUS);
1559 if (err) {
1560 dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
1561 __func__, err);
1562 writel(err, pl08x->base + PL080_ERR_CLEAR);
Linus Walleije8689e62010-09-28 15:57:37 +02001563 }
Viresh Kumar28da2832011-08-05 15:32:36 +05301564 tc = readl(pl08x->base + PL080_INT_STATUS);
1565 if (tc)
1566 writel(tc, pl08x->base + PL080_TC_CLEAR);
1567
1568 if (!err && !tc)
1569 return IRQ_NONE;
1570
Linus Walleije8689e62010-09-28 15:57:37 +02001571 for (i = 0; i < pl08x->vd->channels; i++) {
Viresh Kumar28da2832011-08-05 15:32:36 +05301572 if (((1 << i) & err) || ((1 << i) & tc)) {
Linus Walleije8689e62010-09-28 15:57:37 +02001573 /* Locate physical channel */
1574 struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
1575 struct pl08x_dma_chan *plchan = phychan->serving;
1576
Viresh Kumar28da2832011-08-05 15:32:36 +05301577 if (!plchan) {
1578 dev_err(&pl08x->adev->dev,
1579 "%s Error TC interrupt on unused channel: 0x%08x\n",
1580 __func__, i);
1581 continue;
1582 }
1583
Linus Walleije8689e62010-09-28 15:57:37 +02001584 /* Schedule tasklet on this channel */
1585 tasklet_schedule(&plchan->tasklet);
Linus Walleije8689e62010-09-28 15:57:37 +02001586 mask |= (1 << i);
1587 }
1588 }
Linus Walleije8689e62010-09-28 15:57:37 +02001589
1590 return mask ? IRQ_HANDLED : IRQ_NONE;
1591}
1592
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001593static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
1594{
1595 u32 cctl = pl08x_cctl(chan->cd->cctl);
1596
1597 chan->slave = true;
1598 chan->name = chan->cd->bus_id;
1599 chan->src_addr = chan->cd->addr;
1600 chan->dst_addr = chan->cd->addr;
1601 chan->src_cctl = cctl | PL080_CONTROL_DST_INCR |
1602 pl08x_select_bus(chan->cd->periph_buses, chan->host->mem_buses);
1603 chan->dst_cctl = cctl | PL080_CONTROL_SRC_INCR |
1604 pl08x_select_bus(chan->host->mem_buses, chan->cd->periph_buses);
1605}
1606
Linus Walleije8689e62010-09-28 15:57:37 +02001607/*
1608 * Initialise the DMAC memcpy/slave channels.
1609 * Make a local wrapper to hold required data
1610 */
1611static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301612 struct dma_device *dmadev, unsigned int channels, bool slave)
Linus Walleije8689e62010-09-28 15:57:37 +02001613{
1614 struct pl08x_dma_chan *chan;
1615 int i;
1616
1617 INIT_LIST_HEAD(&dmadev->channels);
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001618
Linus Walleije8689e62010-09-28 15:57:37 +02001619 /*
1620 * Register as many many memcpy as we have physical channels,
1621 * we won't always be able to use all but the code will have
1622 * to cope with that situation.
1623 */
1624 for (i = 0; i < channels; i++) {
Viresh Kumarb201c112011-08-05 15:32:29 +05301625 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
Linus Walleije8689e62010-09-28 15:57:37 +02001626 if (!chan) {
1627 dev_err(&pl08x->adev->dev,
1628 "%s no memory for channel\n", __func__);
1629 return -ENOMEM;
1630 }
1631
1632 chan->host = pl08x;
1633 chan->state = PL08X_CHAN_IDLE;
1634
1635 if (slave) {
Linus Walleije8689e62010-09-28 15:57:37 +02001636 chan->cd = &pl08x->pd->slave_channels[i];
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001637 pl08x_dma_slave_init(chan);
Linus Walleije8689e62010-09-28 15:57:37 +02001638 } else {
1639 chan->cd = &pl08x->pd->memcpy_channel;
1640 chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i);
1641 if (!chan->name) {
1642 kfree(chan);
1643 return -ENOMEM;
1644 }
1645 }
Russell King - ARM Linuxb58b6b52011-01-03 22:34:48 +00001646 if (chan->cd->circular_buffer) {
1647 dev_err(&pl08x->adev->dev,
1648 "channel %s: circular buffers not supported\n",
1649 chan->name);
1650 kfree(chan);
1651 continue;
1652 }
Viresh Kumar175a5e62011-08-05 15:32:32 +05301653 dev_dbg(&pl08x->adev->dev,
Linus Walleije8689e62010-09-28 15:57:37 +02001654 "initialize virtual channel \"%s\"\n",
1655 chan->name);
1656
1657 chan->chan.device = dmadev;
Russell King - ARM Linux91aa5fa2011-01-03 22:31:04 +00001658 chan->chan.cookie = 0;
1659 chan->lc = 0;
Linus Walleije8689e62010-09-28 15:57:37 +02001660
1661 spin_lock_init(&chan->lock);
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001662 INIT_LIST_HEAD(&chan->pend_list);
Linus Walleije8689e62010-09-28 15:57:37 +02001663 tasklet_init(&chan->tasklet, pl08x_tasklet,
1664 (unsigned long) chan);
1665
1666 list_add_tail(&chan->chan.device_node, &dmadev->channels);
1667 }
1668 dev_info(&pl08x->adev->dev, "initialized %d virtual %s channels\n",
1669 i, slave ? "slave" : "memcpy");
1670 return i;
1671}
1672
1673static void pl08x_free_virtual_channels(struct dma_device *dmadev)
1674{
1675 struct pl08x_dma_chan *chan = NULL;
1676 struct pl08x_dma_chan *next;
1677
1678 list_for_each_entry_safe(chan,
1679 next, &dmadev->channels, chan.device_node) {
1680 list_del(&chan->chan.device_node);
1681 kfree(chan);
1682 }
1683}
1684
1685#ifdef CONFIG_DEBUG_FS
1686static const char *pl08x_state_str(enum pl08x_dma_chan_state state)
1687{
1688 switch (state) {
1689 case PL08X_CHAN_IDLE:
1690 return "idle";
1691 case PL08X_CHAN_RUNNING:
1692 return "running";
1693 case PL08X_CHAN_PAUSED:
1694 return "paused";
1695 case PL08X_CHAN_WAITING:
1696 return "waiting";
1697 default:
1698 break;
1699 }
1700 return "UNKNOWN STATE";
1701}
1702
1703static int pl08x_debugfs_show(struct seq_file *s, void *data)
1704{
1705 struct pl08x_driver_data *pl08x = s->private;
1706 struct pl08x_dma_chan *chan;
1707 struct pl08x_phy_chan *ch;
1708 unsigned long flags;
1709 int i;
1710
1711 seq_printf(s, "PL08x physical channels:\n");
1712 seq_printf(s, "CHANNEL:\tUSER:\n");
1713 seq_printf(s, "--------\t-----\n");
1714 for (i = 0; i < pl08x->vd->channels; i++) {
1715 struct pl08x_dma_chan *virt_chan;
1716
1717 ch = &pl08x->phy_chans[i];
1718
1719 spin_lock_irqsave(&ch->lock, flags);
1720 virt_chan = ch->serving;
1721
1722 seq_printf(s, "%d\t\t%s\n",
1723 ch->id, virt_chan ? virt_chan->name : "(none)");
1724
1725 spin_unlock_irqrestore(&ch->lock, flags);
1726 }
1727
1728 seq_printf(s, "\nPL08x virtual memcpy channels:\n");
1729 seq_printf(s, "CHANNEL:\tSTATE:\n");
1730 seq_printf(s, "--------\t------\n");
1731 list_for_each_entry(chan, &pl08x->memcpy.channels, chan.device_node) {
Russell King - ARM Linux3e2a0372011-01-03 22:32:46 +00001732 seq_printf(s, "%s\t\t%s\n", chan->name,
Linus Walleije8689e62010-09-28 15:57:37 +02001733 pl08x_state_str(chan->state));
1734 }
1735
1736 seq_printf(s, "\nPL08x virtual slave channels:\n");
1737 seq_printf(s, "CHANNEL:\tSTATE:\n");
1738 seq_printf(s, "--------\t------\n");
1739 list_for_each_entry(chan, &pl08x->slave.channels, chan.device_node) {
Russell King - ARM Linux3e2a0372011-01-03 22:32:46 +00001740 seq_printf(s, "%s\t\t%s\n", chan->name,
Linus Walleije8689e62010-09-28 15:57:37 +02001741 pl08x_state_str(chan->state));
1742 }
1743
1744 return 0;
1745}
1746
1747static int pl08x_debugfs_open(struct inode *inode, struct file *file)
1748{
1749 return single_open(file, pl08x_debugfs_show, inode->i_private);
1750}
1751
1752static const struct file_operations pl08x_debugfs_operations = {
1753 .open = pl08x_debugfs_open,
1754 .read = seq_read,
1755 .llseek = seq_lseek,
1756 .release = single_release,
1757};
1758
1759static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
1760{
1761 /* Expose a simple debugfs interface to view all clocks */
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301762 (void) debugfs_create_file(dev_name(&pl08x->adev->dev),
1763 S_IFREG | S_IRUGO, NULL, pl08x,
1764 &pl08x_debugfs_operations);
Linus Walleije8689e62010-09-28 15:57:37 +02001765}
1766
1767#else
1768static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
1769{
1770}
1771#endif
1772
Russell Kingaa25afa2011-02-19 15:55:00 +00001773static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
Linus Walleije8689e62010-09-28 15:57:37 +02001774{
1775 struct pl08x_driver_data *pl08x;
Russell King - ARM Linuxf96ca9ec2011-01-03 22:35:08 +00001776 const struct vendor_data *vd = id->data;
Linus Walleije8689e62010-09-28 15:57:37 +02001777 int ret = 0;
1778 int i;
1779
1780 ret = amba_request_regions(adev, NULL);
1781 if (ret)
1782 return ret;
1783
1784 /* Create the driver state holder */
Viresh Kumarb201c112011-08-05 15:32:29 +05301785 pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
Linus Walleije8689e62010-09-28 15:57:37 +02001786 if (!pl08x) {
1787 ret = -ENOMEM;
1788 goto out_no_pl08x;
1789 }
1790
Viresh Kumarb7b60182011-08-05 15:32:33 +05301791 pm_runtime_set_active(&adev->dev);
1792 pm_runtime_enable(&adev->dev);
1793
Linus Walleije8689e62010-09-28 15:57:37 +02001794 /* Initialize memcpy engine */
1795 dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
1796 pl08x->memcpy.dev = &adev->dev;
1797 pl08x->memcpy.device_alloc_chan_resources = pl08x_alloc_chan_resources;
1798 pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources;
1799 pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy;
1800 pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
1801 pl08x->memcpy.device_tx_status = pl08x_dma_tx_status;
1802 pl08x->memcpy.device_issue_pending = pl08x_issue_pending;
1803 pl08x->memcpy.device_control = pl08x_control;
1804
1805 /* Initialize slave engine */
1806 dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
1807 pl08x->slave.dev = &adev->dev;
1808 pl08x->slave.device_alloc_chan_resources = pl08x_alloc_chan_resources;
1809 pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
1810 pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
1811 pl08x->slave.device_tx_status = pl08x_dma_tx_status;
1812 pl08x->slave.device_issue_pending = pl08x_issue_pending;
1813 pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
1814 pl08x->slave.device_control = pl08x_control;
1815
1816 /* Get the platform data */
1817 pl08x->pd = dev_get_platdata(&adev->dev);
1818 if (!pl08x->pd) {
1819 dev_err(&adev->dev, "no platform data supplied\n");
1820 goto out_no_platdata;
1821 }
1822
1823 /* Assign useful pointers to the driver state */
1824 pl08x->adev = adev;
1825 pl08x->vd = vd;
1826
Russell King - ARM Linux30749cb2011-01-03 22:41:13 +00001827 /* By default, AHB1 only. If dualmaster, from platform */
1828 pl08x->lli_buses = PL08X_AHB1;
1829 pl08x->mem_buses = PL08X_AHB1;
1830 if (pl08x->vd->dualmaster) {
1831 pl08x->lli_buses = pl08x->pd->lli_buses;
1832 pl08x->mem_buses = pl08x->pd->mem_buses;
1833 }
1834
Linus Walleije8689e62010-09-28 15:57:37 +02001835 /* A DMA memory pool for LLIs, align on 1-byte boundary */
1836 pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev,
1837 PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0);
1838 if (!pl08x->pool) {
1839 ret = -ENOMEM;
1840 goto out_no_lli_pool;
1841 }
1842
1843 spin_lock_init(&pl08x->lock);
1844
1845 pl08x->base = ioremap(adev->res.start, resource_size(&adev->res));
1846 if (!pl08x->base) {
1847 ret = -ENOMEM;
1848 goto out_no_ioremap;
1849 }
1850
1851 /* Turn on the PL08x */
1852 pl08x_ensure_on(pl08x);
1853
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001854 /* Attach the interrupt handler */
Linus Walleije8689e62010-09-28 15:57:37 +02001855 writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
1856 writel(0x000000FF, pl08x->base + PL080_TC_CLEAR);
1857
1858 ret = request_irq(adev->irq[0], pl08x_irq, IRQF_DISABLED,
Russell King - ARM Linuxb05cd8f2011-01-03 22:33:26 +00001859 DRIVER_NAME, pl08x);
Linus Walleije8689e62010-09-28 15:57:37 +02001860 if (ret) {
1861 dev_err(&adev->dev, "%s failed to request interrupt %d\n",
1862 __func__, adev->irq[0]);
1863 goto out_no_irq;
1864 }
1865
1866 /* Initialize physical channels */
Viresh Kumarb201c112011-08-05 15:32:29 +05301867 pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
Linus Walleije8689e62010-09-28 15:57:37 +02001868 GFP_KERNEL);
1869 if (!pl08x->phy_chans) {
1870 dev_err(&adev->dev, "%s failed to allocate "
1871 "physical channel holders\n",
1872 __func__);
1873 goto out_no_phychans;
1874 }
1875
1876 for (i = 0; i < vd->channels; i++) {
1877 struct pl08x_phy_chan *ch = &pl08x->phy_chans[i];
1878
1879 ch->id = i;
1880 ch->base = pl08x->base + PL080_Cx_BASE(i);
1881 spin_lock_init(&ch->lock);
1882 ch->serving = NULL;
1883 ch->signal = -1;
Viresh Kumar175a5e62011-08-05 15:32:32 +05301884 dev_dbg(&adev->dev, "physical channel %d is %s\n",
1885 i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
Linus Walleije8689e62010-09-28 15:57:37 +02001886 }
1887
1888 /* Register as many memcpy channels as there are physical channels */
1889 ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->memcpy,
1890 pl08x->vd->channels, false);
1891 if (ret <= 0) {
1892 dev_warn(&pl08x->adev->dev,
1893 "%s failed to enumerate memcpy channels - %d\n",
1894 __func__, ret);
1895 goto out_no_memcpy;
1896 }
1897 pl08x->memcpy.chancnt = ret;
1898
1899 /* Register slave channels */
1900 ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301901 pl08x->pd->num_slave_channels, true);
Linus Walleije8689e62010-09-28 15:57:37 +02001902 if (ret <= 0) {
1903 dev_warn(&pl08x->adev->dev,
1904 "%s failed to enumerate slave channels - %d\n",
1905 __func__, ret);
1906 goto out_no_slave;
1907 }
1908 pl08x->slave.chancnt = ret;
1909
1910 ret = dma_async_device_register(&pl08x->memcpy);
1911 if (ret) {
1912 dev_warn(&pl08x->adev->dev,
1913 "%s failed to register memcpy as an async device - %d\n",
1914 __func__, ret);
1915 goto out_no_memcpy_reg;
1916 }
1917
1918 ret = dma_async_device_register(&pl08x->slave);
1919 if (ret) {
1920 dev_warn(&pl08x->adev->dev,
1921 "%s failed to register slave as an async device - %d\n",
1922 __func__, ret);
1923 goto out_no_slave_reg;
1924 }
1925
1926 amba_set_drvdata(adev, pl08x);
1927 init_pl08x_debugfs(pl08x);
Russell King - ARM Linuxb05cd8f2011-01-03 22:33:26 +00001928 dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
1929 amba_part(adev), amba_rev(adev),
1930 (unsigned long long)adev->res.start, adev->irq[0]);
Viresh Kumarb7b60182011-08-05 15:32:33 +05301931
1932 pm_runtime_put(&adev->dev);
Linus Walleije8689e62010-09-28 15:57:37 +02001933 return 0;
1934
1935out_no_slave_reg:
1936 dma_async_device_unregister(&pl08x->memcpy);
1937out_no_memcpy_reg:
1938 pl08x_free_virtual_channels(&pl08x->slave);
1939out_no_slave:
1940 pl08x_free_virtual_channels(&pl08x->memcpy);
1941out_no_memcpy:
1942 kfree(pl08x->phy_chans);
1943out_no_phychans:
1944 free_irq(adev->irq[0], pl08x);
1945out_no_irq:
1946 iounmap(pl08x->base);
1947out_no_ioremap:
1948 dma_pool_destroy(pl08x->pool);
1949out_no_lli_pool:
1950out_no_platdata:
Viresh Kumarb7b60182011-08-05 15:32:33 +05301951 pm_runtime_put(&adev->dev);
1952 pm_runtime_disable(&adev->dev);
1953
Linus Walleije8689e62010-09-28 15:57:37 +02001954 kfree(pl08x);
1955out_no_pl08x:
1956 amba_release_regions(adev);
1957 return ret;
1958}
1959
1960/* PL080 has 8 channels and the PL080 have just 2 */
1961static struct vendor_data vendor_pl080 = {
Linus Walleije8689e62010-09-28 15:57:37 +02001962 .channels = 8,
1963 .dualmaster = true,
1964};
1965
1966static struct vendor_data vendor_pl081 = {
Linus Walleije8689e62010-09-28 15:57:37 +02001967 .channels = 2,
1968 .dualmaster = false,
1969};
1970
1971static struct amba_id pl08x_ids[] = {
1972 /* PL080 */
1973 {
1974 .id = 0x00041080,
1975 .mask = 0x000fffff,
1976 .data = &vendor_pl080,
1977 },
1978 /* PL081 */
1979 {
1980 .id = 0x00041081,
1981 .mask = 0x000fffff,
1982 .data = &vendor_pl081,
1983 },
1984 /* Nomadik 8815 PL080 variant */
1985 {
1986 .id = 0x00280880,
1987 .mask = 0x00ffffff,
1988 .data = &vendor_pl080,
1989 },
1990 { 0, 0 },
1991};
1992
1993static struct amba_driver pl08x_amba_driver = {
1994 .drv.name = DRIVER_NAME,
1995 .id_table = pl08x_ids,
1996 .probe = pl08x_probe,
1997};
1998
1999static int __init pl08x_init(void)
2000{
2001 int retval;
2002 retval = amba_driver_register(&pl08x_amba_driver);
2003 if (retval)
2004 printk(KERN_WARNING DRIVER_NAME
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +00002005 "failed to register as an AMBA device (%d)\n",
Linus Walleije8689e62010-09-28 15:57:37 +02002006 retval);
2007 return retval;
2008}
2009subsys_initcall(pl08x_init);