aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/coldfire/patches/037-Add-ColdFire-MCF54455-PATA-interface-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/coldfire/patches/037-Add-ColdFire-MCF54455-PATA-interface-support.patch')
-rw-r--r--target/linux/coldfire/patches/037-Add-ColdFire-MCF54455-PATA-interface-support.patch934
1 files changed, 0 insertions, 934 deletions
diff --git a/target/linux/coldfire/patches/037-Add-ColdFire-MCF54455-PATA-interface-support.patch b/target/linux/coldfire/patches/037-Add-ColdFire-MCF54455-PATA-interface-support.patch
deleted file mode 100644
index 730086eba1..0000000000
--- a/target/linux/coldfire/patches/037-Add-ColdFire-MCF54455-PATA-interface-support.patch
+++ /dev/null
@@ -1,934 +0,0 @@
-From 8e46c06091fd87904205a977be3c784e3ac61e95 Mon Sep 17 00:00:00 2001
-From: Jingchang Lu <b35083@freescale.com>
-Date: Thu, 4 Aug 2011 09:59:48 +0800
-Subject: [PATCH 37/52] Add ColdFire MCF54455 PATA interface support
-
-ColdFire MCF54455 parallel ATA controller support
-both uDMA and PIO mode, this driver implements all.
-
-Signed-off-by: Jingchang Lu <b35083@freescale.com>
----
- arch/m68k/include/asm/pata_fsl.h | 17 +
- drivers/ata/Kconfig | 23 +-
- drivers/ata/Makefile | 1 +
- drivers/ata/pata_fsl.c | 844 ++++++++++++++++++++++++++++++++++++++
- 4 files changed, 884 insertions(+), 1 deletions(-)
- create mode 100644 arch/m68k/include/asm/pata_fsl.h
- create mode 100644 drivers/ata/pata_fsl.c
-
---- /dev/null
-+++ b/arch/m68k/include/asm/pata_fsl.h
-@@ -0,0 +1,17 @@
-+/*
-+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive
-+ * for more details.
-+ */
-+
-+#ifndef _ASM_M68K_PATA_FSL_H
-+#define _ASM_M68K_PATA_FSL_H
-+
-+/* ATA mapped IO address translate function */
-+extern unsigned int io_ata_virt2phys(void *x);
-+extern void *io_ata_phys2virt(unsigned int x);
-+
-+
-+#endif
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -14,7 +14,7 @@ menuconfig ATA
- tristate "Serial ATA and Parallel ATA drivers"
- depends on HAS_IOMEM
- depends on BLOCK
-- depends on !(M32R || M68K) || BROKEN
-+ depends on !(M32R) || BROKEN
- select SCSI
- ---help---
- If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or
-@@ -687,6 +687,27 @@ config PATA_WINBOND
-
- If unsure, say N.
-
-+config PATA_FSL
-+ tristate "Freescale on-chip PATA support"
-+ depends on (ARCH_MX3 || ARCH_MX27 || PPC_512x || M54455)
-+ help
-+ Some Freescale processors SOC have parallel ATA controller,
-+ such as ColdFire MCF54455.
-+
-+ Say Y here if you wish to use the on-chip ATA interface.
-+
-+ If you are unsure, say N to this.
-+
-+config FSL_PATA_USE_DMA
-+ bool "Freescale PATA eDMA support"
-+ depends on PATA_FSL && COLDFIRE_EDMA
-+ default y
-+ help
-+ This option enables the uDMA support over PATA interface
-+ which can improve performance than PIO mode for read and write.
-+
-+ If unsure, say Y.
-+
- endif # ATA_BMDMA
-
- comment "PIO-only SFF controllers"
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -72,6 +72,7 @@ obj-$(CONFIG_PATA_TOSHIBA) += pata_picco
- obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
- obj-$(CONFIG_PATA_VIA) += pata_via.o
- obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
-+obj-$(CONFIG_PATA_FSL) += pata_fsl.o
-
- # SFF PIO only
- obj-$(CONFIG_PATA_AT32) += pata_at32.o
---- /dev/null
-+++ b/drivers/ata/pata_fsl.c
-@@ -0,0 +1,844 @@
-+/*
-+ * Freescale integrated PATA driver
-+ *
-+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
-+ *
-+ * Description:
-+ * This driver is for Coldfire MCF54455 on-chip ATA module.
-+ *
-+ * This is free software; you can redistribute it and/or modify it
-+ * under the GNU General Public License as published by the Free
-+ * Software Foundation; either version 2 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/blkdev.h>
-+#include <scsi/scsi_host.h>
-+#include <linux/ata.h>
-+#include <linux/libata.h>
-+#include <linux/platform_device.h>
-+#include <linux/fsl_devices.h>
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+#include <asm/mcf_edma.h>
-+#endif
-+#include <asm/pata_fsl.h>
-+
-+#define DRV_NAME "pata_fsl"
-+#define DRV_VERSION "1.0"
-+
-+#ifdef CONFIG_M54455
-+#define WRITE_ATA8(val, reg) \
-+ __raw_writeb(val, (ata_regs + reg));
-+#define WRITE_ATA16(val, reg) \
-+ __raw_writew(val, (ata_regs + reg));
-+#else
-+#define WRITE_ATA8(val, reg) \
-+ __raw_writel(val, (ata_regs + reg));
-+#define WRITE_ATA16(val, reg) \
-+ __raw_writel(val, (ata_regs + reg));
-+#endif
-+
-+#define MAX_FSL_SG 256 /* MCF_EDMA_TCD_PER_CHAN */
-+
-+struct pata_fsl_priv {
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ int ultra;
-+#endif
-+ u8 *fsl_ata_regs;
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ int dma_rchan;
-+ int dma_wchan;
-+ int dma_done;
-+ int dma_dir;
-+#if 0
-+ int nsg;
-+ struct fsl_edma_requestbuf reqbuf[MAX_FSL_SG];
-+#endif
-+#endif
-+};
-+
-+enum {
-+ /* various constants */
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ FSL_ATA_MAX_SG_LEN = 65534,
-+#endif
-+
-+ /* offsets to registers */
-+
-+ FSL_ATA_TIMING_REGS = 0x00,
-+ FSL_ATA_FIFO_FILL = 0x20,
-+ FSL_ATA_CONTROL = 0x24,
-+ FSL_ATA_INT_PEND = 0x28,
-+ FSL_ATA_INT_EN = 0x2C,
-+ FSL_ATA_INT_CLEAR = 0x30,
-+ FSL_ATA_FIFO_ALARM = 0x34,
-+ FSL_ATA_DRIVE_DATA = 0xA0,
-+ FSL_ATA_DRIVE_CONTROL = 0xD8,
-+
-+ /* bits within FSL_ATA_CONTROL */
-+
-+ FSL_ATA_CTRL_FIFO_RST_B = 0x80,
-+ FSL_ATA_CTRL_ATA_RST_B = 0x40,
-+ FSL_ATA_CTRL_FIFO_TX_EN = 0x20,
-+ FSL_ATA_CTRL_FIFO_RCV_EN = 0x10,
-+ FSL_ATA_CTRL_DMA_PENDING = 0x08,
-+ FSL_ATA_CTRL_DMA_ULTRA = 0x04,
-+ FSL_ATA_CTRL_DMA_WRITE = 0x02,
-+ FSL_ATA_CTRL_IORDY_EN = 0x01,
-+
-+ /* bits within the interrupt control registers */
-+
-+ FSL_ATA_INTR_ATA_INTRQ1 = 0x80,
-+ FSL_ATA_INTR_FIFO_UNDERFLOW = 0x40,
-+ FSL_ATA_INTR_FIFO_OVERFLOW = 0x20,
-+ FSL_ATA_INTR_CTRL_IDLE = 0x10,
-+ FSL_ATA_INTR_ATA_INTRQ2 = 0x08,
-+};
-+
-+/*
-+ * This structure contains the timing parameters for
-+ * ATA bus timing in the 5 PIO modes. The timings
-+ * are in nanoseconds, and are converted to clock
-+ * cycles before being stored in the ATA controller
-+ * timing registers.
-+ */
-+static struct {
-+ short t0, t1, t2_8, t2_16, t2i, t4, t9, tA;
-+} pio_specs[] = {
-+ [0] = {
-+ .t0 = 600, .t1 = 70, .t2_8 = 290, .t2_16 = 165, .t2i = 0,
-+ .t4 = 30, .t9 = 20, .tA = 50
-+ },
-+ [1] = {
-+ .t0 = 383, .t1 = 50, .t2_8 = 290, .t2_16 = 125, .t2i = 0,
-+ .t4 = 20, .t9 = 15, .tA = 50
-+ },
-+ [2] = {
-+ .t0 = 240, .t1 = 30, .t2_8 = 290, .t2_16 = 100, .t2i = 0,
-+ .t4 = 15, .t9 = 10, .tA = 50
-+ },
-+ [3] = {
-+ .t0 = 180, .t1 = 30, .t2_8 = 80, .t2_16 = 80, .t2i = 0,
-+ .t4 = 10, .t9 = 10, .tA = 50
-+ },
-+ [4] = {
-+ .t0 = 120, .t1 = 25, .t2_8 = 70, .t2_16 = 70, .t2i = 0,
-+ .t4 = 10, .t9 = 10, .tA = 50
-+ },
-+};
-+
-+#define NR_PIO_SPECS (sizeof pio_specs / sizeof pio_specs[0])
-+
-+/*
-+ * This structure contains the timing parameters for
-+ * ATA bus timing in the 3 MDMA modes. The timings
-+ * are in nanoseconds, and are converted to clock
-+ * cycles before being stored in the ATA controller
-+ * timing registers.
-+ */
-+static struct {
-+ short t0M, tD, tH, tJ, tKW, tM, tN, tJNH;
-+} mdma_specs[] = {
-+ [0] = {
-+ .t0M = 480, .tD = 215, .tH = 20, .tJ = 20, .tKW = 215,
-+ .tM = 50, .tN = 15, .tJNH = 20
-+ },
-+ [1] = {
-+ .t0M = 150, .tD = 80, .tH = 15, .tJ = 5, .tKW = 50,
-+ .tM = 30, .tN = 10, .tJNH = 15
-+ },
-+ [2] = {
-+ .t0M = 120, .tD = 70, .tH = 10, .tJ = 5, .tKW = 25,
-+ .tM = 25, .tN = 10, .tJNH = 10
-+ },
-+};
-+
-+#define NR_MDMA_SPECS (sizeof mdma_specs / sizeof mdma_specs[0])
-+
-+/*
-+ * This structure contains the timing parameters for
-+ * ATA bus timing in the 6 UDMA modes. The timings
-+ * are in nanoseconds, and are converted to clock
-+ * cycles before being stored in the ATA controller
-+ * timing registers.
-+ */
-+static struct {
-+ short t2CYC, tCYC, tDS, tDH, tDVS, tDVH, tCVS, tCVH, tFS_min, tLI_max,
-+ tMLI, tAZ, tZAH, tENV_min, tSR, tRFS, tRP, tACK, tSS, tDZFS;
-+} udma_specs[] = {
-+ [0] = {
-+ .t2CYC = 235, .tCYC = 114, .tDS = 15, .tDH = 5, .tDVS = 70,
-+ .tDVH = 6, .tCVS = 70, .tCVH = 6, .tFS_min = 0,
-+ .tLI_max = 100, .tMLI = 20, .tAZ = 10, .tZAH = 20,
-+ .tENV_min = 20, .tSR = 50, .tRFS = 75, .tRP = 160,
-+ .tACK = 20, .tSS = 50, .tDZFS = 80
-+ },
-+ [1] = {
-+ .t2CYC = 156, .tCYC = 75, .tDS = 10, .tDH = 5, .tDVS = 48,
-+ .tDVH = 6, .tCVS = 48, .tCVH = 6, .tFS_min = 0,
-+ .tLI_max = 100, .tMLI = 20, .tAZ = 10, .tZAH = 20,
-+ .tENV_min = 20, .tSR = 30, .tRFS = 70, .tRP = 125,
-+ .tACK = 20, .tSS = 50, .tDZFS = 63
-+ },
-+ [2] = {
-+ .t2CYC = 117, .tCYC = 55, .tDS = 7, .tDH = 5, .tDVS = 34,
-+ .tDVH = 6, .tCVS = 34, .tCVH = 6, .tFS_min = 0,
-+ .tLI_max = 100, .tMLI = 20, .tAZ = 10, .tZAH = 20,
-+ .tENV_min = 20, .tSR = 20, .tRFS = 60, .tRP = 100,
-+ .tACK = 20, .tSS = 50, .tDZFS = 47
-+ },
-+ [3] = {
-+ .t2CYC = 86, .tCYC = 39, .tDS = 7, .tDH = 5, .tDVS = 20,
-+ .tDVH = 6, .tCVS = 20, .tCVH = 6, .tFS_min = 0,
-+ .tLI_max = 100, .tMLI = 20, .tAZ = 10, .tZAH = 20,
-+ .tENV_min = 20, .tSR = 20, .tRFS = 60, .tRP = 100,
-+ .tACK = 20, .tSS = 50, .tDZFS = 35
-+ },
-+ [4] = {
-+ .t2CYC = 57, .tCYC = 25, .tDS = 5, .tDH = 5, .tDVS = 7,
-+ .tDVH = 6, .tCVS = 7, .tCVH = 6, .tFS_min = 0,
-+ .tLI_max = 100, .tMLI = 20, .tAZ = 10, .tZAH = 20,
-+ .tENV_min = 20, .tSR = 50, .tRFS = 60, .tRP = 100,
-+ .tACK = 20, .tSS = 50, .tDZFS = 25
-+ },
-+ [5] = {
-+ .t2CYC = 38, .tCYC = 17, .tDS = 4, .tDH = 5, .tDVS = 5,
-+ .tDVH = 6, .tCVS = 10, .tCVH = 10, .tFS_min = 0,
-+ .tLI_max = 75, .tMLI = 20, .tAZ = 10, .tZAH = 20,
-+ .tENV_min = 20, .tSR = 20, .tRFS = 50, .tRP = 85,
-+ .tACK = 20, .tSS = 50, .tDZFS = 40
-+ },
-+};
-+
-+#define NR_UDMA_SPECS (sizeof udma_specs / sizeof udma_specs[0])
-+
-+struct fsl_ata_time_regs {
-+ u8 time_off, time_on, time_1, time_2w;
-+ u8 time_2r, time_ax, time_pio_rdx, time_4;
-+ u8 time_9, time_m, time_jn, time_d;
-+ u8 time_k, time_ack, time_env, time_rpx;
-+ u8 time_zah, time_mlix, time_dvh, time_dzfs;
-+ u8 time_dvs, time_cvh, time_ss, time_cyc;
-+} __packed;
-+
-+
-+static void update_timing_config(struct fsl_ata_time_regs *tp,
-+ struct ata_host *host)
-+{
-+ u32 __iomem *lp = (u32 __iomem *)tp;
-+ struct pata_fsl_priv *priv = host->private_data;
-+ u32 __iomem *ctlp = (u32 __iomem *)priv->fsl_ata_regs;
-+ int i;
-+
-+ /*
-+ * JKM - this could have endianess issues on BE depending
-+ * on how the controller is glued to the bus -- probably
-+ * should rewrite this to write byte at a time.
-+ */
-+ for (i = 0; i < 6; i++) {
-+ __raw_writel(*lp, ctlp);
-+ lp++;
-+ ctlp++;
-+ }
-+}
-+
-+/*!
-+ * Calculate values for the ATA bus timing registers and store
-+ * them into the hardware.
-+ *
-+ * @param xfer_mode specifies XFER xfer_mode
-+ * @param pdev specifies platform_device
-+ *
-+ * @return EINVAL speed out of range, or illegal mode
-+ */
-+static int set_ata_bus_timing(u8 xfer_mode, struct platform_device *pdev)
-+{
-+ struct fsl_ata_platform_data *plat = (struct fsl_ata_platform_data *)
-+ pdev->dev.platform_data;
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+
-+ /* get the bus clock cycle time, in ns */
-+ int T = 1 * 1000 * 1000 * 1000 / plat->get_clk_rate();
-+ struct fsl_ata_time_regs tr = {0};
-+ DPRINTK("clk_rate = %d T = %d\n", plat->get_clk_rate(), T);
-+
-+ /*
-+ * every mode gets the same t_off and t_on
-+ */
-+ tr.time_off = 3;
-+ tr.time_on = 3;
-+
-+ if (xfer_mode >= XFER_UDMA_0) {
-+ int speed = xfer_mode - XFER_UDMA_0;
-+ if (speed >= NR_UDMA_SPECS)
-+ return -EINVAL;
-+
-+ tr.time_ack = (udma_specs[speed].tACK + T) / T;
-+ tr.time_env = (udma_specs[speed].tENV_min + T) / T;
-+ tr.time_rpx = (udma_specs[speed].tRP + T) / T + 2;
-+
-+ tr.time_zah = (udma_specs[speed].tZAH + T) / T;
-+ tr.time_mlix = (udma_specs[speed].tMLI + T) / T;
-+ tr.time_dvh = (udma_specs[speed].tDVH + T) / T + 1;
-+ tr.time_dzfs = (udma_specs[speed].tDZFS + T) / T;
-+
-+ tr.time_dvs = (udma_specs[speed].tDVS + T) / T;
-+ tr.time_cvh = (udma_specs[speed].tCVH + T) / T;
-+ tr.time_ss = (udma_specs[speed].tSS + T) / T;
-+ tr.time_cyc = (udma_specs[speed].tCYC + T) / T;
-+ } else if (xfer_mode >= XFER_MW_DMA_0) {
-+ int speed = xfer_mode - XFER_MW_DMA_0;
-+ if (speed >= NR_MDMA_SPECS)
-+ return -EINVAL;
-+
-+ tr.time_m = (mdma_specs[speed].tM + T) / T;
-+ tr.time_jn = (mdma_specs[speed].tJNH + T) / T;
-+ tr.time_d = (mdma_specs[speed].tD + T) / T;
-+
-+ tr.time_k = (mdma_specs[speed].tKW + T) / T;
-+ } else {
-+ int speed = xfer_mode - XFER_PIO_0;
-+ if (speed >= NR_PIO_SPECS)
-+ return -EINVAL;
-+
-+ tr.time_1 = (pio_specs[speed].t1 + T) / T;
-+ tr.time_2w = (pio_specs[speed].t2_8 + T) / T;
-+
-+ tr.time_2r = (pio_specs[speed].t2_8 + T) / T;
-+ tr.time_ax = (pio_specs[speed].tA + T) / T + 2;
-+ tr.time_pio_rdx = 1;
-+ tr.time_4 = (pio_specs[speed].t4 + T) / T;
-+
-+ tr.time_9 = (pio_specs[speed].t9 + T) / T;
-+ }
-+
-+ update_timing_config(&tr, host);
-+
-+ return 0;
-+}
-+
-+static void pata_fsl_set_piomode(struct ata_port *ap, struct ata_device *adev)
-+{
-+ set_ata_bus_timing(adev->pio_mode, to_platform_device(ap->dev));
-+}
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+static void pata_fsl_set_dmamode(struct ata_port *ap, struct ata_device *adev)
-+{
-+ struct pata_fsl_priv *priv = ap->host->private_data;
-+
-+ priv->ultra = adev->dma_mode >= XFER_UDMA_0;
-+
-+ set_ata_bus_timing(adev->dma_mode, to_platform_device(ap->dev));
-+}
-+#endif
-+
-+static int pata_fsl_port_start(struct ata_port *ap)
-+{
-+ return 0;
-+}
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+
-+static irqreturn_t dma_callback(int channel, void *arg)
-+{
-+ struct ata_port *ap = arg;
-+ struct pata_fsl_priv *priv = ap->host->private_data;
-+ u8 __iomem *ata_regs = priv->fsl_ata_regs;
-+
-+ mcf_edma_stop_transfer(channel);
-+ priv->dma_done = 1;
-+ /*
-+ * DMA is finished, so unmask INTRQ from the drive to allow the
-+ * normal ISR to fire.
-+ */
-+#if 0
-+ __raw_writel(FSL_ATA_INTR_ATA_INTRQ2, ata_regs + FSL_ATA_INT_EN);
-+#else
-+ WRITE_ATA8(FSL_ATA_INTR_ATA_INTRQ2, FSL_ATA_INT_EN);
-+ WRITE_ATA8(FSL_ATA_CTRL_ATA_RST_B, FSL_ATA_CONTROL);
-+#endif
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static void pata_fsl_bmdma_setup(struct ata_queued_cmd *qc)
-+{
-+ int chan;
-+ int dma_ultra;
-+ u8 ata_control;
-+ struct ata_port *ap = qc->ap;
-+ struct pata_fsl_priv *priv = ap->host->private_data;
-+ u8 __iomem *ata_regs = priv->fsl_ata_regs;
-+#if 0
-+ struct scatterlist *sg;
-+ struct fsl_edma_requestbuf *pbuf;
-+ unsigned int si;
-+#endif
-+ DPRINTK("ENTER\n");
-+
-+ /* reset the ATA FIFO first */
-+ /*
-+ WRITE_ATA8(FSL_ATA_CTRL_ATA_RST_B,FSL_ATA_CONTROL);
-+ */
-+ priv->dma_dir = qc->dma_dir;
-+
-+ /*
-+ * Configure the on-chip ATA interface hardware.
-+ */
-+ dma_ultra = priv->ultra ?
-+ FSL_ATA_CTRL_DMA_ULTRA : 0;
-+
-+ ata_control = FSL_ATA_CTRL_FIFO_RST_B |
-+ FSL_ATA_CTRL_ATA_RST_B |
-+ FSL_ATA_CTRL_DMA_PENDING |
-+ dma_ultra;
-+
-+ if (qc->dma_dir == DMA_TO_DEVICE) {
-+ chan = priv->dma_wchan;
-+ ata_control |= FSL_ATA_CTRL_FIFO_TX_EN |
-+ FSL_ATA_CTRL_DMA_WRITE;
-+ } else {
-+ chan = priv->dma_rchan;
-+ ata_control |= FSL_ATA_CTRL_FIFO_RCV_EN;
-+ }
-+#if 0
-+ __raw_writel(ata_control, ata_regs + FSL_ATA_CONTROL);
-+ __raw_writel(plat->fifo_alarm, ata_regs + FSL_ATA_FIFO_ALARM);
-+ __raw_writel(FSL_ATA_INTR_ATA_INTRQ1, ata_regs + FSL_ATA_INT_EN);
-+#else
-+ WRITE_ATA8(ata_control, FSL_ATA_CONTROL);
-+ WRITE_ATA8(16/*plat->fifo_alarm*/, FSL_ATA_FIFO_ALARM);
-+ WRITE_ATA8(FSL_ATA_INTR_ATA_INTRQ1, FSL_ATA_INT_EN);
-+#endif
-+ /*mb();*/
-+
-+ /*
-+ * Set up the DMA completion callback.
-+ */
-+ /*
-+ * Copy the sg list to an array.
-+ */
-+#if 0
-+ priv->nsg = 0;
-+ pbuf = priv->reqbuf;
-+
-+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
-+
-+ /*dma_map_sg(NULL, sg, 1, priv->dma_dir); */
-+
-+ if (priv->dma_dir == DMA_TO_DEVICE) { /* WRITE */
-+ pbuf->saddr = sg->dma_address;
-+ pbuf->daddr = (dma_addr_t)(priv->fsl_ata_regs + 0x18);
-+ pbuf->soff = 4;
-+ pbuf->doff = 0;
-+ } else { /* Read */
-+ pbuf->daddr = sg->dma_address;
-+ pbuf->saddr = (dma_addr_t)(priv->fsl_ata_regs + 0x18);
-+ pbuf->doff = 4;
-+ pbuf->soff = 0;
-+ }
-+ pbuf->attr = MCF_EDMA_TCD_ATTR_SSIZE_32BIT
-+ |MCF_EDMA_TCD_ATTR_DSIZE_32BIT;
-+ pbuf->minor_loop = 16*4; /* 16 longwords per request*/
-+ pbuf->len = sg_dma_len(sg);
-+
-+ pbuf++;
-+ priv->nsg++;
-+ }
-+
-+ BUG_ON(*(unsigned char *)(ata_regs + FSL_ATA_FIFO_FILL));
-+ mcf_edma_sg_config(chan, priv->reqbuf, priv->nsg);
-+#else
-+ if (priv->dma_dir == DMA_TO_DEVICE) {
-+ mcf_edma_sglist_config(chan, qc->sg, qc->n_elem, priv->dma_dir,
-+ (dma_addr_t)
-+ ((io_ata_virt2phys((void *)priv->fsl_ata_regs)) + 0x18),
-+ MCF_EDMA_TCD_ATTR_SSIZE_32BIT
-+ | MCF_EDMA_TCD_ATTR_DSIZE_32BIT,
-+ 4, 0, 8*4);
-+ } else {
-+
-+ mcf_edma_sglist_config(chan, qc->sg, qc->n_elem, priv->dma_dir,
-+ (dma_addr_t)
-+ ((io_ata_virt2phys((void *)priv->fsl_ata_regs)) + 0x18),
-+ MCF_EDMA_TCD_ATTR_SSIZE_32BIT
-+ | MCF_EDMA_TCD_ATTR_DSIZE_32BIT,
-+ 0, 4, 8*4);
-+ }
-+
-+#endif
-+ priv->dma_done = 0;
-+
-+ DPRINTK("EXIT\n");
-+
-+}
-+
-+static void pata_fsl_bmdma_start(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+ struct pata_fsl_priv *priv = ap->host->private_data;
-+ int chan;
-+
-+ /*
-+ * Start the channel.
-+ */
-+ chan = qc->dma_dir == DMA_TO_DEVICE ? priv->dma_wchan : priv->dma_rchan;
-+
-+ mcf_edma_enable_transfer(chan);
-+
-+ ap->ops->sff_exec_command(ap, &qc->tf);
-+}
-+
-+static void pata_fsl_bmdma_stop(struct ata_queued_cmd *qc)
-+{
-+ struct ata_port *ap = qc->ap;
-+/*
-+ int chan;
-+
-+ chan = qc->dma_dir == DMA_TO_DEVICE ? priv->dma_wchan : priv->dma_rchan;
-+ mcf_edma_stop_transfer(chan);
-+*/
-+/* do a dummy read as in ata_bmdma_stop */
-+ ata_sff_dma_pause(ap);
-+}
-+
-+static u8 pata_fsl_bmdma_status(struct ata_port *ap)
-+{
-+ struct pata_fsl_priv *priv = ap->host->private_data;
-+
-+ return priv->dma_done ? ATA_DMA_INTR : 0;
-+}
-+
-+static void pata_fsl_dma_init(struct ata_port *ap)
-+{
-+ struct pata_fsl_priv *priv = ap->host->private_data;
-+
-+ priv->dma_rchan = -1;
-+ priv->dma_wchan = -1;
-+
-+ priv->dma_rchan = mcf_edma_request_channel(MCF_EDMA_CHAN_ATA_RX,
-+ dma_callback,
-+ NULL, 0x6,
-+ (void *)ap,
-+ NULL,
-+ "MCF ATA RX");
-+ if (priv->dma_rchan < 0) {
-+ dev_printk(KERN_ERR, ap->dev, "couldn't get RX DMA channel\n");
-+ goto err_out;
-+ }
-+
-+ priv->dma_wchan = mcf_edma_request_channel(MCF_EDMA_CHAN_ATA_TX,
-+ dma_callback,
-+ NULL, 0x6,
-+ (void *)ap,
-+ NULL,
-+ "MCF ATA TX");
-+ if (priv->dma_wchan < 0) {
-+ dev_printk(KERN_ERR, ap->dev, "couldn't get TX DMA channel\n");
-+ goto err_out;
-+ }
-+
-+ dev_printk(KERN_ERR, ap->dev, "rchan=%d wchan=%d\n", priv->dma_rchan,
-+ priv->dma_wchan);
-+ return;
-+
-+err_out:
-+ ap->mwdma_mask = 0;
-+ ap->udma_mask = 0;
-+ mcf_edma_free_channel(priv->dma_rchan, ap);
-+ mcf_edma_free_channel(priv->dma_wchan, ap);
-+ kfree(priv);
-+}
-+#endif /* CONFIG_FSL_PATA_USE_DMA */
-+
-+static void ata_dummy_noret(struct ata_port *ap) { return; }
-+
-+static struct scsi_host_template pata_fsl_sht = {
-+ ATA_BMDMA_SHT(DRV_NAME),
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ .sg_tablesize = MAX_FSL_SG,
-+ .dma_boundary = ATA_DMA_BOUNDARY,
-+#endif
-+};
-+
-+static struct ata_port_operations pata_fsl_port_ops = {
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ .inherits = &ata_bmdma_port_ops,
-+#else
-+ .inherits = &ata_sff_port_ops,
-+#endif
-+ .set_piomode = pata_fsl_set_piomode,
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ .set_dmamode = pata_fsl_set_dmamode,
-+#endif
-+ .cable_detect = ata_cable_40wire,
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ .bmdma_setup = pata_fsl_bmdma_setup,
-+ .bmdma_start = pata_fsl_bmdma_start,
-+#endif
-+
-+ .sff_data_xfer = ata_sff_data_xfer_noirq,
-+ .qc_prep = ata_noop_qc_prep,
-+
-+ .port_start = pata_fsl_port_start,
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ .bmdma_stop = pata_fsl_bmdma_stop,
-+ .bmdma_status = pata_fsl_bmdma_status,
-+#endif
-+};
-+
-+static void fsl_setup_port(struct ata_ioports *ioaddr)
-+{
-+ unsigned int shift = 2;
-+
-+ ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift);
-+ ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift);
-+ ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
-+ ioaddr->nsect_addr = ioaddr->cmd_addr + (ATA_REG_NSECT << shift);
-+ ioaddr->lbal_addr = ioaddr->cmd_addr + (ATA_REG_LBAL << shift);
-+ ioaddr->lbam_addr = ioaddr->cmd_addr + (ATA_REG_LBAM << shift);
-+ ioaddr->lbah_addr = ioaddr->cmd_addr + (ATA_REG_LBAH << shift);
-+ ioaddr->device_addr = ioaddr->cmd_addr + (ATA_REG_DEVICE << shift);
-+ ioaddr->status_addr = ioaddr->cmd_addr + (ATA_REG_STATUS << shift);
-+ ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << shift);
-+}
-+
-+/**
-+ * pata_fsl_probe - attach a platform interface
-+ * @pdev: platform device
-+ *
-+ * Register a platform bus integrated ATA host controller
-+ *
-+ * The 3 platform device resources are used as follows:
-+ *
-+ * - I/O Base (IORESOURCE_MEM) virt. addr. of ATA controller regs
-+ * - CTL Base (IORESOURCE_MEM) unused
-+ * - IRQ (IORESOURCE_IRQ) platform IRQ assigned to ATA
-+ *
-+ */
-+static int __devinit pata_fsl_probe(struct platform_device *pdev)
-+{
-+ struct resource *io_res;
-+ struct ata_host *host;
-+ struct ata_port *ap;
-+ struct fsl_ata_platform_data *plat = (struct fsl_ata_platform_data *)
-+ pdev->dev.platform_data;
-+ struct pata_fsl_priv *priv;
-+ u8 *ata_regs;
-+ int ret;
-+
-+ DPRINTK("ENTER\n");
-+ /*
-+ * Get an ata_host structure for this device
-+ */
-+ host = ata_host_alloc(&pdev->dev, 1);
-+ if (!host)
-+ return -ENOMEM;
-+ ap = host->ports[0];
-+ /*
-+ * Allocate private data
-+ */
-+ priv = kzalloc(sizeof(struct pata_fsl_priv), GFP_KERNEL);
-+ if (priv == NULL) {
-+ /* free(host); */
-+ return -ENOMEM;
-+ }
-+ host->private_data = priv;
-+
-+ /*
-+ * Set up resources
-+ */
-+ if (unlikely(pdev->num_resources != 3)) {
-+ dev_err(&pdev->dev, "invalid number of resources\n");
-+ return -EINVAL;
-+ }
-+
-+ io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ ata_regs = (u8 *)io_res->start;
-+ priv->fsl_ata_regs = ata_regs;
-+ ap->ioaddr.cmd_addr = (void *)(ata_regs + FSL_ATA_DRIVE_DATA);
-+ ap->ioaddr.ctl_addr = (void *)(ata_regs + FSL_ATA_DRIVE_CONTROL);
-+ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
-+ ap->ops = &pata_fsl_port_ops;
-+ ap->pio_mask = 0x3F;
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ ap->mwdma_mask = 0x07;
-+ ap->udma_mask = 0x1F;
-+/* ap->udma_mask = plat->udma_mask; */
-+/* pata_fsl_sht.sg_tablesize = plat->max_sg; */
-+#else
-+ ap->mwdma_mask = 0x00;
-+ ap->udma_mask = 0x00;
-+#endif
-+ fsl_setup_port(&ap->ioaddr);
-+
-+ /*
-+ * Do platform-specific initialization (e.g. allocate pins,
-+ * turn on clock). After this call it is assumed that
-+ * plat->get_clk_rate() can be called to calculate
-+ * timing.
-+ */
-+ if (plat->init && plat->init(pdev)) {
-+ /* REVISIT: don't leak what ata_host_alloc() allocated */
-+ return -ENODEV;
-+ }
-+
-+ /* Deassert the reset bit to enable the interface */
-+ WRITE_ATA8(FSL_ATA_CTRL_ATA_RST_B, FSL_ATA_CONTROL);
-+
-+ /* Set initial timing and mode */
-+ set_ata_bus_timing(XFER_PIO_4, pdev);
-+
-+#ifdef CONFIG_FSL_PATA_USE_DMA
-+ /* get DMA ready */
-+ pata_fsl_dma_init(ap);
-+#endif
-+
-+ /*
-+ * Enable the ATA INTRQ interrupt from the bus, but
-+ * only allow the CPU to see it (INTRQ2) at this point.
-+ * INTRQ1, which goes to the DMA, will be enabled later.
-+ */
-+#if 0
-+ __raw_writel(FSL_ATA_INTR_ATA_INTRQ2, ata_regs + FSL_ATA_INT_EN);
-+#else
-+ WRITE_ATA8(FSL_ATA_INTR_ATA_INTRQ2, FSL_ATA_INT_EN);
-+#endif
-+
-+ /* activate */
-+ ret = ata_host_activate(host, platform_get_irq(pdev, 0),
-+ ata_sff_interrupt, 0, &pata_fsl_sht);
-+ DPRINTK("EXIT ret=%d\n", ret);
-+ return ret;
-+}
-+
-+/**
-+ * pata_fsl_remove - unplug a platform interface
-+ * @pdev: platform device
-+ *
-+ * A platform bus ATA device has been unplugged. Perform the needed
-+ * cleanup. Also called on module unload for any active devices.
-+ */
-+static int __devexit pata_fsl_remove(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct pata_fsl_priv *priv = host->private_data;
-+ struct fsl_ata_platform_data *plat = (struct fsl_ata_platform_data *)
-+ pdev->dev.platform_data;
-+ u8 *ata_regs = priv->fsl_ata_regs;
-+
-+#if 0
-+ __raw_writel(0, ata_regs + FSL_ATA_INT_EN); /* Disable interrupts */
-+#else
-+ WRITE_ATA8(0, FSL_ATA_INT_EN); /* Disable interrupts */
-+#endif
-+
-+ ata_host_detach(host);
-+
-+ if (plat->exit)
-+ plat->exit();
-+
-+ kfree(priv);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int pata_fsl_suspend(struct platform_device *pdev, pm_message_t state)
-+{
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ struct pata_fsl_priv *priv = host->private_data;
-+ struct fsl_ata_platform_data *plat = (struct fsl_ata_platform_data *)
-+ pdev->dev.platform_data;
-+ u8 *ata_regs = priv->fsl_ata_regs;
-+
-+ /* Disable interrupts. */
-+#if 0
-+ __raw_writel(0, ata_regs + FSL_ATA_INT_EN);
-+#else
-+ WRITE_ATA8(0, FSL_ATA_INT_EN);
-+#endif
-+
-+ if (plat->exit)
-+ plat->exit();
-+
-+ return 0;
-+}
-+
-+static int pata_fsl_resume(struct platform_device *pdev)
-+{
-+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
-+ struct pata_fsl_priv *priv = host->private_data;
-+ struct fsl_ata_platform_data *plat = (struct fsl_ata_platform_data *)
-+ pdev->dev.platform_data;
-+ u8 *ata_regs = priv->fsl_ata_regs;
-+
-+ if (plat->init && plat->init(pdev))
-+ return -ENODEV;
-+ /* Deassert the reset bit to enable the interface */
-+#if 0
-+ __raw_writel(FSL_ATA_CTRL_ATA_RST_B, ata_regs + FSL_ATA_CONTROL);
-+#else
-+ WRITE_ATA8(FSL_ATA_CTRL_ATA_RST_B, FSL_ATA_CONTROL);
-+#endif
-+
-+ /* Set initial timing and mode */
-+ set_ata_bus_timing(XFER_PIO_4, pdev);
-+
-+ /*
-+ * Enable hardware interrupts.
-+ */
-+#if 0
-+ __raw_writel(FSL_ATA_INTR_ATA_INTRQ2, ata_regs + FSL_ATA_INT_EN);
-+#else
-+ WRITE_ATA8(FSL_ATA_INTR_ATA_INTRQ2, FSL_ATA_INT_EN);
-+#endif
-+
-+ return 0;
-+}
-+#endif
-+
-+static struct platform_driver pata_fsl_driver = {
-+ .probe = pata_fsl_probe,
-+ .remove = __devexit_p(pata_fsl_remove),
-+#ifdef CONFIG_PM
-+ .suspend = pata_fsl_suspend,
-+ .resume = pata_fsl_resume,
-+#endif
-+ .driver = {
-+ .name = DRV_NAME,
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+static int __init pata_fsl_init(void)
-+{
-+ int ret;
-+
-+ DPRINTK("ENTER\n");
-+ ret = platform_driver_register(&pata_fsl_driver);
-+ DPRINTK("EXIT ret=%d\n", ret);
-+ return ret;
-+}
-+
-+static void __exit pata_fsl_exit(void)
-+{
-+ platform_driver_unregister(&pata_fsl_driver);
-+}
-+module_init(pata_fsl_init);
-+module_exit(pata_fsl_exit);
-+
-+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-+MODULE_DESCRIPTION("low-level driver for Freescale ATA");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);