]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.arch/ppc-efika-bestcomm-ata-dma.patch
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc-efika-bestcomm-ata-dma.patch
1 Subject: Efika ATA DMA
2 From: Matt Sealey <matt@genesi-usa.com>
3 References: 445856
4
5 Enables UDMA operation for ATA disks on Efika, meaning faster (up to
6 ~33MB/s, from ~1.2MB/s) access and lower (5-10% from 40-80%) CPU usage.
7
8 Signed-off-by: Olaf Hering <olh@suse.de>
9
10 ---
11 arch/powerpc/sysdev/bestcomm/ata.c | 3
12 arch/powerpc/sysdev/bestcomm/ata.h | 2
13 arch/powerpc/sysdev/bestcomm/bestcomm.c | 7
14 arch/powerpc/sysdev/bestcomm/bestcomm.h | 33 +-
15 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h | 20 +
16 drivers/ata/pata_mpc52xx.c | 440 +++++++++++++++++++++++++--
17 6 files changed, 473 insertions(+), 32 deletions(-)
18
19 --- a/arch/powerpc/sysdev/bestcomm/ata.c
20 +++ b/arch/powerpc/sysdev/bestcomm/ata.c
21 @@ -61,6 +61,9 @@ bcom_ata_init(int queue_len, int maxbufs
22 struct bcom_ata_var *var;
23 struct bcom_ata_inc *inc;
24
25 + /* Prefetch breaks ATA DMA. Turn it off for ATA DMA */
26 + bcom_disable_prefetch();
27 +
28 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0);
29 if (!tsk)
30 return NULL;
31 --- a/arch/powerpc/sysdev/bestcomm/ata.h
32 +++ b/arch/powerpc/sysdev/bestcomm/ata.h
33 @@ -16,8 +16,8 @@
34
35 struct bcom_ata_bd {
36 u32 status;
37 - u32 dst_pa;
38 u32 src_pa;
39 + u32 dst_pa;
40 };
41
42 extern struct bcom_task *
43 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
44 +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
45 @@ -279,7 +279,6 @@ bcom_engine_init(void)
46 int task;
47 phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
48 unsigned int tdt_size, ctx_size, var_size, fdt_size;
49 - u16 regval;
50
51 /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
52 tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
53 @@ -331,10 +330,8 @@ bcom_engine_init(void)
54 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
55
56 /* Disable COMM Bus Prefetch on the original 5200; it's broken */
57 - if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) {
58 - regval = in_be16(&bcom_eng->regs->PtdCntrl);
59 - out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
60 - }
61 + if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
62 + bcom_disable_prefetch();
63
64 /* Init lock */
65 spin_lock_init(&bcom_eng->lock);
66 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.h
67 +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h
68 @@ -140,15 +140,29 @@ bcom_queue_full(struct bcom_task *tsk)
69 }
70
71 /**
72 + * bcom_get_bd - Get a BD from the queue
73 + * @tsk: The BestComm task structure
74 + * index: Index of the BD to fetch
75 + */
76 +static inline struct bcom_bd
77 +*bcom_get_bd(struct bcom_task *tsk, unsigned int index)
78 +{
79 + return tsk->bd + index * tsk->bd_size;
80 +}
81 +
82 +/**
83 * bcom_buffer_done - Checks if a BestComm
84 * @tsk: The BestComm task structure
85 */
86 static inline int
87 bcom_buffer_done(struct bcom_task *tsk)
88 {
89 + struct bcom_bd *bd;
90 if (bcom_queue_empty(tsk))
91 return 0;
92 - return !(tsk->bd[tsk->outdex].status & BCOM_BD_READY);
93 +
94 + bd = bcom_get_bd(tsk, tsk->outdex);
95 + return !(bd->status & BCOM_BD_READY);
96 }
97
98 /**
99 @@ -160,16 +174,21 @@ bcom_buffer_done(struct bcom_task *tsk)
100 static inline struct bcom_bd *
101 bcom_prepare_next_buffer(struct bcom_task *tsk)
102 {
103 - tsk->bd[tsk->index].status = 0; /* cleanup last status */
104 - return &tsk->bd[tsk->index];
105 + struct bcom_bd *bd;
106 +
107 + bd = bcom_get_bd(tsk, tsk->index);
108 + bd->status = 0; /* cleanup last status */
109 + return bd;
110 }
111
112 static inline void
113 bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
114 {
115 + struct bcom_bd *bd = bcom_get_bd(tsk, tsk->index);
116 +
117 tsk->cookie[tsk->index] = cookie;
118 mb(); /* ensure the bd is really up-to-date */
119 - tsk->bd[tsk->index].status |= BCOM_BD_READY;
120 + bd->status |= BCOM_BD_READY;
121 tsk->index = _bcom_next_index(tsk);
122 if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
123 bcom_enable(tsk);
124 @@ -179,10 +198,12 @@ static inline void *
125 bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
126 {
127 void *cookie = tsk->cookie[tsk->outdex];
128 + struct bcom_bd *bd = bcom_get_bd(tsk, tsk->outdex);
129 +
130 if (p_status)
131 - *p_status = tsk->bd[tsk->outdex].status;
132 + *p_status = bd->status;
133 if (p_bd)
134 - *p_bd = &tsk->bd[tsk->outdex];
135 + *p_bd = bd;
136 tsk->outdex = _bcom_next_outdex(tsk);
137 return cookie;
138 }
139 --- a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
140 +++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
141 @@ -198,8 +198,8 @@ struct bcom_task_header {
142 #define BCOM_IPR_SCTMR_1 2
143 #define BCOM_IPR_FEC_RX 6
144 #define BCOM_IPR_FEC_TX 5
145 -#define BCOM_IPR_ATA_RX 4
146 -#define BCOM_IPR_ATA_TX 3
147 +#define BCOM_IPR_ATA_RX 7
148 +#define BCOM_IPR_ATA_TX 7
149 #define BCOM_IPR_SCPCI_RX 2
150 #define BCOM_IPR_SCPCI_TX 2
151 #define BCOM_IPR_PSC3_RX 2
152 @@ -241,6 +241,22 @@ extern void bcom_set_initiator(int task,
153
154 #define TASK_ENABLE 0x8000
155
156 +/**
157 + * bcom_disable_prefetch - Hook to disable bus prefetching
158 + *
159 + * ATA DMA and the original MPC5200 need this due to silicon bugs. At the
160 + * moment disabling prefetch is a one-way street. There is no mechanism
161 + * in place to turn prefetch back on after it has been disabled. There is
162 + * no reason it couldn't be done, it would just be more complex to implement.
163 + */
164 +static inline void bcom_disable_prefetch(void)
165 +{
166 + u16 regval;
167 +
168 + regval = in_be16(&bcom_eng->regs->PtdCntrl);
169 + out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
170 +};
171 +
172 static inline void
173 bcom_enable_task(int task)
174 {
175 --- a/drivers/ata/pata_mpc52xx.c
176 +++ b/drivers/ata/pata_mpc52xx.c
177 @@ -6,6 +6,9 @@
178 * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
179 * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
180 *
181 + * UDMA support based on patches by Freescale (Bernard Kuhn, John Rigby),
182 + * Domen Puncer and Tim Yamin.
183 + *
184 * This file is licensed under the terms of the GNU General Public License
185 * version 2. This program is licensed "as is" without any warranty of any
186 * kind, whether express or implied.
187 @@ -18,27 +21,46 @@
188 #include <linux/libata.h>
189 #include <linux/of_platform.h>
190
191 +#include <asm/cacheflush.h>
192 #include <asm/types.h>
193 #include <asm/prom.h>
194 #include <asm/mpc52xx.h>
195
196 +#include <sysdev/bestcomm/bestcomm.h>
197 +#include <sysdev/bestcomm/bestcomm_priv.h>
198 +#include <sysdev/bestcomm/ata.h>
199
200 #define DRV_NAME "mpc52xx_ata"
201 #define DRV_VERSION "0.1.2"
202
203 -
204 /* Private structures used by the driver */
205 struct mpc52xx_ata_timings {
206 u32 pio1;
207 u32 pio2;
208 + u32 mdma1;
209 + u32 mdma2;
210 + u32 udma1;
211 + u32 udma2;
212 + u32 udma3;
213 + u32 udma4;
214 + u32 udma5;
215 + int using_udma;
216 };
217
218 struct mpc52xx_ata_priv {
219 unsigned int ipb_period;
220 struct mpc52xx_ata __iomem * ata_regs;
221 + phys_addr_t ata_regs_pa;
222 int ata_irq;
223 struct mpc52xx_ata_timings timings[2];
224 int csel;
225 +
226 + /* DMA */
227 + struct bcom_task *dmatsk;
228 + const struct udmaspec *udmaspec;
229 + const struct mdmaspec *mdmaspec;
230 + int mpc52xx_ata_dma_last_write;
231 + int waiting_for_dma;
232 };
233
234
235 @@ -53,6 +75,107 @@ static const int ataspec_ta[5] = { 35
236
237 #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
238
239 +/* ======================================================================== */
240 +
241 +/* ATAPI-4 MDMA specs (in clocks) */
242 +struct mdmaspec {
243 + u32 t0M;
244 + u32 td;
245 + u32 th;
246 + u32 tj;
247 + u32 tkw;
248 + u32 tm;
249 + u32 tn;
250 +};
251 +
252 +static const struct mdmaspec mdmaspec66[3] = {
253 + { .t0M = 32, .td = 15, .th = 2, .tj = 2, .tkw = 15, .tm = 4, .tn = 1 },
254 + { .t0M = 10, .td = 6, .th = 1, .tj = 1, .tkw = 4, .tm = 2, .tn = 1 },
255 + { .t0M = 8, .td = 5, .th = 1, .tj = 1, .tkw = 2, .tm = 2, .tn = 1 },
256 +};
257 +
258 +static const struct mdmaspec mdmaspec132[3] = {
259 + { .t0M = 64, .td = 29, .th = 3, .tj = 3, .tkw = 29, .tm = 7, .tn = 2 },
260 + { .t0M = 20, .td = 11, .th = 2, .tj = 1, .tkw = 7, .tm = 4, .tn = 1 },
261 + { .t0M = 16, .td = 10, .th = 2, .tj = 1, .tkw = 4, .tm = 4, .tn = 1 },
262 +};
263 +
264 +/* ATAPI-4 UDMA specs (in clocks) */
265 +struct udmaspec {
266 + u32 tcyc;
267 + u32 t2cyc;
268 + u32 tds;
269 + u32 tdh;
270 + u32 tdvs;
271 + u32 tdvh;
272 + u32 tfs;
273 + u32 tli;
274 + u32 tmli;
275 + u32 taz;
276 + u32 tzah;
277 + u32 tenv;
278 + u32 tsr;
279 + u32 trfs;
280 + u32 trp;
281 + u32 tack;
282 + u32 tss;
283 +};
284 +
285 +static const struct udmaspec udmaspec66[6] = {
286 + { .tcyc = 8, .t2cyc = 16, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1,
287 + .tfs = 16, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
288 + .tsr = 3, .trfs = 5, .trp = 11, .tack = 2, .tss = 4,
289 + },
290 + { .tcyc = 5, .t2cyc = 11, .tds = 1, .tdh = 1, .tdvs = 4, .tdvh = 1,
291 + .tfs = 14, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
292 + .tsr = 2, .trfs = 5, .trp = 9, .tack = 2, .tss = 4,
293 + },
294 + { .tcyc = 4, .t2cyc = 8, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1,
295 + .tfs = 12, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
296 + .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4,
297 + },
298 + { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 2, .tdvh = 1,
299 + .tfs = 9, .tli = 7, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
300 + .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4,
301 + },
302 + { .tcyc = 2, .t2cyc = 4, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1,
303 + .tfs = 8, .tli = 8, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
304 + .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4,
305 + },
306 + { .tcyc = 2, .t2cyc = 2, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1,
307 + .tfs = 6, .tli = 5, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
308 + .tsr = 2, .trfs = 4, .trp = 6, .tack = 2, .tss = 4,
309 + },
310 +};
311 +
312 +static const struct udmaspec udmaspec132[6] = {
313 + { .tcyc = 15, .t2cyc = 31, .tds = 2, .tdh = 1, .tdvs = 10, .tdvh = 1,
314 + .tfs = 30, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
315 + .tsr = 7, .trfs = 10, .trp = 22, .tack = 3, .tss = 7,
316 + },
317 + { .tcyc = 10, .t2cyc = 21, .tds = 2, .tdh = 1, .tdvs = 7, .tdvh = 1,
318 + .tfs = 27, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
319 + .tsr = 4, .trfs = 10, .trp = 17, .tack = 3, .tss = 7,
320 + },
321 + { .tcyc = 6, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1,
322 + .tfs = 23, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
323 + .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7,
324 + },
325 + { .tcyc = 7, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1,
326 + .tfs = 15, .tli = 13, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
327 + .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7,
328 + },
329 + { .tcyc = 2, .t2cyc = 5, .tds = 0, .tdh = 0, .tdvs = 1, .tdvh = 1,
330 + .tfs = 16, .tli = 14, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
331 + .tsr = 2, .trfs = 7, .trp = 13, .tack = 2, .tss = 6,
332 + },
333 + { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1,
334 + .tfs = 12, .tli = 10, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
335 + .tsr = 3, .trfs = 7, .trp = 12, .tack = 3, .tss = 7,
336 + },
337 +};
338 +
339 +/* ======================================================================== */
340
341 /* Bit definitions inside the registers */
342 #define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
343 @@ -66,6 +189,7 @@ static const int ataspec_ta[5] = { 35
344 #define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
345
346 #define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
347 +#define MPC52xx_ATA_FIFOSTAT_ERROR 0x40 /* FIFO Error */
348
349 #define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
350 #define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
351 @@ -75,6 +199,8 @@ static const int ataspec_ta[5] = { 35
352 #define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
353 #define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */
354
355 +#define MAX_DMA_BUFFERS 128
356 +#define MAX_DMA_BUFFER_SIZE 0x20000u
357
358 /* Structure of the hardware registers */
359 struct mpc52xx_ata {
360 @@ -140,7 +266,6 @@ struct mpc52xx_ata {
361
362
363 /* MPC52xx low level hw control */
364 -
365 static int
366 mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio)
367 {
368 @@ -165,6 +290,42 @@ mpc52xx_ata_compute_pio_timings(struct m
369 return 0;
370 }
371
372 +static int
373 +mpc52xx_ata_compute_mdma_timings(struct mpc52xx_ata_priv *priv, int dev,
374 + int speed)
375 +{
376 + struct mpc52xx_ata_timings *t = &priv->timings[dev];
377 + const struct mdmaspec *s = &priv->mdmaspec[speed];
378 +
379 + if (speed < 0 || speed > 2)
380 + return -EINVAL;
381 +
382 + t->mdma1 = (s->t0M << 24) | (s->td << 16) | (s->tkw << 8) | (s->tm);
383 + t->mdma2 = (s->th << 24) | (s->tj << 16) | (s->tn << 8);
384 + t->using_udma = 0;
385 +
386 + return 0;
387 +}
388 +
389 +static int
390 +mpc52xx_ata_compute_udma_timings(struct mpc52xx_ata_priv *priv, int dev, int speed)
391 +{
392 + struct mpc52xx_ata_timings *t = &priv->timings[dev];
393 + const struct udmaspec *s = &priv->udmaspec[speed];
394 +
395 + if (speed < 0 || speed > 2)
396 + return -EINVAL;
397 +
398 + t->udma1 = (s->t2cyc << 24) | (s->tcyc << 16) | (s->tds << 8) | s->tdh;
399 + t->udma2 = (s->tdvs << 24) | (s->tdvh << 16) | (s->tfs << 8) | s->tli;
400 + t->udma3 = (s->tmli << 24) | (s->taz << 16) | (s->tenv << 8) | s->tsr;
401 + t->udma4 = (s->tss << 24) | (s->trfs << 16) | (s->trp << 8) | s->tack;
402 + t->udma5 = (s->tzah << 24);
403 + t->using_udma = 1;
404 +
405 + return 0;
406 +}
407 +
408 static void
409 mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device)
410 {
411 @@ -173,14 +334,13 @@ mpc52xx_ata_apply_timings(struct mpc52xx
412
413 out_be32(&regs->pio1, timing->pio1);
414 out_be32(&regs->pio2, timing->pio2);
415 - out_be32(&regs->mdma1, 0);
416 - out_be32(&regs->mdma2, 0);
417 - out_be32(&regs->udma1, 0);
418 - out_be32(&regs->udma2, 0);
419 - out_be32(&regs->udma3, 0);
420 - out_be32(&regs->udma4, 0);
421 - out_be32(&regs->udma5, 0);
422 -
423 + out_be32(&regs->mdma1, timing->mdma1);
424 + out_be32(&regs->mdma2, timing->mdma2);
425 + out_be32(&regs->udma1, timing->udma1);
426 + out_be32(&regs->udma2, timing->udma2);
427 + out_be32(&regs->udma3, timing->udma3);
428 + out_be32(&regs->udma4, timing->udma4);
429 + out_be32(&regs->udma5, timing->udma5);
430 priv->csel = device;
431 }
432
433 @@ -244,6 +404,31 @@ mpc52xx_ata_set_piomode(struct ata_port
434
435 mpc52xx_ata_apply_timings(priv, adev->devno);
436 }
437 +
438 +static void
439 +mpc52xx_ata_set_dmamode(struct ata_port *ap, struct ata_device *adev)
440 +{
441 + struct mpc52xx_ata_priv *priv = ap->host->private_data;
442 + int rv;
443 +
444 + if (adev->dma_mode >= XFER_UDMA_0) {
445 + int dma = adev->dma_mode - XFER_UDMA_0;
446 + rv = mpc52xx_ata_compute_udma_timings(priv, adev->devno, dma);
447 + } else {
448 + int dma = adev->dma_mode - XFER_MW_DMA_0;
449 + rv = mpc52xx_ata_compute_mdma_timings(priv, adev->devno, dma);
450 + }
451 +
452 + if (rv) {
453 + dev_alert(ap->dev,
454 + "Trying to select invalid DMA mode %d\n",
455 + adev->dma_mode);
456 + return;
457 + }
458 +
459 + mpc52xx_ata_apply_timings(priv, adev->devno);
460 +}
461 +
462 static void
463 mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
464 {
465 @@ -255,6 +440,172 @@ mpc52xx_ata_dev_select(struct ata_port *
466 ata_sff_dev_select(ap,device);
467 }
468
469 +static int
470 +mpc52xx_ata_build_dmatable(struct ata_queued_cmd *qc)
471 +{
472 + struct ata_port *ap = qc->ap;
473 + struct mpc52xx_ata_priv *priv = ap->host->private_data;
474 + struct bcom_ata_bd *bd;
475 + unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE), si;
476 + struct scatterlist *sg;
477 + int count = 0;
478 +
479 + if (read)
480 + bcom_ata_rx_prepare(priv->dmatsk);
481 + else
482 + bcom_ata_tx_prepare(priv->dmatsk);
483 +
484 + for_each_sg(qc->sg, sg, qc->n_elem, si) {
485 + dma_addr_t cur_addr = sg_dma_address(sg);
486 + u32 cur_len = sg_dma_len(sg);
487 +
488 + while (cur_len) {
489 + unsigned int tc = min(cur_len, MAX_DMA_BUFFER_SIZE);
490 + bd = (struct bcom_ata_bd *)
491 + bcom_prepare_next_buffer(priv->dmatsk);
492 +
493 + if (read) {
494 + bd->status = tc;
495 + bd->src_pa = (__force u32) priv->ata_regs_pa +
496 + offsetof(struct mpc52xx_ata, fifo_data);
497 + bd->dst_pa = (__force u32) cur_addr;
498 + } else {
499 + bd->status = tc;
500 + bd->src_pa = (__force u32) cur_addr;
501 + bd->dst_pa = (__force u32) priv->ata_regs_pa +
502 + offsetof(struct mpc52xx_ata, fifo_data);
503 + }
504 +
505 + bcom_submit_next_buffer(priv->dmatsk, NULL);
506 +
507 + cur_addr += tc;
508 + cur_len -= tc;
509 + count++;
510 +
511 + if (count > MAX_DMA_BUFFERS) {
512 + dev_alert(ap->dev, "dma table"
513 + "too small\n");
514 + goto use_pio_instead;
515 + }
516 + }
517 + }
518 + return 1;
519 +
520 + use_pio_instead:
521 + bcom_ata_reset_bd(priv->dmatsk);
522 + return 0;
523 +}
524 +
525 +static void
526 +mpc52xx_bmdma_setup(struct ata_queued_cmd *qc)
527 +{
528 + struct ata_port *ap = qc->ap;
529 + struct mpc52xx_ata_priv *priv = ap->host->private_data;
530 + struct mpc52xx_ata __iomem *regs = priv->ata_regs;
531 +
532 + unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE);
533 + u8 dma_mode;
534 +
535 + if (!mpc52xx_ata_build_dmatable(qc))
536 + dev_alert(ap->dev, "%s: %i, return 1?\n",
537 + __func__, __LINE__);
538 +
539 + /* Check FIFO is OK... */
540 + if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR)
541 + dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n",
542 + __func__, in_8(&priv->ata_regs->fifo_status));
543 +
544 + if (read) {
545 + dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_READ |
546 + MPC52xx_ATA_DMAMODE_FE;
547 +
548 + /* Setup FIFO if direction changed */
549 + if (priv->mpc52xx_ata_dma_last_write != 0) {
550 + priv->mpc52xx_ata_dma_last_write = 0;
551 +
552 + /* Configure FIFO with granularity to 7 */
553 + out_8(&regs->fifo_control, 7);
554 + out_be16(&regs->fifo_alarm, 128);
555 +
556 + /* Set FIFO Reset bit (FR) */
557 + out_8(&regs->dma_mode, MPC52xx_ATA_DMAMODE_FR);
558 + }
559 + } else {
560 + dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_WRITE;
561 +
562 + /* Setup FIFO if direction changed */
563 + if (priv->mpc52xx_ata_dma_last_write != 1) {
564 + priv->mpc52xx_ata_dma_last_write = 1;
565 +
566 + /* Configure FIFO with granularity to 4 */
567 + out_8(&regs->fifo_control, 4);
568 + out_be16(&regs->fifo_alarm, 128);
569 + }
570 + }
571 +
572 + if (priv->timings[qc->dev->devno].using_udma)
573 + dma_mode |= MPC52xx_ATA_DMAMODE_UDMA;
574 +
575 + out_8(&regs->dma_mode, dma_mode);
576 + priv->waiting_for_dma = ATA_DMA_ACTIVE;
577 +
578 + ata_wait_idle(ap);
579 + ap->ops->sff_exec_command(ap, &qc->tf);
580 +}
581 +
582 +static void
583 +mpc52xx_bmdma_start(struct ata_queued_cmd *qc)
584 +{
585 + struct ata_port *ap = qc->ap;
586 + struct mpc52xx_ata_priv *priv = ap->host->private_data;
587 +
588 + bcom_set_task_auto_start(priv->dmatsk->tasknum, priv->dmatsk->tasknum);
589 + bcom_enable(priv->dmatsk);
590 +}
591 +
592 +static void
593 +mpc52xx_bmdma_stop(struct ata_queued_cmd *qc)
594 +{
595 + struct ata_port *ap = qc->ap;
596 + struct mpc52xx_ata_priv *priv = ap->host->private_data;
597 +
598 + bcom_disable(priv->dmatsk);
599 + bcom_ata_reset_bd(priv->dmatsk);
600 + priv->waiting_for_dma = 0;
601 +
602 + /* Check FIFO is OK... */
603 + if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR)
604 + dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n",
605 + __func__, in_8(&priv->ata_regs->fifo_status));
606 +}
607 +
608 +static u8
609 +mpc52xx_bmdma_status(struct ata_port *ap)
610 +{
611 + struct mpc52xx_ata_priv *priv = ap->host->private_data;
612 +
613 + /* Check FIFO is OK... */
614 + if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) {
615 + dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n",
616 + __func__, in_8(&priv->ata_regs->fifo_status));
617 + return priv->waiting_for_dma | ATA_DMA_ERR;
618 + }
619 +
620 + return priv->waiting_for_dma;
621 +}
622 +
623 +static irqreturn_t
624 +mpc52xx_ata_task_irq(int irq, void *vpriv)
625 +{
626 + struct mpc52xx_ata_priv *priv = vpriv;
627 + while (bcom_buffer_done(priv->dmatsk))
628 + bcom_retrieve_buffer(priv->dmatsk, NULL, NULL);
629 +
630 + priv->waiting_for_dma |= ATA_DMA_INTR;
631 +
632 + return IRQ_HANDLED;
633 +}
634 +
635 static struct scsi_host_template mpc52xx_ata_sht = {
636 ATA_PIO_SHT(DRV_NAME),
637 };
638 @@ -262,14 +613,18 @@ static struct scsi_host_template mpc52xx
639 static struct ata_port_operations mpc52xx_ata_port_ops = {
640 .inherits = &ata_sff_port_ops,
641 .sff_dev_select = mpc52xx_ata_dev_select,
642 - .cable_detect = ata_cable_40wire,
643 .set_piomode = mpc52xx_ata_set_piomode,
644 - .post_internal_cmd = ATA_OP_NULL,
645 + .set_dmamode = mpc52xx_ata_set_dmamode,
646 + .bmdma_setup = mpc52xx_bmdma_setup,
647 + .bmdma_start = mpc52xx_bmdma_start,
648 + .bmdma_stop = mpc52xx_bmdma_stop,
649 + .bmdma_status = mpc52xx_bmdma_status,
650 + .qc_prep = ata_noop_qc_prep,
651 };
652
653 static int __devinit
654 mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
655 - unsigned long raw_ata_regs)
656 + unsigned long raw_ata_regs, int mwdma_mask, int udma_mask)
657 {
658 struct ata_host *host;
659 struct ata_port *ap;
660 @@ -281,9 +636,9 @@ mpc52xx_ata_init_one(struct device *dev,
661
662 ap = host->ports[0];
663 ap->flags |= ATA_FLAG_SLAVE_POSS;
664 - ap->pio_mask = 0x1f; /* Up to PIO4 */
665 - ap->mwdma_mask = 0x00; /* No MWDMA */
666 - ap->udma_mask = 0x00; /* No UDMA */
667 + ap->pio_mask = ATA_PIO4;
668 + ap->mwdma_mask = mwdma_mask;
669 + ap->udma_mask = udma_mask;
670 ap->ops = &mpc52xx_ata_port_ops;
671 host->private_data = priv;
672
673 @@ -333,7 +688,10 @@ mpc52xx_ata_probe(struct of_device *op,
674 int ata_irq;
675 struct mpc52xx_ata __iomem *ata_regs;
676 struct mpc52xx_ata_priv *priv;
677 - int rv;
678 + int rv, ret, task_irq;
679 + int mwdma_mask = 0, udma_mask = 0;
680 + const __be32 *prop;
681 + int proplen;
682
683 /* Get ipb frequency */
684 ipb_freq = mpc52xx_find_ipb_freq(op->node);
685 @@ -351,6 +709,27 @@ mpc52xx_ata_probe(struct of_device *op,
686 return rv;
687 }
688
689 + /*
690 + * By default, all DMA modes are disabled for the MPC5200. Some
691 + * boards don't have the required signals routed to make DMA work.
692 + * Also, the MPC5200B has a silicon bug that causes data corruption
693 + * with UDMA if it is used at the same time as the LocalPlus bus.
694 + *
695 + * Instead of trying to guess what modes are usable, check the
696 + * ATA device tree node to find out what DMA modes work on the board.
697 + * UDMA/MWDMA modes can also be forced by adding "libata.force=<mode>"
698 + * to the kernel boot parameters.
699 + *
700 + * The MPC5200 ATA controller supports MWDMA modes 0, 1 and 2 and
701 + * UDMA modes 0, 1 and 2.
702 + */
703 + prop = of_get_property(op->node, "mwdma-mode", &proplen);
704 + if ((prop) && (proplen >= 4))
705 + mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1);
706 + prop = of_get_property(op->node, "udma-mode", &proplen);
707 + if ((prop) && (proplen >= 4))
708 + udma_mask = 0x7 & ((1 << (*prop + 1)) - 1);
709 +
710 ata_irq = irq_of_parse_and_map(op->node, 0);
711 if (ata_irq == NO_IRQ) {
712 printk(KERN_ERR DRV_NAME ": "
713 @@ -389,8 +768,32 @@ mpc52xx_ata_probe(struct of_device *op,
714
715 priv->ipb_period = 1000000000 / (ipb_freq / 1000);
716 priv->ata_regs = ata_regs;
717 + priv->ata_regs_pa = res_mem.start;
718 priv->ata_irq = ata_irq;
719 priv->csel = -1;
720 + priv->mpc52xx_ata_dma_last_write = -1;
721 +
722 + if (ipb_freq/1000000 == 66) {
723 + priv->mdmaspec = mdmaspec66;
724 + priv->udmaspec = udmaspec66;
725 + } else {
726 + priv->mdmaspec = mdmaspec132;
727 + priv->udmaspec = udmaspec132;
728 + }
729 +
730 + priv->dmatsk = bcom_ata_init(MAX_DMA_BUFFERS, MAX_DMA_BUFFER_SIZE);
731 + if (!priv->dmatsk) {
732 + dev_err(&op->dev, "bestcomm initialization failed\n");
733 + rv = -ENOMEM;
734 + goto err;
735 + }
736 +
737 + task_irq = bcom_get_task_irq(priv->dmatsk);
738 + ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED,
739 + "ATA task", priv);
740 + if (ret)
741 + dev_alert(&op->dev, "request_irq failed with: "
742 + "%i\n", ret);
743
744 /* Init the hw */
745 rv = mpc52xx_ata_hw_init(priv);
746 @@ -400,7 +803,8 @@ mpc52xx_ata_probe(struct of_device *op,
747 }
748
749 /* Register ourselves to libata */
750 - rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start);
751 + rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start,
752 + mwdma_mask, udma_mask);
753 if (rv) {
754 printk(KERN_ERR DRV_NAME ": "
755 "Error while registering to ATA layer\n");