162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * sata_promise.c - Promise SATA 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Maintained by: Tejun Heo <tj@kernel.org> 662306a36Sopenharmony_ci * Mikael Pettersson 762306a36Sopenharmony_ci * Please ALWAYS copy linux-ide@vger.kernel.org 862306a36Sopenharmony_ci * on emails. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Copyright 2003-2004 Red Hat, Inc. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * libata documentation is available via 'make {ps|pdf}docs', 1362306a36Sopenharmony_ci * as Documentation/driver-api/libata.rst 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Hardware information only available under NDA. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/kernel.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/gfp.h> 2162306a36Sopenharmony_ci#include <linux/pci.h> 2262306a36Sopenharmony_ci#include <linux/blkdev.h> 2362306a36Sopenharmony_ci#include <linux/delay.h> 2462306a36Sopenharmony_ci#include <linux/interrupt.h> 2562306a36Sopenharmony_ci#include <linux/device.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#include "sata_promise.h" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define DRV_NAME "sata_promise" 3362306a36Sopenharmony_ci#define DRV_VERSION "2.12" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cienum { 3662306a36Sopenharmony_ci PDC_MAX_PORTS = 4, 3762306a36Sopenharmony_ci PDC_MMIO_BAR = 3, 3862306a36Sopenharmony_ci PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* host register offsets (from host->iomap[PDC_MMIO_BAR]) */ 4162306a36Sopenharmony_ci PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ 4262306a36Sopenharmony_ci PDC_FLASH_CTL = 0x44, /* Flash control register */ 4362306a36Sopenharmony_ci PDC_PCI_CTL = 0x48, /* PCI control/status reg */ 4462306a36Sopenharmony_ci PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ 4562306a36Sopenharmony_ci PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ 4662306a36Sopenharmony_ci PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ 4762306a36Sopenharmony_ci PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci /* per-port ATA register offsets (from ap->ioaddr.cmd_addr) */ 5062306a36Sopenharmony_ci PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ 5162306a36Sopenharmony_ci PDC_SECTOR_COUNT = 0x08, /* Sector count reg (per port) */ 5262306a36Sopenharmony_ci PDC_SECTOR_NUMBER = 0x0C, /* Sector number reg (per port) */ 5362306a36Sopenharmony_ci PDC_CYLINDER_LOW = 0x10, /* Cylinder low reg (per port) */ 5462306a36Sopenharmony_ci PDC_CYLINDER_HIGH = 0x14, /* Cylinder high reg (per port) */ 5562306a36Sopenharmony_ci PDC_DEVICE = 0x18, /* Device/Head reg (per port) */ 5662306a36Sopenharmony_ci PDC_COMMAND = 0x1C, /* Command/status reg (per port) */ 5762306a36Sopenharmony_ci PDC_ALTSTATUS = 0x38, /* Alternate-status/device-control reg (per port) */ 5862306a36Sopenharmony_ci PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ 5962306a36Sopenharmony_ci PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ 6062306a36Sopenharmony_ci PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* per-port SATA register offsets (from ap->ioaddr.scr_addr) */ 6362306a36Sopenharmony_ci PDC_SATA_ERROR = 0x04, 6462306a36Sopenharmony_ci PDC_PHYMODE4 = 0x14, 6562306a36Sopenharmony_ci PDC_LINK_LAYER_ERRORS = 0x6C, 6662306a36Sopenharmony_ci PDC_FPDMA_CTLSTAT = 0xD8, 6762306a36Sopenharmony_ci PDC_INTERNAL_DEBUG_1 = 0xF8, /* also used for PATA */ 6862306a36Sopenharmony_ci PDC_INTERNAL_DEBUG_2 = 0xFC, /* also used for PATA */ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* PDC_FPDMA_CTLSTAT bit definitions */ 7162306a36Sopenharmony_ci PDC_FPDMA_CTLSTAT_RESET = 1 << 3, 7262306a36Sopenharmony_ci PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG = 1 << 10, 7362306a36Sopenharmony_ci PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG = 1 << 11, 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* PDC_GLOBAL_CTL bit definitions */ 7662306a36Sopenharmony_ci PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */ 7762306a36Sopenharmony_ci PDC_SH_ERR = (1 << 9), /* PCI error while loading S/G table */ 7862306a36Sopenharmony_ci PDC_DH_ERR = (1 << 10), /* PCI error while loading data */ 7962306a36Sopenharmony_ci PDC2_HTO_ERR = (1 << 12), /* host bus timeout */ 8062306a36Sopenharmony_ci PDC2_ATA_HBA_ERR = (1 << 13), /* error during SATA DATA FIS transmission */ 8162306a36Sopenharmony_ci PDC2_ATA_DMA_CNT_ERR = (1 << 14), /* DMA DATA FIS size differs from S/G count */ 8262306a36Sopenharmony_ci PDC_OVERRUN_ERR = (1 << 19), /* S/G byte count larger than HD requires */ 8362306a36Sopenharmony_ci PDC_UNDERRUN_ERR = (1 << 20), /* S/G byte count less than HD requires */ 8462306a36Sopenharmony_ci PDC_DRIVE_ERR = (1 << 21), /* drive error */ 8562306a36Sopenharmony_ci PDC_PCI_SYS_ERR = (1 << 22), /* PCI system error */ 8662306a36Sopenharmony_ci PDC1_PCI_PARITY_ERR = (1 << 23), /* PCI parity error (from SATA150 driver) */ 8762306a36Sopenharmony_ci PDC1_ERR_MASK = PDC1_PCI_PARITY_ERR, 8862306a36Sopenharmony_ci PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | 8962306a36Sopenharmony_ci PDC2_ATA_DMA_CNT_ERR, 9062306a36Sopenharmony_ci PDC_ERR_MASK = PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | 9162306a36Sopenharmony_ci PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR | 9262306a36Sopenharmony_ci PDC_DRIVE_ERR | PDC_PCI_SYS_ERR | 9362306a36Sopenharmony_ci PDC1_ERR_MASK | PDC2_ERR_MASK, 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci board_2037x = 0, /* FastTrak S150 TX2plus */ 9662306a36Sopenharmony_ci board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */ 9762306a36Sopenharmony_ci board_20319 = 2, /* FastTrak S150 TX4 */ 9862306a36Sopenharmony_ci board_20619 = 3, /* FastTrak TX4000 */ 9962306a36Sopenharmony_ci board_2057x = 4, /* SATAII150 Tx2plus */ 10062306a36Sopenharmony_ci board_2057x_pata = 5, /* SATAII150 Tx2plus PATA port */ 10162306a36Sopenharmony_ci board_40518 = 6, /* SATAII150 Tx4 */ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Sequence counter control registers bit definitions */ 10662306a36Sopenharmony_ci PDC_SEQCNTRL_INT_MASK = (1 << 5), /* Sequence Interrupt Mask */ 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* Feature register values */ 10962306a36Sopenharmony_ci PDC_FEATURE_ATAPI_PIO = 0x00, /* ATAPI data xfer by PIO */ 11062306a36Sopenharmony_ci PDC_FEATURE_ATAPI_DMA = 0x01, /* ATAPI data xfer by DMA */ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* Device/Head register values */ 11362306a36Sopenharmony_ci PDC_DEVICE_SATA = 0xE0, /* Device/Head value for SATA devices */ 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* PDC_CTLSTAT bit definitions */ 11662306a36Sopenharmony_ci PDC_DMA_ENABLE = (1 << 7), 11762306a36Sopenharmony_ci PDC_IRQ_DISABLE = (1 << 10), 11862306a36Sopenharmony_ci PDC_RESET = (1 << 11), /* HDMA reset */ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci PDC_COMMON_FLAGS = ATA_FLAG_PIO_POLLING, 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* ap->flags bits */ 12362306a36Sopenharmony_ci PDC_FLAG_GEN_II = (1 << 24), 12462306a36Sopenharmony_ci PDC_FLAG_SATA_PATA = (1 << 25), /* supports SATA + PATA */ 12562306a36Sopenharmony_ci PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */ 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct pdc_port_priv { 12962306a36Sopenharmony_ci u8 *pkt; 13062306a36Sopenharmony_ci dma_addr_t pkt_dma; 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistruct pdc_host_priv { 13462306a36Sopenharmony_ci spinlock_t hard_reset_lock; 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 13862306a36Sopenharmony_cistatic int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 13962306a36Sopenharmony_cistatic int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 14062306a36Sopenharmony_cistatic int pdc_common_port_start(struct ata_port *ap); 14162306a36Sopenharmony_cistatic int pdc_sata_port_start(struct ata_port *ap); 14262306a36Sopenharmony_cistatic enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc); 14362306a36Sopenharmony_cistatic void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 14462306a36Sopenharmony_cistatic void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 14562306a36Sopenharmony_cistatic int pdc_check_atapi_dma(struct ata_queued_cmd *qc); 14662306a36Sopenharmony_cistatic int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc); 14762306a36Sopenharmony_cistatic void pdc_irq_clear(struct ata_port *ap); 14862306a36Sopenharmony_cistatic unsigned int pdc_qc_issue(struct ata_queued_cmd *qc); 14962306a36Sopenharmony_cistatic void pdc_freeze(struct ata_port *ap); 15062306a36Sopenharmony_cistatic void pdc_sata_freeze(struct ata_port *ap); 15162306a36Sopenharmony_cistatic void pdc_thaw(struct ata_port *ap); 15262306a36Sopenharmony_cistatic void pdc_sata_thaw(struct ata_port *ap); 15362306a36Sopenharmony_cistatic int pdc_pata_softreset(struct ata_link *link, unsigned int *class, 15462306a36Sopenharmony_ci unsigned long deadline); 15562306a36Sopenharmony_cistatic int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, 15662306a36Sopenharmony_ci unsigned long deadline); 15762306a36Sopenharmony_cistatic void pdc_error_handler(struct ata_port *ap); 15862306a36Sopenharmony_cistatic void pdc_post_internal_cmd(struct ata_queued_cmd *qc); 15962306a36Sopenharmony_cistatic int pdc_pata_cable_detect(struct ata_port *ap); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic const struct scsi_host_template pdc_ata_sht = { 16262306a36Sopenharmony_ci ATA_BASE_SHT(DRV_NAME), 16362306a36Sopenharmony_ci .sg_tablesize = PDC_MAX_PRD, 16462306a36Sopenharmony_ci .dma_boundary = ATA_DMA_BOUNDARY, 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic const struct ata_port_operations pdc_common_ops = { 16862306a36Sopenharmony_ci .inherits = &ata_sff_port_ops, 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci .sff_tf_load = pdc_tf_load_mmio, 17162306a36Sopenharmony_ci .sff_exec_command = pdc_exec_command_mmio, 17262306a36Sopenharmony_ci .check_atapi_dma = pdc_check_atapi_dma, 17362306a36Sopenharmony_ci .qc_prep = pdc_qc_prep, 17462306a36Sopenharmony_ci .qc_issue = pdc_qc_issue, 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci .sff_irq_clear = pdc_irq_clear, 17762306a36Sopenharmony_ci .lost_interrupt = ATA_OP_NULL, 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci .post_internal_cmd = pdc_post_internal_cmd, 18062306a36Sopenharmony_ci .error_handler = pdc_error_handler, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic struct ata_port_operations pdc_sata_ops = { 18462306a36Sopenharmony_ci .inherits = &pdc_common_ops, 18562306a36Sopenharmony_ci .cable_detect = ata_cable_sata, 18662306a36Sopenharmony_ci .freeze = pdc_sata_freeze, 18762306a36Sopenharmony_ci .thaw = pdc_sata_thaw, 18862306a36Sopenharmony_ci .scr_read = pdc_sata_scr_read, 18962306a36Sopenharmony_ci .scr_write = pdc_sata_scr_write, 19062306a36Sopenharmony_ci .port_start = pdc_sata_port_start, 19162306a36Sopenharmony_ci .hardreset = pdc_sata_hardreset, 19262306a36Sopenharmony_ci}; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/* First-generation chips need a more restrictive ->check_atapi_dma op, 19562306a36Sopenharmony_ci and ->freeze/thaw that ignore the hotplug controls. */ 19662306a36Sopenharmony_cistatic struct ata_port_operations pdc_old_sata_ops = { 19762306a36Sopenharmony_ci .inherits = &pdc_sata_ops, 19862306a36Sopenharmony_ci .freeze = pdc_freeze, 19962306a36Sopenharmony_ci .thaw = pdc_thaw, 20062306a36Sopenharmony_ci .check_atapi_dma = pdc_old_sata_check_atapi_dma, 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic struct ata_port_operations pdc_pata_ops = { 20462306a36Sopenharmony_ci .inherits = &pdc_common_ops, 20562306a36Sopenharmony_ci .cable_detect = pdc_pata_cable_detect, 20662306a36Sopenharmony_ci .freeze = pdc_freeze, 20762306a36Sopenharmony_ci .thaw = pdc_thaw, 20862306a36Sopenharmony_ci .port_start = pdc_common_port_start, 20962306a36Sopenharmony_ci .softreset = pdc_pata_softreset, 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const struct ata_port_info pdc_port_info[] = { 21362306a36Sopenharmony_ci [board_2037x] = 21462306a36Sopenharmony_ci { 21562306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 21662306a36Sopenharmony_ci PDC_FLAG_SATA_PATA, 21762306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 21862306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 21962306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 22062306a36Sopenharmony_ci .port_ops = &pdc_old_sata_ops, 22162306a36Sopenharmony_ci }, 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci [board_2037x_pata] = 22462306a36Sopenharmony_ci { 22562306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, 22662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 22762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 22862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 22962306a36Sopenharmony_ci .port_ops = &pdc_pata_ops, 23062306a36Sopenharmony_ci }, 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci [board_20319] = 23362306a36Sopenharmony_ci { 23462306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 23562306a36Sopenharmony_ci PDC_FLAG_4_PORTS, 23662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 23762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 23862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 23962306a36Sopenharmony_ci .port_ops = &pdc_old_sata_ops, 24062306a36Sopenharmony_ci }, 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci [board_20619] = 24362306a36Sopenharmony_ci { 24462306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | 24562306a36Sopenharmony_ci PDC_FLAG_4_PORTS, 24662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 24762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 24862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 24962306a36Sopenharmony_ci .port_ops = &pdc_pata_ops, 25062306a36Sopenharmony_ci }, 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci [board_2057x] = 25362306a36Sopenharmony_ci { 25462306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 25562306a36Sopenharmony_ci PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, 25662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 25762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 25862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 25962306a36Sopenharmony_ci .port_ops = &pdc_sata_ops, 26062306a36Sopenharmony_ci }, 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci [board_2057x_pata] = 26362306a36Sopenharmony_ci { 26462306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | 26562306a36Sopenharmony_ci PDC_FLAG_GEN_II, 26662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 26762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 26862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 26962306a36Sopenharmony_ci .port_ops = &pdc_pata_ops, 27062306a36Sopenharmony_ci }, 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci [board_40518] = 27362306a36Sopenharmony_ci { 27462306a36Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 27562306a36Sopenharmony_ci PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, 27662306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 27762306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 27862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 27962306a36Sopenharmony_ci .port_ops = &pdc_sata_ops, 28062306a36Sopenharmony_ci }, 28162306a36Sopenharmony_ci}; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic const struct pci_device_id pdc_ata_pci_tbl[] = { 28462306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3371), board_2037x }, 28562306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3373), board_2037x }, 28662306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3375), board_2037x }, 28762306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3376), board_2037x }, 28862306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3570), board_2057x }, 28962306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3571), board_2057x }, 29062306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3574), board_2057x }, 29162306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3577), board_2057x }, 29262306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d73), board_2057x }, 29362306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x }, 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3318), board_20319 }, 29662306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3319), board_20319 }, 29762306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3515), board_40518 }, 29862306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3519), board_40518 }, 29962306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d17), board_40518 }, 30062306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d18), board_40518 }, 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x6629), board_20619 }, 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci { } /* terminate list */ 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic struct pci_driver pdc_ata_pci_driver = { 30862306a36Sopenharmony_ci .name = DRV_NAME, 30962306a36Sopenharmony_ci .id_table = pdc_ata_pci_tbl, 31062306a36Sopenharmony_ci .probe = pdc_ata_init_one, 31162306a36Sopenharmony_ci .remove = ata_pci_remove_one, 31262306a36Sopenharmony_ci}; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int pdc_common_port_start(struct ata_port *ap) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci struct device *dev = ap->host->dev; 31762306a36Sopenharmony_ci struct pdc_port_priv *pp; 31862306a36Sopenharmony_ci int rc; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* we use the same prd table as bmdma, allocate it */ 32162306a36Sopenharmony_ci rc = ata_bmdma_port_start(ap); 32262306a36Sopenharmony_ci if (rc) 32362306a36Sopenharmony_ci return rc; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 32662306a36Sopenharmony_ci if (!pp) 32762306a36Sopenharmony_ci return -ENOMEM; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci pp->pkt = dmam_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); 33062306a36Sopenharmony_ci if (!pp->pkt) 33162306a36Sopenharmony_ci return -ENOMEM; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci ap->private_data = pp; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic int pdc_sata_port_start(struct ata_port *ap) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci int rc; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci rc = pdc_common_port_start(ap); 34362306a36Sopenharmony_ci if (rc) 34462306a36Sopenharmony_ci return rc; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* fix up PHYMODE4 align timing */ 34762306a36Sopenharmony_ci if (ap->flags & PDC_FLAG_GEN_II) { 34862306a36Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 34962306a36Sopenharmony_ci unsigned int tmp; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci tmp = readl(sata_mmio + PDC_PHYMODE4); 35262306a36Sopenharmony_ci tmp = (tmp & ~3) | 1; /* set bits 1:0 = 0:1 */ 35362306a36Sopenharmony_ci writel(tmp, sata_mmio + PDC_PHYMODE4); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return 0; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic void pdc_fpdma_clear_interrupt_flag(struct ata_port *ap) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 36262306a36Sopenharmony_ci u32 tmp; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci tmp = readl(sata_mmio + PDC_FPDMA_CTLSTAT); 36562306a36Sopenharmony_ci tmp |= PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG; 36662306a36Sopenharmony_ci tmp |= PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* It's not allowed to write to the entire FPDMA_CTLSTAT register 36962306a36Sopenharmony_ci when NCQ is running. So do a byte-sized write to bits 10 and 11. */ 37062306a36Sopenharmony_ci writeb(tmp >> 8, sata_mmio + PDC_FPDMA_CTLSTAT + 1); 37162306a36Sopenharmony_ci readb(sata_mmio + PDC_FPDMA_CTLSTAT + 1); /* flush */ 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic void pdc_fpdma_reset(struct ata_port *ap) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 37762306a36Sopenharmony_ci u8 tmp; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci tmp = (u8)readl(sata_mmio + PDC_FPDMA_CTLSTAT); 38062306a36Sopenharmony_ci tmp &= 0x7F; 38162306a36Sopenharmony_ci tmp |= PDC_FPDMA_CTLSTAT_RESET; 38262306a36Sopenharmony_ci writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT); 38362306a36Sopenharmony_ci readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */ 38462306a36Sopenharmony_ci udelay(100); 38562306a36Sopenharmony_ci tmp &= ~PDC_FPDMA_CTLSTAT_RESET; 38662306a36Sopenharmony_ci writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT); 38762306a36Sopenharmony_ci readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */ 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci pdc_fpdma_clear_interrupt_flag(ap); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic void pdc_not_at_command_packet_phase(struct ata_port *ap) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 39562306a36Sopenharmony_ci unsigned int i; 39662306a36Sopenharmony_ci u32 tmp; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* check not at ASIC packet command phase */ 39962306a36Sopenharmony_ci for (i = 0; i < 100; ++i) { 40062306a36Sopenharmony_ci writel(0, sata_mmio + PDC_INTERNAL_DEBUG_1); 40162306a36Sopenharmony_ci tmp = readl(sata_mmio + PDC_INTERNAL_DEBUG_2); 40262306a36Sopenharmony_ci if ((tmp & 0xF) != 1) 40362306a36Sopenharmony_ci break; 40462306a36Sopenharmony_ci udelay(100); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic void pdc_clear_internal_debug_record_error_register(struct ata_port *ap) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci writel(0xffffffff, sata_mmio + PDC_SATA_ERROR); 41362306a36Sopenharmony_ci writel(0xffff0000, sata_mmio + PDC_LINK_LAYER_ERRORS); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_cistatic void pdc_reset_port(struct ata_port *ap) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; 41962306a36Sopenharmony_ci unsigned int i; 42062306a36Sopenharmony_ci u32 tmp; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (ap->flags & PDC_FLAG_GEN_II) 42362306a36Sopenharmony_ci pdc_not_at_command_packet_phase(ap); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci tmp = readl(ata_ctlstat_mmio); 42662306a36Sopenharmony_ci tmp |= PDC_RESET; 42762306a36Sopenharmony_ci writel(tmp, ata_ctlstat_mmio); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci for (i = 11; i > 0; i--) { 43062306a36Sopenharmony_ci tmp = readl(ata_ctlstat_mmio); 43162306a36Sopenharmony_ci if (tmp & PDC_RESET) 43262306a36Sopenharmony_ci break; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci udelay(100); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci tmp |= PDC_RESET; 43762306a36Sopenharmony_ci writel(tmp, ata_ctlstat_mmio); 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci tmp &= ~PDC_RESET; 44162306a36Sopenharmony_ci writel(tmp, ata_ctlstat_mmio); 44262306a36Sopenharmony_ci readl(ata_ctlstat_mmio); /* flush */ 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (sata_scr_valid(&ap->link) && (ap->flags & PDC_FLAG_GEN_II)) { 44562306a36Sopenharmony_ci pdc_fpdma_reset(ap); 44662306a36Sopenharmony_ci pdc_clear_internal_debug_record_error_register(ap); 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic int pdc_pata_cable_detect(struct ata_port *ap) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci u8 tmp; 45362306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci tmp = readb(ata_mmio + PDC_CTLSTAT + 3); 45662306a36Sopenharmony_ci if (tmp & 0x01) 45762306a36Sopenharmony_ci return ATA_CBL_PATA40; 45862306a36Sopenharmony_ci return ATA_CBL_PATA80; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic int pdc_sata_scr_read(struct ata_link *link, 46262306a36Sopenharmony_ci unsigned int sc_reg, u32 *val) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci if (sc_reg > SCR_CONTROL) 46562306a36Sopenharmony_ci return -EINVAL; 46662306a36Sopenharmony_ci *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4)); 46762306a36Sopenharmony_ci return 0; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic int pdc_sata_scr_write(struct ata_link *link, 47162306a36Sopenharmony_ci unsigned int sc_reg, u32 val) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci if (sc_reg > SCR_CONTROL) 47462306a36Sopenharmony_ci return -EINVAL; 47562306a36Sopenharmony_ci writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); 47662306a36Sopenharmony_ci return 0; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic void pdc_atapi_pkt(struct ata_queued_cmd *qc) 48062306a36Sopenharmony_ci{ 48162306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 48262306a36Sopenharmony_ci dma_addr_t sg_table = ap->bmdma_prd_dma; 48362306a36Sopenharmony_ci unsigned int cdb_len = qc->dev->cdb_len; 48462306a36Sopenharmony_ci u8 *cdb = qc->cdb; 48562306a36Sopenharmony_ci struct pdc_port_priv *pp = ap->private_data; 48662306a36Sopenharmony_ci u8 *buf = pp->pkt; 48762306a36Sopenharmony_ci __le32 *buf32 = (__le32 *) buf; 48862306a36Sopenharmony_ci unsigned int dev_sel, feature; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* set control bits (byte 0), zero delay seq id (byte 3), 49162306a36Sopenharmony_ci * and seq id (byte 2) 49262306a36Sopenharmony_ci */ 49362306a36Sopenharmony_ci switch (qc->tf.protocol) { 49462306a36Sopenharmony_ci case ATAPI_PROT_DMA: 49562306a36Sopenharmony_ci if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 49662306a36Sopenharmony_ci buf32[0] = cpu_to_le32(PDC_PKT_READ); 49762306a36Sopenharmony_ci else 49862306a36Sopenharmony_ci buf32[0] = 0; 49962306a36Sopenharmony_ci break; 50062306a36Sopenharmony_ci case ATAPI_PROT_NODATA: 50162306a36Sopenharmony_ci buf32[0] = cpu_to_le32(PDC_PKT_NODATA); 50262306a36Sopenharmony_ci break; 50362306a36Sopenharmony_ci default: 50462306a36Sopenharmony_ci BUG(); 50562306a36Sopenharmony_ci break; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ 50862306a36Sopenharmony_ci buf32[2] = 0; /* no next-packet */ 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci /* select drive */ 51162306a36Sopenharmony_ci if (sata_scr_valid(&ap->link)) 51262306a36Sopenharmony_ci dev_sel = PDC_DEVICE_SATA; 51362306a36Sopenharmony_ci else 51462306a36Sopenharmony_ci dev_sel = qc->tf.device; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci buf[12] = (1 << 5) | ATA_REG_DEVICE; 51762306a36Sopenharmony_ci buf[13] = dev_sel; 51862306a36Sopenharmony_ci buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY; 51962306a36Sopenharmony_ci buf[15] = dev_sel; /* once more, waiting for BSY to clear */ 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci buf[16] = (1 << 5) | ATA_REG_NSECT; 52262306a36Sopenharmony_ci buf[17] = qc->tf.nsect; 52362306a36Sopenharmony_ci buf[18] = (1 << 5) | ATA_REG_LBAL; 52462306a36Sopenharmony_ci buf[19] = qc->tf.lbal; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* set feature and byte counter registers */ 52762306a36Sopenharmony_ci if (qc->tf.protocol != ATAPI_PROT_DMA) 52862306a36Sopenharmony_ci feature = PDC_FEATURE_ATAPI_PIO; 52962306a36Sopenharmony_ci else 53062306a36Sopenharmony_ci feature = PDC_FEATURE_ATAPI_DMA; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci buf[20] = (1 << 5) | ATA_REG_FEATURE; 53362306a36Sopenharmony_ci buf[21] = feature; 53462306a36Sopenharmony_ci buf[22] = (1 << 5) | ATA_REG_BYTEL; 53562306a36Sopenharmony_ci buf[23] = qc->tf.lbam; 53662306a36Sopenharmony_ci buf[24] = (1 << 5) | ATA_REG_BYTEH; 53762306a36Sopenharmony_ci buf[25] = qc->tf.lbah; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* send ATAPI packet command 0xA0 */ 54062306a36Sopenharmony_ci buf[26] = (1 << 5) | ATA_REG_CMD; 54162306a36Sopenharmony_ci buf[27] = qc->tf.command; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* select drive and check DRQ */ 54462306a36Sopenharmony_ci buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY; 54562306a36Sopenharmony_ci buf[29] = dev_sel; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci /* we can represent cdb lengths 2/4/6/8/10/12/14/16 */ 54862306a36Sopenharmony_ci BUG_ON(cdb_len & ~0x1E); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* append the CDB as the final part */ 55162306a36Sopenharmony_ci buf[30] = (((cdb_len >> 1) & 7) << 5) | ATA_REG_DATA | PDC_LAST_REG; 55262306a36Sopenharmony_ci memcpy(buf+31, cdb, cdb_len); 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci/** 55662306a36Sopenharmony_ci * pdc_fill_sg - Fill PCI IDE PRD table 55762306a36Sopenharmony_ci * @qc: Metadata associated with taskfile to be transferred 55862306a36Sopenharmony_ci * 55962306a36Sopenharmony_ci * Fill PCI IDE PRD (scatter-gather) table with segments 56062306a36Sopenharmony_ci * associated with the current disk command. 56162306a36Sopenharmony_ci * Make sure hardware does not choke on it. 56262306a36Sopenharmony_ci * 56362306a36Sopenharmony_ci * LOCKING: 56462306a36Sopenharmony_ci * spin_lock_irqsave(host lock) 56562306a36Sopenharmony_ci * 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_cistatic void pdc_fill_sg(struct ata_queued_cmd *qc) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 57062306a36Sopenharmony_ci struct ata_bmdma_prd *prd = ap->bmdma_prd; 57162306a36Sopenharmony_ci struct scatterlist *sg; 57262306a36Sopenharmony_ci const u32 SG_COUNT_ASIC_BUG = 41*4; 57362306a36Sopenharmony_ci unsigned int si, idx; 57462306a36Sopenharmony_ci u32 len; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 57762306a36Sopenharmony_ci return; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci idx = 0; 58062306a36Sopenharmony_ci for_each_sg(qc->sg, sg, qc->n_elem, si) { 58162306a36Sopenharmony_ci u32 addr, offset; 58262306a36Sopenharmony_ci u32 sg_len; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* determine if physical DMA addr spans 64K boundary. 58562306a36Sopenharmony_ci * Note h/w doesn't support 64-bit, so we unconditionally 58662306a36Sopenharmony_ci * truncate dma_addr_t to u32. 58762306a36Sopenharmony_ci */ 58862306a36Sopenharmony_ci addr = (u32) sg_dma_address(sg); 58962306a36Sopenharmony_ci sg_len = sg_dma_len(sg); 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci while (sg_len) { 59262306a36Sopenharmony_ci offset = addr & 0xffff; 59362306a36Sopenharmony_ci len = sg_len; 59462306a36Sopenharmony_ci if ((offset + sg_len) > 0x10000) 59562306a36Sopenharmony_ci len = 0x10000 - offset; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci prd[idx].addr = cpu_to_le32(addr); 59862306a36Sopenharmony_ci prd[idx].flags_len = cpu_to_le32(len & 0xffff); 59962306a36Sopenharmony_ci ata_port_dbg(ap, "PRD[%u] = (0x%X, 0x%X)\n", 60062306a36Sopenharmony_ci idx, addr, len); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci idx++; 60362306a36Sopenharmony_ci sg_len -= len; 60462306a36Sopenharmony_ci addr += len; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci len = le32_to_cpu(prd[idx - 1].flags_len); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (len > SG_COUNT_ASIC_BUG) { 61162306a36Sopenharmony_ci u32 addr; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci addr = le32_to_cpu(prd[idx - 1].addr); 61462306a36Sopenharmony_ci prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG); 61562306a36Sopenharmony_ci ata_port_dbg(ap, "PRD[%u] = (0x%X, 0x%X)\n", 61662306a36Sopenharmony_ci idx - 1, addr, SG_COUNT_ASIC_BUG); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci addr = addr + len - SG_COUNT_ASIC_BUG; 61962306a36Sopenharmony_ci len = SG_COUNT_ASIC_BUG; 62062306a36Sopenharmony_ci prd[idx].addr = cpu_to_le32(addr); 62162306a36Sopenharmony_ci prd[idx].flags_len = cpu_to_le32(len); 62262306a36Sopenharmony_ci ata_port_dbg(ap, "PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci idx++; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci struct pdc_port_priv *pp = qc->ap->private_data; 63362306a36Sopenharmony_ci unsigned int i; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci switch (qc->tf.protocol) { 63662306a36Sopenharmony_ci case ATA_PROT_DMA: 63762306a36Sopenharmony_ci pdc_fill_sg(qc); 63862306a36Sopenharmony_ci fallthrough; 63962306a36Sopenharmony_ci case ATA_PROT_NODATA: 64062306a36Sopenharmony_ci i = pdc_pkt_header(&qc->tf, qc->ap->bmdma_prd_dma, 64162306a36Sopenharmony_ci qc->dev->devno, pp->pkt); 64262306a36Sopenharmony_ci if (qc->tf.flags & ATA_TFLAG_LBA48) 64362306a36Sopenharmony_ci i = pdc_prep_lba48(&qc->tf, pp->pkt, i); 64462306a36Sopenharmony_ci else 64562306a36Sopenharmony_ci i = pdc_prep_lba28(&qc->tf, pp->pkt, i); 64662306a36Sopenharmony_ci pdc_pkt_footer(&qc->tf, pp->pkt, i); 64762306a36Sopenharmony_ci break; 64862306a36Sopenharmony_ci case ATAPI_PROT_PIO: 64962306a36Sopenharmony_ci pdc_fill_sg(qc); 65062306a36Sopenharmony_ci break; 65162306a36Sopenharmony_ci case ATAPI_PROT_DMA: 65262306a36Sopenharmony_ci pdc_fill_sg(qc); 65362306a36Sopenharmony_ci fallthrough; 65462306a36Sopenharmony_ci case ATAPI_PROT_NODATA: 65562306a36Sopenharmony_ci pdc_atapi_pkt(qc); 65662306a36Sopenharmony_ci break; 65762306a36Sopenharmony_ci default: 65862306a36Sopenharmony_ci break; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci return AC_ERR_OK; 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic int pdc_is_sataii_tx4(unsigned long flags) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; 66762306a36Sopenharmony_ci return (flags & mask) == mask; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic unsigned int pdc_port_no_to_ata_no(unsigned int port_no, 67162306a36Sopenharmony_ci int is_sataii_tx4) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; 67462306a36Sopenharmony_ci return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; 67562306a36Sopenharmony_ci} 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_cistatic unsigned int pdc_sata_nr_ports(const struct ata_port *ap) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci return (ap->flags & PDC_FLAG_4_PORTS) ? 4 : 2; 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci const struct ata_host *host = ap->host; 68562306a36Sopenharmony_ci unsigned int nr_ports = pdc_sata_nr_ports(ap); 68662306a36Sopenharmony_ci unsigned int i; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci for (i = 0; i < nr_ports && host->ports[i] != ap; ++i) 68962306a36Sopenharmony_ci ; 69062306a36Sopenharmony_ci BUG_ON(i >= nr_ports); 69162306a36Sopenharmony_ci return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags)); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic void pdc_freeze(struct ata_port *ap) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 69762306a36Sopenharmony_ci u32 tmp; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci tmp = readl(ata_mmio + PDC_CTLSTAT); 70062306a36Sopenharmony_ci tmp |= PDC_IRQ_DISABLE; 70162306a36Sopenharmony_ci tmp &= ~PDC_DMA_ENABLE; 70262306a36Sopenharmony_ci writel(tmp, ata_mmio + PDC_CTLSTAT); 70362306a36Sopenharmony_ci readl(ata_mmio + PDC_CTLSTAT); /* flush */ 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic void pdc_sata_freeze(struct ata_port *ap) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci struct ata_host *host = ap->host; 70962306a36Sopenharmony_ci void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; 71062306a36Sopenharmony_ci unsigned int hotplug_offset = PDC2_SATA_PLUG_CSR; 71162306a36Sopenharmony_ci unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); 71262306a36Sopenharmony_ci u32 hotplug_status; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci /* Disable hotplug events on this port. 71562306a36Sopenharmony_ci * 71662306a36Sopenharmony_ci * Locking: 71762306a36Sopenharmony_ci * 1) hotplug register accesses must be serialised via host->lock 71862306a36Sopenharmony_ci * 2) ap->lock == &ap->host->lock 71962306a36Sopenharmony_ci * 3) ->freeze() and ->thaw() are called with ap->lock held 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_ci hotplug_status = readl(host_mmio + hotplug_offset); 72262306a36Sopenharmony_ci hotplug_status |= 0x11 << (ata_no + 16); 72362306a36Sopenharmony_ci writel(hotplug_status, host_mmio + hotplug_offset); 72462306a36Sopenharmony_ci readl(host_mmio + hotplug_offset); /* flush */ 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci pdc_freeze(ap); 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_cistatic void pdc_thaw(struct ata_port *ap) 73062306a36Sopenharmony_ci{ 73162306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 73262306a36Sopenharmony_ci u32 tmp; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci /* clear IRQ */ 73562306a36Sopenharmony_ci readl(ata_mmio + PDC_COMMAND); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /* turn IRQ back on */ 73862306a36Sopenharmony_ci tmp = readl(ata_mmio + PDC_CTLSTAT); 73962306a36Sopenharmony_ci tmp &= ~PDC_IRQ_DISABLE; 74062306a36Sopenharmony_ci writel(tmp, ata_mmio + PDC_CTLSTAT); 74162306a36Sopenharmony_ci readl(ata_mmio + PDC_CTLSTAT); /* flush */ 74262306a36Sopenharmony_ci} 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_cistatic void pdc_sata_thaw(struct ata_port *ap) 74562306a36Sopenharmony_ci{ 74662306a36Sopenharmony_ci struct ata_host *host = ap->host; 74762306a36Sopenharmony_ci void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; 74862306a36Sopenharmony_ci unsigned int hotplug_offset = PDC2_SATA_PLUG_CSR; 74962306a36Sopenharmony_ci unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); 75062306a36Sopenharmony_ci u32 hotplug_status; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci pdc_thaw(ap); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* Enable hotplug events on this port. 75562306a36Sopenharmony_ci * Locking: see pdc_sata_freeze(). 75662306a36Sopenharmony_ci */ 75762306a36Sopenharmony_ci hotplug_status = readl(host_mmio + hotplug_offset); 75862306a36Sopenharmony_ci hotplug_status |= 0x11 << ata_no; 75962306a36Sopenharmony_ci hotplug_status &= ~(0x11 << (ata_no + 16)); 76062306a36Sopenharmony_ci writel(hotplug_status, host_mmio + hotplug_offset); 76162306a36Sopenharmony_ci readl(host_mmio + hotplug_offset); /* flush */ 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_cistatic int pdc_pata_softreset(struct ata_link *link, unsigned int *class, 76562306a36Sopenharmony_ci unsigned long deadline) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci pdc_reset_port(link->ap); 76862306a36Sopenharmony_ci return ata_sff_softreset(link, class, deadline); 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic unsigned int pdc_ata_port_to_ata_no(const struct ata_port *ap) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 77462306a36Sopenharmony_ci void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /* ata_mmio == host_mmio + 0x200 + ata_no * 0x80 */ 77762306a36Sopenharmony_ci return (ata_mmio - host_mmio - 0x200) / 0x80; 77862306a36Sopenharmony_ci} 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_cistatic void pdc_hard_reset_port(struct ata_port *ap) 78162306a36Sopenharmony_ci{ 78262306a36Sopenharmony_ci void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 78362306a36Sopenharmony_ci void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; 78462306a36Sopenharmony_ci unsigned int ata_no = pdc_ata_port_to_ata_no(ap); 78562306a36Sopenharmony_ci struct pdc_host_priv *hpriv = ap->host->private_data; 78662306a36Sopenharmony_ci u8 tmp; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci spin_lock(&hpriv->hard_reset_lock); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci tmp = readb(pcictl_b1_mmio); 79162306a36Sopenharmony_ci tmp &= ~(0x10 << ata_no); 79262306a36Sopenharmony_ci writeb(tmp, pcictl_b1_mmio); 79362306a36Sopenharmony_ci readb(pcictl_b1_mmio); /* flush */ 79462306a36Sopenharmony_ci udelay(100); 79562306a36Sopenharmony_ci tmp |= (0x10 << ata_no); 79662306a36Sopenharmony_ci writeb(tmp, pcictl_b1_mmio); 79762306a36Sopenharmony_ci readb(pcictl_b1_mmio); /* flush */ 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci spin_unlock(&hpriv->hard_reset_lock); 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, 80362306a36Sopenharmony_ci unsigned long deadline) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci if (link->ap->flags & PDC_FLAG_GEN_II) 80662306a36Sopenharmony_ci pdc_not_at_command_packet_phase(link->ap); 80762306a36Sopenharmony_ci /* hotplug IRQs should have been masked by pdc_sata_freeze() */ 80862306a36Sopenharmony_ci pdc_hard_reset_port(link->ap); 80962306a36Sopenharmony_ci pdc_reset_port(link->ap); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci /* sata_promise can't reliably acquire the first D2H Reg FIS 81262306a36Sopenharmony_ci * after hardreset. Do non-waiting hardreset and request 81362306a36Sopenharmony_ci * follow-up SRST. 81462306a36Sopenharmony_ci */ 81562306a36Sopenharmony_ci return sata_std_hardreset(link, class, deadline); 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cistatic void pdc_error_handler(struct ata_port *ap) 81962306a36Sopenharmony_ci{ 82062306a36Sopenharmony_ci if (!ata_port_is_frozen(ap)) 82162306a36Sopenharmony_ci pdc_reset_port(ap); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci ata_sff_error_handler(ap); 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_cistatic void pdc_post_internal_cmd(struct ata_queued_cmd *qc) 82762306a36Sopenharmony_ci{ 82862306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* make DMA engine forget about the failed command */ 83162306a36Sopenharmony_ci if (qc->flags & ATA_QCFLAG_EH) 83262306a36Sopenharmony_ci pdc_reset_port(ap); 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_cistatic void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, 83662306a36Sopenharmony_ci u32 port_status, u32 err_mask) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci struct ata_eh_info *ehi = &ap->link.eh_info; 83962306a36Sopenharmony_ci unsigned int ac_err_mask = 0; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci ata_ehi_clear_desc(ehi); 84262306a36Sopenharmony_ci ata_ehi_push_desc(ehi, "port_status 0x%08x", port_status); 84362306a36Sopenharmony_ci port_status &= err_mask; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (port_status & PDC_DRIVE_ERR) 84662306a36Sopenharmony_ci ac_err_mask |= AC_ERR_DEV; 84762306a36Sopenharmony_ci if (port_status & (PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR)) 84862306a36Sopenharmony_ci ac_err_mask |= AC_ERR_OTHER; 84962306a36Sopenharmony_ci if (port_status & (PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR)) 85062306a36Sopenharmony_ci ac_err_mask |= AC_ERR_ATA_BUS; 85162306a36Sopenharmony_ci if (port_status & (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC2_HTO_ERR 85262306a36Sopenharmony_ci | PDC_PCI_SYS_ERR | PDC1_PCI_PARITY_ERR)) 85362306a36Sopenharmony_ci ac_err_mask |= AC_ERR_HOST_BUS; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci if (sata_scr_valid(&ap->link)) { 85662306a36Sopenharmony_ci u32 serror; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci pdc_sata_scr_read(&ap->link, SCR_ERROR, &serror); 85962306a36Sopenharmony_ci ehi->serror |= serror; 86062306a36Sopenharmony_ci } 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci qc->err_mask |= ac_err_mask; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci pdc_reset_port(ap); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci ata_port_abort(ap); 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic unsigned int pdc_host_intr(struct ata_port *ap, 87062306a36Sopenharmony_ci struct ata_queued_cmd *qc) 87162306a36Sopenharmony_ci{ 87262306a36Sopenharmony_ci unsigned int handled = 0; 87362306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 87462306a36Sopenharmony_ci u32 port_status, err_mask; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci err_mask = PDC_ERR_MASK; 87762306a36Sopenharmony_ci if (ap->flags & PDC_FLAG_GEN_II) 87862306a36Sopenharmony_ci err_mask &= ~PDC1_ERR_MASK; 87962306a36Sopenharmony_ci else 88062306a36Sopenharmony_ci err_mask &= ~PDC2_ERR_MASK; 88162306a36Sopenharmony_ci port_status = readl(ata_mmio + PDC_GLOBAL_CTL); 88262306a36Sopenharmony_ci if (unlikely(port_status & err_mask)) { 88362306a36Sopenharmony_ci pdc_error_intr(ap, qc, port_status, err_mask); 88462306a36Sopenharmony_ci return 1; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci switch (qc->tf.protocol) { 88862306a36Sopenharmony_ci case ATA_PROT_DMA: 88962306a36Sopenharmony_ci case ATA_PROT_NODATA: 89062306a36Sopenharmony_ci case ATAPI_PROT_DMA: 89162306a36Sopenharmony_ci case ATAPI_PROT_NODATA: 89262306a36Sopenharmony_ci qc->err_mask |= ac_err_mask(ata_wait_idle(ap)); 89362306a36Sopenharmony_ci ata_qc_complete(qc); 89462306a36Sopenharmony_ci handled = 1; 89562306a36Sopenharmony_ci break; 89662306a36Sopenharmony_ci default: 89762306a36Sopenharmony_ci ap->stats.idle_irq++; 89862306a36Sopenharmony_ci break; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci return handled; 90262306a36Sopenharmony_ci} 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_cistatic void pdc_irq_clear(struct ata_port *ap) 90562306a36Sopenharmony_ci{ 90662306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci readl(ata_mmio + PDC_COMMAND); 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_cistatic irqreturn_t pdc_interrupt(int irq, void *dev_instance) 91262306a36Sopenharmony_ci{ 91362306a36Sopenharmony_ci struct ata_host *host = dev_instance; 91462306a36Sopenharmony_ci struct ata_port *ap; 91562306a36Sopenharmony_ci u32 mask = 0; 91662306a36Sopenharmony_ci unsigned int i, tmp; 91762306a36Sopenharmony_ci unsigned int handled = 0; 91862306a36Sopenharmony_ci void __iomem *host_mmio; 91962306a36Sopenharmony_ci unsigned int hotplug_offset, ata_no; 92062306a36Sopenharmony_ci u32 hotplug_status; 92162306a36Sopenharmony_ci int is_sataii_tx4; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci if (!host || !host->iomap[PDC_MMIO_BAR]) 92462306a36Sopenharmony_ci return IRQ_NONE; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci host_mmio = host->iomap[PDC_MMIO_BAR]; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci spin_lock(&host->lock); 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci /* read and clear hotplug flags for all ports */ 93162306a36Sopenharmony_ci if (host->ports[0]->flags & PDC_FLAG_GEN_II) { 93262306a36Sopenharmony_ci hotplug_offset = PDC2_SATA_PLUG_CSR; 93362306a36Sopenharmony_ci hotplug_status = readl(host_mmio + hotplug_offset); 93462306a36Sopenharmony_ci if (hotplug_status & 0xff) 93562306a36Sopenharmony_ci writel(hotplug_status | 0xff, host_mmio + hotplug_offset); 93662306a36Sopenharmony_ci hotplug_status &= 0xff; /* clear uninteresting bits */ 93762306a36Sopenharmony_ci } else 93862306a36Sopenharmony_ci hotplug_status = 0; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci /* reading should also clear interrupts */ 94162306a36Sopenharmony_ci mask = readl(host_mmio + PDC_INT_SEQMASK); 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci if (mask == 0xffffffff && hotplug_status == 0) 94462306a36Sopenharmony_ci goto done_irq; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci mask &= 0xffff; /* only 16 SEQIDs possible */ 94762306a36Sopenharmony_ci if (mask == 0 && hotplug_status == 0) 94862306a36Sopenharmony_ci goto done_irq; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci writel(mask, host_mmio + PDC_INT_SEQMASK); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 95562306a36Sopenharmony_ci ap = host->ports[i]; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci /* check for a plug or unplug event */ 95862306a36Sopenharmony_ci ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4); 95962306a36Sopenharmony_ci tmp = hotplug_status & (0x11 << ata_no); 96062306a36Sopenharmony_ci if (tmp) { 96162306a36Sopenharmony_ci struct ata_eh_info *ehi = &ap->link.eh_info; 96262306a36Sopenharmony_ci ata_ehi_clear_desc(ehi); 96362306a36Sopenharmony_ci ata_ehi_hotplugged(ehi); 96462306a36Sopenharmony_ci ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp); 96562306a36Sopenharmony_ci ata_port_freeze(ap); 96662306a36Sopenharmony_ci ++handled; 96762306a36Sopenharmony_ci continue; 96862306a36Sopenharmony_ci } 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci /* check for a packet interrupt */ 97162306a36Sopenharmony_ci tmp = mask & (1 << (i + 1)); 97262306a36Sopenharmony_ci if (tmp) { 97362306a36Sopenharmony_ci struct ata_queued_cmd *qc; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci qc = ata_qc_from_tag(ap, ap->link.active_tag); 97662306a36Sopenharmony_ci if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) 97762306a36Sopenharmony_ci handled += pdc_host_intr(ap, qc); 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci } 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cidone_irq: 98262306a36Sopenharmony_ci spin_unlock(&host->lock); 98362306a36Sopenharmony_ci return IRQ_RETVAL(handled); 98462306a36Sopenharmony_ci} 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_cistatic void pdc_packet_start(struct ata_queued_cmd *qc) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 98962306a36Sopenharmony_ci struct pdc_port_priv *pp = ap->private_data; 99062306a36Sopenharmony_ci void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 99162306a36Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 99262306a36Sopenharmony_ci unsigned int port_no = ap->port_no; 99362306a36Sopenharmony_ci u8 seq = (u8) (port_no + 1); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci writel(0x00000001, host_mmio + (seq * 4)); 99662306a36Sopenharmony_ci readl(host_mmio + (seq * 4)); /* flush */ 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci pp->pkt[2] = seq; 99962306a36Sopenharmony_ci wmb(); /* flush PRD, pkt writes */ 100062306a36Sopenharmony_ci writel(pp->pkt_dma, ata_mmio + PDC_PKT_SUBMIT); 100162306a36Sopenharmony_ci readl(ata_mmio + PDC_PKT_SUBMIT); /* flush */ 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_cistatic unsigned int pdc_qc_issue(struct ata_queued_cmd *qc) 100562306a36Sopenharmony_ci{ 100662306a36Sopenharmony_ci switch (qc->tf.protocol) { 100762306a36Sopenharmony_ci case ATAPI_PROT_NODATA: 100862306a36Sopenharmony_ci if (qc->dev->flags & ATA_DFLAG_CDB_INTR) 100962306a36Sopenharmony_ci break; 101062306a36Sopenharmony_ci fallthrough; 101162306a36Sopenharmony_ci case ATA_PROT_NODATA: 101262306a36Sopenharmony_ci if (qc->tf.flags & ATA_TFLAG_POLLING) 101362306a36Sopenharmony_ci break; 101462306a36Sopenharmony_ci fallthrough; 101562306a36Sopenharmony_ci case ATAPI_PROT_DMA: 101662306a36Sopenharmony_ci case ATA_PROT_DMA: 101762306a36Sopenharmony_ci pdc_packet_start(qc); 101862306a36Sopenharmony_ci return 0; 101962306a36Sopenharmony_ci default: 102062306a36Sopenharmony_ci break; 102162306a36Sopenharmony_ci } 102262306a36Sopenharmony_ci return ata_sff_qc_issue(qc); 102362306a36Sopenharmony_ci} 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_cistatic void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); 102862306a36Sopenharmony_ci ata_sff_tf_load(ap, tf); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic void pdc_exec_command_mmio(struct ata_port *ap, 103262306a36Sopenharmony_ci const struct ata_taskfile *tf) 103362306a36Sopenharmony_ci{ 103462306a36Sopenharmony_ci WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); 103562306a36Sopenharmony_ci ata_sff_exec_command(ap, tf); 103662306a36Sopenharmony_ci} 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_cistatic int pdc_check_atapi_dma(struct ata_queued_cmd *qc) 103962306a36Sopenharmony_ci{ 104062306a36Sopenharmony_ci u8 *scsicmd = qc->scsicmd->cmnd; 104162306a36Sopenharmony_ci int pio = 1; /* atapi dma off by default */ 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* Whitelist commands that may use DMA. */ 104462306a36Sopenharmony_ci switch (scsicmd[0]) { 104562306a36Sopenharmony_ci case WRITE_12: 104662306a36Sopenharmony_ci case WRITE_10: 104762306a36Sopenharmony_ci case WRITE_6: 104862306a36Sopenharmony_ci case READ_12: 104962306a36Sopenharmony_ci case READ_10: 105062306a36Sopenharmony_ci case READ_6: 105162306a36Sopenharmony_ci case 0xad: /* READ_DVD_STRUCTURE */ 105262306a36Sopenharmony_ci case 0xbe: /* READ_CD */ 105362306a36Sopenharmony_ci pio = 0; 105462306a36Sopenharmony_ci } 105562306a36Sopenharmony_ci /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ 105662306a36Sopenharmony_ci if (scsicmd[0] == WRITE_10) { 105762306a36Sopenharmony_ci unsigned int lba = 105862306a36Sopenharmony_ci (scsicmd[2] << 24) | 105962306a36Sopenharmony_ci (scsicmd[3] << 16) | 106062306a36Sopenharmony_ci (scsicmd[4] << 8) | 106162306a36Sopenharmony_ci scsicmd[5]; 106262306a36Sopenharmony_ci if (lba >= 0xFFFF4FA2) 106362306a36Sopenharmony_ci pio = 1; 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci return pio; 106662306a36Sopenharmony_ci} 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_cistatic int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc) 106962306a36Sopenharmony_ci{ 107062306a36Sopenharmony_ci /* First generation chips cannot use ATAPI DMA on SATA ports */ 107162306a36Sopenharmony_ci return 1; 107262306a36Sopenharmony_ci} 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_cistatic void pdc_ata_setup_port(struct ata_port *ap, 107562306a36Sopenharmony_ci void __iomem *base, void __iomem *scr_addr) 107662306a36Sopenharmony_ci{ 107762306a36Sopenharmony_ci ap->ioaddr.cmd_addr = base; 107862306a36Sopenharmony_ci ap->ioaddr.data_addr = base; 107962306a36Sopenharmony_ci ap->ioaddr.feature_addr = 108062306a36Sopenharmony_ci ap->ioaddr.error_addr = base + 0x4; 108162306a36Sopenharmony_ci ap->ioaddr.nsect_addr = base + 0x8; 108262306a36Sopenharmony_ci ap->ioaddr.lbal_addr = base + 0xc; 108362306a36Sopenharmony_ci ap->ioaddr.lbam_addr = base + 0x10; 108462306a36Sopenharmony_ci ap->ioaddr.lbah_addr = base + 0x14; 108562306a36Sopenharmony_ci ap->ioaddr.device_addr = base + 0x18; 108662306a36Sopenharmony_ci ap->ioaddr.command_addr = 108762306a36Sopenharmony_ci ap->ioaddr.status_addr = base + 0x1c; 108862306a36Sopenharmony_ci ap->ioaddr.altstatus_addr = 108962306a36Sopenharmony_ci ap->ioaddr.ctl_addr = base + 0x38; 109062306a36Sopenharmony_ci ap->ioaddr.scr_addr = scr_addr; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic void pdc_host_init(struct ata_host *host) 109462306a36Sopenharmony_ci{ 109562306a36Sopenharmony_ci void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; 109662306a36Sopenharmony_ci int is_gen2 = host->ports[0]->flags & PDC_FLAG_GEN_II; 109762306a36Sopenharmony_ci int hotplug_offset; 109862306a36Sopenharmony_ci u32 tmp; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci if (is_gen2) 110162306a36Sopenharmony_ci hotplug_offset = PDC2_SATA_PLUG_CSR; 110262306a36Sopenharmony_ci else 110362306a36Sopenharmony_ci hotplug_offset = PDC_SATA_PLUG_CSR; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci /* 110662306a36Sopenharmony_ci * Except for the hotplug stuff, this is voodoo from the 110762306a36Sopenharmony_ci * Promise driver. Label this entire section 110862306a36Sopenharmony_ci * "TODO: figure out why we do this" 110962306a36Sopenharmony_ci */ 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci /* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */ 111262306a36Sopenharmony_ci tmp = readl(host_mmio + PDC_FLASH_CTL); 111362306a36Sopenharmony_ci tmp |= 0x02000; /* bit 13 (enable bmr burst) */ 111462306a36Sopenharmony_ci if (!is_gen2) 111562306a36Sopenharmony_ci tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */ 111662306a36Sopenharmony_ci writel(tmp, host_mmio + PDC_FLASH_CTL); 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci /* clear plug/unplug flags for all ports */ 111962306a36Sopenharmony_ci tmp = readl(host_mmio + hotplug_offset); 112062306a36Sopenharmony_ci writel(tmp | 0xff, host_mmio + hotplug_offset); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci tmp = readl(host_mmio + hotplug_offset); 112362306a36Sopenharmony_ci if (is_gen2) /* unmask plug/unplug ints */ 112462306a36Sopenharmony_ci writel(tmp & ~0xff0000, host_mmio + hotplug_offset); 112562306a36Sopenharmony_ci else /* mask plug/unplug ints */ 112662306a36Sopenharmony_ci writel(tmp | 0xff0000, host_mmio + hotplug_offset); 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci /* don't initialise TBG or SLEW on 2nd generation chips */ 112962306a36Sopenharmony_ci if (is_gen2) 113062306a36Sopenharmony_ci return; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci /* reduce TBG clock to 133 Mhz. */ 113362306a36Sopenharmony_ci tmp = readl(host_mmio + PDC_TBG_MODE); 113462306a36Sopenharmony_ci tmp &= ~0x30000; /* clear bit 17, 16*/ 113562306a36Sopenharmony_ci tmp |= 0x10000; /* set bit 17:16 = 0:1 */ 113662306a36Sopenharmony_ci writel(tmp, host_mmio + PDC_TBG_MODE); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci readl(host_mmio + PDC_TBG_MODE); /* flush */ 113962306a36Sopenharmony_ci msleep(10); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci /* adjust slew rate control register. */ 114262306a36Sopenharmony_ci tmp = readl(host_mmio + PDC_SLEW_CTL); 114362306a36Sopenharmony_ci tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */ 114462306a36Sopenharmony_ci tmp |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */ 114562306a36Sopenharmony_ci writel(tmp, host_mmio + PDC_SLEW_CTL); 114662306a36Sopenharmony_ci} 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_cistatic int pdc_ata_init_one(struct pci_dev *pdev, 114962306a36Sopenharmony_ci const struct pci_device_id *ent) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; 115262306a36Sopenharmony_ci const struct ata_port_info *ppi[PDC_MAX_PORTS]; 115362306a36Sopenharmony_ci struct ata_host *host; 115462306a36Sopenharmony_ci struct pdc_host_priv *hpriv; 115562306a36Sopenharmony_ci void __iomem *host_mmio; 115662306a36Sopenharmony_ci int n_ports, i, rc; 115762306a36Sopenharmony_ci int is_sataii_tx4; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci /* enable and acquire resources */ 116262306a36Sopenharmony_ci rc = pcim_enable_device(pdev); 116362306a36Sopenharmony_ci if (rc) 116462306a36Sopenharmony_ci return rc; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci rc = pcim_iomap_regions(pdev, 1 << PDC_MMIO_BAR, DRV_NAME); 116762306a36Sopenharmony_ci if (rc == -EBUSY) 116862306a36Sopenharmony_ci pcim_pin_device(pdev); 116962306a36Sopenharmony_ci if (rc) 117062306a36Sopenharmony_ci return rc; 117162306a36Sopenharmony_ci host_mmio = pcim_iomap_table(pdev)[PDC_MMIO_BAR]; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci /* determine port configuration and setup host */ 117462306a36Sopenharmony_ci n_ports = 2; 117562306a36Sopenharmony_ci if (pi->flags & PDC_FLAG_4_PORTS) 117662306a36Sopenharmony_ci n_ports = 4; 117762306a36Sopenharmony_ci for (i = 0; i < n_ports; i++) 117862306a36Sopenharmony_ci ppi[i] = pi; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (pi->flags & PDC_FLAG_SATA_PATA) { 118162306a36Sopenharmony_ci u8 tmp = readb(host_mmio + PDC_FLASH_CTL + 1); 118262306a36Sopenharmony_ci if (!(tmp & 0x80)) 118362306a36Sopenharmony_ci ppi[n_ports++] = pi + 1; 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 118762306a36Sopenharmony_ci if (!host) { 118862306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to allocate host\n"); 118962306a36Sopenharmony_ci return -ENOMEM; 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); 119262306a36Sopenharmony_ci if (!hpriv) 119362306a36Sopenharmony_ci return -ENOMEM; 119462306a36Sopenharmony_ci spin_lock_init(&hpriv->hard_reset_lock); 119562306a36Sopenharmony_ci host->private_data = hpriv; 119662306a36Sopenharmony_ci host->iomap = pcim_iomap_table(pdev); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); 119962306a36Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 120062306a36Sopenharmony_ci struct ata_port *ap = host->ports[i]; 120162306a36Sopenharmony_ci unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4); 120262306a36Sopenharmony_ci unsigned int ata_offset = 0x200 + ata_no * 0x80; 120362306a36Sopenharmony_ci unsigned int scr_offset = 0x400 + ata_no * 0x100; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci pdc_ata_setup_port(ap, host_mmio + ata_offset, host_mmio + scr_offset); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio"); 120862306a36Sopenharmony_ci ata_port_pbar_desc(ap, PDC_MMIO_BAR, ata_offset, "ata"); 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci /* initialize adapter */ 121262306a36Sopenharmony_ci pdc_host_init(host); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); 121562306a36Sopenharmony_ci if (rc) 121662306a36Sopenharmony_ci return rc; 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci /* start host, request IRQ and attach */ 121962306a36Sopenharmony_ci pci_set_master(pdev); 122062306a36Sopenharmony_ci return ata_host_activate(host, pdev->irq, pdc_interrupt, IRQF_SHARED, 122162306a36Sopenharmony_ci &pdc_ata_sht); 122262306a36Sopenharmony_ci} 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_cimodule_pci_driver(pdc_ata_pci_driver); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ciMODULE_AUTHOR("Jeff Garzik"); 122762306a36Sopenharmony_ciMODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver"); 122862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 122962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl); 123062306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 1231