/drivers/ata/pata_mpc52xx.c
C | 925 lines | 692 code | 156 blank | 77 comment | 54 complexity | ce1d982d61c3928ef9b06ad887ae0506 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * drivers/ata/pata_mpc52xx.c
- *
- * libata driver for the Freescale MPC52xx on-chip IDE interface
- *
- * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
- *
- * UDMA support based on patches by Freescale (Bernard Kuhn, John Rigby),
- * Domen Puncer and Tim Yamin.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/gfp.h>
- #include <linux/delay.h>
- #include <linux/libata.h>
- #include <linux/of_platform.h>
- #include <linux/types.h>
- #include <asm/cacheflush.h>
- #include <asm/prom.h>
- #include <asm/mpc52xx.h>
- #include <sysdev/bestcomm/bestcomm.h>
- #include <sysdev/bestcomm/bestcomm_priv.h>
- #include <sysdev/bestcomm/ata.h>
- #define DRV_NAME "mpc52xx_ata"
- /* Private structures used by the driver */
- 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 {
- unsigned int ipb_period;
- struct mpc52xx_ata __iomem *ata_regs;
- phys_addr_t ata_regs_pa;
- int ata_irq;
- struct mpc52xx_ata_timings timings[2];
- int csel;
- /* DMA */
- struct bcom_task *dmatsk;
- const struct udmaspec *udmaspec;
- const struct mdmaspec *mdmaspec;
- int mpc52xx_ata_dma_last_write;
- int waiting_for_dma;
- };
- /* ATAPI-4 PIO specs (in ns) */
- static const u16 ataspec_t0[5] = {600, 383, 240, 180, 120};
- static const u16 ataspec_t1[5] = { 70, 50, 30, 30, 25};
- static const u16 ataspec_t2_8[5] = {290, 290, 290, 80, 70};
- static const u16 ataspec_t2_16[5] = {165, 125, 100, 80, 70};
- static const u16 ataspec_t2i[5] = { 0, 0, 0, 70, 25};
- static const u16 ataspec_t4[5] = { 30, 20, 15, 10, 10};
- static const u16 ataspec_ta[5] = { 35, 35, 35, 35, 35};
- #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
- /* ======================================================================== */
- /* ATAPI-4 MDMA specs (in clocks) */
- struct mdmaspec {
- u8 t0M;
- u8 td;
- u8 th;
- u8 tj;
- u8 tkw;
- u8 tm;
- u8 tn;
- };
- static const struct mdmaspec mdmaspec66[3] = {
- { .t0M = 32, .td = 15, .th = 2, .tj = 2, .tkw = 15, .tm = 4, .tn = 1 },
- { .t0M = 10, .td = 6, .th = 1, .tj = 1, .tkw = 4, .tm = 2, .tn = 1 },
- { .t0M = 8, .td = 5, .th = 1, .tj = 1, .tkw = 2, .tm = 2, .tn = 1 },
- };
- static const struct mdmaspec mdmaspec132[3] = {
- { .t0M = 64, .td = 29, .th = 3, .tj = 3, .tkw = 29, .tm = 7, .tn = 2 },
- { .t0M = 20, .td = 11, .th = 2, .tj = 1, .tkw = 7, .tm = 4, .tn = 1 },
- { .t0M = 16, .td = 10, .th = 2, .tj = 1, .tkw = 4, .tm = 4, .tn = 1 },
- };
- /* ATAPI-4 UDMA specs (in clocks) */
- struct udmaspec {
- u8 tcyc;
- u8 t2cyc;
- u8 tds;
- u8 tdh;
- u8 tdvs;
- u8 tdvh;
- u8 tfs;
- u8 tli;
- u8 tmli;
- u8 taz;
- u8 tzah;
- u8 tenv;
- u8 tsr;
- u8 trfs;
- u8 trp;
- u8 tack;
- u8 tss;
- };
- static const struct udmaspec udmaspec66[6] = {
- { .tcyc = 8, .t2cyc = 16, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1,
- .tfs = 16, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 3, .trfs = 5, .trp = 11, .tack = 2, .tss = 4,
- },
- { .tcyc = 5, .t2cyc = 11, .tds = 1, .tdh = 1, .tdvs = 4, .tdvh = 1,
- .tfs = 14, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 2, .trfs = 5, .trp = 9, .tack = 2, .tss = 4,
- },
- { .tcyc = 4, .t2cyc = 8, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1,
- .tfs = 12, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4,
- },
- { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 2, .tdvh = 1,
- .tfs = 9, .tli = 7, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4,
- },
- { .tcyc = 2, .t2cyc = 4, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1,
- .tfs = 8, .tli = 8, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4,
- },
- { .tcyc = 2, .t2cyc = 2, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1,
- .tfs = 6, .tli = 5, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 2, .trfs = 4, .trp = 6, .tack = 2, .tss = 4,
- },
- };
- static const struct udmaspec udmaspec132[6] = {
- { .tcyc = 15, .t2cyc = 31, .tds = 2, .tdh = 1, .tdvs = 10, .tdvh = 1,
- .tfs = 30, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
- .tsr = 7, .trfs = 10, .trp = 22, .tack = 3, .tss = 7,
- },
- { .tcyc = 10, .t2cyc = 21, .tds = 2, .tdh = 1, .tdvs = 7, .tdvh = 1,
- .tfs = 27, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
- .tsr = 4, .trfs = 10, .trp = 17, .tack = 3, .tss = 7,
- },
- { .tcyc = 6, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1,
- .tfs = 23, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
- .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7,
- },
- { .tcyc = 7, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1,
- .tfs = 15, .tli = 13, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
- .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7,
- },
- { .tcyc = 2, .t2cyc = 5, .tds = 0, .tdh = 0, .tdvs = 1, .tdvh = 1,
- .tfs = 16, .tli = 14, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2,
- .tsr = 2, .trfs = 7, .trp = 13, .tack = 2, .tss = 6,
- },
- { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1,
- .tfs = 12, .tli = 10, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3,
- .tsr = 3, .trfs = 7, .trp = 12, .tack = 3, .tss = 7,
- },
- };
- /* ======================================================================== */
- /* Bit definitions inside the registers */
- #define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
- #define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
- #define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */
- #define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */
- #define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */
- #define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */
- #define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */
- #define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
- #define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
- #define MPC52xx_ATA_FIFOSTAT_ERROR 0x40 /* FIFO Error */
- #define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
- #define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
- #define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */
- #define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */
- #define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */
- #define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
- #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 {
- /* Host interface registers */
- u32 config; /* ATA + 0x00 Host configuration */
- u32 host_status; /* ATA + 0x04 Host controller status */
- u32 pio1; /* ATA + 0x08 PIO Timing 1 */
- u32 pio2; /* ATA + 0x0c PIO Timing 2 */
- u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */
- u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */
- u32 udma1; /* ATA + 0x18 UDMA Timing 1 */
- u32 udma2; /* ATA + 0x1c UDMA Timing 2 */
- u32 udma3; /* ATA + 0x20 UDMA Timing 3 */
- u32 udma4; /* ATA + 0x24 UDMA Timing 4 */
- u32 udma5; /* ATA + 0x28 UDMA Timing 5 */
- u32 share_cnt; /* ATA + 0x2c ATA share counter */
- u32 reserved0[3];
- /* FIFO registers */
- u32 fifo_data; /* ATA + 0x3c */
- u8 fifo_status_frame; /* ATA + 0x40 */
- u8 fifo_status; /* ATA + 0x41 */
- u16 reserved7[1];
- u8 fifo_control; /* ATA + 0x44 */
- u8 reserved8[5];
- u16 fifo_alarm; /* ATA + 0x4a */
- u16 reserved9;
- u16 fifo_rdp; /* ATA + 0x4e */
- u16 reserved10;
- u16 fifo_wrp; /* ATA + 0x52 */
- u16 reserved11;
- u16 fifo_lfrdp; /* ATA + 0x56 */
- u16 reserved12;
- u16 fifo_lfwrp; /* ATA + 0x5a */
- /* Drive TaskFile registers */
- u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */
- u8 reserved13[3];
- u16 tf_data; /* ATA + 0x60 TASKFILE Data */
- u16 reserved14;
- u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */
- u8 reserved15[3];
- u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */
- u8 reserved16[3];
-