Subject: pata_mpc52xx - no interrupts when using bestcomm/dma?

From: Domen Puncer <[email-masked]>
Date: Mon, 27 Aug 2007 11:44:54 +0200

Hi!

I'm taking a stab at adding DMA support to pata_mpc52xx driver.

It's based on patches from Freescale's ltib (old ide driver).

The problem is that I can't seem to get any interrupts
(not ata, not bestcomm task), when setting up MWDMA/UDMA mode.

Ideas?

My current patch:

---
 drivers/ata/pata_mpc52xx.c |  491 +++++++++++++++++++++++++++++++++++++++++++--
 include/linux/libata.h     |    2 
 2 files changed, 477 insertions(+), 16 deletions(-)

Index: work-powerpc.git/drivers/ata/pata_mpc52xx.c
===================================================================
--- work-powerpc.git.orig/drivers/ata/pata_mpc52xx.c
+++ work-powerpc.git/drivers/ata/pata_mpc52xx.c
@@ -4,6 +4,7 @@
  * libata driver for the Freescale MPC52xx on-chip IDE interface
  *
  * Copyright (C) 2006 Sylvain Munaut <[email-masked]>
+ * Copyright (C) 2005,2006 Freescale - Bernard Kuhn, John Rigby
  * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
  *
  * This file is licensed under the terms of the GNU General Public License
@@ -22,6 +23,8 @@
 #include <asm/of_platform.h>
 #include <asm/mpc52xx.h>
 
+#include <sysdev/bestcomm/bestcomm.h>
+#include <sysdev/bestcomm/ata.h>
 
 #define DRV_NAME	"mpc52xx_ata"
 #define DRV_VERSION	"0.1.0ac2"
@@ -31,6 +34,14 @@
 struct mpc52xx_ata_timings {
 	u32	pio1;
 	u32	pio2;
+	u32	mdma1;
+	u32	mdma2;
+	u32	udma1;
+	u32	udma2;
+	u32	udma3;
+	u32	udma4;
+	u32	udma5;
+	int	using_udma;
 };
 
 struct mpc52xx_ata_priv {
@@ -39,6 +50,12 @@ struct mpc52xx_ata_priv {
 	int				ata_irq;
 	struct mpc52xx_ata_timings	timings[2];
 	int				csel;
+
+	/* dma stuff follows */
+	struct bcom_task *		dmatsk;
+	const struct udmaspec *		udmaspec;
+	const struct mdmaspec *		mdmaspec;
+	int 				mpc52xx_ata_dma_last_write;
 };

@@ -53,6 +70,102 @@ static const int ataspec_ta[5]    = { 35
 
 #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
 
+/* ATAPI-4 MDMA specs (in clocks) */
+struct mdmaspec {
+	u32 t0M[3];
+	u32 td[3];
+	u32 th[3];
+	u32 tj[3];
+	u32 tkw[3];
+	u32 tm[3];
+	u32 tn[3];
+};
+
+// -----------------------------------------------------------------------------------------------
+
+static const struct mdmaspec mdmaspec66 = {
+	{32,  10,  8},
+	{15,  6,   5},
+	{2,   1,   1},
+	{2,   1,   1},
+	{15,  4,   2},
+	{4,   2,   2},
+	{1,   1,   1}
+};
+
+static const struct mdmaspec mdmaspec132 = {
+	{64,  20,  16},
+	{29,  11,  10},
+	{3,   2,   2},
+	{3,   1,   1},
+	{29,  7,   4},
+	{7,   4,   4},
+	{2,   1,   1}
+};
+
+
+/* ATAPI-4 UDMA specs (in clocks) */
+struct udmaspec {
+	u32 tcyc[6];
+	u32 t2cyc[6];
+	u32 tds[6];
+	u32 tdh[6];
+	u32 tdvs[6];
+	u32 tdvh[6];
+	u32 tfs_min[6];
+	u32 tli_max[6];
+	u32 tmli[6];
+	u32 taz[6];
+	u32 tzah[6];
+	u32 tenv_min[6];
+	u32 tsr[6];
+	u32 trfs[6];
+	u32 trp[6];
+	u32 tack[6];
+	u32 tss[6];
+};
+
+static const struct udmaspec udmaspec66 = {
+	{ 8,  5,  4,  3,  2,  2},
+	{16, 11,  8,  6,  4 , 2},
+	{ 1,  1,  1,  1,  1,  1},
+	{ 1,  1,  1,  1,  1,  1},
+	{ 5,  4,  3,  2,  1,  1},
+	{ 1,  1,  1,  1,  1,  1},
+	{16, 14, 12,  9,  8,  6},
+	{10, 10, 10,  7,  8,  5},
+	{ 2,  2,  2,  2,  2,  2},
+	{ 1,  1,  1,  1,  1,  1},
+	{ 2,  2,  2,  2,  2,  2},
+	{ 2,  2,  2,  2,  2,  2},
+	{ 3,  2,  2,  2,  2,  2},
+	{ 5,  5,  4,  4,  4,  4},
+	{11,  9,  7,  7,  7,  6},
+	{ 2,  2,  2,  2,  2,  2},
+	{ 4,  4,  4,  4,  4,  4}
+};
+
+static const struct udmaspec udmaspec132 = {
+	{15, 10,  6,  7,  2,  3},
+	{31, 21, 12, 12,  5,  6},
+	{ 2,  2,  1,  1,  0,  1},
+	{ 1,  1,  1,  1,  0,  1},
+	{10,  7,  5,  3,  1,  1},
+	{ 1,  1,  1,  1,  1,  1},
+	{30, 27, 23, 15, 16, 12},
+	{20, 20, 20, 13, 14, 10},
+	{ 3,  3,  3,  3,  2,  3},
+	{ 2,  2,  2,  2,  1,  2},
+	{ 3,  3,  3,  3,  2,  3},
+	{ 3,  3,  3,  3,  2,  3},
+	{ 7,  4,  3,  3,  2,  3},
+	{10, 10,  8,  8,  7,  7},
+	{22, 17, 14, 14, 13, 12},
+	{ 3,  3,  3,  3,  2,  3},
+	{ 7,  7,  7,  7,  6,  7},
+};
+
+// -----------------------------------------------------------------------------------------------
 
 /* Bit definitions inside the registers */
 #define MPC52xx_ATA_HOSTCONF_SMR	0x80000000UL /* State machine reset */
@@ -76,6 +189,10 @@ static const int ataspec_ta[5]    = { 35
 #define MPC52xx_ATA_DMAMODE_HUT		0x40 /* Host UDMA burst terminate */

+#define MAX_DMA_BUFFERS 128
+#define MAX_DMA_BUFFER_SIZE 0x20000u
+
+
 /* Structure of the hardware registers */
 struct mpc52xx_ata {
 
@@ -141,6 +258,19 @@ struct mpc52xx_ata {
 
 /* MPC52xx low level hw control */
 
+static inline void
+mpc52xx_ata_wait_tip_bit_clear(struct mpc52xx_ata __iomem *regs)
+{
+	int timeout = 1000;
+
+	while (in_be32(&regs->host_status) & MPC52xx_ATA_HOSTSTAT_TIP)
+		if (timeout-- == 0) {
+			printk(KERN_ERR "mpc52xx-ide: Timeout waiting for TIP clear\n");
+			break;
+		}
+	udelay(10);     /* FIXME: Necessary ??? */
+}
+
 static int
 mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio)
 {
@@ -165,6 +295,96 @@ mpc52xx_ata_compute_pio_timings(struct m
 	return 0;
 }
 
+static int
+mpc52xx_ata_compute_mdma_timings(struct mpc52xx_ata_priv *priv, int dev, int speed)
+{
+	struct mpc52xx_ata_timings *timing = &priv->timings[dev];
+	u32 t0M, td, tkw, tm, th, tj, tn;
+
+	if (speed < 0 || speed > 2)
+		return -EINVAL;
+
+	t0M = priv->mdmaspec->t0M[speed];
+	td = priv->mdmaspec->td[speed];
+	tkw = priv->mdmaspec->tkw[speed];
+	tm = priv->mdmaspec->tm[speed];
+	th = priv->mdmaspec->th[speed];
+	tj = priv->mdmaspec->tj[speed];
+	tn = priv->mdmaspec->tn[speed];
+
+	/*
+	DPRINTK ("t0M = %d\n", t0M);
+	DPRINTK ("td  = %d\n", td);
+	DPRINTK ("tkw = %d\n", tkw);
+	DPRINTK ("tm  = %d\n", tm);
+	DPRINTK ("th  = %d\n", th);
+	DPRINTK ("tj  = %d\n", tj);
+	DPRINTK ("tn  = %d\n", tn);
+	*/
+	timing->mdma1 = (t0M << 24) | (td << 16) | (tkw << 8) | (tm);
+	timing->mdma2 = (th << 24) | (tj << 16) | (tn << 8);
+
+	timing->using_udma = 0;
+
+	return 0;
+}
+
+static int
+mpc52xx_ata_compute_udma_timings(struct mpc52xx_ata_priv *priv, int dev, int speed)
+{
+	struct mpc52xx_ata_timings *timing = &priv->timings[dev];
+	u32 t2cyc, tcyc, tds, tdh, tdvs, tdvh, tfs, tli, tmli, taz, tenv, tsr, tss, trfs, trp, tack, tzah;
+
+	if (speed < 0 || speed > 2)
+		return -EINVAL;
+
+	t2cyc = priv->udmaspec->t2cyc[speed];
+	tcyc = priv->udmaspec->tcyc[speed];
+	tds = priv->udmaspec->tds[speed];
+	tdh = priv->udmaspec->tdh[speed];
+	tdvs = priv->udmaspec->tdvs[speed];
+	tdvh = priv->udmaspec->tdvh[speed];
+	tfs = priv->udmaspec->tfs_min[speed];
+	tmli = priv->udmaspec->tmli[speed];
+	tenv = priv->udmaspec->tenv_min[speed];
+	tss = priv->udmaspec->tss[speed];
+	trp = priv->udmaspec->trp[speed];
+	tack = priv->udmaspec->tack[speed];
+	tzah = priv->udmaspec->tzah[speed];
+	taz = priv->udmaspec->taz[speed];
+	trfs = priv->udmaspec->trfs[speed];
+	tsr = priv->udmaspec->tsr[speed];
+	tli = priv->udmaspec->tli_max[speed];
+/*
+	DPRINTK ("UDMA t2cyc = %d\n", t2cyc);
+	DPRINTK ("UDMA tcyc  = %d\n", tcyc);
+	DPRINTK ("UDMA tds   = %d\n", tds);
+	DPRINTK ("UDMA tdh   = %d\n", tdh);
+	DPRINTK ("UDMA tdvs  = %d\n", tdvs);
+	DPRINTK ("UDMA tdvh  = %d\n", tdvh);
+	DPRINTK ("UDMA tfs   = %d\n", tfs);
+	DPRINTK ("UDMA tli   = %d\n", tli);
+	DPRINTK ("UDMA tmli  = %d\n", tmli);
+	DPRINTK ("UDMA taz   = %d\n", taz);
+	DPRINTK ("UDMA tenv  = %d\n", tenv);
+	DPRINTK ("UDMA tsr   = %d\n", tsr);
+	DPRINTK ("UDMA tss   = %d\n", tss);
+	DPRINTK ("UDMA trfs  = %d\n", trfs);
+	DPRINTK ("UDMA trp   = %d\n", trp);
+	DPRINTK ("UDMA tack  = %d\n", tack);
+	DPRINTK ("UDMA tzah  = %d\n", tzah);
+*/
+	timing->udma1 = (t2cyc << 24) | (tcyc << 16) | (tds << 8) | (tdh);
+	timing->udma2 = (tdvs << 24) | (tdvh << 16) | (tfs << 8) | (tli);
+	timing->udma3 = (tmli << 24) | (taz << 16) | (tenv << 8) | (tsr);
+	timing->udma4 = (tss << 24) | (trfs << 16) | (trp << 8) | (tack);
+	timing->udma5 = (tzah << 24);
+
+	timing->using_udma = 1;
+
+	return 0;
+}
+
 static void
 mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device)
 {
@@ -173,13 +393,13 @@ mpc52xx_ata_apply_timings(struct mpc52xx
 
 	out_be32(&regs->pio1,  timing->pio1);
 	out_be32(&regs->pio2,  timing->pio2);
-	out_be32(&regs->mdma1, 0);
-	out_be32(&regs->mdma2, 0);
-	out_be32(&regs->udma1, 0);
-	out_be32(&regs->udma2, 0);
-	out_be32(&regs->udma3, 0);
-	out_be32(&regs->udma4, 0);
-	out_be32(&regs->udma5, 0);
+	out_be32(&regs->mdma1, timing->mdma1);
+	out_be32(&regs->mdma2, timing->mdma2);
+	out_be32(&regs->udma1, timing->udma1);
+	out_be32(&regs->udma2, timing->udma2);
+	out_be32(&regs->udma3, timing->udma3);
+	out_be32(&regs->udma4, timing->udma4);
+	out_be32(&regs->udma5, timing->udma5);
 
 	priv->csel = device;
 }
@@ -234,6 +454,7 @@ mpc52xx_ata_set_piomode(struct ata_port 
 
 	pio = adev->pio_mode - XFER_PIO_0;
 
+	// FIXME, can be called for dma mode?
 	rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio);
 
 	if (rv) {
@@ -245,6 +466,28 @@ mpc52xx_ata_set_piomode(struct ata_port 
 	mpc52xx_ata_apply_timings(priv, adev->devno);
 }
 static void
+mpc52xx_ata_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+	int rv;
+
+	if (adev->dma_mode >= XFER_UDMA_0) {
+		int dma = adev->dma_mode - XFER_UDMA_0;
+		rv = mpc52xx_ata_compute_udma_timings(priv, adev->devno, dma);
+	} else {
+		int dma = adev->dma_mode - XFER_MW_DMA_0;
+		rv = mpc52xx_ata_compute_mdma_timings(priv, adev->devno, dma);
+	}
+
+	if (rv) {
+		printk(KERN_ERR DRV_NAME
+			": Trying to select invalid DMA mode %d\n", adev->dma_mode);
+		return;
+	}
+
+	mpc52xx_ata_apply_timings(priv, adev->devno);
+}
+static void
 mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
 {
 	struct mpc52xx_ata_priv *priv = ap->host->private_data;
@@ -258,10 +501,174 @@ mpc52xx_ata_dev_select(struct ata_port *
 static void
 mpc52xx_ata_error_handler(struct ata_port *ap)
 {
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+
+	printk(KERN_ALERT "%s: status: %08x; fifo_status_frame: %08x; fifo_status: %08x\n",
+			__func__, in_be32(&regs->host_status),
+			in_be32(&regs->fifo_status_frame),
+			in_be32(&regs->fifo_status));
+
 	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
 			ata_std_postreset);
 }
 
+static void
+mpc52xx_ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+
+	mpc52xx_ata_wait_tip_bit_clear(priv->ata_regs);
+
+	ata_exec_command(ap, tf);
+}
+
+static int
+mpc52xx_ata_build_dmatable(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+	struct scatterlist *sg;
+	unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE);
+	int count = 0;
+
+	if (read)
+		bcom_ata_rx_prepare(priv->dmatsk);
+	else
+		bcom_ata_tx_prepare(priv->dmatsk);
+
+
+	ata_for_each_sg(sg, qc) {
+		u32 cur_addr = sg_dma_address(sg);
+		u32 cur_len = sg_dma_len(sg);
+
+		while (cur_len) {
+			unsigned int tc = min(cur_len, MAX_DMA_BUFFER_SIZE);
+			struct bcom_ata_bd *bd;
+
+			bd = (struct bcom_ata_bd *)
+				bcom_prepare_next_buffer(priv->dmatsk);
+
+			if (read) {
+				bd->status = tc;
+				bd->dst_pa = cur_addr;
+				bd->src_pa = (__force u32)&regs->fifo_data; // virt_to_phys?
+			} else {
+				bd->status = tc;
+				bd->dst_pa = (__force u32)&regs->fifo_data; // virt_to_phys?
+				bd->src_pa = cur_addr;
+
+				/* and how does bestcomm know to increase one, and not other?
+				 * XXX TODO */
+			}
+
+			bcom_submit_next_buffer(priv->dmatsk, phys_to_virt(cur_addr)); // qc is just a cookie
+
+			cur_addr += tc;
+			cur_len -= tc;
+			count++;
+
+			if (count == MAX_DMA_BUFFERS) {
+				printk(KERN_ALERT "%s: %i dma table too small\n",
+						__func__, __LINE__);
+				goto use_pio_instead;
+			}
+		}
+	}
+	return 1;
+
+ use_pio_instead:
+	bcom_ata_reset_bd(priv->dmatsk);
+	//pci_unmap_sg ???
+
+	return 0;
+}
+
+static void
+mpc52xx_bmdma_setup(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+	unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 dma_mode;
+printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+
+	if (!mpc52xx_ata_build_dmatable(qc)) {
+		//ide_map_sg(drive, rq);
+		printk(KERN_ALERT "%s: %i, return 1?\n", __func__, __LINE__);
+	}
+
+	if (read) {
+		dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_READ |
+				MPC52xx_ATA_DMAMODE_FE;
+
+		/* Setup FIFO if direction changed */
+		if (priv->mpc52xx_ata_dma_last_write) {
+			priv->mpc52xx_ata_dma_last_write = 0;
+			mpc52xx_ata_wait_tip_bit_clear(regs);
+			out_8(&regs->dma_mode, MPC52xx_ATA_DMAMODE_FR);
+			/* Configure it with granularity to 7 like sample code */
+			out_8(&regs->fifo_control, 7);
+			out_be16(&regs->fifo_alarm, 128);
+		}
+	} else {
+		dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_WRITE;
+
+		/* Setup FIFO if direction changed */
+		if (!priv->mpc52xx_ata_dma_last_write) {
+			priv->mpc52xx_ata_dma_last_write = 1;
+			mpc52xx_ata_wait_tip_bit_clear(regs);
+			/* Configure FIFO with granularity to 4 like sample code */
+			out_8(&regs->fifo_control, 4);
+			//out_be16(&regs->fifo_alarm, 256);
+			out_be16(&regs->fifo_alarm, 128);
+		}
+	}
+
+	if (priv->timings[qc->dev->devno].using_udma)
+		dma_mode |= MPC52xx_ATA_DMAMODE_UDMA;
+
+	mpc52xx_ata_wait_tip_bit_clear(regs);
+	out_8(&regs->dma_mode, dma_mode);
+
+	ap->ops->exec_command(ap, &qc->tf); // added, ata_bmdma_setup has it
+}
+
+static void
+mpc52xx_bmdma_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+
+	//xlb_clear(); // WTF
+	bcom_enable(priv->dmatsk);
+}
+
+static void
+mpc52xx_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	// uh? looks like destructor for setup not start
+	struct ata_port *ap = qc->ap;
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+
+	bcom_disable(priv->dmatsk);
+	//bcom_clear_irq(priv->dmatsk); //!!
+	bcom_ata_reset_bd(priv->dmatsk);
+
+	//	mpc52xx_ata_destroy_dmatable();
+}
+// waiting_for_dma eliminated
+
+static u8
+mpc52xx_bmdma_status(struct ata_port *ap)
+{
+printk(KERN_ALERT "%s: %i TODO\n", __func__, __LINE__);
+	return 0;
+}

 static struct scsi_host_template mpc52xx_ata_sht = {
@@ -282,25 +689,47 @@ static struct scsi_host_template mpc52xx
 	.bios_param		= ata_std_bios_param,
 };
 
+static void mpc52xx_ata_bmdma_freeze(struct ata_port *ap)
+{
+	printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+	ata_bmdma_freeze(ap);
+}
+static void mpc52xx_ata_bmdma_thaw(struct ata_port *ap)
+{
+	printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+	ata_bmdma_thaw(ap);
+}
+static void ata_dummy_noret(struct ata_port *ap)
+{
+printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+}
 static struct ata_port_operations mpc52xx_ata_port_ops = {
 	.port_disable		= ata_port_disable,
 	.set_piomode		= mpc52xx_ata_set_piomode,
+	.set_dmamode		= mpc52xx_ata_set_dmamode,
 	.dev_select		= mpc52xx_ata_dev_select,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
 	.check_status		= ata_check_status,
-	.exec_command		= ata_exec_command,
-	.freeze			= ata_bmdma_freeze,
-	.thaw			= ata_bmdma_thaw,
+	.exec_command		= mpc52xx_ata_exec_command,
+	.freeze			= mpc52xx_ata_bmdma_freeze,
+	.thaw			= mpc52xx_ata_bmdma_thaw,
 	.error_handler		= mpc52xx_ata_error_handler,
 	.cable_detect		= ata_cable_40wire,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_data_xfer,
-	.irq_clear		= ata_bmdma_irq_clear,
+//	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_clear		= ata_dummy_noret,
 	.irq_on			= ata_irq_on,
 	.irq_ack		= ata_irq_ack,
 	.port_start		= ata_port_start,
+	.bmdma_setup		= mpc52xx_bmdma_setup,
+	.bmdma_start		= mpc52xx_bmdma_start,
+	.bmdma_stop		= mpc52xx_bmdma_stop,
+	.bmdma_status		= mpc52xx_bmdma_status,
+
+// not ide_dma_check	int  (*check_atapi_dma) (struct ata_queued_cmd *qc);
 };
 
 static int __devinit
@@ -309,7 +738,6 @@ mpc52xx_ata_init_one(struct device *dev,
 	struct ata_host *host;
 	struct ata_port *ap;
 	struct ata_ioports *aio;
-	int rc;
 
 	host = ata_host_alloc(dev, 1);
 	if (!host)
@@ -317,9 +745,9 @@ mpc52xx_ata_init_one(struct device *dev,
 
 	ap = host->ports[0];
 	ap->flags		|= ATA_FLAG_SLAVE_POSS;
-	ap->pio_mask		= 0x1f;	/* Up to PIO4 */
-	ap->mwdma_mask		= 0x00;	/* No MWDMA   */
-	ap->udma_mask		= 0x00;	/* No UDMA    */
+	ap->pio_mask		= ATA_PIO4;	/* Up to PIO4 */
+	ap->mwdma_mask		= 0x07;		/* Up to MWDMA2 */
+	ap->udma_mask		= ATA_UDMA2;	/* Up to UDMA2 */
 	ap->ops			= &mpc52xx_ata_port_ops;
 	host->private_data	= priv;
 
@@ -359,6 +787,15 @@ mpc52xx_ata_remove_one(struct device *de
 /* OF Platform driver                                                       */
 /* ======================================================================== */
 
+static irqreturn_t
+mpc52xx_ata_task_irq(int irq, void *vpriv)
+{
+	struct mpc52xx_ata_priv *priv = vpriv;
+printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+
+	return IRQ_HANDLED;
+}
+
 static int __devinit
 mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
 {
@@ -426,6 +863,30 @@ mpc52xx_ata_probe(struct of_device *op, 
 	priv->ata_irq = ata_irq;
 	priv->csel = -1;
 
+	if (ipb_freq/1000000 == 66) {
+		priv->mdmaspec = &mdmaspec66;
+		priv->udmaspec = &udmaspec66;
+	} else {
+		priv->mdmaspec = &mdmaspec132;
+		priv->udmaspec = &udmaspec132;
+	}
+
+	priv->dmatsk = bcom_ata_init(MAX_DMA_BUFFERS, MAX_DMA_BUFFER_SIZE);
+	if (!priv->dmatsk) {
+		printk(KERN_ALERT "%s: %i\n", __func__, __LINE__);
+		rv = -ENOMEM;
+		goto err;
+	}
+	// XXX task irq? nope, it doesn't get any irq's
+	{
+		int ret;
+		int task_irq = bcom_get_task_irq(priv->dmatsk);
+		printk(KERN_ALERT "%s: ata task irq: %i\n", __func__, task_irq);
+		ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED, "ata task", priv);
+		if (ret)
+			printk(KERN_ALERT "%s: request_irq failed with: %i\n", __func__, ret);
+	}
+
 	/* Init the hw */
 	rv = mpc52xx_ata_hw_init(priv);
 	if (rv) {
Index: work-powerpc.git/include/linux/libata.h
===================================================================
--- work-powerpc.git.orig/include/linux/libata.h
+++ work-powerpc.git/include/linux/libata.h
@@ -51,7 +51,7 @@
  * compile-time options: to be removed as soon as all the drivers are
  * converted to the new debugging mechanism
  */
-#undef ATA_DEBUG		/* debugging output */
+#define ATA_DEBUG		/* debugging output */
 #undef ATA_VERBOSE_DEBUG	/* yet more debugging output */
 #undef ATA_IRQ_TRAP		/* define to ack screaming irqs */
 #undef ATA_NDEBUG		/* define to disable quick runtime checks */