blob: 849eab85514bcf8fd25dbd3786f871f4755cbfa4 [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) {
Viresh Kumar57001a62011-08-05 15:32:45 +05301177 spin_lock_irqsave(&plchan->lock, flags);
1178 pl08x_free_txd(pl08x, txd);
1179 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001180 return -EINVAL;
Russell King - ARM Linuxdafa7312011-01-03 22:31:45 +00001181 }
Linus Walleije8689e62010-09-28 15:57:37 +02001182
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001183 spin_lock_irqsave(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001184
Linus Walleije8689e62010-09-28 15:57:37 +02001185 /*
1186 * See if we already have a physical channel allocated,
1187 * else this is the time to try to get one.
1188 */
1189 ret = prep_phy_channel(plchan, txd);
1190 if (ret) {
1191 /*
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +00001192 * No physical channel was available.
1193 *
1194 * memcpy transfers can be sorted out at submission time.
1195 *
1196 * Slave transfers may have been denied due to platform
1197 * channel muxing restrictions. Since there is no guarantee
1198 * that this will ever be resolved, and the signal must be
1199 * acquired AFTER acquiring the physical channel, we will let
1200 * them be NACK:ed with -EBUSY here. The drivers can retry
1201 * the prep() call if they are eager on doing this using DMA.
Linus Walleije8689e62010-09-28 15:57:37 +02001202 */
1203 if (plchan->slave) {
1204 pl08x_free_txd_list(pl08x, plchan);
Russell King - ARM Linux501e67e2011-01-03 22:44:57 +00001205 pl08x_free_txd(pl08x, txd);
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001206 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001207 return -EBUSY;
1208 }
Linus Walleije8689e62010-09-28 15:57:37 +02001209 } else
1210 /*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001211 * Else we're all set, paused and ready to roll, status
1212 * will switch to PL08X_CHAN_RUNNING when we call
1213 * issue_pending(). If there is something running on the
1214 * channel already we don't change its state.
Linus Walleije8689e62010-09-28 15:57:37 +02001215 */
1216 if (plchan->state == PL08X_CHAN_IDLE)
1217 plchan->state = PL08X_CHAN_PAUSED;
1218
Russell King - ARM Linuxc370e592011-01-03 22:45:37 +00001219 spin_unlock_irqrestore(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001220
1221 return 0;
1222}
1223
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001224static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
1225 unsigned long flags)
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001226{
Viresh Kumarb201c112011-08-05 15:32:29 +05301227 struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001228
1229 if (txd) {
1230 dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001231 txd->tx.flags = flags;
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001232 txd->tx.tx_submit = pl08x_tx_submit;
1233 INIT_LIST_HEAD(&txd->node);
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001234
1235 /* Always enable error and terminal interrupts */
1236 txd->ccfg = PL080_CONFIG_ERR_IRQ_MASK |
1237 PL080_CONFIG_TC_IRQ_MASK;
Russell King - ARM Linuxac3cd202011-01-03 22:35:49 +00001238 }
1239 return txd;
1240}
1241
Linus Walleije8689e62010-09-28 15:57:37 +02001242/*
1243 * Initialize a descriptor to be used by memcpy submit
1244 */
1245static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
1246 struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
1247 size_t len, unsigned long flags)
1248{
1249 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1250 struct pl08x_driver_data *pl08x = plchan->host;
1251 struct pl08x_txd *txd;
1252 int ret;
1253
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001254 txd = pl08x_get_txd(plchan, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001255 if (!txd) {
1256 dev_err(&pl08x->adev->dev,
1257 "%s no memory for descriptor\n", __func__);
1258 return NULL;
1259 }
1260
Linus Walleije8689e62010-09-28 15:57:37 +02001261 txd->direction = DMA_NONE;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +00001262 txd->src_addr = src;
1263 txd->dst_addr = dest;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001264 txd->len = len;
Linus Walleije8689e62010-09-28 15:57:37 +02001265
1266 /* Set platform data for m2m */
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001267 txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001268 txd->cctl = pl08x->pd->memcpy_channel.cctl &
1269 ~(PL080_CONTROL_DST_AHB2 | PL080_CONTROL_SRC_AHB2);
Russell King - ARM Linux4983a042011-01-03 22:39:33 +00001270
Linus Walleije8689e62010-09-28 15:57:37 +02001271 /* Both to be incremented or the code will break */
Russell King - ARM Linux70b5ed62011-01-03 22:40:13 +00001272 txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001273
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001274 if (pl08x->vd->dualmaster)
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001275 txd->cctl |= pl08x_select_bus(pl08x->mem_buses,
1276 pl08x->mem_buses);
Linus Walleije8689e62010-09-28 15:57:37 +02001277
Linus Walleije8689e62010-09-28 15:57:37 +02001278 ret = pl08x_prep_channel_resources(plchan, txd);
1279 if (ret)
1280 return NULL;
Linus Walleije8689e62010-09-28 15:57:37 +02001281
1282 return &txd->tx;
1283}
1284
Russell King - ARM Linux3e2a0372011-01-03 22:32:46 +00001285static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
Linus Walleije8689e62010-09-28 15:57:37 +02001286 struct dma_chan *chan, struct scatterlist *sgl,
1287 unsigned int sg_len, enum dma_data_direction direction,
1288 unsigned long flags)
1289{
1290 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1291 struct pl08x_driver_data *pl08x = plchan->host;
1292 struct pl08x_txd *txd;
Viresh Kumar0a235652011-08-05 15:32:42 +05301293 int ret, tmp;
Linus Walleije8689e62010-09-28 15:57:37 +02001294
1295 /*
1296 * Current implementation ASSUMES only one sg
1297 */
1298 if (sg_len != 1) {
1299 dev_err(&pl08x->adev->dev, "%s prepared too long sglist\n",
1300 __func__);
1301 BUG();
1302 }
1303
1304 dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
1305 __func__, sgl->length, plchan->name);
1306
Russell King - ARM Linuxc0428792011-01-03 22:43:56 +00001307 txd = pl08x_get_txd(plchan, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001308 if (!txd) {
1309 dev_err(&pl08x->adev->dev, "%s no txd\n", __func__);
1310 return NULL;
1311 }
1312
Linus Walleije8689e62010-09-28 15:57:37 +02001313 if (direction != plchan->runtime_direction)
1314 dev_err(&pl08x->adev->dev, "%s DMA setup does not match "
1315 "the direction configured for the PrimeCell\n",
1316 __func__);
1317
1318 /*
1319 * Set up addresses, the PrimeCell configured address
1320 * will take precedence since this may configure the
1321 * channel target address dynamically at runtime.
1322 */
1323 txd->direction = direction;
Russell King - ARM Linuxc7da9a52011-01-03 22:40:53 +00001324 txd->len = sgl->length;
1325
Linus Walleije8689e62010-09-28 15:57:37 +02001326 if (direction == DMA_TO_DEVICE) {
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001327 txd->cctl = plchan->dst_cctl;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +00001328 txd->src_addr = sgl->dma_address;
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001329 txd->dst_addr = plchan->dst_addr;
Linus Walleije8689e62010-09-28 15:57:37 +02001330 } else if (direction == DMA_FROM_DEVICE) {
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001331 txd->cctl = plchan->src_cctl;
Russell King - ARM Linuxb207b4d2011-07-21 17:12:27 +01001332 txd->src_addr = plchan->src_addr;
Russell King - ARM Linuxd7244e92011-01-03 22:43:35 +00001333 txd->dst_addr = sgl->dma_address;
Linus Walleije8689e62010-09-28 15:57:37 +02001334 } else {
1335 dev_err(&pl08x->adev->dev,
1336 "%s direction unsupported\n", __func__);
1337 return NULL;
1338 }
Linus Walleije8689e62010-09-28 15:57:37 +02001339
Viresh Kumar0a235652011-08-05 15:32:42 +05301340 if (plchan->cd->device_fc)
1341 tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
1342 PL080_FLOW_PER2MEM_PER;
1343 else
1344 tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
1345 PL080_FLOW_PER2MEM;
1346
1347 txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1348
Linus Walleije8689e62010-09-28 15:57:37 +02001349 ret = pl08x_prep_channel_resources(plchan, txd);
1350 if (ret)
1351 return NULL;
Linus Walleije8689e62010-09-28 15:57:37 +02001352
1353 return &txd->tx;
1354}
1355
1356static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1357 unsigned long arg)
1358{
1359 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1360 struct pl08x_driver_data *pl08x = plchan->host;
1361 unsigned long flags;
1362 int ret = 0;
1363
1364 /* Controls applicable to inactive channels */
1365 if (cmd == DMA_SLAVE_CONFIG) {
Russell King - ARM Linuxf0fd9442011-01-03 22:45:57 +00001366 return dma_set_runtime_config(chan,
1367 (struct dma_slave_config *)arg);
Linus Walleije8689e62010-09-28 15:57:37 +02001368 }
1369
1370 /*
1371 * Anything succeeds on channels with no physical allocation and
1372 * no queued transfers.
1373 */
1374 spin_lock_irqsave(&plchan->lock, flags);
1375 if (!plchan->phychan && !plchan->at) {
1376 spin_unlock_irqrestore(&plchan->lock, flags);
1377 return 0;
1378 }
1379
1380 switch (cmd) {
1381 case DMA_TERMINATE_ALL:
1382 plchan->state = PL08X_CHAN_IDLE;
1383
1384 if (plchan->phychan) {
Russell King - ARM Linuxfb526212011-01-27 12:32:53 +00001385 pl08x_terminate_phy_chan(pl08x, plchan->phychan);
Linus Walleije8689e62010-09-28 15:57:37 +02001386
1387 /*
1388 * Mark physical channel as free and free any slave
1389 * signal
1390 */
Russell King - ARM Linux8c8cc2b2011-01-03 22:36:09 +00001391 release_phy_channel(plchan);
Linus Walleije8689e62010-09-28 15:57:37 +02001392 }
Linus Walleije8689e62010-09-28 15:57:37 +02001393 /* Dequeue jobs and free LLIs */
1394 if (plchan->at) {
1395 pl08x_free_txd(pl08x, plchan->at);
1396 plchan->at = NULL;
1397 }
1398 /* Dequeue jobs not yet fired as well */
1399 pl08x_free_txd_list(pl08x, plchan);
1400 break;
1401 case DMA_PAUSE:
1402 pl08x_pause_phy_chan(plchan->phychan);
1403 plchan->state = PL08X_CHAN_PAUSED;
1404 break;
1405 case DMA_RESUME:
1406 pl08x_resume_phy_chan(plchan->phychan);
1407 plchan->state = PL08X_CHAN_RUNNING;
1408 break;
1409 default:
1410 /* Unknown command */
1411 ret = -ENXIO;
1412 break;
1413 }
1414
1415 spin_unlock_irqrestore(&plchan->lock, flags);
1416
1417 return ret;
1418}
1419
1420bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
1421{
1422 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1423 char *name = chan_id;
1424
1425 /* Check that the channel is not taken! */
1426 if (!strcmp(plchan->name, name))
1427 return true;
1428
1429 return false;
1430}
1431
1432/*
1433 * Just check that the device is there and active
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001434 * TODO: turn this bit on/off depending on the number of physical channels
1435 * actually used, if it is zero... well shut it off. That will save some
1436 * power. Cut the clock at the same time.
Linus Walleije8689e62010-09-28 15:57:37 +02001437 */
1438static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
1439{
Viresh Kumar48a59ef2011-08-05 15:32:34 +05301440 writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
Linus Walleije8689e62010-09-28 15:57:37 +02001441}
1442
Russell King - ARM Linux3d992e12011-01-03 22:44:16 +00001443static void pl08x_unmap_buffers(struct pl08x_txd *txd)
1444{
1445 struct device *dev = txd->tx.chan->device->dev;
1446
1447 if (!(txd->tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
1448 if (txd->tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
1449 dma_unmap_single(dev, txd->src_addr, txd->len,
1450 DMA_TO_DEVICE);
1451 else
1452 dma_unmap_page(dev, txd->src_addr, txd->len,
1453 DMA_TO_DEVICE);
1454 }
1455 if (!(txd->tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
1456 if (txd->tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
1457 dma_unmap_single(dev, txd->dst_addr, txd->len,
1458 DMA_FROM_DEVICE);
1459 else
1460 dma_unmap_page(dev, txd->dst_addr, txd->len,
1461 DMA_FROM_DEVICE);
1462 }
1463}
1464
Linus Walleije8689e62010-09-28 15:57:37 +02001465static void pl08x_tasklet(unsigned long data)
1466{
1467 struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data;
Linus Walleije8689e62010-09-28 15:57:37 +02001468 struct pl08x_driver_data *pl08x = plchan->host;
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001469 struct pl08x_txd *txd;
Russell King - ARM Linuxbf072af2011-01-03 22:31:24 +00001470 unsigned long flags;
Linus Walleije8689e62010-09-28 15:57:37 +02001471
Russell King - ARM Linuxbf072af2011-01-03 22:31:24 +00001472 spin_lock_irqsave(&plchan->lock, flags);
Linus Walleije8689e62010-09-28 15:57:37 +02001473
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001474 txd = plchan->at;
1475 plchan->at = NULL;
1476
1477 if (txd) {
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001478 /* Update last completed */
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001479 plchan->lc = txd->tx.cookie;
Linus Walleije8689e62010-09-28 15:57:37 +02001480 }
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +00001481
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001482 /* If a new descriptor is queued, set it up plchan->at is NULL here */
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001483 if (!list_empty(&plchan->pend_list)) {
Linus Walleije8689e62010-09-28 15:57:37 +02001484 struct pl08x_txd *next;
1485
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001486 next = list_first_entry(&plchan->pend_list,
Linus Walleije8689e62010-09-28 15:57:37 +02001487 struct pl08x_txd,
1488 node);
1489 list_del(&next->node);
Russell King - ARM Linuxc885bee2011-01-03 22:38:52 +00001490
1491 pl08x_start_txd(plchan, next);
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +00001492 } else if (plchan->phychan_hold) {
1493 /*
1494 * This channel is still in use - we have a new txd being
1495 * prepared and will soon be queued. Don't give up the
1496 * physical channel.
1497 */
Linus Walleije8689e62010-09-28 15:57:37 +02001498 } else {
1499 struct pl08x_dma_chan *waiting = NULL;
1500
1501 /*
1502 * No more jobs, so free up the physical channel
1503 * Free any allocated signal on slave transfers too
1504 */
Russell King - ARM Linux8c8cc2b2011-01-03 22:36:09 +00001505 release_phy_channel(plchan);
Linus Walleije8689e62010-09-28 15:57:37 +02001506 plchan->state = PL08X_CHAN_IDLE;
1507
1508 /*
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001509 * And NOW before anyone else can grab that free:d up
1510 * physical channel, see if there is some memcpy pending
1511 * that seriously needs to start because of being stacked
1512 * up while we were choking the physical channels with data.
Linus Walleije8689e62010-09-28 15:57:37 +02001513 */
1514 list_for_each_entry(waiting, &pl08x->memcpy.channels,
1515 chan.device_node) {
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301516 if (waiting->state == PL08X_CHAN_WAITING &&
1517 waiting->waiting != NULL) {
Linus Walleije8689e62010-09-28 15:57:37 +02001518 int ret;
1519
1520 /* This should REALLY not fail now */
1521 ret = prep_phy_channel(waiting,
1522 waiting->waiting);
1523 BUG_ON(ret);
Russell King - ARM Linux8087aac2011-01-03 22:45:17 +00001524 waiting->phychan_hold--;
Linus Walleije8689e62010-09-28 15:57:37 +02001525 waiting->state = PL08X_CHAN_RUNNING;
1526 waiting->waiting = NULL;
1527 pl08x_issue_pending(&waiting->chan);
1528 break;
1529 }
1530 }
1531 }
1532
Russell King - ARM Linuxbf072af2011-01-03 22:31:24 +00001533 spin_unlock_irqrestore(&plchan->lock, flags);
Russell King - ARM Linux858c21c2011-01-03 22:41:34 +00001534
Russell King - ARM Linux3d992e12011-01-03 22:44:16 +00001535 if (txd) {
1536 dma_async_tx_callback callback = txd->tx.callback;
1537 void *callback_param = txd->tx.callback_param;
1538
1539 /* Don't try to unmap buffers on slave channels */
1540 if (!plchan->slave)
1541 pl08x_unmap_buffers(txd);
1542
1543 /* Free the descriptor */
1544 spin_lock_irqsave(&plchan->lock, flags);
1545 pl08x_free_txd(pl08x, txd);
1546 spin_unlock_irqrestore(&plchan->lock, flags);
1547
1548 /* Callback to signal completion */
1549 if (callback)
1550 callback(callback_param);
1551 }
Linus Walleije8689e62010-09-28 15:57:37 +02001552}
1553
1554static irqreturn_t pl08x_irq(int irq, void *dev)
1555{
1556 struct pl08x_driver_data *pl08x = dev;
Viresh Kumar28da2832011-08-05 15:32:36 +05301557 u32 mask = 0, err, tc, i;
Linus Walleije8689e62010-09-28 15:57:37 +02001558
Viresh Kumar28da2832011-08-05 15:32:36 +05301559 /* check & clear - ERR & TC interrupts */
1560 err = readl(pl08x->base + PL080_ERR_STATUS);
1561 if (err) {
1562 dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
1563 __func__, err);
1564 writel(err, pl08x->base + PL080_ERR_CLEAR);
Linus Walleije8689e62010-09-28 15:57:37 +02001565 }
Viresh Kumar28da2832011-08-05 15:32:36 +05301566 tc = readl(pl08x->base + PL080_INT_STATUS);
1567 if (tc)
1568 writel(tc, pl08x->base + PL080_TC_CLEAR);
1569
1570 if (!err && !tc)
1571 return IRQ_NONE;
1572
Linus Walleije8689e62010-09-28 15:57:37 +02001573 for (i = 0; i < pl08x->vd->channels; i++) {
Viresh Kumar28da2832011-08-05 15:32:36 +05301574 if (((1 << i) & err) || ((1 << i) & tc)) {
Linus Walleije8689e62010-09-28 15:57:37 +02001575 /* Locate physical channel */
1576 struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
1577 struct pl08x_dma_chan *plchan = phychan->serving;
1578
Viresh Kumar28da2832011-08-05 15:32:36 +05301579 if (!plchan) {
1580 dev_err(&pl08x->adev->dev,
1581 "%s Error TC interrupt on unused channel: 0x%08x\n",
1582 __func__, i);
1583 continue;
1584 }
1585
Linus Walleije8689e62010-09-28 15:57:37 +02001586 /* Schedule tasklet on this channel */
1587 tasklet_schedule(&plchan->tasklet);
Linus Walleije8689e62010-09-28 15:57:37 +02001588 mask |= (1 << i);
1589 }
1590 }
Linus Walleije8689e62010-09-28 15:57:37 +02001591
1592 return mask ? IRQ_HANDLED : IRQ_NONE;
1593}
1594
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001595static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
1596{
1597 u32 cctl = pl08x_cctl(chan->cd->cctl);
1598
1599 chan->slave = true;
1600 chan->name = chan->cd->bus_id;
1601 chan->src_addr = chan->cd->addr;
1602 chan->dst_addr = chan->cd->addr;
1603 chan->src_cctl = cctl | PL080_CONTROL_DST_INCR |
1604 pl08x_select_bus(chan->cd->periph_buses, chan->host->mem_buses);
1605 chan->dst_cctl = cctl | PL080_CONTROL_SRC_INCR |
1606 pl08x_select_bus(chan->host->mem_buses, chan->cd->periph_buses);
1607}
1608
Linus Walleije8689e62010-09-28 15:57:37 +02001609/*
1610 * Initialise the DMAC memcpy/slave channels.
1611 * Make a local wrapper to hold required data
1612 */
1613static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301614 struct dma_device *dmadev, unsigned int channels, bool slave)
Linus Walleije8689e62010-09-28 15:57:37 +02001615{
1616 struct pl08x_dma_chan *chan;
1617 int i;
1618
1619 INIT_LIST_HEAD(&dmadev->channels);
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001620
Linus Walleije8689e62010-09-28 15:57:37 +02001621 /*
1622 * Register as many many memcpy as we have physical channels,
1623 * we won't always be able to use all but the code will have
1624 * to cope with that situation.
1625 */
1626 for (i = 0; i < channels; i++) {
Viresh Kumarb201c112011-08-05 15:32:29 +05301627 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
Linus Walleije8689e62010-09-28 15:57:37 +02001628 if (!chan) {
1629 dev_err(&pl08x->adev->dev,
1630 "%s no memory for channel\n", __func__);
1631 return -ENOMEM;
1632 }
1633
1634 chan->host = pl08x;
1635 chan->state = PL08X_CHAN_IDLE;
1636
1637 if (slave) {
Linus Walleije8689e62010-09-28 15:57:37 +02001638 chan->cd = &pl08x->pd->slave_channels[i];
Russell King - ARM Linux121c8472011-07-21 17:13:48 +01001639 pl08x_dma_slave_init(chan);
Linus Walleije8689e62010-09-28 15:57:37 +02001640 } else {
1641 chan->cd = &pl08x->pd->memcpy_channel;
1642 chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i);
1643 if (!chan->name) {
1644 kfree(chan);
1645 return -ENOMEM;
1646 }
1647 }
Russell King - ARM Linuxb58b6b52011-01-03 22:34:48 +00001648 if (chan->cd->circular_buffer) {
1649 dev_err(&pl08x->adev->dev,
1650 "channel %s: circular buffers not supported\n",
1651 chan->name);
1652 kfree(chan);
1653 continue;
1654 }
Viresh Kumar175a5e62011-08-05 15:32:32 +05301655 dev_dbg(&pl08x->adev->dev,
Linus Walleije8689e62010-09-28 15:57:37 +02001656 "initialize virtual channel \"%s\"\n",
1657 chan->name);
1658
1659 chan->chan.device = dmadev;
Russell King - ARM Linux91aa5fa2011-01-03 22:31:04 +00001660 chan->chan.cookie = 0;
1661 chan->lc = 0;
Linus Walleije8689e62010-09-28 15:57:37 +02001662
1663 spin_lock_init(&chan->lock);
Russell King - ARM Linux15c17232011-01-03 22:44:36 +00001664 INIT_LIST_HEAD(&chan->pend_list);
Linus Walleije8689e62010-09-28 15:57:37 +02001665 tasklet_init(&chan->tasklet, pl08x_tasklet,
1666 (unsigned long) chan);
1667
1668 list_add_tail(&chan->chan.device_node, &dmadev->channels);
1669 }
1670 dev_info(&pl08x->adev->dev, "initialized %d virtual %s channels\n",
1671 i, slave ? "slave" : "memcpy");
1672 return i;
1673}
1674
1675static void pl08x_free_virtual_channels(struct dma_device *dmadev)
1676{
1677 struct pl08x_dma_chan *chan = NULL;
1678 struct pl08x_dma_chan *next;
1679
1680 list_for_each_entry_safe(chan,
1681 next, &dmadev->channels, chan.device_node) {
1682 list_del(&chan->chan.device_node);
1683 kfree(chan);
1684 }
1685}
1686
1687#ifdef CONFIG_DEBUG_FS
1688static const char *pl08x_state_str(enum pl08x_dma_chan_state state)
1689{
1690 switch (state) {
1691 case PL08X_CHAN_IDLE:
1692 return "idle";
1693 case PL08X_CHAN_RUNNING:
1694 return "running";
1695 case PL08X_CHAN_PAUSED:
1696 return "paused";
1697 case PL08X_CHAN_WAITING:
1698 return "waiting";
1699 default:
1700 break;
1701 }
1702 return "UNKNOWN STATE";
1703}
1704
1705static int pl08x_debugfs_show(struct seq_file *s, void *data)
1706{
1707 struct pl08x_driver_data *pl08x = s->private;
1708 struct pl08x_dma_chan *chan;
1709 struct pl08x_phy_chan *ch;
1710 unsigned long flags;
1711 int i;
1712
1713 seq_printf(s, "PL08x physical channels:\n");
1714 seq_printf(s, "CHANNEL:\tUSER:\n");
1715 seq_printf(s, "--------\t-----\n");
1716 for (i = 0; i < pl08x->vd->channels; i++) {
1717 struct pl08x_dma_chan *virt_chan;
1718
1719 ch = &pl08x->phy_chans[i];
1720
1721 spin_lock_irqsave(&ch->lock, flags);
1722 virt_chan = ch->serving;
1723
1724 seq_printf(s, "%d\t\t%s\n",
1725 ch->id, virt_chan ? virt_chan->name : "(none)");
1726
1727 spin_unlock_irqrestore(&ch->lock, flags);
1728 }
1729
1730 seq_printf(s, "\nPL08x virtual memcpy channels:\n");
1731 seq_printf(s, "CHANNEL:\tSTATE:\n");
1732 seq_printf(s, "--------\t------\n");
1733 list_for_each_entry(chan, &pl08x->memcpy.channels, chan.device_node) {
Russell King - ARM Linux3e2a0372011-01-03 22:32:46 +00001734 seq_printf(s, "%s\t\t%s\n", chan->name,
Linus Walleije8689e62010-09-28 15:57:37 +02001735 pl08x_state_str(chan->state));
1736 }
1737
1738 seq_printf(s, "\nPL08x virtual slave channels:\n");
1739 seq_printf(s, "CHANNEL:\tSTATE:\n");
1740 seq_printf(s, "--------\t------\n");
1741 list_for_each_entry(chan, &pl08x->slave.channels, chan.device_node) {
Russell King - ARM Linux3e2a0372011-01-03 22:32:46 +00001742 seq_printf(s, "%s\t\t%s\n", chan->name,
Linus Walleije8689e62010-09-28 15:57:37 +02001743 pl08x_state_str(chan->state));
1744 }
1745
1746 return 0;
1747}
1748
1749static int pl08x_debugfs_open(struct inode *inode, struct file *file)
1750{
1751 return single_open(file, pl08x_debugfs_show, inode->i_private);
1752}
1753
1754static const struct file_operations pl08x_debugfs_operations = {
1755 .open = pl08x_debugfs_open,
1756 .read = seq_read,
1757 .llseek = seq_lseek,
1758 .release = single_release,
1759};
1760
1761static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
1762{
1763 /* Expose a simple debugfs interface to view all clocks */
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301764 (void) debugfs_create_file(dev_name(&pl08x->adev->dev),
1765 S_IFREG | S_IRUGO, NULL, pl08x,
1766 &pl08x_debugfs_operations);
Linus Walleije8689e62010-09-28 15:57:37 +02001767}
1768
1769#else
1770static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
1771{
1772}
1773#endif
1774
Russell Kingaa25afa2011-02-19 15:55:00 +00001775static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
Linus Walleije8689e62010-09-28 15:57:37 +02001776{
1777 struct pl08x_driver_data *pl08x;
Russell King - ARM Linuxf96ca9ec2011-01-03 22:35:08 +00001778 const struct vendor_data *vd = id->data;
Linus Walleije8689e62010-09-28 15:57:37 +02001779 int ret = 0;
1780 int i;
1781
1782 ret = amba_request_regions(adev, NULL);
1783 if (ret)
1784 return ret;
1785
1786 /* Create the driver state holder */
Viresh Kumarb201c112011-08-05 15:32:29 +05301787 pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
Linus Walleije8689e62010-09-28 15:57:37 +02001788 if (!pl08x) {
1789 ret = -ENOMEM;
1790 goto out_no_pl08x;
1791 }
1792
Viresh Kumarb7b60182011-08-05 15:32:33 +05301793 pm_runtime_set_active(&adev->dev);
1794 pm_runtime_enable(&adev->dev);
1795
Linus Walleije8689e62010-09-28 15:57:37 +02001796 /* Initialize memcpy engine */
1797 dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
1798 pl08x->memcpy.dev = &adev->dev;
1799 pl08x->memcpy.device_alloc_chan_resources = pl08x_alloc_chan_resources;
1800 pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources;
1801 pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy;
1802 pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
1803 pl08x->memcpy.device_tx_status = pl08x_dma_tx_status;
1804 pl08x->memcpy.device_issue_pending = pl08x_issue_pending;
1805 pl08x->memcpy.device_control = pl08x_control;
1806
1807 /* Initialize slave engine */
1808 dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
1809 pl08x->slave.dev = &adev->dev;
1810 pl08x->slave.device_alloc_chan_resources = pl08x_alloc_chan_resources;
1811 pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
1812 pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
1813 pl08x->slave.device_tx_status = pl08x_dma_tx_status;
1814 pl08x->slave.device_issue_pending = pl08x_issue_pending;
1815 pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
1816 pl08x->slave.device_control = pl08x_control;
1817
1818 /* Get the platform data */
1819 pl08x->pd = dev_get_platdata(&adev->dev);
1820 if (!pl08x->pd) {
1821 dev_err(&adev->dev, "no platform data supplied\n");
1822 goto out_no_platdata;
1823 }
1824
1825 /* Assign useful pointers to the driver state */
1826 pl08x->adev = adev;
1827 pl08x->vd = vd;
1828
Russell King - ARM Linux30749cb2011-01-03 22:41:13 +00001829 /* By default, AHB1 only. If dualmaster, from platform */
1830 pl08x->lli_buses = PL08X_AHB1;
1831 pl08x->mem_buses = PL08X_AHB1;
1832 if (pl08x->vd->dualmaster) {
1833 pl08x->lli_buses = pl08x->pd->lli_buses;
1834 pl08x->mem_buses = pl08x->pd->mem_buses;
1835 }
1836
Linus Walleije8689e62010-09-28 15:57:37 +02001837 /* A DMA memory pool for LLIs, align on 1-byte boundary */
1838 pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev,
1839 PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0);
1840 if (!pl08x->pool) {
1841 ret = -ENOMEM;
1842 goto out_no_lli_pool;
1843 }
1844
1845 spin_lock_init(&pl08x->lock);
1846
1847 pl08x->base = ioremap(adev->res.start, resource_size(&adev->res));
1848 if (!pl08x->base) {
1849 ret = -ENOMEM;
1850 goto out_no_ioremap;
1851 }
1852
1853 /* Turn on the PL08x */
1854 pl08x_ensure_on(pl08x);
1855
Russell King - ARM Linux94ae8522011-01-16 20:18:05 +00001856 /* Attach the interrupt handler */
Linus Walleije8689e62010-09-28 15:57:37 +02001857 writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
1858 writel(0x000000FF, pl08x->base + PL080_TC_CLEAR);
1859
1860 ret = request_irq(adev->irq[0], pl08x_irq, IRQF_DISABLED,
Russell King - ARM Linuxb05cd8f2011-01-03 22:33:26 +00001861 DRIVER_NAME, pl08x);
Linus Walleije8689e62010-09-28 15:57:37 +02001862 if (ret) {
1863 dev_err(&adev->dev, "%s failed to request interrupt %d\n",
1864 __func__, adev->irq[0]);
1865 goto out_no_irq;
1866 }
1867
1868 /* Initialize physical channels */
Viresh Kumarb201c112011-08-05 15:32:29 +05301869 pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
Linus Walleije8689e62010-09-28 15:57:37 +02001870 GFP_KERNEL);
1871 if (!pl08x->phy_chans) {
1872 dev_err(&adev->dev, "%s failed to allocate "
1873 "physical channel holders\n",
1874 __func__);
1875 goto out_no_phychans;
1876 }
1877
1878 for (i = 0; i < vd->channels; i++) {
1879 struct pl08x_phy_chan *ch = &pl08x->phy_chans[i];
1880
1881 ch->id = i;
1882 ch->base = pl08x->base + PL080_Cx_BASE(i);
1883 spin_lock_init(&ch->lock);
1884 ch->serving = NULL;
1885 ch->signal = -1;
Viresh Kumar175a5e62011-08-05 15:32:32 +05301886 dev_dbg(&adev->dev, "physical channel %d is %s\n",
1887 i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
Linus Walleije8689e62010-09-28 15:57:37 +02001888 }
1889
1890 /* Register as many memcpy channels as there are physical channels */
1891 ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->memcpy,
1892 pl08x->vd->channels, false);
1893 if (ret <= 0) {
1894 dev_warn(&pl08x->adev->dev,
1895 "%s failed to enumerate memcpy channels - %d\n",
1896 __func__, ret);
1897 goto out_no_memcpy;
1898 }
1899 pl08x->memcpy.chancnt = ret;
1900
1901 /* Register slave channels */
1902 ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
Viresh Kumar3e27ee82011-08-05 15:32:27 +05301903 pl08x->pd->num_slave_channels, true);
Linus Walleije8689e62010-09-28 15:57:37 +02001904 if (ret <= 0) {
1905 dev_warn(&pl08x->adev->dev,
1906 "%s failed to enumerate slave channels - %d\n",
1907 __func__, ret);
1908 goto out_no_slave;
1909 }
1910 pl08x->slave.chancnt = ret;
1911
1912 ret = dma_async_device_register(&pl08x->memcpy);
1913 if (ret) {
1914 dev_warn(&pl08x->adev->dev,
1915 "%s failed to register memcpy as an async device - %d\n",
1916 __func__, ret);
1917 goto out_no_memcpy_reg;
1918 }
1919
1920 ret = dma_async_device_register(&pl08x->slave);
1921 if (ret) {
1922 dev_warn(&pl08x->adev->dev,
1923 "%s failed to register slave as an async device - %d\n",
1924 __func__, ret);
1925 goto out_no_slave_reg;
1926 }
1927
1928 amba_set_drvdata(adev, pl08x);
1929 init_pl08x_debugfs(pl08x);
Russell King - ARM Linuxb05cd8f2011-01-03 22:33:26 +00001930 dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
1931 amba_part(adev), amba_rev(adev),
1932 (unsigned long long)adev->res.start, adev->irq[0]);
Viresh Kumarb7b60182011-08-05 15:32:33 +05301933
1934 pm_runtime_put(&adev->dev);
Linus Walleije8689e62010-09-28 15:57:37 +02001935 return 0;
1936
1937out_no_slave_reg:
1938 dma_async_device_unregister(&pl08x->memcpy);
1939out_no_memcpy_reg:
1940 pl08x_free_virtual_channels(&pl08x->slave);
1941out_no_slave:
1942 pl08x_free_virtual_channels(&pl08x->memcpy);
1943out_no_memcpy:
1944 kfree(pl08x->phy_chans);
1945out_no_phychans:
1946 free_irq(adev->irq[0], pl08x);
1947out_no_irq:
1948 iounmap(pl08x->base);
1949out_no_ioremap:
1950 dma_pool_destroy(pl08x->pool);
1951out_no_lli_pool:
1952out_no_platdata:
Viresh Kumarb7b60182011-08-05 15:32:33 +05301953 pm_runtime_put(&adev->dev);
1954 pm_runtime_disable(&adev->dev);
1955
Linus Walleije8689e62010-09-28 15:57:37 +02001956 kfree(pl08x);
1957out_no_pl08x:
1958 amba_release_regions(adev);
1959 return ret;
1960}
1961
1962/* PL080 has 8 channels and the PL080 have just 2 */
1963static struct vendor_data vendor_pl080 = {
Linus Walleije8689e62010-09-28 15:57:37 +02001964 .channels = 8,
1965 .dualmaster = true,
1966};
1967
1968static struct vendor_data vendor_pl081 = {
Linus Walleije8689e62010-09-28 15:57:37 +02001969 .channels = 2,
1970 .dualmaster = false,
1971};
1972
1973static struct amba_id pl08x_ids[] = {
1974 /* PL080 */
1975 {
1976 .id = 0x00041080,
1977 .mask = 0x000fffff,
1978 .data = &vendor_pl080,
1979 },
1980 /* PL081 */
1981 {
1982 .id = 0x00041081,
1983 .mask = 0x000fffff,
1984 .data = &vendor_pl081,
1985 },
1986 /* Nomadik 8815 PL080 variant */
1987 {
1988 .id = 0x00280880,
1989 .mask = 0x00ffffff,
1990 .data = &vendor_pl080,
1991 },
1992 { 0, 0 },
1993};
1994
1995static struct amba_driver pl08x_amba_driver = {
1996 .drv.name = DRIVER_NAME,
1997 .id_table = pl08x_ids,
1998 .probe = pl08x_probe,
1999};
2000
2001static int __init pl08x_init(void)
2002{
2003 int retval;
2004 retval = amba_driver_register(&pl08x_amba_driver);
2005 if (retval)
2006 printk(KERN_WARNING DRIVER_NAME
Russell King - ARM Linuxe8b5e112011-01-03 22:30:24 +00002007 "failed to register as an AMBA device (%d)\n",
Linus Walleije8689e62010-09-28 15:57:37 +02002008 retval);
2009 return retval;
2010}
2011subsys_initcall(pl08x_init);