diff options
Diffstat (limited to 'target/linux/coldfire/patches/013-m5445x_ata.patch')
-rw-r--r-- | target/linux/coldfire/patches/013-m5445x_ata.patch | 1079 |
1 files changed, 0 insertions, 1079 deletions
diff --git a/target/linux/coldfire/patches/013-m5445x_ata.patch b/target/linux/coldfire/patches/013-m5445x_ata.patch deleted file mode 100644 index 0f269c15ec..0000000000 --- a/target/linux/coldfire/patches/013-m5445x_ata.patch +++ /dev/null @@ -1,1079 +0,0 @@ -From c9e68ea1a541b9762ec0b656509aef3cdd75e035 Mon Sep 17 00:00:00 2001 -From: Kurt Mahan <kmahan@freescale.com> -Date: Mon, 19 Nov 2007 12:01:34 -0700 -Subject: [PATCH] Add support for the M5445x ATA controller. - -LTIBName: m5445x-ata -Signed-off-by: Kurt Mahan <kmahan@freescale.com> ---- - arch/m68k/coldfire/Makefile | 1 + - arch/m68k/coldfire/head.S | 5 + - arch/m68k/coldfire/mcf5445x-devices.c | 125 +++++ - drivers/ata/Kconfig | 11 +- - drivers/ata/Makefile | 2 +- - drivers/ata/pata_fsl.c | 829 +++++++++++++++++++++++++++++++++ - include/asm-m68k/pci.h | 10 +- - include/linux/fsl_devices.h | 11 + - 8 files changed, 990 insertions(+), 4 deletions(-) - create mode 100644 arch/m68k/coldfire/mcf5445x-devices.c - create mode 100644 drivers/ata/pata_fsl.c - ---- a/arch/m68k/coldfire/Makefile -+++ b/arch/m68k/coldfire/Makefile -@@ -9,3 +9,4 @@ ifneq ($(strip $(CONFIG_USB) $(CONFIG_US - endif - - obj-$(CONFIG_PCI) += pci.o mcf5445x-pci.o iomap.o -+obj-$(CONFIG_M54455) += mcf5445x-devices.o ---- a/arch/m68k/coldfire/head.S -+++ b/arch/m68k/coldfire/head.S -@@ -374,6 +374,11 @@ ENTRY(__start) - MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ - 0, MMUDR_LK, %d0 - -+ /* Map ATA registers -- sacrifice a data TLB due to the hw design */ -+ mmu_map (0x90000000), (0x90000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ - /* Do unity mapping to enable the MMU. Map first 16 MB in place as - code (delete TLBs after MMU is enabled and we are executing in high - memory). */ ---- /dev/null -+++ b/arch/m68k/coldfire/mcf5445x-devices.c -@@ -0,0 +1,125 @@ -+/* -+ * arch/m68k/coldfire/mcf5445x-devices.c -+ * -+ * Coldfire M5445x Platform Device Configuration -+ * -+ * Based on the Freescale MXC devices.c -+ * -+ * Copyright (c) 2007 Freescale Semiconductor, Inc. -+ * Kurt Mahan <kmahan@freescale.com> -+ */ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+ -+#include <asm/coldfire.h> -+#include <asm/mcfsim.h> -+ -+/* ATA Interrupt */ -+#define IRQ_ATA (64 + 64 + 54) -+ -+/* ATA Base */ -+#define BASE_IO_ATA 0x90000000 -+ -+#define ATA_IER MCF_REG08(BASE_IO_ATA+0x2c) /* int enable reg */ -+#define ATA_ICR MCF_REG08(BASE_IO_ATA+0x30) /* int clear reg */ -+ -+/* -+ * On-chip PATA -+ */ -+#if defined(CONFIG_PATA_FSL) || defined(CONFIG_PATA_FSL_MODULE) -+static int ata_init(struct platform_device *pdev) -+{ -+ /* clear ints */ -+ ATA_IER = 0x00; -+ ATA_ICR = 0xff; -+ -+ /* setup shared pins */ -+ MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC & MCF_GPIO_PAR_FEC_FEC1_MASK) | -+ MCF_GPIO_PAR_FEC_FEC1_ATA; -+ -+ MCF_GPIO_PAR_FECI2C = (MCF_GPIO_PAR_FECI2C & -+ (MCF_GPIO_PAR_FECI2C_MDC1_MASK & -+ MCF_GPIO_PAR_FECI2C_MDIO1_MASK)) | -+ MCF_GPIO_PAR_FECI2C_MDC1_ATA_DIOR | -+ MCF_GPIO_PAR_FECI2C_MDIO1_ATA_DIOW; -+ -+ MCF_GPIO_PAR_ATA = MCF_GPIO_PAR_ATA_BUFEN | -+ MCF_GPIO_PAR_ATA_CS1 | -+ MCF_GPIO_PAR_ATA_CS0 | -+ MCF_GPIO_PAR_ATA_DA2 | -+ MCF_GPIO_PAR_ATA_DA1 | -+ MCF_GPIO_PAR_ATA_DA0 | -+ MCF_GPIO_PAR_ATA_RESET_RESET | -+ MCF_GPIO_PAR_ATA_DMARQ_DMARQ | -+ MCF_GPIO_PAR_ATA_IORDY_IORDY; -+ -+ MCF_GPIO_PAR_PCI = (MCF_GPIO_PAR_PCI & -+ (MCF_GPIO_PAR_PCI_GNT3_MASK & -+ MCF_GPIO_PAR_PCI_REQ3_MASK)) | -+ MCF_GPIO_PAR_PCI_GNT3_ATA_DMACK | -+ MCF_GPIO_PAR_PCI_REQ3_ATA_INTRQ; -+ -+ return 0; -+} -+ -+static void ata_exit(void) -+{ -+ printk(KERN_INFO "** ata_exit\n"); -+} -+ -+static int ata_get_clk_rate(void) -+{ -+ return MCF_BUSCLK; -+} -+ -+static struct fsl_ata_platform_data ata_data = { -+ .init = ata_init, -+ .exit = ata_exit, -+ .get_clk_rate = ata_get_clk_rate, -+}; -+ -+static struct resource pata_fsl_resources[] = { -+ [0] = { /* I/O */ -+ .start = BASE_IO_ATA, -+ .end = BASE_IO_ATA + 0x000000d8, -+ .flags = IORESOURCE_MEM, -+ }, -+ [2] = { /* IRQ */ -+ .start = IRQ_ATA, -+ .end = IRQ_ATA, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device pata_fsl_device = { -+ .name = "pata_fsl", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(pata_fsl_resources), -+ .resource = pata_fsl_resources, -+ .dev = { -+ .platform_data = &ata_data, -+ .coherent_dma_mask = ~0, /* $$$ REVISIT */ -+ }, -+}; -+ -+static inline void mcf5445x_init_pata(void) -+{ -+ (void)platform_device_register(&pata_fsl_device); -+} -+#else -+static inline void mcf5445x_init_pata(void) -+{ -+} -+#endif -+ -+static int __init mcf5445x_init_devices(void) -+{ -+ printk(KERN_INFO "MCF5445x INIT_DEVICES\n"); -+ mcf5445x_init_pata(); -+ -+ return 0; -+} -+arch_initcall(mcf5445x_init_devices); ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -6,7 +6,7 @@ menuconfig ATA - tristate "Serial ATA (prod) and Parallel ATA (experimental) drivers" - depends on HAS_IOMEM - depends on BLOCK -- depends on !(M32R || M68K) || BROKEN -+ depends on !M32R || BROKEN - depends on !SUN4 || BROKEN - select SCSI - ---help--- -@@ -679,4 +679,13 @@ config PATA_BF54X - - If unsure, say N. - -+config PATA_FSL -+ tristate "Freescale on-chip PATA support" -+ depends on (ARCH_MX3 || ARCH_MX27 || PPC_512x || M54455) -+ help -+ On Freescale processors, say Y here if you wish to use the on-chip -+ ATA interface. -+ -+ If you are unsure, say N to this. -+ - endif # ATA ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -1,4 +1,3 @@ -- - obj-$(CONFIG_ATA) += libata.o - - obj-$(CONFIG_SATA_AHCI) += ahci.o -@@ -71,6 +70,7 @@ obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o - obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o - obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o - obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o -+obj-$(CONFIG_PATA_FSL) += pata_fsl.o - # Should be last but two libata driver - obj-$(CONFIG_PATA_ACPI) += pata_acpi.o - # Should be last but one libata driver ---- /dev/null -+++ b/drivers/ata/pata_fsl.c -@@ -0,0 +1,829 @@ -+/* -+ * Freescale integrated PATA driver -+ */ -+ -+/* -+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#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/dma.h> -+#endif -+ -+#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 -+ -+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; -+#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; -+}; -+ -+static void update_timing_config(struct fsl_ata_time_regs *tp, struct ata_host *host) -+{ -+ u32 *lp = (u32 *)tp; -+ struct pata_fsl_priv *priv = host->private_data; -+ u32 *ctlp = (u32 *)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 < 5; i++) { -+ __raw_writel(*lp, ctlp); -+ lp++; -+ ctlp++; -+ } -+ mb(); -+} -+ -+/*! -+ * 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 void dma_callback(void *arg, int error_status, unsigned int count) -+{ -+ struct ata_port *ap = arg; -+ struct pata_fsl_priv *priv = ap->host->private_data; -+ u8 *ata_regs = priv->fsl_ata_regs; -+ -+ 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); -+#endif -+ mb(); -+} -+ -+static void pata_fsl_bmdma_setup(struct ata_queued_cmd *qc) -+{ -+ int nr_sg = 0; -+ int chan; -+ int dma_mode = 0, dma_ultra; -+ u8 ata_control; -+ struct ata_port *ap = qc->ap; -+ struct pata_fsl_priv *priv = ap->host->private_data; -+ u8 *ata_regs = priv->fsl_ata_regs; -+ struct fsl_ata_platform_data *plat = ap->dev->platform_data; -+ struct scatterlist tmp[plat->max_sg], *tsg, *sg; -+ int err; -+ -+ DPRINTK("ENTER\n"); -+ -+ 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; -+ dma_mode = DMA_MODE_WRITE; -+ } else { -+ chan = priv->dma_rchan; -+ ata_control |= FSL_ATA_CTRL_FIFO_RCV_EN; -+ dma_mode = DMA_MODE_READ; -+ } -+#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(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. -+ */ -+ mxc_dma_callback_set(chan, dma_callback, (void *)ap); -+ -+ /* -+ * Copy the sg list to an array. -+ */ -+ tsg = tmp; -+ ata_for_each_sg(sg, qc) { -+ memcpy(tsg, sg, sizeof *sg); -+ tsg++; -+ nr_sg++; -+ } -+ -+ err = mxc_dma_sg_config(chan, tmp, nr_sg, 0, dma_mode); -+ if (err) { -+ printk(KERN_ERR "pata_fsl_bmdma_setup: error %d\n", err); -+ } -+ 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; -+ int err; -+ -+ /* -+ * Start the channel. -+ */ -+ chan = qc->dma_dir == DMA_TO_DEVICE ? priv->dma_wchan : priv->dma_rchan; -+ -+ priv->dma_done = 0; -+ -+ err = mxc_dma_enable(chan); -+ if (err) { -+ printk(KERN_ERR "%s: : error %d\n", __func__, err); -+ } -+ -+ ap->ops->exec_command(ap, &qc->tf); -+} -+ -+static void pata_fsl_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ -+ /* do a dummy read as in ata_bmdma_stop */ -+ ata_altstatus(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 = mxc_dma_request(MXC_DMA_ATA_RX, "MXC 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 = mxc_dma_request(MXC_DMA_ATA_TX, "MXC 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; -+ mxc_dma_free(priv->dma_rchan); -+ mxc_dma_free(priv->dma_wchan); -+ kfree(priv); -+} -+#endif /* CONFIG_FSL_PATA_USE_DMA */ -+ -+static u8 pata_fsl_irq_ack(struct ata_port *ap, unsigned int chk_drq) -+{ -+ unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; -+ u8 status; -+ -+ status = ata_busy_wait(ap, bits, 1000); -+ if (status & bits) -+ if (ata_msg_err(ap)) -+ printk(KERN_ERR "abnormal status 0x%X\n", status); -+ -+ return status; -+} -+ -+static void ata_dummy_noret(struct ata_port *ap) { return; } -+ -+static struct scsi_host_template pata_fsl_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+#ifdef CONFIG_FSL_PATA_USE_DMA -+ .dma_boundary = FSL_ATA_MAX_SG_LEN, -+#endif -+ .slave_configure = ata_scsi_slave_config, -+ .slave_destroy = ata_scsi_slave_destroy, -+ .bios_param = ata_std_bios_param, -+}; -+ -+static struct ata_port_operations pata_fsl_port_ops = { -+ .set_piomode = pata_fsl_set_piomode, -+#ifdef CONFIG_FSL_PATA_USE_DMA -+ .set_dmamode = pata_fsl_set_dmamode, -+#endif -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .freeze = ata_bmdma_freeze, -+ .thaw = ata_bmdma_thaw, -+ .error_handler = ata_bmdma_error_handler, -+ .post_internal_cmd = ata_bmdma_post_internal_cmd, -+ .cable_detect = ata_cable_unknown, -+ -+#ifdef CONFIG_FSL_PATA_USE_DMA -+ .bmdma_setup = pata_fsl_bmdma_setup, -+ .bmdma_start = pata_fsl_bmdma_start, -+#endif -+ -+ .qc_prep = ata_noop_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ -+ .data_xfer = ata_data_xfer_noirq, -+ -+ .irq_clear = ata_dummy_noret, -+ .irq_on = ata_irq_on, -+ .irq_ack = pata_fsl_irq_ack, -+ -+ .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 = 0x7F; -+#ifdef CONFIG_FSL_PATA_USE_DMA -+ ap->mwdma_mask = 0x7F; -+ 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); -+ mb(); -+ -+ /* 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 -+ mb(); -+ -+ /* activate */ -+ ret = ata_host_activate(host, platform_get_irq(pdev, 0), ata_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 -+ mb(); -+ -+ 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 -+ mb(); -+ -+ 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 -+ mb(); -+ -+ /* 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 -+ mb(); -+ -+ 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); ---- a/include/asm-m68k/pci.h -+++ b/include/asm-m68k/pci.h -@@ -7,8 +7,14 @@ - #ifndef _ASM_M68K_PCI_H - #define _ASM_M68K_PCI_H - --#ifdef CONFIG_PCI -- -+#ifndef CONFIG_PCI -+/* -+ * The PCI address space does equal the physical memory -+ * address space. The networking and block device layers use -+ * this boolean for bounce buffer decisions. -+ */ -+#define PCI_DMA_BUS_IS_PHYS (1) -+#else - #include <asm-generic/pci-dma-compat.h> - - /* ---- a/include/linux/fsl_devices.h -+++ b/include/linux/fsl_devices.h -@@ -126,5 +126,16 @@ struct mpc8xx_pcmcia_ops { - int(*voltage_set)(int slot, int vcc, int vpp); - }; - -+struct fsl_ata_platform_data { -+#ifdef CONFIG_FSL_PATA_USE_DMA -+ int udma_mask; /* UDMA modes h/w can handle */ -+ int fifo_alarm; /* value for fifo_alarm reg */ -+ int max_sg; /* longest sglist h/w can handle */ -+#endif -+ int (*init)(struct platform_device *pdev); -+ void (*exit)(void); -+ int (*get_clk_rate)(void); -+}; -+ - #endif /* _FSL_DEVICE_H_ */ - #endif /* __KERNEL__ */ |