/* $Id: cris-ide-driver.patch,v 1.1 2005/06/29 21:39:07 akpm Exp $
*
* Etrax specific IDE functions, like init and PIO-mode setting etc.
* Almost the entire ide.c is used for the rest of the Etrax ATA driver.
* Copyright (c) 2000-2005 Axis Communications AB
*
* Authors: Bjorn Wesen (initial version)
* Mikael Starvik (crisv32 port)
*/
/* Regarding DMA:
*
* There are two forms of DMA - "DMA handshaking" between the interface and the drive,
* and DMA between the memory and the interface. We can ALWAYS use the latter, since it's
* something built-in in the Etrax. However only some drives support the DMA-mode handshaking
* on the ATA-bus. The normal PC driver and Triton interface disables memory-if DMA when the
* device can't do DMA handshaking for some stupid reason. We don't need to do that.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/dma.h>
/* number of DMA descriptors */
#define MAX_DMA_DESCRS 64
/* number of times to retry busy-flags when reading/writing IDE-registers
* this can't be too high because a hung harddisk might cause the watchdog
* to trigger (sometimes INB and OUTB are called with irq's disabled)
*/
#define IDE_REGISTER_TIMEOUT 300
#define LOWDB(x)
#define D(x)
enum /* Transfer types */
{
TYPE_PIO,
TYPE_DMA,
TYPE_UDMA
};
/* CRISv32 specifics */
#ifdef CONFIG_ETRAX_ARCH_V32
#include <asm/arch/hwregs/ata_defs.h>
#include <asm/arch/hwregs/dma_defs.h>
#include <asm/arch/hwregs/dma.h>
#include <asm/arch/pinmux.h>
#define ATA_UDMA2_CYC 2
#define ATA_UDMA2_DVS 3
#define ATA_UDMA1_CYC 2
#define ATA_UDMA1_DVS 4
#define ATA_UDMA0_CYC 4
#define ATA_UDMA0_DVS 6
#define ATA_DMA2_STROBE 7
#define ATA_DMA2_HOLD 1
#define ATA_DMA1_STROBE 8
#define ATA_DMA1_HOLD 3
#define ATA_DMA0_STROBE 25
#define ATA_DMA0_HOLD 19
#define ATA_PIO4_SETUP 3
#define ATA_PIO4_STROBE 7
#define ATA_PIO4_HOLD 1
#define ATA_PIO3_SETUP 3
#define ATA_PIO3_STROBE 9
#define ATA_PIO3_HOLD 3
#define ATA_PIO2_SETUP 3
#define ATA_PIO2_STROBE 13
#define ATA_PIO2_HOLD 5
#define ATA_PIO1_SETUP 5
#define ATA_PIO1_STROBE 23
#define ATA_PIO1_HOLD 9
#define ATA_PIO0_SETUP 9
#define ATA_PIO0_STROBE 39
#define ATA_PIO0_HOLD 9
int
cris_ide_ack_intr(ide_hwif_t* hwif)
{
reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2,
int, hwif->io_ports[0]);
REG_WR_INT(ata, regi_ata, rw_ack_intr, 1 << ctrl2.sel);
return 1;
}
static inline int
cris_ide_busy(void)
{
reg_ata_rs_stat_data stat_data;
stat_data = REG_RD(ata, regi_ata, rs_stat_data);
return stat_data.busy;
}
static inline int
cris_ide_ready(void)
{
return !cris_ide_busy();
}
static inline int
cris_ide_data_available(unsigned short* data)
{
reg_ata_rs_stat_data stat_data;
stat_data = REG_RD(ata, regi_ata, rs_stat_data);
*data = stat_data.data;
return stat_data.dav;
}
static void
cris_ide_write_command(unsigned long command)
{
REG_WR_INT(ata, regi_ata, rw_ctrl2, command); /* write data to the drive's register */
}
static void
cris_ide_set_speed(int type, int setup, int strobe, int hold)
{
reg_ata_rw_ctrl0 ctrl0 = REG_RD(ata, regi_ata, rw_ctrl0);
reg_ata_rw_ctrl1 ctrl1 = REG_RD(ata, regi_ata, rw_ctrl1);
if (type == TYPE_PIO) {
ctrl0.pio_setup = setup;
ctrl0.pio_strb = strobe;
ctrl0.pio_hold = hold;
} else if (type == TYPE_DMA) {
ctrl0.dma_strb = strobe;
ctrl0.dma_hold = hold;
} else if (type == TYPE_UDMA) {
ctrl1.udma_tcyc = setup;
ctrl1.udma_tdvs = strobe;
}
REG_WR(ata, regi_ata, rw_ctrl0, ctrl0);
REG_WR(ata, regi_ata, rw_ctrl1, ctrl1);
}
static unsigned long
cris_ide_base_address(int bus)
{
reg_ata_rw_ctrl2 ctrl2 = {0};
ctrl2.sel = bus;
return REG_TYPE_CONV(int, reg_ata_rw_ctrl2, ctrl2);
}
static unsigned long
cris_ide_reg_addr(unsigned long addr, int cs0, int cs1)
{
reg_ata_rw_ctrl2 ctrl2 = {0};
ctrl2.addr = addr;
ctrl2.cs1 = cs1;
ctrl2.cs0 = cs0;
return REG_TYPE_CONV(int, reg_ata_rw_ctrl2, ctrl2);
}
static __init void
cris_ide_reset(unsigned val)
{
reg_ata_rw_ctrl0 ctrl0 =