]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/ppc-efika-bestcomm-ata-dma.patch
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / ppc-efika-bestcomm-ata-dma.patch
CommitLineData
2cb7cef9
BS
1Subject: Efika ATA DMA
2From: Matt Sealey <matt@genesi-usa.com>
3References: 445856
4
5Enables 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
8Signed-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");