diff options
| author | Rafal Prylowski <prylowski@metasoft.pl> | 2012-04-12 08:13:16 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2012-05-22 16:02:34 -0400 |
| commit | 2fff27512600f9ad91335577e485a8552edb0abf (patch) | |
| tree | eba9659d44dfef5d36c15e41cae91cb45e6a66f1 | |
| parent | d70e551c8e1ecb6f20422f8db6bfe6a0049edcb8 (diff) | |
PATA host controller driver for ep93xx
Add PATA host controller driver for ep93xx.
Signed-off-by: Rafal Prylowski <prylowski@metasoft.pl>
Cc: Joao Ramos <joao.ramos@inov.pt>
Cc: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ryan Mallon <rmallon@gmail.com>
Cc: Sergei Shtylyov <sshtylyov@mvista.com>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
| -rw-r--r-- | drivers/ata/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/ata/Makefile | 1 | ||||
| -rw-r--r-- | drivers/ata/pata_ep93xx.c | 1044 |
3 files changed, 1054 insertions, 0 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6bdedd7cca2c..2be8ef1d3093 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
| @@ -416,6 +416,15 @@ config PATA_EFAR | |||
| 416 | 416 | ||
| 417 | If unsure, say N. | 417 | If unsure, say N. |
| 418 | 418 | ||
| 419 | config PATA_EP93XX | ||
| 420 | tristate "Cirrus Logic EP93xx PATA support" | ||
| 421 | depends on ARCH_EP93XX | ||
| 422 | help | ||
| 423 | This option enables support for the PATA controller in | ||
| 424 | the Cirrus Logic EP9312 and EP9315 ARM CPU. | ||
| 425 | |||
| 426 | If unsure, say N. | ||
| 427 | |||
| 419 | config PATA_HPT366 | 428 | config PATA_HPT366 |
| 420 | tristate "HPT 366/368 PATA support" | 429 | tristate "HPT 366/368 PATA support" |
| 421 | depends on PCI | 430 | depends on PCI |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 6ece5b7231a3..a454a139b1d2 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
| @@ -43,6 +43,7 @@ obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o | |||
| 43 | obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o | 43 | obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o |
| 44 | obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o | 44 | obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o |
| 45 | obj-$(CONFIG_PATA_EFAR) += pata_efar.o | 45 | obj-$(CONFIG_PATA_EFAR) += pata_efar.o |
| 46 | obj-$(CONFIG_PATA_EP93XX) += pata_ep93xx.o | ||
| 46 | obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o | 47 | obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o |
| 47 | obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o | 48 | obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o |
| 48 | obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o | 49 | obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o |
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c new file mode 100644 index 000000000000..6ef2e3741f76 --- /dev/null +++ b/drivers/ata/pata_ep93xx.c | |||
| @@ -0,0 +1,1044 @@ | |||
| 1 | /* | ||
| 2 | * EP93XX PATA controller driver. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012, Metasoft s.c. | ||
| 5 | * Rafal Prylowski <prylowski@metasoft.pl> | ||
| 6 | * | ||
| 7 | * Based on pata_scc.c, pata_icside.c and on earlier version of EP93XX | ||
| 8 | * PATA driver by Lennert Buytenhek and Alessandro Zummo. | ||
| 9 | * Read/Write timings, resource management and other improvements | ||
| 10 | * from driver by Joao Ramos and Bartlomiej Zolnierkiewicz. | ||
| 11 | * DMA engine support based on spi-ep93xx.c by Mika Westerberg. | ||
| 12 | * | ||
| 13 | * Original copyrights: | ||
| 14 | * | ||
| 15 | * Support for Cirrus Logic's EP93xx (EP9312, EP9315) CPUs | ||
| 16 | * PATA host controller driver. | ||
| 17 | * | ||
| 18 | * Copyright (c) 2009, Bartlomiej Zolnierkiewicz | ||
| 19 | * | ||
| 20 | * Heavily based on the ep93xx-ide.c driver: | ||
| 21 | * | ||
| 22 | * Copyright (c) 2009, Joao Ramos <joao.ramos@inov.pt> | ||
| 23 | * INESC Inovacao (INOV) | ||
| 24 | * | ||
| 25 | * EP93XX PATA controller driver. | ||
| 26 | * Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org> | ||
| 27 | * | ||
| 28 | * An ATA driver for the Cirrus Logic EP93xx PATA controller. | ||
| 29 | * | ||
| 30 | * Based on an earlier version by Alessandro Zummo, which is: | ||
| 31 | * Copyright (C) 2006 Tower Technologies | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/kernel.h> | ||
| 35 | #include <linux/module.h> | ||
| 36 | #include <linux/init.h> | ||
| 37 | #include <linux/blkdev.h> | ||
| 38 | #include <scsi/scsi_host.h> | ||
| 39 | #include <linux/ata.h> | ||
| 40 | #include <linux/libata.h> | ||
| 41 | #include <linux/platform_device.h> | ||
| 42 | #include <linux/delay.h> | ||
| 43 | #include <linux/dmaengine.h> | ||
| 44 | #include <linux/ktime.h> | ||
| 45 | |||
| 46 | #include <mach/dma.h> | ||
| 47 | #include <mach/platform.h> | ||
| 48 | |||
| 49 | #define DRV_NAME "ep93xx-ide" | ||
| 50 | #define DRV_VERSION "1.0" | ||
| 51 | |||
| 52 | enum { | ||
| 53 | /* IDE Control Register */ | ||
| 54 | IDECTRL = 0x00, | ||
| 55 | IDECTRL_CS0N = (1 << 0), | ||
| 56 | IDECTRL_CS1N = (1 << 1), | ||
| 57 | IDECTRL_DIORN = (1 << 5), | ||
| 58 | IDECTRL_DIOWN = (1 << 6), | ||
| 59 | IDECTRL_INTRQ = (1 << 9), | ||
| 60 | IDECTRL_IORDY = (1 << 10), | ||
| 61 | /* | ||
| 62 | * the device IDE register to be accessed is selected through | ||
| 63 | * IDECTRL register's specific bitfields 'DA', 'CS1N' and 'CS0N': | ||
| 64 | * b4 b3 b2 b1 b0 | ||
| 65 | * A2 A1 A0 CS1N CS0N | ||
| 66 | * the values filled in this structure allows the value to be directly | ||
| 67 | * ORed to the IDECTRL register, hence giving directly the A[2:0] and | ||
| 68 | * CS1N/CS0N values for each IDE register. | ||
| 69 | * The values correspond to the transformation: | ||
| 70 | * ((real IDE address) << 2) | CS1N value << 1 | CS0N value | ||
| 71 | */ | ||
| 72 | IDECTRL_ADDR_CMD = 0 + 2, /* CS1 */ | ||
| 73 | IDECTRL_ADDR_DATA = (ATA_REG_DATA << 2) + 2, | ||
| 74 | IDECTRL_ADDR_ERROR = (ATA_REG_ERR << 2) + 2, | ||
| 75 | IDECTRL_ADDR_FEATURE = (ATA_REG_FEATURE << 2) + 2, | ||
| 76 | IDECTRL_ADDR_NSECT = (ATA_REG_NSECT << 2) + 2, | ||
| 77 | IDECTRL_ADDR_LBAL = (ATA_REG_LBAL << 2) + 2, | ||
| 78 | IDECTRL_ADDR_LBAM = (ATA_REG_LBAM << 2) + 2, | ||
| 79 | IDECTRL_ADDR_LBAH = (ATA_REG_LBAH << 2) + 2, | ||
| 80 | IDECTRL_ADDR_DEVICE = (ATA_REG_DEVICE << 2) + 2, | ||
| 81 | IDECTRL_ADDR_STATUS = (ATA_REG_STATUS << 2) + 2, | ||
| 82 | IDECTRL_ADDR_COMMAND = (ATA_REG_CMD << 2) + 2, | ||
| 83 | IDECTRL_ADDR_ALTSTATUS = (0x06 << 2) + 1, /* CS0 */ | ||
| 84 | IDECTRL_ADDR_CTL = (0x06 << 2) + 1, /* CS0 */ | ||
| 85 | |||
| 86 | /* IDE Configuration Register */ | ||
| 87 | IDECFG = 0x04, | ||
| 88 | IDECFG_IDEEN = (1 << 0), | ||
| 89 | IDECFG_PIO = (1 << 1), | ||
| 90 | IDECFG_MDMA = (1 << 2), | ||
| 91 | IDECFG_UDMA = (1 << 3), | ||
| 92 | IDECFG_MODE_SHIFT = 4, | ||
| 93 | IDECFG_MODE_MASK = (0xf << 4), | ||
| 94 | IDECFG_WST_SHIFT = 8, | ||
| 95 | IDECFG_WST_MASK = (0x3 << 8), | ||
| 96 | |||
| 97 | /* MDMA Operation Register */ | ||
| 98 | IDEMDMAOP = 0x08, | ||
| 99 | |||
| 100 | /* UDMA Operation Register */ | ||
| 101 | IDEUDMAOP = 0x0c, | ||
| 102 | IDEUDMAOP_UEN = (1 << 0), | ||
| 103 | IDEUDMAOP_RWOP = (1 << 1), | ||
| 104 | |||
| 105 | /* PIO/MDMA/UDMA Data Registers */ | ||
| 106 | IDEDATAOUT = 0x10, | ||
| 107 | IDEDATAIN = 0x14, | ||
| 108 | IDEMDMADATAOUT = 0x18, | ||
| 109 | IDEMDMADATAIN = 0x1c, | ||
| 110 | IDEUDMADATAOUT = 0x20, | ||
| 111 | IDEUDMADATAIN = 0x24, | ||
| 112 | |||
| 113 | /* UDMA Status Register */ | ||
| 114 | IDEUDMASTS = 0x28, | ||
| 115 | IDEUDMASTS_DMAIDE = (1 << 16), | ||
| 116 | IDEUDMASTS_INTIDE = (1 << 17), | ||
| 117 | IDEUDMASTS_SBUSY = (1 << 18), | ||
| 118 | IDEUDMASTS_NDO = (1 << 24), | ||
| 119 | IDEUDMASTS_NDI = (1 << 25), | ||
| 120 | IDEUDMASTS_N4X = (1 << 26), | ||
| 121 | |||
| 122 | /* UDMA Debug Status Register */ | ||
| 123 | IDEUDMADEBUG = 0x2c, | ||
| 124 | }; | ||
| 125 | |||
| 126 | struct ep93xx_pata_data { | ||
| 127 | const struct platform_device *pdev; | ||
| 128 | void __iomem *ide_base; | ||
| 129 | struct ata_timing t; | ||
| 130 | bool iordy; | ||
| 131 | |||
| 132 | unsigned long udma_in_phys; | ||
| 133 | unsigned long udma_out_phys; | ||
| 134 | |||
| 135 | struct dma_chan *dma_rx_channel; | ||
| 136 | struct ep93xx_dma_data dma_rx_data; | ||
| 137 | struct dma_chan *dma_tx_channel; | ||
| 138 | struct ep93xx_dma_data dma_tx_data; | ||
| 139 | }; | ||
| 140 | |||
| 141 | static void ep93xx_pata_clear_regs(void __iomem *base) | ||
| 142 | { | ||
| 143 | writel(IDECTRL_CS0N | IDECTRL_CS1N | IDECTRL_DIORN | | ||
| 144 | IDECTRL_DIOWN, base + IDECTRL); | ||
| 145 | |||
| 146 | writel(0, base + IDECFG); | ||
| 147 | writel(0, base + IDEMDMAOP); | ||
| 148 | writel(0, base + IDEUDMAOP); | ||
| 149 | writel(0, base + IDEDATAOUT); | ||
| 150 | writel(0, base + IDEDATAIN); | ||
| 151 | writel(0, base + IDEMDMADATAOUT); | ||
| 152 | writel(0, base + IDEMDMADATAIN); | ||
| 153 | writel(0, base + IDEUDMADATAOUT); | ||
| 154 | writel(0, base + IDEUDMADATAIN); | ||
| 155 | writel(0, base + IDEUDMADEBUG); | ||
| 156 | } | ||
| 157 | |||
| 158 | static bool ep93xx_pata_check_iordy(void __iomem *base) | ||
| 159 | { | ||
