162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Ported to libata by: 662306a36Sopenharmony_ci * Albert Lee <albertcc@tw.ibm.com> IBM Corporation 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> 962306a36Sopenharmony_ci * Portions Copyright (C) 1999 Promise Technology, Inc. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Author: Frank Tiernan (frankt@promise.com) 1262306a36Sopenharmony_ci * Released under terms of General Public License 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * libata documentation is available via 'make {ps|pdf}docs', 1562306a36Sopenharmony_ci * as Documentation/driver-api/libata.rst 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Hardware information only available under NDA. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci#include <linux/kernel.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/pci.h> 2262306a36Sopenharmony_ci#include <linux/blkdev.h> 2362306a36Sopenharmony_ci#include <linux/delay.h> 2462306a36Sopenharmony_ci#include <linux/device.h> 2562306a36Sopenharmony_ci#include <linux/ktime.h> 2662306a36Sopenharmony_ci#include <scsi/scsi.h> 2762306a36Sopenharmony_ci#include <scsi/scsi_host.h> 2862306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 2962306a36Sopenharmony_ci#include <linux/libata.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define DRV_NAME "pata_pdc2027x" 3262306a36Sopenharmony_ci#define DRV_VERSION "1.0" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cienum { 3562306a36Sopenharmony_ci PDC_MMIO_BAR = 5, 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci PDC_UDMA_100 = 0, 3862306a36Sopenharmony_ci PDC_UDMA_133 = 1, 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci PDC_100_MHZ = 100000000, 4162306a36Sopenharmony_ci PDC_133_MHZ = 133333333, 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci PDC_SYS_CTL = 0x1100, 4462306a36Sopenharmony_ci PDC_ATA_CTL = 0x1104, 4562306a36Sopenharmony_ci PDC_GLOBAL_CTL = 0x1108, 4662306a36Sopenharmony_ci PDC_CTCR0 = 0x110C, 4762306a36Sopenharmony_ci PDC_CTCR1 = 0x1110, 4862306a36Sopenharmony_ci PDC_BYTE_COUNT = 0x1120, 4962306a36Sopenharmony_ci PDC_PLL_CTL = 0x1202, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 5362306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 5462306a36Sopenharmony_cistatic int pdc2027x_reinit_one(struct pci_dev *pdev); 5562306a36Sopenharmony_ci#endif 5662306a36Sopenharmony_cistatic int pdc2027x_prereset(struct ata_link *link, unsigned long deadline); 5762306a36Sopenharmony_cistatic void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev); 5862306a36Sopenharmony_cistatic void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev); 5962306a36Sopenharmony_cistatic int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc); 6062306a36Sopenharmony_cistatic unsigned int pdc2027x_mode_filter(struct ata_device *adev, unsigned int mask); 6162306a36Sopenharmony_cistatic int pdc2027x_cable_detect(struct ata_port *ap); 6262306a36Sopenharmony_cistatic int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci * ATA Timing Tables based on 133MHz controller clock. 6662306a36Sopenharmony_ci * These tables are only used when the controller is in 133MHz clock. 6762306a36Sopenharmony_ci * If the controller is in 100MHz clock, the ASIC hardware will 6862306a36Sopenharmony_ci * set the timing registers automatically when "set feature" command 6962306a36Sopenharmony_ci * is issued to the device. However, if the controller clock is 133MHz, 7062306a36Sopenharmony_ci * the following tables must be used. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_cistatic const struct pdc2027x_pio_timing { 7362306a36Sopenharmony_ci u8 value0, value1, value2; 7462306a36Sopenharmony_ci} pdc2027x_pio_timing_tbl[] = { 7562306a36Sopenharmony_ci { 0xfb, 0x2b, 0xac }, /* PIO mode 0 */ 7662306a36Sopenharmony_ci { 0x46, 0x29, 0xa4 }, /* PIO mode 1 */ 7762306a36Sopenharmony_ci { 0x23, 0x26, 0x64 }, /* PIO mode 2 */ 7862306a36Sopenharmony_ci { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ 7962306a36Sopenharmony_ci { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic const struct pdc2027x_mdma_timing { 8362306a36Sopenharmony_ci u8 value0, value1; 8462306a36Sopenharmony_ci} pdc2027x_mdma_timing_tbl[] = { 8562306a36Sopenharmony_ci { 0xdf, 0x5f }, /* MDMA mode 0 */ 8662306a36Sopenharmony_ci { 0x6b, 0x27 }, /* MDMA mode 1 */ 8762306a36Sopenharmony_ci { 0x69, 0x25 }, /* MDMA mode 2 */ 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic const struct pdc2027x_udma_timing { 9162306a36Sopenharmony_ci u8 value0, value1, value2; 9262306a36Sopenharmony_ci} pdc2027x_udma_timing_tbl[] = { 9362306a36Sopenharmony_ci { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ 9462306a36Sopenharmony_ci { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ 9562306a36Sopenharmony_ci { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ 9662306a36Sopenharmony_ci { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ 9762306a36Sopenharmony_ci { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ 9862306a36Sopenharmony_ci { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ 9962306a36Sopenharmony_ci { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic const struct pci_device_id pdc2027x_pci_tbl[] = { 10362306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), PDC_UDMA_100 }, 10462306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), PDC_UDMA_133 }, 10562306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), PDC_UDMA_100 }, 10662306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), PDC_UDMA_133 }, 10762306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), PDC_UDMA_133 }, 10862306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), PDC_UDMA_133 }, 10962306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), PDC_UDMA_133 }, 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci { } /* terminate list */ 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic struct pci_driver pdc2027x_pci_driver = { 11562306a36Sopenharmony_ci .name = DRV_NAME, 11662306a36Sopenharmony_ci .id_table = pdc2027x_pci_tbl, 11762306a36Sopenharmony_ci .probe = pdc2027x_init_one, 11862306a36Sopenharmony_ci .remove = ata_pci_remove_one, 11962306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 12062306a36Sopenharmony_ci .suspend = ata_pci_device_suspend, 12162306a36Sopenharmony_ci .resume = pdc2027x_reinit_one, 12262306a36Sopenharmony_ci#endif 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic const struct scsi_host_template pdc2027x_sht = { 12662306a36Sopenharmony_ci ATA_BMDMA_SHT(DRV_NAME), 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic struct ata_port_operations pdc2027x_pata100_ops = { 13062306a36Sopenharmony_ci .inherits = &ata_bmdma_port_ops, 13162306a36Sopenharmony_ci .check_atapi_dma = pdc2027x_check_atapi_dma, 13262306a36Sopenharmony_ci .cable_detect = pdc2027x_cable_detect, 13362306a36Sopenharmony_ci .prereset = pdc2027x_prereset, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic struct ata_port_operations pdc2027x_pata133_ops = { 13762306a36Sopenharmony_ci .inherits = &pdc2027x_pata100_ops, 13862306a36Sopenharmony_ci .mode_filter = pdc2027x_mode_filter, 13962306a36Sopenharmony_ci .set_piomode = pdc2027x_set_piomode, 14062306a36Sopenharmony_ci .set_dmamode = pdc2027x_set_dmamode, 14162306a36Sopenharmony_ci .set_mode = pdc2027x_set_mode, 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic struct ata_port_info pdc2027x_port_info[] = { 14562306a36Sopenharmony_ci /* PDC_UDMA_100 */ 14662306a36Sopenharmony_ci { 14762306a36Sopenharmony_ci .flags = ATA_FLAG_SLAVE_POSS, 14862306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 14962306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 15062306a36Sopenharmony_ci .udma_mask = ATA_UDMA5, 15162306a36Sopenharmony_ci .port_ops = &pdc2027x_pata100_ops, 15262306a36Sopenharmony_ci }, 15362306a36Sopenharmony_ci /* PDC_UDMA_133 */ 15462306a36Sopenharmony_ci { 15562306a36Sopenharmony_ci .flags = ATA_FLAG_SLAVE_POSS, 15662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 15762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 15862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 15962306a36Sopenharmony_ci .port_ops = &pdc2027x_pata133_ops, 16062306a36Sopenharmony_ci }, 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciMODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee"); 16462306a36Sopenharmony_ciMODULE_DESCRIPTION("libata driver module for Promise PDC20268 to PDC20277"); 16562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 16662306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 16762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pdc2027x_pci_tbl); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/** 17062306a36Sopenharmony_ci * port_mmio - Get the MMIO address of PDC2027x extended registers 17162306a36Sopenharmony_ci * @ap: Port 17262306a36Sopenharmony_ci * @offset: offset from mmio base 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_cistatic inline void __iomem *port_mmio(struct ata_port *ap, unsigned int offset) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci return ap->host->iomap[PDC_MMIO_BAR] + ap->port_no * 0x100 + offset; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/** 18062306a36Sopenharmony_ci * dev_mmio - Get the MMIO address of PDC2027x extended registers 18162306a36Sopenharmony_ci * @ap: Port 18262306a36Sopenharmony_ci * @adev: device 18362306a36Sopenharmony_ci * @offset: offset from mmio base 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_cistatic inline void __iomem *dev_mmio(struct ata_port *ap, struct ata_device *adev, unsigned int offset) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci u8 adj = (adev->devno) ? 0x08 : 0x00; 18862306a36Sopenharmony_ci return port_mmio(ap, offset) + adj; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci/** 19262306a36Sopenharmony_ci * pdc2027x_cable_detect - Probe host controller cable detect info 19362306a36Sopenharmony_ci * @ap: Port for which cable detect info is desired 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * Read 80c cable indicator from Promise extended register. 19662306a36Sopenharmony_ci * This register is latched when the system is reset. 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * LOCKING: 19962306a36Sopenharmony_ci * None (inherited from caller). 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_cistatic int pdc2027x_cable_detect(struct ata_port *ap) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci u32 cgcr; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* check cable detect results */ 20662306a36Sopenharmony_ci cgcr = ioread32(port_mmio(ap, PDC_GLOBAL_CTL)); 20762306a36Sopenharmony_ci if (cgcr & (1 << 26)) 20862306a36Sopenharmony_ci goto cbl40; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci ata_port_dbg(ap, "No cable or 80-conductor cable\n"); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return ATA_CBL_PATA80; 21362306a36Sopenharmony_cicbl40: 21462306a36Sopenharmony_ci ata_port_info(ap, DRV_NAME ":40-conductor cable detected\n"); 21562306a36Sopenharmony_ci return ATA_CBL_PATA40; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * pdc2027x_port_enabled - Check PDC ATA control register to see whether the port is enabled. 22062306a36Sopenharmony_ci * @ap: Port to check 22162306a36Sopenharmony_ci */ 22262306a36Sopenharmony_cistatic inline int pdc2027x_port_enabled(struct ata_port *ap) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci return ioread8(port_mmio(ap, PDC_ATA_CTL)) & 0x02; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/** 22862306a36Sopenharmony_ci * pdc2027x_prereset - prereset for PATA host controller 22962306a36Sopenharmony_ci * @link: Target link 23062306a36Sopenharmony_ci * @deadline: deadline jiffies for the operation 23162306a36Sopenharmony_ci * 23262306a36Sopenharmony_ci * Probeinit including cable detection. 23362306a36Sopenharmony_ci * 23462306a36Sopenharmony_ci * LOCKING: 23562306a36Sopenharmony_ci * None (inherited from caller). 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int pdc2027x_prereset(struct ata_link *link, unsigned long deadline) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci /* Check whether port enabled */ 24162306a36Sopenharmony_ci if (!pdc2027x_port_enabled(link->ap)) 24262306a36Sopenharmony_ci return -ENOENT; 24362306a36Sopenharmony_ci return ata_sff_prereset(link, deadline); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/** 24762306a36Sopenharmony_ci * pdc2027x_mode_filter - mode selection filter 24862306a36Sopenharmony_ci * @adev: ATA device 24962306a36Sopenharmony_ci * @mask: list of modes proposed 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * Block UDMA on devices that cause trouble with this controller. 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic unsigned int pdc2027x_mode_filter(struct ata_device *adev, unsigned int mask) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci unsigned char model_num[ATA_ID_PROD_LEN + 1]; 25762306a36Sopenharmony_ci struct ata_device *pair = ata_dev_pair(adev); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (adev->class != ATA_DEV_ATA || adev->devno == 0 || pair == NULL) 26062306a36Sopenharmony_ci return mask; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Check for slave of a Maxtor at UDMA6 */ 26362306a36Sopenharmony_ci ata_id_c_string(pair->id, model_num, ATA_ID_PROD, 26462306a36Sopenharmony_ci ATA_ID_PROD_LEN + 1); 26562306a36Sopenharmony_ci /* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */ 26662306a36Sopenharmony_ci if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6) 26762306a36Sopenharmony_ci mask &= ~ (1 << (6 + ATA_SHIFT_UDMA)); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return mask; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci/** 27362306a36Sopenharmony_ci * pdc2027x_set_piomode - Initialize host controller PATA PIO timings 27462306a36Sopenharmony_ci * @ap: Port to configure 27562306a36Sopenharmony_ci * @adev: um 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * Set PIO mode for device. 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * LOCKING: 28062306a36Sopenharmony_ci * None (inherited from caller). 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci unsigned int pio = adev->pio_mode - XFER_PIO_0; 28662306a36Sopenharmony_ci u32 ctcr0, ctcr1; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci ata_port_dbg(ap, "adev->pio_mode[%X]\n", adev->pio_mode); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* Sanity check */ 29162306a36Sopenharmony_ci if (pio > 4) { 29262306a36Sopenharmony_ci ata_port_err(ap, "Unknown pio mode [%d] ignored\n", pio); 29362306a36Sopenharmony_ci return; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* Set the PIO timing registers using value table for 133MHz */ 29862306a36Sopenharmony_ci ata_port_dbg(ap, "Set pio regs... \n"); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0)); 30162306a36Sopenharmony_ci ctcr0 &= 0xffff0000; 30262306a36Sopenharmony_ci ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 | 30362306a36Sopenharmony_ci (pdc2027x_pio_timing_tbl[pio].value1 << 8); 30462306a36Sopenharmony_ci iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); 30762306a36Sopenharmony_ci ctcr1 &= 0x00ffffff; 30862306a36Sopenharmony_ci ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); 30962306a36Sopenharmony_ci iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci ata_port_dbg(ap, "Set to pio mode[%u] \n", pio); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci/** 31562306a36Sopenharmony_ci * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings 31662306a36Sopenharmony_ci * @ap: Port to configure 31762306a36Sopenharmony_ci * @adev: um 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * Set UDMA mode for device. 32062306a36Sopenharmony_ci * 32162306a36Sopenharmony_ci * LOCKING: 32262306a36Sopenharmony_ci * None (inherited from caller). 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_cistatic void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci unsigned int dma_mode = adev->dma_mode; 32762306a36Sopenharmony_ci u32 ctcr0, ctcr1; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if ((dma_mode >= XFER_UDMA_0) && 33062306a36Sopenharmony_ci (dma_mode <= XFER_UDMA_6)) { 33162306a36Sopenharmony_ci /* Set the UDMA timing registers with value table for 133MHz */ 33262306a36Sopenharmony_ci unsigned int udma_mode = dma_mode & 0x07; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (dma_mode == XFER_UDMA_2) { 33562306a36Sopenharmony_ci /* 33662306a36Sopenharmony_ci * Turn off tHOLD. 33762306a36Sopenharmony_ci * If tHOLD is '1', the hardware will add half clock for data hold time. 33862306a36Sopenharmony_ci * This code segment seems to be no effect. tHOLD will be overwritten below. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); 34162306a36Sopenharmony_ci iowrite32(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci ata_port_dbg(ap, "Set udma regs... \n"); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1)); 34762306a36Sopenharmony_ci ctcr1 &= 0xff000000; 34862306a36Sopenharmony_ci ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 | 34962306a36Sopenharmony_ci (pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) | 35062306a36Sopenharmony_ci (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); 35162306a36Sopenharmony_ci iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci ata_port_dbg(ap, "Set to udma mode[%u] \n", udma_mode); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci } else if ((dma_mode >= XFER_MW_DMA_0) && 35662306a36Sopenharmony_ci (dma_mode <= XFER_MW_DMA_2)) { 35762306a36Sopenharmony_ci /* Set the MDMA timing registers with value table for 133MHz */ 35862306a36Sopenharmony_ci unsigned int mdma_mode = dma_mode & 0x07; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci ata_port_dbg(ap, "Set mdma regs... \n"); 36162306a36Sopenharmony_ci ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0)); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci ctcr0 &= 0x0000ffff; 36462306a36Sopenharmony_ci ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) | 36562306a36Sopenharmony_ci (pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ata_port_dbg(ap, "Set to mdma mode[%u] \n", mdma_mode); 37062306a36Sopenharmony_ci } else { 37162306a36Sopenharmony_ci ata_port_err(ap, "Unknown dma mode [%u] ignored\n", dma_mode); 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/** 37662306a36Sopenharmony_ci * pdc2027x_set_mode - Set the timing registers back to correct values. 37762306a36Sopenharmony_ci * @link: link to configure 37862306a36Sopenharmony_ci * @r_failed: Returned device for failure 37962306a36Sopenharmony_ci * 38062306a36Sopenharmony_ci * The pdc2027x hardware will look at "SET FEATURES" and change the timing registers 38162306a36Sopenharmony_ci * automatically. The values set by the hardware might be incorrect, under 133Mhz PLL. 38262306a36Sopenharmony_ci * This function overwrites the possibly incorrect values set by the hardware to be correct. 38362306a36Sopenharmony_ci */ 38462306a36Sopenharmony_cistatic int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci struct ata_port *ap = link->ap; 38762306a36Sopenharmony_ci struct ata_device *dev; 38862306a36Sopenharmony_ci int rc; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci rc = ata_do_set_mode(link, r_failed); 39162306a36Sopenharmony_ci if (rc < 0) 39262306a36Sopenharmony_ci return rc; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci ata_for_each_dev(dev, link, ENABLED) { 39562306a36Sopenharmony_ci pdc2027x_set_piomode(ap, dev); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci /* 39862306a36Sopenharmony_ci * Enable prefetch if the device support PIO only. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ci if (dev->xfer_shift == ATA_SHIFT_PIO) { 40162306a36Sopenharmony_ci u32 ctcr1 = ioread32(dev_mmio(ap, dev, PDC_CTCR1)); 40262306a36Sopenharmony_ci ctcr1 |= (1 << 25); 40362306a36Sopenharmony_ci iowrite32(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci ata_dev_dbg(dev, "Turn on prefetch\n"); 40662306a36Sopenharmony_ci } else { 40762306a36Sopenharmony_ci pdc2027x_set_dmamode(ap, dev); 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci return 0; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci/** 41462306a36Sopenharmony_ci * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command 41562306a36Sopenharmony_ci * @qc: Metadata associated with taskfile to check 41662306a36Sopenharmony_ci * 41762306a36Sopenharmony_ci * LOCKING: 41862306a36Sopenharmony_ci * None (inherited from caller). 41962306a36Sopenharmony_ci * 42062306a36Sopenharmony_ci * RETURNS: 0 when ATAPI DMA can be used 42162306a36Sopenharmony_ci * 1 otherwise 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_cistatic int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 42662306a36Sopenharmony_ci u8 *scsicmd = cmd->cmnd; 42762306a36Sopenharmony_ci int rc = 1; /* atapi dma off by default */ 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci /* 43062306a36Sopenharmony_ci * This workaround is from Promise's GPL driver. 43162306a36Sopenharmony_ci * If ATAPI DMA is used for commands not in the 43262306a36Sopenharmony_ci * following white list, say MODE_SENSE and REQUEST_SENSE, 43362306a36Sopenharmony_ci * pdc2027x might hit the irq lost problem. 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_ci switch (scsicmd[0]) { 43662306a36Sopenharmony_ci case READ_10: 43762306a36Sopenharmony_ci case WRITE_10: 43862306a36Sopenharmony_ci case READ_12: 43962306a36Sopenharmony_ci case WRITE_12: 44062306a36Sopenharmony_ci case READ_6: 44162306a36Sopenharmony_ci case WRITE_6: 44262306a36Sopenharmony_ci case 0xad: /* READ_DVD_STRUCTURE */ 44362306a36Sopenharmony_ci case 0xbe: /* READ_CD */ 44462306a36Sopenharmony_ci /* ATAPI DMA is ok */ 44562306a36Sopenharmony_ci rc = 0; 44662306a36Sopenharmony_ci break; 44762306a36Sopenharmony_ci default: 44862306a36Sopenharmony_ci ; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci return rc; 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci/** 45562306a36Sopenharmony_ci * pdc_read_counter - Read the ctr counter 45662306a36Sopenharmony_ci * @host: target ATA host 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic long pdc_read_counter(struct ata_host *host) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR]; 46262306a36Sopenharmony_ci long counter; 46362306a36Sopenharmony_ci int retry = 1; 46462306a36Sopenharmony_ci u32 bccrl, bccrh, bccrlv, bccrhv; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ciretry: 46762306a36Sopenharmony_ci bccrl = ioread32(mmio_base + PDC_BYTE_COUNT) & 0x7fff; 46862306a36Sopenharmony_ci bccrh = ioread32(mmio_base + PDC_BYTE_COUNT + 0x100) & 0x7fff; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* Read the counter values again for verification */ 47162306a36Sopenharmony_ci bccrlv = ioread32(mmio_base + PDC_BYTE_COUNT) & 0x7fff; 47262306a36Sopenharmony_ci bccrhv = ioread32(mmio_base + PDC_BYTE_COUNT + 0x100) & 0x7fff; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci counter = (bccrh << 15) | bccrl; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci dev_dbg(host->dev, "bccrh [%X] bccrl [%X]\n", bccrh, bccrl); 47762306a36Sopenharmony_ci dev_dbg(host->dev, "bccrhv[%X] bccrlv[%X]\n", bccrhv, bccrlv); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci /* 48062306a36Sopenharmony_ci * The 30-bit decreasing counter are read by 2 pieces. 48162306a36Sopenharmony_ci * Incorrect value may be read when both bccrh and bccrl are changing. 48262306a36Sopenharmony_ci * Ex. When 7900 decrease to 78FF, wrong value 7800 might be read. 48362306a36Sopenharmony_ci */ 48462306a36Sopenharmony_ci if (retry && !(bccrh == bccrhv && bccrl >= bccrlv)) { 48562306a36Sopenharmony_ci retry--; 48662306a36Sopenharmony_ci dev_dbg(host->dev, "rereading counter\n"); 48762306a36Sopenharmony_ci goto retry; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci return counter; 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci/** 49462306a36Sopenharmony_ci * pdc_adjust_pll - Adjust the PLL input clock in Hz. 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * @host: target ATA host 49762306a36Sopenharmony_ci * @pll_clock: The input of PLL in HZ 49862306a36Sopenharmony_ci * @board_idx: board identifier 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_cistatic void pdc_adjust_pll(struct ata_host *host, long pll_clock, unsigned int board_idx) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR]; 50362306a36Sopenharmony_ci u16 pll_ctl; 50462306a36Sopenharmony_ci long pll_clock_khz = pll_clock / 1000; 50562306a36Sopenharmony_ci long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ; 50662306a36Sopenharmony_ci long ratio = pout_required / pll_clock_khz; 50762306a36Sopenharmony_ci int F, R; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci /* Sanity check */ 51062306a36Sopenharmony_ci if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) { 51162306a36Sopenharmony_ci dev_err(host->dev, "Invalid PLL input clock %ldkHz, give up!\n", 51262306a36Sopenharmony_ci pll_clock_khz); 51362306a36Sopenharmony_ci return; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci dev_dbg(host->dev, "pout_required is %ld\n", pout_required); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* Show the current clock value of PLL control register 51962306a36Sopenharmony_ci * (maybe already configured by the firmware) 52062306a36Sopenharmony_ci */ 52162306a36Sopenharmony_ci pll_ctl = ioread16(mmio_base + PDC_PLL_CTL); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci dev_dbg(host->dev, "pll_ctl[%X]\n", pll_ctl); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci /* 52662306a36Sopenharmony_ci * Calculate the ratio of F, R and OD 52762306a36Sopenharmony_ci * POUT = (F + 2) / (( R + 2) * NO) 52862306a36Sopenharmony_ci */ 52962306a36Sopenharmony_ci if (ratio < 8600L) { /* 8.6x */ 53062306a36Sopenharmony_ci /* Using NO = 0x01, R = 0x0D */ 53162306a36Sopenharmony_ci R = 0x0d; 53262306a36Sopenharmony_ci } else if (ratio < 12900L) { /* 12.9x */ 53362306a36Sopenharmony_ci /* Using NO = 0x01, R = 0x08 */ 53462306a36Sopenharmony_ci R = 0x08; 53562306a36Sopenharmony_ci } else if (ratio < 16100L) { /* 16.1x */ 53662306a36Sopenharmony_ci /* Using NO = 0x01, R = 0x06 */ 53762306a36Sopenharmony_ci R = 0x06; 53862306a36Sopenharmony_ci } else if (ratio < 64000L) { /* 64x */ 53962306a36Sopenharmony_ci R = 0x00; 54062306a36Sopenharmony_ci } else { 54162306a36Sopenharmony_ci /* Invalid ratio */ 54262306a36Sopenharmony_ci dev_err(host->dev, "Invalid ratio %ld, give up!\n", ratio); 54362306a36Sopenharmony_ci return; 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci F = (ratio * (R+2)) / 1000 - 2; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci if (unlikely(F < 0 || F > 127)) { 54962306a36Sopenharmony_ci /* Invalid F */ 55062306a36Sopenharmony_ci dev_err(host->dev, "F[%d] invalid!\n", F); 55162306a36Sopenharmony_ci return; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci dev_dbg(host->dev, "F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci pll_ctl = (R << 8) | F; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci dev_dbg(host->dev, "Writing pll_ctl[%X]\n", pll_ctl); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci iowrite16(pll_ctl, mmio_base + PDC_PLL_CTL); 56162306a36Sopenharmony_ci ioread16(mmio_base + PDC_PLL_CTL); /* flush */ 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* Wait the PLL circuit to be stable */ 56462306a36Sopenharmony_ci msleep(30); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci /* 56762306a36Sopenharmony_ci * Show the current clock value of PLL control register 56862306a36Sopenharmony_ci * (maybe configured by the firmware) 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_ci pll_ctl = ioread16(mmio_base + PDC_PLL_CTL); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci dev_dbg(host->dev, "pll_ctl[%X]\n", pll_ctl); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci return; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci/** 57862306a36Sopenharmony_ci * pdc_detect_pll_input_clock - Detect the PLL input clock in Hz. 57962306a36Sopenharmony_ci * @host: target ATA host 58062306a36Sopenharmony_ci * Ex. 16949000 on 33MHz PCI bus for pdc20275. 58162306a36Sopenharmony_ci * Half of the PCI clock. 58262306a36Sopenharmony_ci */ 58362306a36Sopenharmony_cistatic long pdc_detect_pll_input_clock(struct ata_host *host) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR]; 58662306a36Sopenharmony_ci u32 scr; 58762306a36Sopenharmony_ci long start_count, end_count; 58862306a36Sopenharmony_ci ktime_t start_time, end_time; 58962306a36Sopenharmony_ci long pll_clock, usec_elapsed; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /* Start the test mode */ 59262306a36Sopenharmony_ci scr = ioread32(mmio_base + PDC_SYS_CTL); 59362306a36Sopenharmony_ci dev_dbg(host->dev, "scr[%X]\n", scr); 59462306a36Sopenharmony_ci iowrite32(scr | (0x01 << 14), mmio_base + PDC_SYS_CTL); 59562306a36Sopenharmony_ci ioread32(mmio_base + PDC_SYS_CTL); /* flush */ 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* Read current counter value */ 59862306a36Sopenharmony_ci start_count = pdc_read_counter(host); 59962306a36Sopenharmony_ci start_time = ktime_get(); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci /* Let the counter run for 100 ms. */ 60262306a36Sopenharmony_ci msleep(100); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* Read the counter values again */ 60562306a36Sopenharmony_ci end_count = pdc_read_counter(host); 60662306a36Sopenharmony_ci end_time = ktime_get(); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* Stop the test mode */ 60962306a36Sopenharmony_ci scr = ioread32(mmio_base + PDC_SYS_CTL); 61062306a36Sopenharmony_ci dev_dbg(host->dev, "scr[%X]\n", scr); 61162306a36Sopenharmony_ci iowrite32(scr & ~(0x01 << 14), mmio_base + PDC_SYS_CTL); 61262306a36Sopenharmony_ci ioread32(mmio_base + PDC_SYS_CTL); /* flush */ 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* calculate the input clock in Hz */ 61562306a36Sopenharmony_ci usec_elapsed = (long) ktime_us_delta(end_time, start_time); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci pll_clock = ((start_count - end_count) & 0x3fffffff) / 100 * 61862306a36Sopenharmony_ci (100000000 / usec_elapsed); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci dev_dbg(host->dev, "start[%ld] end[%ld] PLL input clock[%ld]HZ\n", 62162306a36Sopenharmony_ci start_count, end_count, pll_clock); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci return pll_clock; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci/** 62762306a36Sopenharmony_ci * pdc_hardware_init - Initialize the hardware. 62862306a36Sopenharmony_ci * @host: target ATA host 62962306a36Sopenharmony_ci * @board_idx: board identifier 63062306a36Sopenharmony_ci */ 63162306a36Sopenharmony_cistatic void pdc_hardware_init(struct ata_host *host, unsigned int board_idx) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci long pll_clock; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* 63662306a36Sopenharmony_ci * Detect PLL input clock rate. 63762306a36Sopenharmony_ci * On some system, where PCI bus is running at non-standard clock rate. 63862306a36Sopenharmony_ci * Ex. 25MHz or 40MHz, we have to adjust the cycle_time. 63962306a36Sopenharmony_ci * The pdc20275 controller employs PLL circuit to help correct timing registers setting. 64062306a36Sopenharmony_ci */ 64162306a36Sopenharmony_ci pll_clock = pdc_detect_pll_input_clock(host); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci dev_info(host->dev, "PLL input clock %ld kHz\n", pll_clock/1000); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci /* Adjust PLL control register */ 64662306a36Sopenharmony_ci pdc_adjust_pll(host, pll_clock, board_idx); 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci/** 65062306a36Sopenharmony_ci * pdc_ata_setup_port - setup the mmio address 65162306a36Sopenharmony_ci * @port: ata ioports to setup 65262306a36Sopenharmony_ci * @base: base address 65362306a36Sopenharmony_ci */ 65462306a36Sopenharmony_cistatic void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci port->cmd_addr = 65762306a36Sopenharmony_ci port->data_addr = base; 65862306a36Sopenharmony_ci port->feature_addr = 65962306a36Sopenharmony_ci port->error_addr = base + 0x05; 66062306a36Sopenharmony_ci port->nsect_addr = base + 0x0a; 66162306a36Sopenharmony_ci port->lbal_addr = base + 0x0f; 66262306a36Sopenharmony_ci port->lbam_addr = base + 0x10; 66362306a36Sopenharmony_ci port->lbah_addr = base + 0x15; 66462306a36Sopenharmony_ci port->device_addr = base + 0x1a; 66562306a36Sopenharmony_ci port->command_addr = 66662306a36Sopenharmony_ci port->status_addr = base + 0x1f; 66762306a36Sopenharmony_ci port->altstatus_addr = 66862306a36Sopenharmony_ci port->ctl_addr = base + 0x81a; 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci/** 67262306a36Sopenharmony_ci * pdc2027x_init_one - PCI probe function 67362306a36Sopenharmony_ci * Called when an instance of PCI adapter is inserted. 67462306a36Sopenharmony_ci * This function checks whether the hardware is supported, 67562306a36Sopenharmony_ci * initialize hardware and register an instance of ata_host to 67662306a36Sopenharmony_ci * libata. (implements struct pci_driver.probe() ) 67762306a36Sopenharmony_ci * 67862306a36Sopenharmony_ci * @pdev: instance of pci_dev found 67962306a36Sopenharmony_ci * @ent: matching entry in the id_tbl[] 68062306a36Sopenharmony_ci */ 68162306a36Sopenharmony_cistatic int pdc2027x_init_one(struct pci_dev *pdev, 68262306a36Sopenharmony_ci const struct pci_device_id *ent) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci static const unsigned long cmd_offset[] = { 0x17c0, 0x15c0 }; 68562306a36Sopenharmony_ci static const unsigned long bmdma_offset[] = { 0x1000, 0x1008 }; 68662306a36Sopenharmony_ci unsigned int board_idx = (unsigned int) ent->driver_data; 68762306a36Sopenharmony_ci const struct ata_port_info *ppi[] = 68862306a36Sopenharmony_ci { &pdc2027x_port_info[board_idx], NULL }; 68962306a36Sopenharmony_ci struct ata_host *host; 69062306a36Sopenharmony_ci void __iomem *mmio_base; 69162306a36Sopenharmony_ci int i, rc; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* alloc host */ 69662306a36Sopenharmony_ci host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); 69762306a36Sopenharmony_ci if (!host) 69862306a36Sopenharmony_ci return -ENOMEM; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* acquire resources and fill host */ 70162306a36Sopenharmony_ci rc = pcim_enable_device(pdev); 70262306a36Sopenharmony_ci if (rc) 70362306a36Sopenharmony_ci return rc; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci rc = pcim_iomap_regions(pdev, 1 << PDC_MMIO_BAR, DRV_NAME); 70662306a36Sopenharmony_ci if (rc) 70762306a36Sopenharmony_ci return rc; 70862306a36Sopenharmony_ci host->iomap = pcim_iomap_table(pdev); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); 71162306a36Sopenharmony_ci if (rc) 71262306a36Sopenharmony_ci return rc; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci mmio_base = host->iomap[PDC_MMIO_BAR]; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 71762306a36Sopenharmony_ci struct ata_port *ap = host->ports[i]; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci pdc_ata_setup_port(&ap->ioaddr, mmio_base + cmd_offset[i]); 72062306a36Sopenharmony_ci ap->ioaddr.bmdma_addr = mmio_base + bmdma_offset[i]; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio"); 72362306a36Sopenharmony_ci ata_port_pbar_desc(ap, PDC_MMIO_BAR, cmd_offset[i], "cmd"); 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci //pci_enable_intx(pdev); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci /* initialize adapter */ 72962306a36Sopenharmony_ci pdc_hardware_init(host, board_idx); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci pci_set_master(pdev); 73262306a36Sopenharmony_ci return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, 73362306a36Sopenharmony_ci IRQF_SHARED, &pdc2027x_sht); 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 73762306a36Sopenharmony_cistatic int pdc2027x_reinit_one(struct pci_dev *pdev) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 74062306a36Sopenharmony_ci unsigned int board_idx; 74162306a36Sopenharmony_ci int rc; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci rc = ata_pci_device_do_resume(pdev); 74462306a36Sopenharmony_ci if (rc) 74562306a36Sopenharmony_ci return rc; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 || 74862306a36Sopenharmony_ci pdev->device == PCI_DEVICE_ID_PROMISE_20270) 74962306a36Sopenharmony_ci board_idx = PDC_UDMA_100; 75062306a36Sopenharmony_ci else 75162306a36Sopenharmony_ci board_idx = PDC_UDMA_133; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci pdc_hardware_init(host, board_idx); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci ata_host_resume(host); 75662306a36Sopenharmony_ci return 0; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci#endif 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cimodule_pci_driver(pdc2027x_pci_driver); 761