/*
* Driver for the Octeon bootbus compact flash.
*
* 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.
*
* Copyright (C) 2005 - 2009 Cavium Networks
* Copyright (C) 2008 Wind River Systems
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/libata.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <scsi/scsi_host.h>
#include <asm/octeon/octeon.h>
/*
* The Octeon bootbus compact flash interface is connected in at least
* 3 different configurations on various evaluation boards:
*
* -- 8 bits no irq, no DMA
* -- 16 bits no irq, no DMA
* -- 16 bits True IDE mode with DMA, but no irq.
*
* In the last case the DMA engine can generate an interrupt when the
* transfer is complete. For the first two cases only PIO is supported.
*
*/
#define DRV_NAME "pata_octeon_cf"
#define DRV_VERSION "2.1"
struct octeon_cf_port {
struct workqueue_struct *wq;
struct delayed_work delayed_finish;
struct ata_port *ap;
int dma_finished;
};
static struct scsi_host_template octeon_cf_sht = {
ATA_PIO_SHT(DRV_NAME),
};
/**
* Convert nanosecond based time to setting used in the
* boot bus timing register, based on timing multiple
*/
static unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs)
{
unsigned int val;
/*
* Compute # of eclock periods to get desired duration in
* nanoseconds.
*/
val = DIV_ROUND_UP(nsecs * (octeon_get_clock_rate() / 1000000),
1000 * tim_mult);
return val;
}
static void octeon_cf_set_boot_reg_cfg(int cs)
{
union cvmx_mio_boot_reg_cfgx reg_cfg;
reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
reg_cfg.s.dmack = 0; /* Don't assert DMACK on access */
reg_cfg.s.tim_mult = 2; /* Timing mutiplier 2x */
reg_cfg.s.rd_dly = 0; /* Sample on falling edge of BOOT_OE */
reg_cfg.s.sam = 0; /* Don't combine write and output enable */
reg_cfg.s.we_ext = 0; /* No write enable extension */
reg_cfg.s.oe_ext = 0; /* No read enable extension */
reg_cfg.s.en = 1; /* Enable this region */
reg_cfg.s.orbit = 0; /* Don't combine with previous region */
reg_cfg.s.ale = 0; /* Don't do address multiplexing */
cvmx_write_csr(CVMX_MIO_BOOT_REG_CFGX(cs), reg_cfg.u64);
}
/**
* Called after libata determines the needed PIO mode. This
* function programs the Octeon bootbus regions to support the
* timing requirements of the PIO mode.
*
* @ap: ATA port information
* @dev: ATA device
*/
static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
{
struct octeon_cf_data *ocd = ap->dev->platform_data;
union cvmx_mio_boot_reg_timx reg_tim;
int cs = ocd->base_region;
int T;
struct ata_timing timing;
int use_iordy;
int trh;
int pause;
/* These names are timing parameters from the ATA spec */
int t1;
int t2;
int t2i;
T = (int)(2000000000000LL / octeon_get_clock_rate());
if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T))
BUG();
t1 = timing.setup;
if (t1)
t1--;
t2 = timing.active;
if (t2)
t2--;
t2i = timing.act8b;
if (t2i)
t2i--;
trh = ns_to_tim_reg(2, 20);
if (trh)
trh--;
pause = timing.cycle - timing.active - timing.setup - trh;
if (pause)
pause--;
octeon_cf_set_boot_reg_cfg(cs);
if (ocd->dma_engine >= 0)
/* True IDE mode, program both chip selects. */
octeon_cf_set_boot_reg_cfg(cs + 1);
use_iordy = ata_pio_need_iordy(dev);
reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cs));
/* Disable page mode */
reg_tim.s.pagem = 0;
/* Enable dynamic timing */
reg_tim.s.waitm = use_iordy;
/* Pages are disabled */
reg_tim.s.pages = 0;
/* We don't use multiplexed address mode */
reg_tim.s.ale = 0;
/* Not used */
reg_tim.s.page = 0;
/* Time after IORDY to coninue to assert the data */
reg_tim.s.wait = 0;
/* Time to wait to complete the cycle. */
reg_tim.s.pause = pause;
/* How long to hold after a write to de-assert CE. */
reg_tim.s.wr_hld = trh;
/* How long to wait after a read to de-assert CE. */
reg_tim.s.rd_hld = trh;
/* How long write enable is asserted */
reg_tim.s.we = t2;
/* How long read enable is asserted */
reg_tim.s.oe = t2;
/* Time after CE that read/write starts */
reg_tim.s.ce = ns_to_tim_reg(2, 5);
/* Time before CE that address is valid */
reg_tim.s.adr = 0;
/* Program the bootbus region timing for the data port chip select. */
cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs), reg_tim.u64);
if (ocd->dma_engine >= 0)