162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Driver for the Octeon bootbus compact flash. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 562306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 662306a36Sopenharmony_ci * for more details. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2005 - 2012 Cavium Inc. 962306a36Sopenharmony_ci * Copyright (C) 2008 Wind River Systems 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/libata.h> 1562306a36Sopenharmony_ci#include <linux/hrtimer.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci#include <linux/irq.h> 1862306a36Sopenharmony_ci#include <linux/of.h> 1962306a36Sopenharmony_ci#include <linux/of_address.h> 2062306a36Sopenharmony_ci#include <linux/of_platform.h> 2162306a36Sopenharmony_ci#include <linux/platform_device.h> 2262306a36Sopenharmony_ci#include <scsi/scsi_host.h> 2362306a36Sopenharmony_ci#include <trace/events/libata.h> 2462306a36Sopenharmony_ci#include <asm/byteorder.h> 2562306a36Sopenharmony_ci#include <asm/octeon/octeon.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * The Octeon bootbus compact flash interface is connected in at least 2962306a36Sopenharmony_ci * 3 different configurations on various evaluation boards: 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * -- 8 bits no irq, no DMA 3262306a36Sopenharmony_ci * -- 16 bits no irq, no DMA 3362306a36Sopenharmony_ci * -- 16 bits True IDE mode with DMA, but no irq. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * In the last case the DMA engine can generate an interrupt when the 3662306a36Sopenharmony_ci * transfer is complete. For the first two cases only PIO is supported. 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define DRV_NAME "pata_octeon_cf" 4162306a36Sopenharmony_ci#define DRV_VERSION "2.2" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* Poll interval in nS. */ 4462306a36Sopenharmony_ci#define OCTEON_CF_BUSY_POLL_INTERVAL 500000 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define DMA_CFG 0 4762306a36Sopenharmony_ci#define DMA_TIM 0x20 4862306a36Sopenharmony_ci#define DMA_INT 0x38 4962306a36Sopenharmony_ci#define DMA_INT_EN 0x50 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistruct octeon_cf_port { 5262306a36Sopenharmony_ci struct hrtimer delayed_finish; 5362306a36Sopenharmony_ci struct ata_port *ap; 5462306a36Sopenharmony_ci int dma_finished; 5562306a36Sopenharmony_ci void *c0; 5662306a36Sopenharmony_ci unsigned int cs0; 5762306a36Sopenharmony_ci unsigned int cs1; 5862306a36Sopenharmony_ci bool is_true_ide; 5962306a36Sopenharmony_ci u64 dma_base; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct scsi_host_template octeon_cf_sht = { 6362306a36Sopenharmony_ci ATA_PIO_SHT(DRV_NAME), 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int enable_dma; 6762306a36Sopenharmony_cimodule_param(enable_dma, int, 0444); 6862306a36Sopenharmony_ciMODULE_PARM_DESC(enable_dma, 6962306a36Sopenharmony_ci "Enable use of DMA on interfaces that support it (0=no dma [default], 1=use dma)"); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * Convert nanosecond based time to setting used in the 7362306a36Sopenharmony_ci * boot bus timing register, based on timing multiple 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_cistatic unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci /* 7862306a36Sopenharmony_ci * Compute # of eclock periods to get desired duration in 7962306a36Sopenharmony_ci * nanoseconds. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci return DIV_ROUND_UP(nsecs * (octeon_get_io_clock_rate() / 1000000), 8262306a36Sopenharmony_ci 1000 * tim_mult); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic void octeon_cf_set_boot_reg_cfg(int cs, unsigned int multiplier) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci union cvmx_mio_boot_reg_cfgx reg_cfg; 8862306a36Sopenharmony_ci unsigned int tim_mult; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci switch (multiplier) { 9162306a36Sopenharmony_ci case 8: 9262306a36Sopenharmony_ci tim_mult = 3; 9362306a36Sopenharmony_ci break; 9462306a36Sopenharmony_ci case 4: 9562306a36Sopenharmony_ci tim_mult = 0; 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci case 2: 9862306a36Sopenharmony_ci tim_mult = 2; 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci default: 10162306a36Sopenharmony_ci tim_mult = 1; 10262306a36Sopenharmony_ci break; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); 10662306a36Sopenharmony_ci reg_cfg.s.dmack = 0; /* Don't assert DMACK on access */ 10762306a36Sopenharmony_ci reg_cfg.s.tim_mult = tim_mult; /* Timing mutiplier */ 10862306a36Sopenharmony_ci reg_cfg.s.rd_dly = 0; /* Sample on falling edge of BOOT_OE */ 10962306a36Sopenharmony_ci reg_cfg.s.sam = 0; /* Don't combine write and output enable */ 11062306a36Sopenharmony_ci reg_cfg.s.we_ext = 0; /* No write enable extension */ 11162306a36Sopenharmony_ci reg_cfg.s.oe_ext = 0; /* No read enable extension */ 11262306a36Sopenharmony_ci reg_cfg.s.en = 1; /* Enable this region */ 11362306a36Sopenharmony_ci reg_cfg.s.orbit = 0; /* Don't combine with previous region */ 11462306a36Sopenharmony_ci reg_cfg.s.ale = 0; /* Don't do address multiplexing */ 11562306a36Sopenharmony_ci cvmx_write_csr(CVMX_MIO_BOOT_REG_CFGX(cs), reg_cfg.u64); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* 11962306a36Sopenharmony_ci * Called after libata determines the needed PIO mode. This 12062306a36Sopenharmony_ci * function programs the Octeon bootbus regions to support the 12162306a36Sopenharmony_ci * timing requirements of the PIO mode. 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * @ap: ATA port information 12462306a36Sopenharmony_ci * @dev: ATA device 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_cistatic void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci struct octeon_cf_port *cf_port = ap->private_data; 12962306a36Sopenharmony_ci union cvmx_mio_boot_reg_timx reg_tim; 13062306a36Sopenharmony_ci int T; 13162306a36Sopenharmony_ci struct ata_timing timing; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci unsigned int div; 13462306a36Sopenharmony_ci int use_iordy; 13562306a36Sopenharmony_ci int trh; 13662306a36Sopenharmony_ci int pause; 13762306a36Sopenharmony_ci /* These names are timing parameters from the ATA spec */ 13862306a36Sopenharmony_ci int t2; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* 14162306a36Sopenharmony_ci * A divisor value of four will overflow the timing fields at 14262306a36Sopenharmony_ci * clock rates greater than 800MHz 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci if (octeon_get_io_clock_rate() <= 800000000) 14562306a36Sopenharmony_ci div = 4; 14662306a36Sopenharmony_ci else 14762306a36Sopenharmony_ci div = 8; 14862306a36Sopenharmony_ci T = (int)((1000000000000LL * div) / octeon_get_io_clock_rate()); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci BUG_ON(ata_timing_compute(dev, dev->pio_mode, &timing, T, T)); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci t2 = timing.active; 15362306a36Sopenharmony_ci if (t2) 15462306a36Sopenharmony_ci t2--; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci trh = ns_to_tim_reg(div, 20); 15762306a36Sopenharmony_ci if (trh) 15862306a36Sopenharmony_ci trh--; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci pause = (int)timing.cycle - (int)timing.active - 16162306a36Sopenharmony_ci (int)timing.setup - trh; 16262306a36Sopenharmony_ci if (pause < 0) 16362306a36Sopenharmony_ci pause = 0; 16462306a36Sopenharmony_ci if (pause) 16562306a36Sopenharmony_ci pause--; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci octeon_cf_set_boot_reg_cfg(cf_port->cs0, div); 16862306a36Sopenharmony_ci if (cf_port->is_true_ide) 16962306a36Sopenharmony_ci /* True IDE mode, program both chip selects. */ 17062306a36Sopenharmony_ci octeon_cf_set_boot_reg_cfg(cf_port->cs1, div); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci use_iordy = ata_pio_need_iordy(dev); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0)); 17662306a36Sopenharmony_ci /* Disable page mode */ 17762306a36Sopenharmony_ci reg_tim.s.pagem = 0; 17862306a36Sopenharmony_ci /* Enable dynamic timing */ 17962306a36Sopenharmony_ci reg_tim.s.waitm = use_iordy; 18062306a36Sopenharmony_ci /* Pages are disabled */ 18162306a36Sopenharmony_ci reg_tim.s.pages = 0; 18262306a36Sopenharmony_ci /* We don't use multiplexed address mode */ 18362306a36Sopenharmony_ci reg_tim.s.ale = 0; 18462306a36Sopenharmony_ci /* Not used */ 18562306a36Sopenharmony_ci reg_tim.s.page = 0; 18662306a36Sopenharmony_ci /* Time after IORDY to coninue to assert the data */ 18762306a36Sopenharmony_ci reg_tim.s.wait = 0; 18862306a36Sopenharmony_ci /* Time to wait to complete the cycle. */ 18962306a36Sopenharmony_ci reg_tim.s.pause = pause; 19062306a36Sopenharmony_ci /* How long to hold after a write to de-assert CE. */ 19162306a36Sopenharmony_ci reg_tim.s.wr_hld = trh; 19262306a36Sopenharmony_ci /* How long to wait after a read to de-assert CE. */ 19362306a36Sopenharmony_ci reg_tim.s.rd_hld = trh; 19462306a36Sopenharmony_ci /* How long write enable is asserted */ 19562306a36Sopenharmony_ci reg_tim.s.we = t2; 19662306a36Sopenharmony_ci /* How long read enable is asserted */ 19762306a36Sopenharmony_ci reg_tim.s.oe = t2; 19862306a36Sopenharmony_ci /* Time after CE that read/write starts */ 19962306a36Sopenharmony_ci reg_tim.s.ce = ns_to_tim_reg(div, 5); 20062306a36Sopenharmony_ci /* Time before CE that address is valid */ 20162306a36Sopenharmony_ci reg_tim.s.adr = 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Program the bootbus region timing for the data port chip select. */ 20462306a36Sopenharmony_ci cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0), reg_tim.u64); 20562306a36Sopenharmony_ci if (cf_port->is_true_ide) 20662306a36Sopenharmony_ci /* True IDE mode, program both chip selects. */ 20762306a36Sopenharmony_ci cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs1), 20862306a36Sopenharmony_ci reg_tim.u64); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci struct octeon_cf_port *cf_port = ap->private_data; 21462306a36Sopenharmony_ci union cvmx_mio_boot_pin_defs pin_defs; 21562306a36Sopenharmony_ci union cvmx_mio_boot_dma_timx dma_tim; 21662306a36Sopenharmony_ci unsigned int oe_a; 21762306a36Sopenharmony_ci unsigned int oe_n; 21862306a36Sopenharmony_ci unsigned int dma_ackh; 21962306a36Sopenharmony_ci unsigned int dma_arq; 22062306a36Sopenharmony_ci unsigned int pause; 22162306a36Sopenharmony_ci unsigned int T0, Tkr, Td; 22262306a36Sopenharmony_ci unsigned int tim_mult; 22362306a36Sopenharmony_ci int c; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci const struct ata_timing *timing; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci timing = ata_timing_find_mode(dev->dma_mode); 22862306a36Sopenharmony_ci T0 = timing->cycle; 22962306a36Sopenharmony_ci Td = timing->active; 23062306a36Sopenharmony_ci Tkr = timing->recover; 23162306a36Sopenharmony_ci dma_ackh = timing->dmack_hold; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci dma_tim.u64 = 0; 23462306a36Sopenharmony_ci /* dma_tim.s.tim_mult = 0 --> 4x */ 23562306a36Sopenharmony_ci tim_mult = 4; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* not spec'ed, value in eclocks, not affected by tim_mult */ 23862306a36Sopenharmony_ci dma_arq = 8; 23962306a36Sopenharmony_ci pause = 25 - dma_arq * 1000 / 24062306a36Sopenharmony_ci (octeon_get_io_clock_rate() / 1000000); /* Tz */ 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci oe_a = Td; 24362306a36Sopenharmony_ci /* Tkr from cf spec, lengthened to meet T0 */ 24462306a36Sopenharmony_ci oe_n = max(T0 - oe_a, Tkr); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci pin_defs.u64 = cvmx_read_csr(CVMX_MIO_BOOT_PIN_DEFS); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* DMA channel number. */ 24962306a36Sopenharmony_ci c = (cf_port->dma_base & 8) >> 3; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* Invert the polarity if the default is 0*/ 25262306a36Sopenharmony_ci dma_tim.s.dmack_pi = (pin_defs.u64 & (1ull << (11 + c))) ? 0 : 1; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n); 25562306a36Sopenharmony_ci dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * This is tI, C.F. spec. says 0, but Sony CF card requires 25962306a36Sopenharmony_ci * more, we use 20 nS. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci dma_tim.s.dmack_s = ns_to_tim_reg(tim_mult, 20); 26262306a36Sopenharmony_ci dma_tim.s.dmack_h = ns_to_tim_reg(tim_mult, dma_ackh); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci dma_tim.s.dmarq = dma_arq; 26562306a36Sopenharmony_ci dma_tim.s.pause = ns_to_tim_reg(tim_mult, pause); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci dma_tim.s.rd_dly = 0; /* Sample right on edge */ 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* writes only */ 27062306a36Sopenharmony_ci dma_tim.s.we_n = ns_to_tim_reg(tim_mult, oe_n); 27162306a36Sopenharmony_ci dma_tim.s.we_a = ns_to_tim_reg(tim_mult, oe_a); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci ata_dev_dbg(dev, "ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60, 27462306a36Sopenharmony_ci ns_to_tim_reg(tim_mult, 60)); 27562306a36Sopenharmony_ci ata_dev_dbg(dev, "oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: %d, dmarq: %d, pause: %d\n", 27662306a36Sopenharmony_ci dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s, 27762306a36Sopenharmony_ci dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_TIM, dma_tim.u64); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* 28362306a36Sopenharmony_ci * Handle an 8 bit I/O request. 28462306a36Sopenharmony_ci * 28562306a36Sopenharmony_ci * @qc: Queued command 28662306a36Sopenharmony_ci * @buffer: Data buffer 28762306a36Sopenharmony_ci * @buflen: Length of the buffer. 28862306a36Sopenharmony_ci * @rw: True to write. 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_cistatic unsigned int octeon_cf_data_xfer8(struct ata_queued_cmd *qc, 29162306a36Sopenharmony_ci unsigned char *buffer, 29262306a36Sopenharmony_ci unsigned int buflen, 29362306a36Sopenharmony_ci int rw) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci struct ata_port *ap = qc->dev->link->ap; 29662306a36Sopenharmony_ci void __iomem *data_addr = ap->ioaddr.data_addr; 29762306a36Sopenharmony_ci unsigned long words; 29862306a36Sopenharmony_ci int count; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci words = buflen; 30162306a36Sopenharmony_ci if (rw) { 30262306a36Sopenharmony_ci count = 16; 30362306a36Sopenharmony_ci while (words--) { 30462306a36Sopenharmony_ci iowrite8(*buffer, data_addr); 30562306a36Sopenharmony_ci buffer++; 30662306a36Sopenharmony_ci /* 30762306a36Sopenharmony_ci * Every 16 writes do a read so the bootbus 30862306a36Sopenharmony_ci * FIFO doesn't fill up. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_ci if (--count == 0) { 31162306a36Sopenharmony_ci ioread8(ap->ioaddr.altstatus_addr); 31262306a36Sopenharmony_ci count = 16; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci } else { 31662306a36Sopenharmony_ci ioread8_rep(data_addr, buffer, words); 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci return buflen; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/* 32262306a36Sopenharmony_ci * Handle a 16 bit I/O request. 32362306a36Sopenharmony_ci * 32462306a36Sopenharmony_ci * @qc: Queued command 32562306a36Sopenharmony_ci * @buffer: Data buffer 32662306a36Sopenharmony_ci * @buflen: Length of the buffer. 32762306a36Sopenharmony_ci * @rw: True to write. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_cistatic unsigned int octeon_cf_data_xfer16(struct ata_queued_cmd *qc, 33062306a36Sopenharmony_ci unsigned char *buffer, 33162306a36Sopenharmony_ci unsigned int buflen, 33262306a36Sopenharmony_ci int rw) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci struct ata_port *ap = qc->dev->link->ap; 33562306a36Sopenharmony_ci void __iomem *data_addr = ap->ioaddr.data_addr; 33662306a36Sopenharmony_ci unsigned long words; 33762306a36Sopenharmony_ci int count; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci words = buflen / 2; 34062306a36Sopenharmony_ci if (rw) { 34162306a36Sopenharmony_ci count = 16; 34262306a36Sopenharmony_ci while (words--) { 34362306a36Sopenharmony_ci iowrite16(*(uint16_t *)buffer, data_addr); 34462306a36Sopenharmony_ci buffer += sizeof(uint16_t); 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * Every 16 writes do a read so the bootbus 34762306a36Sopenharmony_ci * FIFO doesn't fill up. 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci if (--count == 0) { 35062306a36Sopenharmony_ci ioread8(ap->ioaddr.altstatus_addr); 35162306a36Sopenharmony_ci count = 16; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci } else { 35562306a36Sopenharmony_ci while (words--) { 35662306a36Sopenharmony_ci *(uint16_t *)buffer = ioread16(data_addr); 35762306a36Sopenharmony_ci buffer += sizeof(uint16_t); 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci /* Transfer trailing 1 byte, if any. */ 36162306a36Sopenharmony_ci if (unlikely(buflen & 0x01)) { 36262306a36Sopenharmony_ci __le16 align_buf[1] = { 0 }; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (rw == READ) { 36562306a36Sopenharmony_ci align_buf[0] = cpu_to_le16(ioread16(data_addr)); 36662306a36Sopenharmony_ci memcpy(buffer, align_buf, 1); 36762306a36Sopenharmony_ci } else { 36862306a36Sopenharmony_ci memcpy(align_buf, buffer, 1); 36962306a36Sopenharmony_ci iowrite16(le16_to_cpu(align_buf[0]), data_addr); 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci words++; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci return buflen; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/* 37762306a36Sopenharmony_ci * Read the taskfile for 16bit non-True IDE only. 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_cistatic void octeon_cf_tf_read16(struct ata_port *ap, struct ata_taskfile *tf) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci u16 blob; 38262306a36Sopenharmony_ci /* The base of the registers is at ioaddr.data_addr. */ 38362306a36Sopenharmony_ci void __iomem *base = ap->ioaddr.data_addr; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci blob = __raw_readw(base + 0xc); 38662306a36Sopenharmony_ci tf->error = blob >> 8; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci blob = __raw_readw(base + 2); 38962306a36Sopenharmony_ci tf->nsect = blob & 0xff; 39062306a36Sopenharmony_ci tf->lbal = blob >> 8; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci blob = __raw_readw(base + 4); 39362306a36Sopenharmony_ci tf->lbam = blob & 0xff; 39462306a36Sopenharmony_ci tf->lbah = blob >> 8; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci blob = __raw_readw(base + 6); 39762306a36Sopenharmony_ci tf->device = blob & 0xff; 39862306a36Sopenharmony_ci tf->status = blob >> 8; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (tf->flags & ATA_TFLAG_LBA48) { 40162306a36Sopenharmony_ci if (likely(ap->ioaddr.ctl_addr)) { 40262306a36Sopenharmony_ci iowrite8(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci blob = __raw_readw(base + 0xc); 40562306a36Sopenharmony_ci tf->hob_feature = blob >> 8; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci blob = __raw_readw(base + 2); 40862306a36Sopenharmony_ci tf->hob_nsect = blob & 0xff; 40962306a36Sopenharmony_ci tf->hob_lbal = blob >> 8; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci blob = __raw_readw(base + 4); 41262306a36Sopenharmony_ci tf->hob_lbam = blob & 0xff; 41362306a36Sopenharmony_ci tf->hob_lbah = blob >> 8; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci iowrite8(tf->ctl, ap->ioaddr.ctl_addr); 41662306a36Sopenharmony_ci ap->last_ctl = tf->ctl; 41762306a36Sopenharmony_ci } else { 41862306a36Sopenharmony_ci WARN_ON(1); 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic u8 octeon_cf_check_status16(struct ata_port *ap) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci u16 blob; 42662306a36Sopenharmony_ci void __iomem *base = ap->ioaddr.data_addr; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci blob = __raw_readw(base + 6); 42962306a36Sopenharmony_ci return blob >> 8; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic int octeon_cf_softreset16(struct ata_link *link, unsigned int *classes, 43362306a36Sopenharmony_ci unsigned long deadline) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci struct ata_port *ap = link->ap; 43662306a36Sopenharmony_ci void __iomem *base = ap->ioaddr.data_addr; 43762306a36Sopenharmony_ci int rc; 43862306a36Sopenharmony_ci u8 err; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci __raw_writew(ap->ctl, base + 0xe); 44162306a36Sopenharmony_ci udelay(20); 44262306a36Sopenharmony_ci __raw_writew(ap->ctl | ATA_SRST, base + 0xe); 44362306a36Sopenharmony_ci udelay(20); 44462306a36Sopenharmony_ci __raw_writew(ap->ctl, base + 0xe); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci rc = ata_sff_wait_after_reset(link, 1, deadline); 44762306a36Sopenharmony_ci if (rc) { 44862306a36Sopenharmony_ci ata_link_err(link, "SRST failed (errno=%d)\n", rc); 44962306a36Sopenharmony_ci return rc; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* determine by signature whether we have ATA or ATAPI devices */ 45362306a36Sopenharmony_ci classes[0] = ata_sff_dev_classify(&link->device[0], 1, &err); 45462306a36Sopenharmony_ci return 0; 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci/* 45862306a36Sopenharmony_ci * Load the taskfile for 16bit non-True IDE only. The device_addr is 45962306a36Sopenharmony_ci * not loaded, we do this as part of octeon_cf_exec_command16. 46062306a36Sopenharmony_ci */ 46162306a36Sopenharmony_cistatic void octeon_cf_tf_load16(struct ata_port *ap, 46262306a36Sopenharmony_ci const struct ata_taskfile *tf) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; 46562306a36Sopenharmony_ci /* The base of the registers is at ioaddr.data_addr. */ 46662306a36Sopenharmony_ci void __iomem *base = ap->ioaddr.data_addr; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if (tf->ctl != ap->last_ctl) { 46962306a36Sopenharmony_ci iowrite8(tf->ctl, ap->ioaddr.ctl_addr); 47062306a36Sopenharmony_ci ap->last_ctl = tf->ctl; 47162306a36Sopenharmony_ci ata_wait_idle(ap); 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { 47462306a36Sopenharmony_ci __raw_writew(tf->hob_feature << 8, base + 0xc); 47562306a36Sopenharmony_ci __raw_writew(tf->hob_nsect | tf->hob_lbal << 8, base + 2); 47662306a36Sopenharmony_ci __raw_writew(tf->hob_lbam | tf->hob_lbah << 8, base + 4); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci if (is_addr) { 47962306a36Sopenharmony_ci __raw_writew(tf->feature << 8, base + 0xc); 48062306a36Sopenharmony_ci __raw_writew(tf->nsect | tf->lbal << 8, base + 2); 48162306a36Sopenharmony_ci __raw_writew(tf->lbam | tf->lbah << 8, base + 4); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci ata_wait_idle(ap); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic void octeon_cf_dev_select(struct ata_port *ap, unsigned int device) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci/* There is only one device, do nothing. */ 49062306a36Sopenharmony_ci return; 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci/* 49462306a36Sopenharmony_ci * Issue ATA command to host controller. The device_addr is also sent 49562306a36Sopenharmony_ci * as it must be written in a combined write with the command. 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_cistatic void octeon_cf_exec_command16(struct ata_port *ap, 49862306a36Sopenharmony_ci const struct ata_taskfile *tf) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci /* The base of the registers is at ioaddr.data_addr. */ 50162306a36Sopenharmony_ci void __iomem *base = ap->ioaddr.data_addr; 50262306a36Sopenharmony_ci u16 blob = 0; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (tf->flags & ATA_TFLAG_DEVICE) 50562306a36Sopenharmony_ci blob = tf->device; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci blob |= (tf->command << 8); 50862306a36Sopenharmony_ci __raw_writew(blob, base + 6); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci ata_wait_idle(ap); 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic void octeon_cf_ata_port_noaction(struct ata_port *ap) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic void octeon_cf_dma_setup(struct ata_queued_cmd *qc) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 52062306a36Sopenharmony_ci struct octeon_cf_port *cf_port; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci cf_port = ap->private_data; 52362306a36Sopenharmony_ci /* issue r/w command */ 52462306a36Sopenharmony_ci qc->cursg = qc->sg; 52562306a36Sopenharmony_ci cf_port->dma_finished = 0; 52662306a36Sopenharmony_ci ap->ops->sff_exec_command(ap, &qc->tf); 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci/* 53062306a36Sopenharmony_ci * Start a DMA transfer that was already setup 53162306a36Sopenharmony_ci * 53262306a36Sopenharmony_ci * @qc: Information about the DMA 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_cistatic void octeon_cf_dma_start(struct ata_queued_cmd *qc) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci struct octeon_cf_port *cf_port = qc->ap->private_data; 53762306a36Sopenharmony_ci union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg; 53862306a36Sopenharmony_ci union cvmx_mio_boot_dma_intx mio_boot_dma_int; 53962306a36Sopenharmony_ci struct scatterlist *sg; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* Get the scatter list entry we need to DMA into */ 54262306a36Sopenharmony_ci sg = qc->cursg; 54362306a36Sopenharmony_ci BUG_ON(!sg); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci /* 54662306a36Sopenharmony_ci * Clear the DMA complete status. 54762306a36Sopenharmony_ci */ 54862306a36Sopenharmony_ci mio_boot_dma_int.u64 = 0; 54962306a36Sopenharmony_ci mio_boot_dma_int.s.done = 1; 55062306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT, mio_boot_dma_int.u64); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci /* Enable the interrupt. */ 55362306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, mio_boot_dma_int.u64); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci /* Set the direction of the DMA */ 55662306a36Sopenharmony_ci mio_boot_dma_cfg.u64 = 0; 55762306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN 55862306a36Sopenharmony_ci mio_boot_dma_cfg.s.endian = 1; 55962306a36Sopenharmony_ci#endif 56062306a36Sopenharmony_ci mio_boot_dma_cfg.s.en = 1; 56162306a36Sopenharmony_ci mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* 56462306a36Sopenharmony_ci * Don't stop the DMA if the device deasserts DMARQ. Many 56562306a36Sopenharmony_ci * compact flashes deassert DMARQ for a short time between 56662306a36Sopenharmony_ci * sectors. Instead of stopping and restarting the DMA, we'll 56762306a36Sopenharmony_ci * let the hardware do it. If the DMA is really stopped early 56862306a36Sopenharmony_ci * due to an error condition, a later timeout will force us to 56962306a36Sopenharmony_ci * stop. 57062306a36Sopenharmony_ci */ 57162306a36Sopenharmony_ci mio_boot_dma_cfg.s.clr = 0; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci /* Size is specified in 16bit words and minus one notation */ 57462306a36Sopenharmony_ci mio_boot_dma_cfg.s.size = sg_dma_len(sg) / 2 - 1; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /* We need to swap the high and low bytes of every 16 bits */ 57762306a36Sopenharmony_ci mio_boot_dma_cfg.s.swap8 = 1; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci mio_boot_dma_cfg.s.adr = sg_dma_address(sg); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_CFG, mio_boot_dma_cfg.u64); 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci/* 58562306a36Sopenharmony_ci * 58662306a36Sopenharmony_ci * LOCKING: 58762306a36Sopenharmony_ci * spin_lock_irqsave(host lock) 58862306a36Sopenharmony_ci * 58962306a36Sopenharmony_ci */ 59062306a36Sopenharmony_cistatic unsigned int octeon_cf_dma_finished(struct ata_port *ap, 59162306a36Sopenharmony_ci struct ata_queued_cmd *qc) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci struct ata_eh_info *ehi = &ap->link.eh_info; 59462306a36Sopenharmony_ci struct octeon_cf_port *cf_port = ap->private_data; 59562306a36Sopenharmony_ci union cvmx_mio_boot_dma_cfgx dma_cfg; 59662306a36Sopenharmony_ci union cvmx_mio_boot_dma_intx dma_int; 59762306a36Sopenharmony_ci u8 status; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci trace_ata_bmdma_stop(ap, &qc->tf, qc->tag); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci if (ap->hsm_task_state != HSM_ST_LAST) 60262306a36Sopenharmony_ci return 0; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG); 60562306a36Sopenharmony_ci if (dma_cfg.s.size != 0xfffff) { 60662306a36Sopenharmony_ci /* Error, the transfer was not complete. */ 60762306a36Sopenharmony_ci qc->err_mask |= AC_ERR_HOST_BUS; 60862306a36Sopenharmony_ci ap->hsm_task_state = HSM_ST_ERR; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* Stop and clear the dma engine. */ 61262306a36Sopenharmony_ci dma_cfg.u64 = 0; 61362306a36Sopenharmony_ci dma_cfg.s.size = -1; 61462306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* Disable the interrupt. */ 61762306a36Sopenharmony_ci dma_int.u64 = 0; 61862306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci /* Clear the DMA complete status */ 62162306a36Sopenharmony_ci dma_int.s.done = 1; 62262306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci status = ap->ops->sff_check_status(ap); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci ata_sff_hsm_move(ap, qc, status, 0); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA)) 62962306a36Sopenharmony_ci ata_ehi_push_desc(ehi, "DMA stat 0x%x", status); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci return 1; 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/* 63562306a36Sopenharmony_ci * Check if any queued commands have more DMAs, if so start the next 63662306a36Sopenharmony_ci * transfer, else do end of transfer handling. 63762306a36Sopenharmony_ci */ 63862306a36Sopenharmony_cistatic irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci struct ata_host *host = dev_instance; 64162306a36Sopenharmony_ci struct octeon_cf_port *cf_port; 64262306a36Sopenharmony_ci int i; 64362306a36Sopenharmony_ci unsigned int handled = 0; 64462306a36Sopenharmony_ci unsigned long flags; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, flags); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 64962306a36Sopenharmony_ci u8 status; 65062306a36Sopenharmony_ci struct ata_port *ap; 65162306a36Sopenharmony_ci struct ata_queued_cmd *qc; 65262306a36Sopenharmony_ci union cvmx_mio_boot_dma_intx dma_int; 65362306a36Sopenharmony_ci union cvmx_mio_boot_dma_cfgx dma_cfg; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci ap = host->ports[i]; 65662306a36Sopenharmony_ci cf_port = ap->private_data; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci dma_int.u64 = cvmx_read_csr(cf_port->dma_base + DMA_INT); 65962306a36Sopenharmony_ci dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci qc = ata_qc_from_tag(ap, ap->link.active_tag); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (!qc || (qc->tf.flags & ATA_TFLAG_POLLING)) 66462306a36Sopenharmony_ci continue; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci if (dma_int.s.done && !dma_cfg.s.en) { 66762306a36Sopenharmony_ci if (!sg_is_last(qc->cursg)) { 66862306a36Sopenharmony_ci qc->cursg = sg_next(qc->cursg); 66962306a36Sopenharmony_ci handled = 1; 67062306a36Sopenharmony_ci trace_ata_bmdma_start(ap, &qc->tf, qc->tag); 67162306a36Sopenharmony_ci octeon_cf_dma_start(qc); 67262306a36Sopenharmony_ci continue; 67362306a36Sopenharmony_ci } else { 67462306a36Sopenharmony_ci cf_port->dma_finished = 1; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci if (!cf_port->dma_finished) 67862306a36Sopenharmony_ci continue; 67962306a36Sopenharmony_ci status = ioread8(ap->ioaddr.altstatus_addr); 68062306a36Sopenharmony_ci if (status & (ATA_BUSY | ATA_DRQ)) { 68162306a36Sopenharmony_ci /* 68262306a36Sopenharmony_ci * We are busy, try to handle it later. This 68362306a36Sopenharmony_ci * is the DMA finished interrupt, and it could 68462306a36Sopenharmony_ci * take a little while for the card to be 68562306a36Sopenharmony_ci * ready for more commands. 68662306a36Sopenharmony_ci */ 68762306a36Sopenharmony_ci /* Clear DMA irq. */ 68862306a36Sopenharmony_ci dma_int.u64 = 0; 68962306a36Sopenharmony_ci dma_int.s.done = 1; 69062306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT, 69162306a36Sopenharmony_ci dma_int.u64); 69262306a36Sopenharmony_ci hrtimer_start_range_ns(&cf_port->delayed_finish, 69362306a36Sopenharmony_ci ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL), 69462306a36Sopenharmony_ci OCTEON_CF_BUSY_POLL_INTERVAL / 5, 69562306a36Sopenharmony_ci HRTIMER_MODE_REL); 69662306a36Sopenharmony_ci handled = 1; 69762306a36Sopenharmony_ci } else { 69862306a36Sopenharmony_ci handled |= octeon_cf_dma_finished(ap, qc); 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, flags); 70262306a36Sopenharmony_ci return IRQ_RETVAL(handled); 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_cistatic enum hrtimer_restart octeon_cf_delayed_finish(struct hrtimer *hrt) 70662306a36Sopenharmony_ci{ 70762306a36Sopenharmony_ci struct octeon_cf_port *cf_port = container_of(hrt, 70862306a36Sopenharmony_ci struct octeon_cf_port, 70962306a36Sopenharmony_ci delayed_finish); 71062306a36Sopenharmony_ci struct ata_port *ap = cf_port->ap; 71162306a36Sopenharmony_ci struct ata_host *host = ap->host; 71262306a36Sopenharmony_ci struct ata_queued_cmd *qc; 71362306a36Sopenharmony_ci unsigned long flags; 71462306a36Sopenharmony_ci u8 status; 71562306a36Sopenharmony_ci enum hrtimer_restart rv = HRTIMER_NORESTART; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, flags); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * If the port is not waiting for completion, it must have 72162306a36Sopenharmony_ci * handled it previously. The hsm_task_state is 72262306a36Sopenharmony_ci * protected by host->lock. 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci if (ap->hsm_task_state != HSM_ST_LAST || !cf_port->dma_finished) 72562306a36Sopenharmony_ci goto out; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci status = ioread8(ap->ioaddr.altstatus_addr); 72862306a36Sopenharmony_ci if (status & (ATA_BUSY | ATA_DRQ)) { 72962306a36Sopenharmony_ci /* Still busy, try again. */ 73062306a36Sopenharmony_ci hrtimer_forward_now(hrt, 73162306a36Sopenharmony_ci ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL)); 73262306a36Sopenharmony_ci rv = HRTIMER_RESTART; 73362306a36Sopenharmony_ci goto out; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci qc = ata_qc_from_tag(ap, ap->link.active_tag); 73662306a36Sopenharmony_ci if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) 73762306a36Sopenharmony_ci octeon_cf_dma_finished(ap, qc); 73862306a36Sopenharmony_ciout: 73962306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, flags); 74062306a36Sopenharmony_ci return rv; 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic void octeon_cf_dev_config(struct ata_device *dev) 74462306a36Sopenharmony_ci{ 74562306a36Sopenharmony_ci /* 74662306a36Sopenharmony_ci * A maximum of 2^20 - 1 16 bit transfers are possible with 74762306a36Sopenharmony_ci * the bootbus DMA. So we need to throttle max_sectors to 74862306a36Sopenharmony_ci * (2^12 - 1 == 4095) to assure that this can never happen. 74962306a36Sopenharmony_ci */ 75062306a36Sopenharmony_ci dev->max_sectors = min(dev->max_sectors, 4095U); 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci/* 75462306a36Sopenharmony_ci * We don't do ATAPI DMA so return 0. 75562306a36Sopenharmony_ci */ 75662306a36Sopenharmony_cistatic int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc) 75762306a36Sopenharmony_ci{ 75862306a36Sopenharmony_ci return 0; 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_cistatic unsigned int octeon_cf_qc_issue(struct ata_queued_cmd *qc) 76262306a36Sopenharmony_ci{ 76362306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci switch (qc->tf.protocol) { 76662306a36Sopenharmony_ci case ATA_PROT_DMA: 76762306a36Sopenharmony_ci WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci trace_ata_tf_load(ap, &qc->tf); 77062306a36Sopenharmony_ci ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */ 77162306a36Sopenharmony_ci trace_ata_bmdma_setup(ap, &qc->tf, qc->tag); 77262306a36Sopenharmony_ci octeon_cf_dma_setup(qc); /* set up dma */ 77362306a36Sopenharmony_ci trace_ata_bmdma_start(ap, &qc->tf, qc->tag); 77462306a36Sopenharmony_ci octeon_cf_dma_start(qc); /* initiate dma */ 77562306a36Sopenharmony_ci ap->hsm_task_state = HSM_ST_LAST; 77662306a36Sopenharmony_ci break; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci case ATAPI_PROT_DMA: 77962306a36Sopenharmony_ci dev_err(ap->dev, "Error, ATAPI not supported\n"); 78062306a36Sopenharmony_ci BUG(); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci default: 78362306a36Sopenharmony_ci return ata_sff_qc_issue(qc); 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return 0; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic struct ata_port_operations octeon_cf_ops = { 79062306a36Sopenharmony_ci .inherits = &ata_sff_port_ops, 79162306a36Sopenharmony_ci .check_atapi_dma = octeon_cf_check_atapi_dma, 79262306a36Sopenharmony_ci .qc_prep = ata_noop_qc_prep, 79362306a36Sopenharmony_ci .qc_issue = octeon_cf_qc_issue, 79462306a36Sopenharmony_ci .sff_dev_select = octeon_cf_dev_select, 79562306a36Sopenharmony_ci .sff_irq_on = octeon_cf_ata_port_noaction, 79662306a36Sopenharmony_ci .sff_irq_clear = octeon_cf_ata_port_noaction, 79762306a36Sopenharmony_ci .cable_detect = ata_cable_40wire, 79862306a36Sopenharmony_ci .set_piomode = octeon_cf_set_piomode, 79962306a36Sopenharmony_ci .set_dmamode = octeon_cf_set_dmamode, 80062306a36Sopenharmony_ci .dev_config = octeon_cf_dev_config, 80162306a36Sopenharmony_ci}; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic int octeon_cf_probe(struct platform_device *pdev) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct resource *res_cs0, *res_cs1; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci bool is_16bit; 80862306a36Sopenharmony_ci u64 reg; 80962306a36Sopenharmony_ci struct device_node *node; 81062306a36Sopenharmony_ci void __iomem *cs0; 81162306a36Sopenharmony_ci void __iomem *cs1 = NULL; 81262306a36Sopenharmony_ci struct ata_host *host; 81362306a36Sopenharmony_ci struct ata_port *ap; 81462306a36Sopenharmony_ci int irq = 0; 81562306a36Sopenharmony_ci irq_handler_t irq_handler = NULL; 81662306a36Sopenharmony_ci void __iomem *base; 81762306a36Sopenharmony_ci struct octeon_cf_port *cf_port; 81862306a36Sopenharmony_ci u32 bus_width; 81962306a36Sopenharmony_ci int rv; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci node = pdev->dev.of_node; 82262306a36Sopenharmony_ci if (node == NULL) 82362306a36Sopenharmony_ci return -EINVAL; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci cf_port = devm_kzalloc(&pdev->dev, sizeof(*cf_port), GFP_KERNEL); 82662306a36Sopenharmony_ci if (!cf_port) 82762306a36Sopenharmony_ci return -ENOMEM; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci cf_port->is_true_ide = of_property_read_bool(node, "cavium,true-ide"); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (of_property_read_u32(node, "cavium,bus-width", &bus_width) == 0) 83262306a36Sopenharmony_ci is_16bit = (bus_width == 16); 83362306a36Sopenharmony_ci else 83462306a36Sopenharmony_ci is_16bit = false; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci rv = of_property_read_reg(node, 0, ®, NULL); 83762306a36Sopenharmony_ci if (rv < 0) 83862306a36Sopenharmony_ci return rv; 83962306a36Sopenharmony_ci cf_port->cs0 = upper_32_bits(reg); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (cf_port->is_true_ide) { 84262306a36Sopenharmony_ci struct device_node *dma_node; 84362306a36Sopenharmony_ci dma_node = of_parse_phandle(node, 84462306a36Sopenharmony_ci "cavium,dma-engine-handle", 0); 84562306a36Sopenharmony_ci if (dma_node) { 84662306a36Sopenharmony_ci struct platform_device *dma_dev; 84762306a36Sopenharmony_ci dma_dev = of_find_device_by_node(dma_node); 84862306a36Sopenharmony_ci if (dma_dev) { 84962306a36Sopenharmony_ci struct resource *res_dma; 85062306a36Sopenharmony_ci int i; 85162306a36Sopenharmony_ci res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0); 85262306a36Sopenharmony_ci if (!res_dma) { 85362306a36Sopenharmony_ci put_device(&dma_dev->dev); 85462306a36Sopenharmony_ci of_node_put(dma_node); 85562306a36Sopenharmony_ci return -EINVAL; 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci cf_port->dma_base = (u64)devm_ioremap(&pdev->dev, res_dma->start, 85862306a36Sopenharmony_ci resource_size(res_dma)); 85962306a36Sopenharmony_ci if (!cf_port->dma_base) { 86062306a36Sopenharmony_ci put_device(&dma_dev->dev); 86162306a36Sopenharmony_ci of_node_put(dma_node); 86262306a36Sopenharmony_ci return -EINVAL; 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci i = platform_get_irq(dma_dev, 0); 86662306a36Sopenharmony_ci if (i > 0) { 86762306a36Sopenharmony_ci irq = i; 86862306a36Sopenharmony_ci irq_handler = octeon_cf_interrupt; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci put_device(&dma_dev->dev); 87162306a36Sopenharmony_ci } 87262306a36Sopenharmony_ci of_node_put(dma_node); 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 87562306a36Sopenharmony_ci if (!res_cs1) 87662306a36Sopenharmony_ci return -EINVAL; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci cs1 = devm_ioremap(&pdev->dev, res_cs1->start, 87962306a36Sopenharmony_ci resource_size(res_cs1)); 88062306a36Sopenharmony_ci if (!cs1) 88162306a36Sopenharmony_ci return -EINVAL; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci rv = of_property_read_reg(node, 1, ®, NULL); 88462306a36Sopenharmony_ci if (rv < 0) 88562306a36Sopenharmony_ci return rv; 88662306a36Sopenharmony_ci cf_port->cs1 = upper_32_bits(reg); 88762306a36Sopenharmony_ci } 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); 89062306a36Sopenharmony_ci if (!res_cs0) 89162306a36Sopenharmony_ci return -EINVAL; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci cs0 = devm_ioremap(&pdev->dev, res_cs0->start, 89462306a36Sopenharmony_ci resource_size(res_cs0)); 89562306a36Sopenharmony_ci if (!cs0) 89662306a36Sopenharmony_ci return -ENOMEM; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci /* allocate host */ 89962306a36Sopenharmony_ci host = ata_host_alloc(&pdev->dev, 1); 90062306a36Sopenharmony_ci if (!host) 90162306a36Sopenharmony_ci return -ENOMEM; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci ap = host->ports[0]; 90462306a36Sopenharmony_ci ap->private_data = cf_port; 90562306a36Sopenharmony_ci pdev->dev.platform_data = cf_port; 90662306a36Sopenharmony_ci cf_port->ap = ap; 90762306a36Sopenharmony_ci ap->ops = &octeon_cf_ops; 90862306a36Sopenharmony_ci ap->pio_mask = ATA_PIO6; 90962306a36Sopenharmony_ci ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if (!is_16bit) { 91262306a36Sopenharmony_ci base = cs0 + 0x800; 91362306a36Sopenharmony_ci ap->ioaddr.cmd_addr = base; 91462306a36Sopenharmony_ci ata_sff_std_ports(&ap->ioaddr); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci ap->ioaddr.altstatus_addr = base + 0xe; 91762306a36Sopenharmony_ci ap->ioaddr.ctl_addr = base + 0xe; 91862306a36Sopenharmony_ci octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8; 91962306a36Sopenharmony_ci } else if (cf_port->is_true_ide) { 92062306a36Sopenharmony_ci base = cs0; 92162306a36Sopenharmony_ci ap->ioaddr.cmd_addr = base + (ATA_REG_CMD << 1) + 1; 92262306a36Sopenharmony_ci ap->ioaddr.data_addr = base + (ATA_REG_DATA << 1); 92362306a36Sopenharmony_ci ap->ioaddr.error_addr = base + (ATA_REG_ERR << 1) + 1; 92462306a36Sopenharmony_ci ap->ioaddr.feature_addr = base + (ATA_REG_FEATURE << 1) + 1; 92562306a36Sopenharmony_ci ap->ioaddr.nsect_addr = base + (ATA_REG_NSECT << 1) + 1; 92662306a36Sopenharmony_ci ap->ioaddr.lbal_addr = base + (ATA_REG_LBAL << 1) + 1; 92762306a36Sopenharmony_ci ap->ioaddr.lbam_addr = base + (ATA_REG_LBAM << 1) + 1; 92862306a36Sopenharmony_ci ap->ioaddr.lbah_addr = base + (ATA_REG_LBAH << 1) + 1; 92962306a36Sopenharmony_ci ap->ioaddr.device_addr = base + (ATA_REG_DEVICE << 1) + 1; 93062306a36Sopenharmony_ci ap->ioaddr.status_addr = base + (ATA_REG_STATUS << 1) + 1; 93162306a36Sopenharmony_ci ap->ioaddr.command_addr = base + (ATA_REG_CMD << 1) + 1; 93262306a36Sopenharmony_ci ap->ioaddr.altstatus_addr = cs1 + (6 << 1) + 1; 93362306a36Sopenharmony_ci ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1; 93462306a36Sopenharmony_ci octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci ap->mwdma_mask = enable_dma ? ATA_MWDMA4 : 0; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci /* True IDE mode needs a timer to poll for not-busy. */ 93962306a36Sopenharmony_ci hrtimer_init(&cf_port->delayed_finish, CLOCK_MONOTONIC, 94062306a36Sopenharmony_ci HRTIMER_MODE_REL); 94162306a36Sopenharmony_ci cf_port->delayed_finish.function = octeon_cf_delayed_finish; 94262306a36Sopenharmony_ci } else { 94362306a36Sopenharmony_ci /* 16 bit but not True IDE */ 94462306a36Sopenharmony_ci base = cs0 + 0x800; 94562306a36Sopenharmony_ci octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; 94662306a36Sopenharmony_ci octeon_cf_ops.softreset = octeon_cf_softreset16; 94762306a36Sopenharmony_ci octeon_cf_ops.sff_check_status = octeon_cf_check_status16; 94862306a36Sopenharmony_ci octeon_cf_ops.sff_tf_read = octeon_cf_tf_read16; 94962306a36Sopenharmony_ci octeon_cf_ops.sff_tf_load = octeon_cf_tf_load16; 95062306a36Sopenharmony_ci octeon_cf_ops.sff_exec_command = octeon_cf_exec_command16; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci ap->ioaddr.data_addr = base + ATA_REG_DATA; 95362306a36Sopenharmony_ci ap->ioaddr.nsect_addr = base + ATA_REG_NSECT; 95462306a36Sopenharmony_ci ap->ioaddr.lbal_addr = base + ATA_REG_LBAL; 95562306a36Sopenharmony_ci ap->ioaddr.ctl_addr = base + 0xe; 95662306a36Sopenharmony_ci ap->ioaddr.altstatus_addr = base + 0xe; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci cf_port->c0 = ap->ioaddr.ctl_addr; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci rv = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 96162306a36Sopenharmony_ci if (rv) 96262306a36Sopenharmony_ci return rv; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n", 96762306a36Sopenharmony_ci is_16bit ? 16 : 8, 96862306a36Sopenharmony_ci cf_port->is_true_ide ? ", True IDE" : ""); 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci return ata_host_activate(host, irq, irq_handler, 97162306a36Sopenharmony_ci IRQF_SHARED, &octeon_cf_sht); 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cistatic void octeon_cf_shutdown(struct device *dev) 97562306a36Sopenharmony_ci{ 97662306a36Sopenharmony_ci union cvmx_mio_boot_dma_cfgx dma_cfg; 97762306a36Sopenharmony_ci union cvmx_mio_boot_dma_intx dma_int; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci struct octeon_cf_port *cf_port = dev_get_platdata(dev); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci if (cf_port->dma_base) { 98262306a36Sopenharmony_ci /* Stop and clear the dma engine. */ 98362306a36Sopenharmony_ci dma_cfg.u64 = 0; 98462306a36Sopenharmony_ci dma_cfg.s.size = -1; 98562306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci /* Disable the interrupt. */ 98862306a36Sopenharmony_ci dma_int.u64 = 0; 98962306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci /* Clear the DMA complete status */ 99262306a36Sopenharmony_ci dma_int.s.done = 1; 99362306a36Sopenharmony_ci cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci __raw_writeb(0, cf_port->c0); 99662306a36Sopenharmony_ci udelay(20); 99762306a36Sopenharmony_ci __raw_writeb(ATA_SRST, cf_port->c0); 99862306a36Sopenharmony_ci udelay(20); 99962306a36Sopenharmony_ci __raw_writeb(0, cf_port->c0); 100062306a36Sopenharmony_ci mdelay(100); 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_cistatic const struct of_device_id octeon_cf_match[] = { 100562306a36Sopenharmony_ci { .compatible = "cavium,ebt3000-compact-flash", }, 100662306a36Sopenharmony_ci { /* sentinel */ } 100762306a36Sopenharmony_ci}; 100862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, octeon_cf_match); 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_cistatic struct platform_driver octeon_cf_driver = { 101162306a36Sopenharmony_ci .probe = octeon_cf_probe, 101262306a36Sopenharmony_ci .driver = { 101362306a36Sopenharmony_ci .name = DRV_NAME, 101462306a36Sopenharmony_ci .of_match_table = octeon_cf_match, 101562306a36Sopenharmony_ci .shutdown = octeon_cf_shutdown 101662306a36Sopenharmony_ci }, 101762306a36Sopenharmony_ci}; 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_cistatic int __init octeon_cf_init(void) 102062306a36Sopenharmony_ci{ 102162306a36Sopenharmony_ci return platform_driver_register(&octeon_cf_driver); 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ciMODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); 102662306a36Sopenharmony_ciMODULE_DESCRIPTION("low-level driver for Cavium OCTEON Compact Flash PATA"); 102762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 102862306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 102962306a36Sopenharmony_ciMODULE_ALIAS("platform:" DRV_NAME); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cimodule_init(octeon_cf_init); 1032