18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * sata_promise.c - Promise SATA 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Maintained by: Tejun Heo <tj@kernel.org> 68c2ecf20Sopenharmony_ci * Mikael Pettersson 78c2ecf20Sopenharmony_ci * Please ALWAYS copy linux-ide@vger.kernel.org 88c2ecf20Sopenharmony_ci * on emails. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright 2003-2004 Red Hat, Inc. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * libata documentation is available via 'make {ps|pdf}docs', 138c2ecf20Sopenharmony_ci * as Documentation/driver-api/libata.rst 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Hardware information only available under NDA. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/gfp.h> 218c2ecf20Sopenharmony_ci#include <linux/pci.h> 228c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 238c2ecf20Sopenharmony_ci#include <linux/delay.h> 248c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 258c2ecf20Sopenharmony_ci#include <linux/device.h> 268c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 278c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 288c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h> 298c2ecf20Sopenharmony_ci#include <linux/libata.h> 308c2ecf20Sopenharmony_ci#include "sata_promise.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define DRV_NAME "sata_promise" 338c2ecf20Sopenharmony_ci#define DRV_VERSION "2.12" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cienum { 368c2ecf20Sopenharmony_ci PDC_MAX_PORTS = 4, 378c2ecf20Sopenharmony_ci PDC_MMIO_BAR = 3, 388c2ecf20Sopenharmony_ci PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* host register offsets (from host->iomap[PDC_MMIO_BAR]) */ 418c2ecf20Sopenharmony_ci PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ 428c2ecf20Sopenharmony_ci PDC_FLASH_CTL = 0x44, /* Flash control register */ 438c2ecf20Sopenharmony_ci PDC_PCI_CTL = 0x48, /* PCI control/status reg */ 448c2ecf20Sopenharmony_ci PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ 458c2ecf20Sopenharmony_ci PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ 468c2ecf20Sopenharmony_ci PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ 478c2ecf20Sopenharmony_ci PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* per-port ATA register offsets (from ap->ioaddr.cmd_addr) */ 508c2ecf20Sopenharmony_ci PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ 518c2ecf20Sopenharmony_ci PDC_SECTOR_COUNT = 0x08, /* Sector count reg (per port) */ 528c2ecf20Sopenharmony_ci PDC_SECTOR_NUMBER = 0x0C, /* Sector number reg (per port) */ 538c2ecf20Sopenharmony_ci PDC_CYLINDER_LOW = 0x10, /* Cylinder low reg (per port) */ 548c2ecf20Sopenharmony_ci PDC_CYLINDER_HIGH = 0x14, /* Cylinder high reg (per port) */ 558c2ecf20Sopenharmony_ci PDC_DEVICE = 0x18, /* Device/Head reg (per port) */ 568c2ecf20Sopenharmony_ci PDC_COMMAND = 0x1C, /* Command/status reg (per port) */ 578c2ecf20Sopenharmony_ci PDC_ALTSTATUS = 0x38, /* Alternate-status/device-control reg (per port) */ 588c2ecf20Sopenharmony_ci PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ 598c2ecf20Sopenharmony_ci PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ 608c2ecf20Sopenharmony_ci PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* per-port SATA register offsets (from ap->ioaddr.scr_addr) */ 638c2ecf20Sopenharmony_ci PDC_SATA_ERROR = 0x04, 648c2ecf20Sopenharmony_ci PDC_PHYMODE4 = 0x14, 658c2ecf20Sopenharmony_ci PDC_LINK_LAYER_ERRORS = 0x6C, 668c2ecf20Sopenharmony_ci PDC_FPDMA_CTLSTAT = 0xD8, 678c2ecf20Sopenharmony_ci PDC_INTERNAL_DEBUG_1 = 0xF8, /* also used for PATA */ 688c2ecf20Sopenharmony_ci PDC_INTERNAL_DEBUG_2 = 0xFC, /* also used for PATA */ 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* PDC_FPDMA_CTLSTAT bit definitions */ 718c2ecf20Sopenharmony_ci PDC_FPDMA_CTLSTAT_RESET = 1 << 3, 728c2ecf20Sopenharmony_ci PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG = 1 << 10, 738c2ecf20Sopenharmony_ci PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG = 1 << 11, 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* PDC_GLOBAL_CTL bit definitions */ 768c2ecf20Sopenharmony_ci PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */ 778c2ecf20Sopenharmony_ci PDC_SH_ERR = (1 << 9), /* PCI error while loading S/G table */ 788c2ecf20Sopenharmony_ci PDC_DH_ERR = (1 << 10), /* PCI error while loading data */ 798c2ecf20Sopenharmony_ci PDC2_HTO_ERR = (1 << 12), /* host bus timeout */ 808c2ecf20Sopenharmony_ci PDC2_ATA_HBA_ERR = (1 << 13), /* error during SATA DATA FIS transmission */ 818c2ecf20Sopenharmony_ci PDC2_ATA_DMA_CNT_ERR = (1 << 14), /* DMA DATA FIS size differs from S/G count */ 828c2ecf20Sopenharmony_ci PDC_OVERRUN_ERR = (1 << 19), /* S/G byte count larger than HD requires */ 838c2ecf20Sopenharmony_ci PDC_UNDERRUN_ERR = (1 << 20), /* S/G byte count less than HD requires */ 848c2ecf20Sopenharmony_ci PDC_DRIVE_ERR = (1 << 21), /* drive error */ 858c2ecf20Sopenharmony_ci PDC_PCI_SYS_ERR = (1 << 22), /* PCI system error */ 868c2ecf20Sopenharmony_ci PDC1_PCI_PARITY_ERR = (1 << 23), /* PCI parity error (from SATA150 driver) */ 878c2ecf20Sopenharmony_ci PDC1_ERR_MASK = PDC1_PCI_PARITY_ERR, 888c2ecf20Sopenharmony_ci PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | 898c2ecf20Sopenharmony_ci PDC2_ATA_DMA_CNT_ERR, 908c2ecf20Sopenharmony_ci PDC_ERR_MASK = PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | 918c2ecf20Sopenharmony_ci PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR | 928c2ecf20Sopenharmony_ci PDC_DRIVE_ERR | PDC_PCI_SYS_ERR | 938c2ecf20Sopenharmony_ci PDC1_ERR_MASK | PDC2_ERR_MASK, 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci board_2037x = 0, /* FastTrak S150 TX2plus */ 968c2ecf20Sopenharmony_ci board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */ 978c2ecf20Sopenharmony_ci board_20319 = 2, /* FastTrak S150 TX4 */ 988c2ecf20Sopenharmony_ci board_20619 = 3, /* FastTrak TX4000 */ 998c2ecf20Sopenharmony_ci board_2057x = 4, /* SATAII150 Tx2plus */ 1008c2ecf20Sopenharmony_ci board_2057x_pata = 5, /* SATAII150 Tx2plus PATA port */ 1018c2ecf20Sopenharmony_ci board_40518 = 6, /* SATAII150 Tx4 */ 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Sequence counter control registers bit definitions */ 1068c2ecf20Sopenharmony_ci PDC_SEQCNTRL_INT_MASK = (1 << 5), /* Sequence Interrupt Mask */ 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Feature register values */ 1098c2ecf20Sopenharmony_ci PDC_FEATURE_ATAPI_PIO = 0x00, /* ATAPI data xfer by PIO */ 1108c2ecf20Sopenharmony_ci PDC_FEATURE_ATAPI_DMA = 0x01, /* ATAPI data xfer by DMA */ 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* Device/Head register values */ 1138c2ecf20Sopenharmony_ci PDC_DEVICE_SATA = 0xE0, /* Device/Head value for SATA devices */ 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* PDC_CTLSTAT bit definitions */ 1168c2ecf20Sopenharmony_ci PDC_DMA_ENABLE = (1 << 7), 1178c2ecf20Sopenharmony_ci PDC_IRQ_DISABLE = (1 << 10), 1188c2ecf20Sopenharmony_ci PDC_RESET = (1 << 11), /* HDMA reset */ 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci PDC_COMMON_FLAGS = ATA_FLAG_PIO_POLLING, 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* ap->flags bits */ 1238c2ecf20Sopenharmony_ci PDC_FLAG_GEN_II = (1 << 24), 1248c2ecf20Sopenharmony_ci PDC_FLAG_SATA_PATA = (1 << 25), /* supports SATA + PATA */ 1258c2ecf20Sopenharmony_ci PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */ 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistruct pdc_port_priv { 1298c2ecf20Sopenharmony_ci u8 *pkt; 1308c2ecf20Sopenharmony_ci dma_addr_t pkt_dma; 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistruct pdc_host_priv { 1348c2ecf20Sopenharmony_ci spinlock_t hard_reset_lock; 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 1388c2ecf20Sopenharmony_cistatic int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 1398c2ecf20Sopenharmony_cistatic int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 1408c2ecf20Sopenharmony_cistatic int pdc_common_port_start(struct ata_port *ap); 1418c2ecf20Sopenharmony_cistatic int pdc_sata_port_start(struct ata_port *ap); 1428c2ecf20Sopenharmony_cistatic enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc); 1438c2ecf20Sopenharmony_cistatic void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 1448c2ecf20Sopenharmony_cistatic void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 1458c2ecf20Sopenharmony_cistatic int pdc_check_atapi_dma(struct ata_queued_cmd *qc); 1468c2ecf20Sopenharmony_cistatic int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc); 1478c2ecf20Sopenharmony_cistatic void pdc_irq_clear(struct ata_port *ap); 1488c2ecf20Sopenharmony_cistatic unsigned int pdc_qc_issue(struct ata_queued_cmd *qc); 1498c2ecf20Sopenharmony_cistatic void pdc_freeze(struct ata_port *ap); 1508c2ecf20Sopenharmony_cistatic void pdc_sata_freeze(struct ata_port *ap); 1518c2ecf20Sopenharmony_cistatic void pdc_thaw(struct ata_port *ap); 1528c2ecf20Sopenharmony_cistatic void pdc_sata_thaw(struct ata_port *ap); 1538c2ecf20Sopenharmony_cistatic int pdc_pata_softreset(struct ata_link *link, unsigned int *class, 1548c2ecf20Sopenharmony_ci unsigned long deadline); 1558c2ecf20Sopenharmony_cistatic int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, 1568c2ecf20Sopenharmony_ci unsigned long deadline); 1578c2ecf20Sopenharmony_cistatic void pdc_error_handler(struct ata_port *ap); 1588c2ecf20Sopenharmony_cistatic void pdc_post_internal_cmd(struct ata_queued_cmd *qc); 1598c2ecf20Sopenharmony_cistatic int pdc_pata_cable_detect(struct ata_port *ap); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic struct scsi_host_template pdc_ata_sht = { 1628c2ecf20Sopenharmony_ci ATA_BASE_SHT(DRV_NAME), 1638c2ecf20Sopenharmony_ci .sg_tablesize = PDC_MAX_PRD, 1648c2ecf20Sopenharmony_ci .dma_boundary = ATA_DMA_BOUNDARY, 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic const struct ata_port_operations pdc_common_ops = { 1688c2ecf20Sopenharmony_ci .inherits = &ata_sff_port_ops, 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci .sff_tf_load = pdc_tf_load_mmio, 1718c2ecf20Sopenharmony_ci .sff_exec_command = pdc_exec_command_mmio, 1728c2ecf20Sopenharmony_ci .check_atapi_dma = pdc_check_atapi_dma, 1738c2ecf20Sopenharmony_ci .qc_prep = pdc_qc_prep, 1748c2ecf20Sopenharmony_ci .qc_issue = pdc_qc_issue, 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci .sff_irq_clear = pdc_irq_clear, 1778c2ecf20Sopenharmony_ci .lost_interrupt = ATA_OP_NULL, 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci .post_internal_cmd = pdc_post_internal_cmd, 1808c2ecf20Sopenharmony_ci .error_handler = pdc_error_handler, 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic struct ata_port_operations pdc_sata_ops = { 1848c2ecf20Sopenharmony_ci .inherits = &pdc_common_ops, 1858c2ecf20Sopenharmony_ci .cable_detect = ata_cable_sata, 1868c2ecf20Sopenharmony_ci .freeze = pdc_sata_freeze, 1878c2ecf20Sopenharmony_ci .thaw = pdc_sata_thaw, 1888c2ecf20Sopenharmony_ci .scr_read = pdc_sata_scr_read, 1898c2ecf20Sopenharmony_ci .scr_write = pdc_sata_scr_write, 1908c2ecf20Sopenharmony_ci .port_start = pdc_sata_port_start, 1918c2ecf20Sopenharmony_ci .hardreset = pdc_sata_hardreset, 1928c2ecf20Sopenharmony_ci}; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci/* First-generation chips need a more restrictive ->check_atapi_dma op, 1958c2ecf20Sopenharmony_ci and ->freeze/thaw that ignore the hotplug controls. */ 1968c2ecf20Sopenharmony_cistatic struct ata_port_operations pdc_old_sata_ops = { 1978c2ecf20Sopenharmony_ci .inherits = &pdc_sata_ops, 1988c2ecf20Sopenharmony_ci .freeze = pdc_freeze, 1998c2ecf20Sopenharmony_ci .thaw = pdc_thaw, 2008c2ecf20Sopenharmony_ci .check_atapi_dma = pdc_old_sata_check_atapi_dma, 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic struct ata_port_operations pdc_pata_ops = { 2048c2ecf20Sopenharmony_ci .inherits = &pdc_common_ops, 2058c2ecf20Sopenharmony_ci .cable_detect = pdc_pata_cable_detect, 2068c2ecf20Sopenharmony_ci .freeze = pdc_freeze, 2078c2ecf20Sopenharmony_ci .thaw = pdc_thaw, 2088c2ecf20Sopenharmony_ci .port_start = pdc_common_port_start, 2098c2ecf20Sopenharmony_ci .softreset = pdc_pata_softreset, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic const struct ata_port_info pdc_port_info[] = { 2138c2ecf20Sopenharmony_ci [board_2037x] = 2148c2ecf20Sopenharmony_ci { 2158c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 2168c2ecf20Sopenharmony_ci PDC_FLAG_SATA_PATA, 2178c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2188c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2198c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2208c2ecf20Sopenharmony_ci .port_ops = &pdc_old_sata_ops, 2218c2ecf20Sopenharmony_ci }, 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci [board_2037x_pata] = 2248c2ecf20Sopenharmony_ci { 2258c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, 2268c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2278c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2288c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2298c2ecf20Sopenharmony_ci .port_ops = &pdc_pata_ops, 2308c2ecf20Sopenharmony_ci }, 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci [board_20319] = 2338c2ecf20Sopenharmony_ci { 2348c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 2358c2ecf20Sopenharmony_ci PDC_FLAG_4_PORTS, 2368c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2378c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2388c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2398c2ecf20Sopenharmony_ci .port_ops = &pdc_old_sata_ops, 2408c2ecf20Sopenharmony_ci }, 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci [board_20619] = 2438c2ecf20Sopenharmony_ci { 2448c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | 2458c2ecf20Sopenharmony_ci PDC_FLAG_4_PORTS, 2468c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2478c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2488c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2498c2ecf20Sopenharmony_ci .port_ops = &pdc_pata_ops, 2508c2ecf20Sopenharmony_ci }, 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci [board_2057x] = 2538c2ecf20Sopenharmony_ci { 2548c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 2558c2ecf20Sopenharmony_ci PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, 2568c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2578c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2588c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2598c2ecf20Sopenharmony_ci .port_ops = &pdc_sata_ops, 2608c2ecf20Sopenharmony_ci }, 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci [board_2057x_pata] = 2638c2ecf20Sopenharmony_ci { 2648c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | 2658c2ecf20Sopenharmony_ci PDC_FLAG_GEN_II, 2668c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2678c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2688c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2698c2ecf20Sopenharmony_ci .port_ops = &pdc_pata_ops, 2708c2ecf20Sopenharmony_ci }, 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci [board_40518] = 2738c2ecf20Sopenharmony_ci { 2748c2ecf20Sopenharmony_ci .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | 2758c2ecf20Sopenharmony_ci PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, 2768c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 2778c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 2788c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 2798c2ecf20Sopenharmony_ci .port_ops = &pdc_sata_ops, 2808c2ecf20Sopenharmony_ci }, 2818c2ecf20Sopenharmony_ci}; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic const struct pci_device_id pdc_ata_pci_tbl[] = { 2848c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3371), board_2037x }, 2858c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3373), board_2037x }, 2868c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3375), board_2037x }, 2878c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3376), board_2037x }, 2888c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3570), board_2057x }, 2898c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3571), board_2057x }, 2908c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3574), board_2057x }, 2918c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3577), board_2057x }, 2928c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d73), board_2057x }, 2938c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x }, 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3318), board_20319 }, 2968c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3319), board_20319 }, 2978c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3515), board_40518 }, 2988c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3519), board_40518 }, 2998c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d17), board_40518 }, 3008c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x3d18), board_40518 }, 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci { PCI_VDEVICE(PROMISE, 0x6629), board_20619 }, 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci { } /* terminate list */ 3058c2ecf20Sopenharmony_ci}; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic struct pci_driver pdc_ata_pci_driver = { 3088c2ecf20Sopenharmony_ci .name = DRV_NAME, 3098c2ecf20Sopenharmony_ci .id_table = pdc_ata_pci_tbl, 3108c2ecf20Sopenharmony_ci .probe = pdc_ata_init_one, 3118c2ecf20Sopenharmony_ci .remove = ata_pci_remove_one, 3128c2ecf20Sopenharmony_ci}; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic int pdc_common_port_start(struct ata_port *ap) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct device *dev = ap->host->dev; 3178c2ecf20Sopenharmony_ci struct pdc_port_priv *pp; 3188c2ecf20Sopenharmony_ci int rc; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* we use the same prd table as bmdma, allocate it */ 3218c2ecf20Sopenharmony_ci rc = ata_bmdma_port_start(ap); 3228c2ecf20Sopenharmony_ci if (rc) 3238c2ecf20Sopenharmony_ci return rc; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 3268c2ecf20Sopenharmony_ci if (!pp) 3278c2ecf20Sopenharmony_ci return -ENOMEM; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci pp->pkt = dmam_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); 3308c2ecf20Sopenharmony_ci if (!pp->pkt) 3318c2ecf20Sopenharmony_ci return -ENOMEM; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci ap->private_data = pp; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return 0; 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic int pdc_sata_port_start(struct ata_port *ap) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci int rc; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci rc = pdc_common_port_start(ap); 3438c2ecf20Sopenharmony_ci if (rc) 3448c2ecf20Sopenharmony_ci return rc; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* fix up PHYMODE4 align timing */ 3478c2ecf20Sopenharmony_ci if (ap->flags & PDC_FLAG_GEN_II) { 3488c2ecf20Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 3498c2ecf20Sopenharmony_ci unsigned int tmp; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci tmp = readl(sata_mmio + PDC_PHYMODE4); 3528c2ecf20Sopenharmony_ci tmp = (tmp & ~3) | 1; /* set bits 1:0 = 0:1 */ 3538c2ecf20Sopenharmony_ci writel(tmp, sata_mmio + PDC_PHYMODE4); 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return 0; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic void pdc_fpdma_clear_interrupt_flag(struct ata_port *ap) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 3628c2ecf20Sopenharmony_ci u32 tmp; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci tmp = readl(sata_mmio + PDC_FPDMA_CTLSTAT); 3658c2ecf20Sopenharmony_ci tmp |= PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG; 3668c2ecf20Sopenharmony_ci tmp |= PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* It's not allowed to write to the entire FPDMA_CTLSTAT register 3698c2ecf20Sopenharmony_ci when NCQ is running. So do a byte-sized write to bits 10 and 11. */ 3708c2ecf20Sopenharmony_ci writeb(tmp >> 8, sata_mmio + PDC_FPDMA_CTLSTAT + 1); 3718c2ecf20Sopenharmony_ci readb(sata_mmio + PDC_FPDMA_CTLSTAT + 1); /* flush */ 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic void pdc_fpdma_reset(struct ata_port *ap) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 3778c2ecf20Sopenharmony_ci u8 tmp; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci tmp = (u8)readl(sata_mmio + PDC_FPDMA_CTLSTAT); 3808c2ecf20Sopenharmony_ci tmp &= 0x7F; 3818c2ecf20Sopenharmony_ci tmp |= PDC_FPDMA_CTLSTAT_RESET; 3828c2ecf20Sopenharmony_ci writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT); 3838c2ecf20Sopenharmony_ci readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */ 3848c2ecf20Sopenharmony_ci udelay(100); 3858c2ecf20Sopenharmony_ci tmp &= ~PDC_FPDMA_CTLSTAT_RESET; 3868c2ecf20Sopenharmony_ci writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT); 3878c2ecf20Sopenharmony_ci readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */ 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci pdc_fpdma_clear_interrupt_flag(ap); 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic void pdc_not_at_command_packet_phase(struct ata_port *ap) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 3958c2ecf20Sopenharmony_ci unsigned int i; 3968c2ecf20Sopenharmony_ci u32 tmp; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* check not at ASIC packet command phase */ 3998c2ecf20Sopenharmony_ci for (i = 0; i < 100; ++i) { 4008c2ecf20Sopenharmony_ci writel(0, sata_mmio + PDC_INTERNAL_DEBUG_1); 4018c2ecf20Sopenharmony_ci tmp = readl(sata_mmio + PDC_INTERNAL_DEBUG_2); 4028c2ecf20Sopenharmony_ci if ((tmp & 0xF) != 1) 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci udelay(100); 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic void pdc_clear_internal_debug_record_error_register(struct ata_port *ap) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci void __iomem *sata_mmio = ap->ioaddr.scr_addr; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci writel(0xffffffff, sata_mmio + PDC_SATA_ERROR); 4138c2ecf20Sopenharmony_ci writel(0xffff0000, sata_mmio + PDC_LINK_LAYER_ERRORS); 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic void pdc_reset_port(struct ata_port *ap) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; 4198c2ecf20Sopenharmony_ci unsigned int i; 4208c2ecf20Sopenharmony_ci u32 tmp; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci if (ap->flags & PDC_FLAG_GEN_II) 4238c2ecf20Sopenharmony_ci pdc_not_at_command_packet_phase(ap); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci tmp = readl(ata_ctlstat_mmio); 4268c2ecf20Sopenharmony_ci tmp |= PDC_RESET; 4278c2ecf20Sopenharmony_ci writel(tmp, ata_ctlstat_mmio); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci for (i = 11; i > 0; i--) { 4308c2ecf20Sopenharmony_ci tmp = readl(ata_ctlstat_mmio); 4318c2ecf20Sopenharmony_ci if (tmp & PDC_RESET) 4328c2ecf20Sopenharmony_ci break; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci udelay(100); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci tmp |= PDC_RESET; 4378c2ecf20Sopenharmony_ci writel(tmp, ata_ctlstat_mmio); 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci tmp &= ~PDC_RESET; 4418c2ecf20Sopenharmony_ci writel(tmp, ata_ctlstat_mmio); 4428c2ecf20Sopenharmony_ci readl(ata_ctlstat_mmio); /* flush */ 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci if (sata_scr_valid(&ap->link) && (ap->flags & PDC_FLAG_GEN_II)) { 4458c2ecf20Sopenharmony_ci pdc_fpdma_reset(ap); 4468c2ecf20Sopenharmony_ci pdc_clear_internal_debug_record_error_register(ap); 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int pdc_pata_cable_detect(struct ata_port *ap) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci u8 tmp; 4538c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci tmp = readb(ata_mmio + PDC_CTLSTAT + 3); 4568c2ecf20Sopenharmony_ci if (tmp & 0x01) 4578c2ecf20Sopenharmony_ci return ATA_CBL_PATA40; 4588c2ecf20Sopenharmony_ci return ATA_CBL_PATA80; 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic int pdc_sata_scr_read(struct ata_link *link, 4628c2ecf20Sopenharmony_ci unsigned int sc_reg, u32 *val) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci if (sc_reg > SCR_CONTROL) 4658c2ecf20Sopenharmony_ci return -EINVAL; 4668c2ecf20Sopenharmony_ci *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4)); 4678c2ecf20Sopenharmony_ci return 0; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic int pdc_sata_scr_write(struct ata_link *link, 4718c2ecf20Sopenharmony_ci unsigned int sc_reg, u32 val) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci if (sc_reg > SCR_CONTROL) 4748c2ecf20Sopenharmony_ci return -EINVAL; 4758c2ecf20Sopenharmony_ci writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); 4768c2ecf20Sopenharmony_ci return 0; 4778c2ecf20Sopenharmony_ci} 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_cistatic void pdc_atapi_pkt(struct ata_queued_cmd *qc) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 4828c2ecf20Sopenharmony_ci dma_addr_t sg_table = ap->bmdma_prd_dma; 4838c2ecf20Sopenharmony_ci unsigned int cdb_len = qc->dev->cdb_len; 4848c2ecf20Sopenharmony_ci u8 *cdb = qc->cdb; 4858c2ecf20Sopenharmony_ci struct pdc_port_priv *pp = ap->private_data; 4868c2ecf20Sopenharmony_ci u8 *buf = pp->pkt; 4878c2ecf20Sopenharmony_ci __le32 *buf32 = (__le32 *) buf; 4888c2ecf20Sopenharmony_ci unsigned int dev_sel, feature; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci /* set control bits (byte 0), zero delay seq id (byte 3), 4918c2ecf20Sopenharmony_ci * and seq id (byte 2) 4928c2ecf20Sopenharmony_ci */ 4938c2ecf20Sopenharmony_ci switch (qc->tf.protocol) { 4948c2ecf20Sopenharmony_ci case ATAPI_PROT_DMA: 4958c2ecf20Sopenharmony_ci if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 4968c2ecf20Sopenharmony_ci buf32[0] = cpu_to_le32(PDC_PKT_READ); 4978c2ecf20Sopenharmony_ci else 4988c2ecf20Sopenharmony_ci buf32[0] = 0; 4998c2ecf20Sopenharmony_ci break; 5008c2ecf20Sopenharmony_ci case ATAPI_PROT_NODATA: 5018c2ecf20Sopenharmony_ci buf32[0] = cpu_to_le32(PDC_PKT_NODATA); 5028c2ecf20Sopenharmony_ci break; 5038c2ecf20Sopenharmony_ci default: 5048c2ecf20Sopenharmony_ci BUG(); 5058c2ecf20Sopenharmony_ci break; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ 5088c2ecf20Sopenharmony_ci buf32[2] = 0; /* no next-packet */ 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* select drive */ 5118c2ecf20Sopenharmony_ci if (sata_scr_valid(&ap->link)) 5128c2ecf20Sopenharmony_ci dev_sel = PDC_DEVICE_SATA; 5138c2ecf20Sopenharmony_ci else 5148c2ecf20Sopenharmony_ci dev_sel = qc->tf.device; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci buf[12] = (1 << 5) | ATA_REG_DEVICE; 5178c2ecf20Sopenharmony_ci buf[13] = dev_sel; 5188c2ecf20Sopenharmony_ci buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY; 5198c2ecf20Sopenharmony_ci buf[15] = dev_sel; /* once more, waiting for BSY to clear */ 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci buf[16] = (1 << 5) | ATA_REG_NSECT; 5228c2ecf20Sopenharmony_ci buf[17] = qc->tf.nsect; 5238c2ecf20Sopenharmony_ci buf[18] = (1 << 5) | ATA_REG_LBAL; 5248c2ecf20Sopenharmony_ci buf[19] = qc->tf.lbal; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci /* set feature and byte counter registers */ 5278c2ecf20Sopenharmony_ci if (qc->tf.protocol != ATAPI_PROT_DMA) 5288c2ecf20Sopenharmony_ci feature = PDC_FEATURE_ATAPI_PIO; 5298c2ecf20Sopenharmony_ci else 5308c2ecf20Sopenharmony_ci feature = PDC_FEATURE_ATAPI_DMA; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci buf[20] = (1 << 5) | ATA_REG_FEATURE; 5338c2ecf20Sopenharmony_ci buf[21] = feature; 5348c2ecf20Sopenharmony_ci buf[22] = (1 << 5) | ATA_REG_BYTEL; 5358c2ecf20Sopenharmony_ci buf[23] = qc->tf.lbam; 5368c2ecf20Sopenharmony_ci buf[24] = (1 << 5) | ATA_REG_BYTEH; 5378c2ecf20Sopenharmony_ci buf[25] = qc->tf.lbah; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci /* send ATAPI packet command 0xA0 */ 5408c2ecf20Sopenharmony_ci buf[26] = (1 << 5) | ATA_REG_CMD; 5418c2ecf20Sopenharmony_ci buf[27] = qc->tf.command; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* select drive and check DRQ */ 5448c2ecf20Sopenharmony_ci buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY; 5458c2ecf20Sopenharmony_ci buf[29] = dev_sel; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* we can represent cdb lengths 2/4/6/8/10/12/14/16 */ 5488c2ecf20Sopenharmony_ci BUG_ON(cdb_len & ~0x1E); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci /* append the CDB as the final part */ 5518c2ecf20Sopenharmony_ci buf[30] = (((cdb_len >> 1) & 7) << 5) | ATA_REG_DATA | PDC_LAST_REG; 5528c2ecf20Sopenharmony_ci memcpy(buf+31, cdb, cdb_len); 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci/** 5568c2ecf20Sopenharmony_ci * pdc_fill_sg - Fill PCI IDE PRD table 5578c2ecf20Sopenharmony_ci * @qc: Metadata associated with taskfile to be transferred 5588c2ecf20Sopenharmony_ci * 5598c2ecf20Sopenharmony_ci * Fill PCI IDE PRD (scatter-gather) table with segments 5608c2ecf20Sopenharmony_ci * associated with the current disk command. 5618c2ecf20Sopenharmony_ci * Make sure hardware does not choke on it. 5628c2ecf20Sopenharmony_ci * 5638c2ecf20Sopenharmony_ci * LOCKING: 5648c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 5658c2ecf20Sopenharmony_ci * 5668c2ecf20Sopenharmony_ci */ 5678c2ecf20Sopenharmony_cistatic void pdc_fill_sg(struct ata_queued_cmd *qc) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 5708c2ecf20Sopenharmony_ci struct ata_bmdma_prd *prd = ap->bmdma_prd; 5718c2ecf20Sopenharmony_ci struct scatterlist *sg; 5728c2ecf20Sopenharmony_ci const u32 SG_COUNT_ASIC_BUG = 41*4; 5738c2ecf20Sopenharmony_ci unsigned int si, idx; 5748c2ecf20Sopenharmony_ci u32 len; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 5778c2ecf20Sopenharmony_ci return; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci idx = 0; 5808c2ecf20Sopenharmony_ci for_each_sg(qc->sg, sg, qc->n_elem, si) { 5818c2ecf20Sopenharmony_ci u32 addr, offset; 5828c2ecf20Sopenharmony_ci u32 sg_len; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /* determine if physical DMA addr spans 64K boundary. 5858c2ecf20Sopenharmony_ci * Note h/w doesn't support 64-bit, so we unconditionally 5868c2ecf20Sopenharmony_ci * truncate dma_addr_t to u32. 5878c2ecf20Sopenharmony_ci */ 5888c2ecf20Sopenharmony_ci addr = (u32) sg_dma_address(sg); 5898c2ecf20Sopenharmony_ci sg_len = sg_dma_len(sg); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci while (sg_len) { 5928c2ecf20Sopenharmony_ci offset = addr & 0xffff; 5938c2ecf20Sopenharmony_ci len = sg_len; 5948c2ecf20Sopenharmony_ci if ((offset + sg_len) > 0x10000) 5958c2ecf20Sopenharmony_ci len = 0x10000 - offset; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci prd[idx].addr = cpu_to_le32(addr); 5988c2ecf20Sopenharmony_ci prd[idx].flags_len = cpu_to_le32(len & 0xffff); 5998c2ecf20Sopenharmony_ci VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci idx++; 6028c2ecf20Sopenharmony_ci sg_len -= len; 6038c2ecf20Sopenharmony_ci addr += len; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci len = le32_to_cpu(prd[idx - 1].flags_len); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (len > SG_COUNT_ASIC_BUG) { 6108c2ecf20Sopenharmony_ci u32 addr; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci VPRINTK("Splitting last PRD.\n"); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci addr = le32_to_cpu(prd[idx - 1].addr); 6158c2ecf20Sopenharmony_ci prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG); 6168c2ecf20Sopenharmony_ci VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG); 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci addr = addr + len - SG_COUNT_ASIC_BUG; 6198c2ecf20Sopenharmony_ci len = SG_COUNT_ASIC_BUG; 6208c2ecf20Sopenharmony_ci prd[idx].addr = cpu_to_le32(addr); 6218c2ecf20Sopenharmony_ci prd[idx].flags_len = cpu_to_le32(len); 6228c2ecf20Sopenharmony_ci VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci idx++; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_cistatic enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci struct pdc_port_priv *pp = qc->ap->private_data; 6338c2ecf20Sopenharmony_ci unsigned int i; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci switch (qc->tf.protocol) { 6388c2ecf20Sopenharmony_ci case ATA_PROT_DMA: 6398c2ecf20Sopenharmony_ci pdc_fill_sg(qc); 6408c2ecf20Sopenharmony_ci fallthrough; 6418c2ecf20Sopenharmony_ci case ATA_PROT_NODATA: 6428c2ecf20Sopenharmony_ci i = pdc_pkt_header(&qc->tf, qc->ap->bmdma_prd_dma, 6438c2ecf20Sopenharmony_ci qc->dev->devno, pp->pkt); 6448c2ecf20Sopenharmony_ci if (qc->tf.flags & ATA_TFLAG_LBA48) 6458c2ecf20Sopenharmony_ci i = pdc_prep_lba48(&qc->tf, pp->pkt, i); 6468c2ecf20Sopenharmony_ci else 6478c2ecf20Sopenharmony_ci i = pdc_prep_lba28(&qc->tf, pp->pkt, i); 6488c2ecf20Sopenharmony_ci pdc_pkt_footer(&qc->tf, pp->pkt, i); 6498c2ecf20Sopenharmony_ci break; 6508c2ecf20Sopenharmony_ci case ATAPI_PROT_PIO: 6518c2ecf20Sopenharmony_ci pdc_fill_sg(qc); 6528c2ecf20Sopenharmony_ci break; 6538c2ecf20Sopenharmony_ci case ATAPI_PROT_DMA: 6548c2ecf20Sopenharmony_ci pdc_fill_sg(qc); 6558c2ecf20Sopenharmony_ci fallthrough; 6568c2ecf20Sopenharmony_ci case ATAPI_PROT_NODATA: 6578c2ecf20Sopenharmony_ci pdc_atapi_pkt(qc); 6588c2ecf20Sopenharmony_ci break; 6598c2ecf20Sopenharmony_ci default: 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci return AC_ERR_OK; 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistatic int pdc_is_sataii_tx4(unsigned long flags) 6678c2ecf20Sopenharmony_ci{ 6688c2ecf20Sopenharmony_ci const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; 6698c2ecf20Sopenharmony_ci return (flags & mask) == mask; 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic unsigned int pdc_port_no_to_ata_no(unsigned int port_no, 6738c2ecf20Sopenharmony_ci int is_sataii_tx4) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; 6768c2ecf20Sopenharmony_ci return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic unsigned int pdc_sata_nr_ports(const struct ata_port *ap) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci return (ap->flags & PDC_FLAG_4_PORTS) ? 4 : 2; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistatic unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci const struct ata_host *host = ap->host; 6878c2ecf20Sopenharmony_ci unsigned int nr_ports = pdc_sata_nr_ports(ap); 6888c2ecf20Sopenharmony_ci unsigned int i; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci for (i = 0; i < nr_ports && host->ports[i] != ap; ++i) 6918c2ecf20Sopenharmony_ci ; 6928c2ecf20Sopenharmony_ci BUG_ON(i >= nr_ports); 6938c2ecf20Sopenharmony_ci return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags)); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_cistatic void pdc_freeze(struct ata_port *ap) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 6998c2ecf20Sopenharmony_ci u32 tmp; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci tmp = readl(ata_mmio + PDC_CTLSTAT); 7028c2ecf20Sopenharmony_ci tmp |= PDC_IRQ_DISABLE; 7038c2ecf20Sopenharmony_ci tmp &= ~PDC_DMA_ENABLE; 7048c2ecf20Sopenharmony_ci writel(tmp, ata_mmio + PDC_CTLSTAT); 7058c2ecf20Sopenharmony_ci readl(ata_mmio + PDC_CTLSTAT); /* flush */ 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic void pdc_sata_freeze(struct ata_port *ap) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci struct ata_host *host = ap->host; 7118c2ecf20Sopenharmony_ci void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; 7128c2ecf20Sopenharmony_ci unsigned int hotplug_offset = PDC2_SATA_PLUG_CSR; 7138c2ecf20Sopenharmony_ci unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); 7148c2ecf20Sopenharmony_ci u32 hotplug_status; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci /* Disable hotplug events on this port. 7178c2ecf20Sopenharmony_ci * 7188c2ecf20Sopenharmony_ci * Locking: 7198c2ecf20Sopenharmony_ci * 1) hotplug register accesses must be serialised via host->lock 7208c2ecf20Sopenharmony_ci * 2) ap->lock == &ap->host->lock 7218c2ecf20Sopenharmony_ci * 3) ->freeze() and ->thaw() are called with ap->lock held 7228c2ecf20Sopenharmony_ci */ 7238c2ecf20Sopenharmony_ci hotplug_status = readl(host_mmio + hotplug_offset); 7248c2ecf20Sopenharmony_ci hotplug_status |= 0x11 << (ata_no + 16); 7258c2ecf20Sopenharmony_ci writel(hotplug_status, host_mmio + hotplug_offset); 7268c2ecf20Sopenharmony_ci readl(host_mmio + hotplug_offset); /* flush */ 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci pdc_freeze(ap); 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic void pdc_thaw(struct ata_port *ap) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 7348c2ecf20Sopenharmony_ci u32 tmp; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci /* clear IRQ */ 7378c2ecf20Sopenharmony_ci readl(ata_mmio + PDC_COMMAND); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* turn IRQ back on */ 7408c2ecf20Sopenharmony_ci tmp = readl(ata_mmio + PDC_CTLSTAT); 7418c2ecf20Sopenharmony_ci tmp &= ~PDC_IRQ_DISABLE; 7428c2ecf20Sopenharmony_ci writel(tmp, ata_mmio + PDC_CTLSTAT); 7438c2ecf20Sopenharmony_ci readl(ata_mmio + PDC_CTLSTAT); /* flush */ 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cistatic void pdc_sata_thaw(struct ata_port *ap) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci struct ata_host *host = ap->host; 7498c2ecf20Sopenharmony_ci void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; 7508c2ecf20Sopenharmony_ci unsigned int hotplug_offset = PDC2_SATA_PLUG_CSR; 7518c2ecf20Sopenharmony_ci unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap); 7528c2ecf20Sopenharmony_ci u32 hotplug_status; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci pdc_thaw(ap); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* Enable hotplug events on this port. 7578c2ecf20Sopenharmony_ci * Locking: see pdc_sata_freeze(). 7588c2ecf20Sopenharmony_ci */ 7598c2ecf20Sopenharmony_ci hotplug_status = readl(host_mmio + hotplug_offset); 7608c2ecf20Sopenharmony_ci hotplug_status |= 0x11 << ata_no; 7618c2ecf20Sopenharmony_ci hotplug_status &= ~(0x11 << (ata_no + 16)); 7628c2ecf20Sopenharmony_ci writel(hotplug_status, host_mmio + hotplug_offset); 7638c2ecf20Sopenharmony_ci readl(host_mmio + hotplug_offset); /* flush */ 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_cistatic int pdc_pata_softreset(struct ata_link *link, unsigned int *class, 7678c2ecf20Sopenharmony_ci unsigned long deadline) 7688c2ecf20Sopenharmony_ci{ 7698c2ecf20Sopenharmony_ci pdc_reset_port(link->ap); 7708c2ecf20Sopenharmony_ci return ata_sff_softreset(link, class, deadline); 7718c2ecf20Sopenharmony_ci} 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_cistatic unsigned int pdc_ata_port_to_ata_no(const struct ata_port *ap) 7748c2ecf20Sopenharmony_ci{ 7758c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 7768c2ecf20Sopenharmony_ci void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci /* ata_mmio == host_mmio + 0x200 + ata_no * 0x80 */ 7798c2ecf20Sopenharmony_ci return (ata_mmio - host_mmio - 0x200) / 0x80; 7808c2ecf20Sopenharmony_ci} 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_cistatic void pdc_hard_reset_port(struct ata_port *ap) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 7858c2ecf20Sopenharmony_ci void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; 7868c2ecf20Sopenharmony_ci unsigned int ata_no = pdc_ata_port_to_ata_no(ap); 7878c2ecf20Sopenharmony_ci struct pdc_host_priv *hpriv = ap->host->private_data; 7888c2ecf20Sopenharmony_ci u8 tmp; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci spin_lock(&hpriv->hard_reset_lock); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci tmp = readb(pcictl_b1_mmio); 7938c2ecf20Sopenharmony_ci tmp &= ~(0x10 << ata_no); 7948c2ecf20Sopenharmony_ci writeb(tmp, pcictl_b1_mmio); 7958c2ecf20Sopenharmony_ci readb(pcictl_b1_mmio); /* flush */ 7968c2ecf20Sopenharmony_ci udelay(100); 7978c2ecf20Sopenharmony_ci tmp |= (0x10 << ata_no); 7988c2ecf20Sopenharmony_ci writeb(tmp, pcictl_b1_mmio); 7998c2ecf20Sopenharmony_ci readb(pcictl_b1_mmio); /* flush */ 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci spin_unlock(&hpriv->hard_reset_lock); 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_cistatic int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, 8058c2ecf20Sopenharmony_ci unsigned long deadline) 8068c2ecf20Sopenharmony_ci{ 8078c2ecf20Sopenharmony_ci if (link->ap->flags & PDC_FLAG_GEN_II) 8088c2ecf20Sopenharmony_ci pdc_not_at_command_packet_phase(link->ap); 8098c2ecf20Sopenharmony_ci /* hotplug IRQs should have been masked by pdc_sata_freeze() */ 8108c2ecf20Sopenharmony_ci pdc_hard_reset_port(link->ap); 8118c2ecf20Sopenharmony_ci pdc_reset_port(link->ap); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci /* sata_promise can't reliably acquire the first D2H Reg FIS 8148c2ecf20Sopenharmony_ci * after hardreset. Do non-waiting hardreset and request 8158c2ecf20Sopenharmony_ci * follow-up SRST. 8168c2ecf20Sopenharmony_ci */ 8178c2ecf20Sopenharmony_ci return sata_std_hardreset(link, class, deadline); 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic void pdc_error_handler(struct ata_port *ap) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci if (!(ap->pflags & ATA_PFLAG_FROZEN)) 8238c2ecf20Sopenharmony_ci pdc_reset_port(ap); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci ata_sff_error_handler(ap); 8268c2ecf20Sopenharmony_ci} 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_cistatic void pdc_post_internal_cmd(struct ata_queued_cmd *qc) 8298c2ecf20Sopenharmony_ci{ 8308c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci /* make DMA engine forget about the failed command */ 8338c2ecf20Sopenharmony_ci if (qc->flags & ATA_QCFLAG_FAILED) 8348c2ecf20Sopenharmony_ci pdc_reset_port(ap); 8358c2ecf20Sopenharmony_ci} 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_cistatic void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, 8388c2ecf20Sopenharmony_ci u32 port_status, u32 err_mask) 8398c2ecf20Sopenharmony_ci{ 8408c2ecf20Sopenharmony_ci struct ata_eh_info *ehi = &ap->link.eh_info; 8418c2ecf20Sopenharmony_ci unsigned int ac_err_mask = 0; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci ata_ehi_clear_desc(ehi); 8448c2ecf20Sopenharmony_ci ata_ehi_push_desc(ehi, "port_status 0x%08x", port_status); 8458c2ecf20Sopenharmony_ci port_status &= err_mask; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci if (port_status & PDC_DRIVE_ERR) 8488c2ecf20Sopenharmony_ci ac_err_mask |= AC_ERR_DEV; 8498c2ecf20Sopenharmony_ci if (port_status & (PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR)) 8508c2ecf20Sopenharmony_ci ac_err_mask |= AC_ERR_OTHER; 8518c2ecf20Sopenharmony_ci if (port_status & (PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR)) 8528c2ecf20Sopenharmony_ci ac_err_mask |= AC_ERR_ATA_BUS; 8538c2ecf20Sopenharmony_ci if (port_status & (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC2_HTO_ERR 8548c2ecf20Sopenharmony_ci | PDC_PCI_SYS_ERR | PDC1_PCI_PARITY_ERR)) 8558c2ecf20Sopenharmony_ci ac_err_mask |= AC_ERR_HOST_BUS; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci if (sata_scr_valid(&ap->link)) { 8588c2ecf20Sopenharmony_ci u32 serror; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci pdc_sata_scr_read(&ap->link, SCR_ERROR, &serror); 8618c2ecf20Sopenharmony_ci ehi->serror |= serror; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci qc->err_mask |= ac_err_mask; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci pdc_reset_port(ap); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci ata_port_abort(ap); 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic unsigned int pdc_host_intr(struct ata_port *ap, 8728c2ecf20Sopenharmony_ci struct ata_queued_cmd *qc) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci unsigned int handled = 0; 8758c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 8768c2ecf20Sopenharmony_ci u32 port_status, err_mask; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci err_mask = PDC_ERR_MASK; 8798c2ecf20Sopenharmony_ci if (ap->flags & PDC_FLAG_GEN_II) 8808c2ecf20Sopenharmony_ci err_mask &= ~PDC1_ERR_MASK; 8818c2ecf20Sopenharmony_ci else 8828c2ecf20Sopenharmony_ci err_mask &= ~PDC2_ERR_MASK; 8838c2ecf20Sopenharmony_ci port_status = readl(ata_mmio + PDC_GLOBAL_CTL); 8848c2ecf20Sopenharmony_ci if (unlikely(port_status & err_mask)) { 8858c2ecf20Sopenharmony_ci pdc_error_intr(ap, qc, port_status, err_mask); 8868c2ecf20Sopenharmony_ci return 1; 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci switch (qc->tf.protocol) { 8908c2ecf20Sopenharmony_ci case ATA_PROT_DMA: 8918c2ecf20Sopenharmony_ci case ATA_PROT_NODATA: 8928c2ecf20Sopenharmony_ci case ATAPI_PROT_DMA: 8938c2ecf20Sopenharmony_ci case ATAPI_PROT_NODATA: 8948c2ecf20Sopenharmony_ci qc->err_mask |= ac_err_mask(ata_wait_idle(ap)); 8958c2ecf20Sopenharmony_ci ata_qc_complete(qc); 8968c2ecf20Sopenharmony_ci handled = 1; 8978c2ecf20Sopenharmony_ci break; 8988c2ecf20Sopenharmony_ci default: 8998c2ecf20Sopenharmony_ci ap->stats.idle_irq++; 9008c2ecf20Sopenharmony_ci break; 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci return handled; 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic void pdc_irq_clear(struct ata_port *ap) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci readl(ata_mmio + PDC_COMMAND); 9118c2ecf20Sopenharmony_ci} 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_cistatic irqreturn_t pdc_interrupt(int irq, void *dev_instance) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci struct ata_host *host = dev_instance; 9168c2ecf20Sopenharmony_ci struct ata_port *ap; 9178c2ecf20Sopenharmony_ci u32 mask = 0; 9188c2ecf20Sopenharmony_ci unsigned int i, tmp; 9198c2ecf20Sopenharmony_ci unsigned int handled = 0; 9208c2ecf20Sopenharmony_ci void __iomem *host_mmio; 9218c2ecf20Sopenharmony_ci unsigned int hotplug_offset, ata_no; 9228c2ecf20Sopenharmony_ci u32 hotplug_status; 9238c2ecf20Sopenharmony_ci int is_sataii_tx4; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (!host || !host->iomap[PDC_MMIO_BAR]) { 9288c2ecf20Sopenharmony_ci VPRINTK("QUICK EXIT\n"); 9298c2ecf20Sopenharmony_ci return IRQ_NONE; 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci host_mmio = host->iomap[PDC_MMIO_BAR]; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci spin_lock(&host->lock); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* read and clear hotplug flags for all ports */ 9378c2ecf20Sopenharmony_ci if (host->ports[0]->flags & PDC_FLAG_GEN_II) { 9388c2ecf20Sopenharmony_ci hotplug_offset = PDC2_SATA_PLUG_CSR; 9398c2ecf20Sopenharmony_ci hotplug_status = readl(host_mmio + hotplug_offset); 9408c2ecf20Sopenharmony_ci if (hotplug_status & 0xff) 9418c2ecf20Sopenharmony_ci writel(hotplug_status | 0xff, host_mmio + hotplug_offset); 9428c2ecf20Sopenharmony_ci hotplug_status &= 0xff; /* clear uninteresting bits */ 9438c2ecf20Sopenharmony_ci } else 9448c2ecf20Sopenharmony_ci hotplug_status = 0; 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci /* reading should also clear interrupts */ 9478c2ecf20Sopenharmony_ci mask = readl(host_mmio + PDC_INT_SEQMASK); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci if (mask == 0xffffffff && hotplug_status == 0) { 9508c2ecf20Sopenharmony_ci VPRINTK("QUICK EXIT 2\n"); 9518c2ecf20Sopenharmony_ci goto done_irq; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci mask &= 0xffff; /* only 16 SEQIDs possible */ 9558c2ecf20Sopenharmony_ci if (mask == 0 && hotplug_status == 0) { 9568c2ecf20Sopenharmony_ci VPRINTK("QUICK EXIT 3\n"); 9578c2ecf20Sopenharmony_ci goto done_irq; 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci writel(mask, host_mmio + PDC_INT_SEQMASK); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 9658c2ecf20Sopenharmony_ci VPRINTK("port %u\n", i); 9668c2ecf20Sopenharmony_ci ap = host->ports[i]; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci /* check for a plug or unplug event */ 9698c2ecf20Sopenharmony_ci ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4); 9708c2ecf20Sopenharmony_ci tmp = hotplug_status & (0x11 << ata_no); 9718c2ecf20Sopenharmony_ci if (tmp) { 9728c2ecf20Sopenharmony_ci struct ata_eh_info *ehi = &ap->link.eh_info; 9738c2ecf20Sopenharmony_ci ata_ehi_clear_desc(ehi); 9748c2ecf20Sopenharmony_ci ata_ehi_hotplugged(ehi); 9758c2ecf20Sopenharmony_ci ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp); 9768c2ecf20Sopenharmony_ci ata_port_freeze(ap); 9778c2ecf20Sopenharmony_ci ++handled; 9788c2ecf20Sopenharmony_ci continue; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci /* check for a packet interrupt */ 9828c2ecf20Sopenharmony_ci tmp = mask & (1 << (i + 1)); 9838c2ecf20Sopenharmony_ci if (tmp) { 9848c2ecf20Sopenharmony_ci struct ata_queued_cmd *qc; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci qc = ata_qc_from_tag(ap, ap->link.active_tag); 9878c2ecf20Sopenharmony_ci if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) 9888c2ecf20Sopenharmony_ci handled += pdc_host_intr(ap, qc); 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci VPRINTK("EXIT\n"); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_cidone_irq: 9958c2ecf20Sopenharmony_ci spin_unlock(&host->lock); 9968c2ecf20Sopenharmony_ci return IRQ_RETVAL(handled); 9978c2ecf20Sopenharmony_ci} 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_cistatic void pdc_packet_start(struct ata_queued_cmd *qc) 10008c2ecf20Sopenharmony_ci{ 10018c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 10028c2ecf20Sopenharmony_ci struct pdc_port_priv *pp = ap->private_data; 10038c2ecf20Sopenharmony_ci void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 10048c2ecf20Sopenharmony_ci void __iomem *ata_mmio = ap->ioaddr.cmd_addr; 10058c2ecf20Sopenharmony_ci unsigned int port_no = ap->port_no; 10068c2ecf20Sopenharmony_ci u8 seq = (u8) (port_no + 1); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci VPRINTK("ENTER, ap %p\n", ap); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci writel(0x00000001, host_mmio + (seq * 4)); 10118c2ecf20Sopenharmony_ci readl(host_mmio + (seq * 4)); /* flush */ 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci pp->pkt[2] = seq; 10148c2ecf20Sopenharmony_ci wmb(); /* flush PRD, pkt writes */ 10158c2ecf20Sopenharmony_ci writel(pp->pkt_dma, ata_mmio + PDC_PKT_SUBMIT); 10168c2ecf20Sopenharmony_ci readl(ata_mmio + PDC_PKT_SUBMIT); /* flush */ 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_cistatic unsigned int pdc_qc_issue(struct ata_queued_cmd *qc) 10208c2ecf20Sopenharmony_ci{ 10218c2ecf20Sopenharmony_ci switch (qc->tf.protocol) { 10228c2ecf20Sopenharmony_ci case ATAPI_PROT_NODATA: 10238c2ecf20Sopenharmony_ci if (qc->dev->flags & ATA_DFLAG_CDB_INTR) 10248c2ecf20Sopenharmony_ci break; 10258c2ecf20Sopenharmony_ci fallthrough; 10268c2ecf20Sopenharmony_ci case ATA_PROT_NODATA: 10278c2ecf20Sopenharmony_ci if (qc->tf.flags & ATA_TFLAG_POLLING) 10288c2ecf20Sopenharmony_ci break; 10298c2ecf20Sopenharmony_ci fallthrough; 10308c2ecf20Sopenharmony_ci case ATAPI_PROT_DMA: 10318c2ecf20Sopenharmony_ci case ATA_PROT_DMA: 10328c2ecf20Sopenharmony_ci pdc_packet_start(qc); 10338c2ecf20Sopenharmony_ci return 0; 10348c2ecf20Sopenharmony_ci default: 10358c2ecf20Sopenharmony_ci break; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci return ata_sff_qc_issue(qc); 10388c2ecf20Sopenharmony_ci} 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_cistatic void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); 10438c2ecf20Sopenharmony_ci ata_sff_tf_load(ap, tf); 10448c2ecf20Sopenharmony_ci} 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_cistatic void pdc_exec_command_mmio(struct ata_port *ap, 10478c2ecf20Sopenharmony_ci const struct ata_taskfile *tf) 10488c2ecf20Sopenharmony_ci{ 10498c2ecf20Sopenharmony_ci WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); 10508c2ecf20Sopenharmony_ci ata_sff_exec_command(ap, tf); 10518c2ecf20Sopenharmony_ci} 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_cistatic int pdc_check_atapi_dma(struct ata_queued_cmd *qc) 10548c2ecf20Sopenharmony_ci{ 10558c2ecf20Sopenharmony_ci u8 *scsicmd = qc->scsicmd->cmnd; 10568c2ecf20Sopenharmony_ci int pio = 1; /* atapi dma off by default */ 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* Whitelist commands that may use DMA. */ 10598c2ecf20Sopenharmony_ci switch (scsicmd[0]) { 10608c2ecf20Sopenharmony_ci case WRITE_12: 10618c2ecf20Sopenharmony_ci case WRITE_10: 10628c2ecf20Sopenharmony_ci case WRITE_6: 10638c2ecf20Sopenharmony_ci case READ_12: 10648c2ecf20Sopenharmony_ci case READ_10: 10658c2ecf20Sopenharmony_ci case READ_6: 10668c2ecf20Sopenharmony_ci case 0xad: /* READ_DVD_STRUCTURE */ 10678c2ecf20Sopenharmony_ci case 0xbe: /* READ_CD */ 10688c2ecf20Sopenharmony_ci pio = 0; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ 10718c2ecf20Sopenharmony_ci if (scsicmd[0] == WRITE_10) { 10728c2ecf20Sopenharmony_ci unsigned int lba = 10738c2ecf20Sopenharmony_ci (scsicmd[2] << 24) | 10748c2ecf20Sopenharmony_ci (scsicmd[3] << 16) | 10758c2ecf20Sopenharmony_ci (scsicmd[4] << 8) | 10768c2ecf20Sopenharmony_ci scsicmd[5]; 10778c2ecf20Sopenharmony_ci if (lba >= 0xFFFF4FA2) 10788c2ecf20Sopenharmony_ci pio = 1; 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci return pio; 10818c2ecf20Sopenharmony_ci} 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc) 10848c2ecf20Sopenharmony_ci{ 10858c2ecf20Sopenharmony_ci /* First generation chips cannot use ATAPI DMA on SATA ports */ 10868c2ecf20Sopenharmony_ci return 1; 10878c2ecf20Sopenharmony_ci} 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_cistatic void pdc_ata_setup_port(struct ata_port *ap, 10908c2ecf20Sopenharmony_ci void __iomem *base, void __iomem *scr_addr) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci ap->ioaddr.cmd_addr = base; 10938c2ecf20Sopenharmony_ci ap->ioaddr.data_addr = base; 10948c2ecf20Sopenharmony_ci ap->ioaddr.feature_addr = 10958c2ecf20Sopenharmony_ci ap->ioaddr.error_addr = base + 0x4; 10968c2ecf20Sopenharmony_ci ap->ioaddr.nsect_addr = base + 0x8; 10978c2ecf20Sopenharmony_ci ap->ioaddr.lbal_addr = base + 0xc; 10988c2ecf20Sopenharmony_ci ap->ioaddr.lbam_addr = base + 0x10; 10998c2ecf20Sopenharmony_ci ap->ioaddr.lbah_addr = base + 0x14; 11008c2ecf20Sopenharmony_ci ap->ioaddr.device_addr = base + 0x18; 11018c2ecf20Sopenharmony_ci ap->ioaddr.command_addr = 11028c2ecf20Sopenharmony_ci ap->ioaddr.status_addr = base + 0x1c; 11038c2ecf20Sopenharmony_ci ap->ioaddr.altstatus_addr = 11048c2ecf20Sopenharmony_ci ap->ioaddr.ctl_addr = base + 0x38; 11058c2ecf20Sopenharmony_ci ap->ioaddr.scr_addr = scr_addr; 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic void pdc_host_init(struct ata_host *host) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR]; 11118c2ecf20Sopenharmony_ci int is_gen2 = host->ports[0]->flags & PDC_FLAG_GEN_II; 11128c2ecf20Sopenharmony_ci int hotplug_offset; 11138c2ecf20Sopenharmony_ci u32 tmp; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (is_gen2) 11168c2ecf20Sopenharmony_ci hotplug_offset = PDC2_SATA_PLUG_CSR; 11178c2ecf20Sopenharmony_ci else 11188c2ecf20Sopenharmony_ci hotplug_offset = PDC_SATA_PLUG_CSR; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* 11218c2ecf20Sopenharmony_ci * Except for the hotplug stuff, this is voodoo from the 11228c2ecf20Sopenharmony_ci * Promise driver. Label this entire section 11238c2ecf20Sopenharmony_ci * "TODO: figure out why we do this" 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci /* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */ 11278c2ecf20Sopenharmony_ci tmp = readl(host_mmio + PDC_FLASH_CTL); 11288c2ecf20Sopenharmony_ci tmp |= 0x02000; /* bit 13 (enable bmr burst) */ 11298c2ecf20Sopenharmony_ci if (!is_gen2) 11308c2ecf20Sopenharmony_ci tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */ 11318c2ecf20Sopenharmony_ci writel(tmp, host_mmio + PDC_FLASH_CTL); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci /* clear plug/unplug flags for all ports */ 11348c2ecf20Sopenharmony_ci tmp = readl(host_mmio + hotplug_offset); 11358c2ecf20Sopenharmony_ci writel(tmp | 0xff, host_mmio + hotplug_offset); 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci tmp = readl(host_mmio + hotplug_offset); 11388c2ecf20Sopenharmony_ci if (is_gen2) /* unmask plug/unplug ints */ 11398c2ecf20Sopenharmony_ci writel(tmp & ~0xff0000, host_mmio + hotplug_offset); 11408c2ecf20Sopenharmony_ci else /* mask plug/unplug ints */ 11418c2ecf20Sopenharmony_ci writel(tmp | 0xff0000, host_mmio + hotplug_offset); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci /* don't initialise TBG or SLEW on 2nd generation chips */ 11448c2ecf20Sopenharmony_ci if (is_gen2) 11458c2ecf20Sopenharmony_ci return; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci /* reduce TBG clock to 133 Mhz. */ 11488c2ecf20Sopenharmony_ci tmp = readl(host_mmio + PDC_TBG_MODE); 11498c2ecf20Sopenharmony_ci tmp &= ~0x30000; /* clear bit 17, 16*/ 11508c2ecf20Sopenharmony_ci tmp |= 0x10000; /* set bit 17:16 = 0:1 */ 11518c2ecf20Sopenharmony_ci writel(tmp, host_mmio + PDC_TBG_MODE); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci readl(host_mmio + PDC_TBG_MODE); /* flush */ 11548c2ecf20Sopenharmony_ci msleep(10); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci /* adjust slew rate control register. */ 11578c2ecf20Sopenharmony_ci tmp = readl(host_mmio + PDC_SLEW_CTL); 11588c2ecf20Sopenharmony_ci tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */ 11598c2ecf20Sopenharmony_ci tmp |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */ 11608c2ecf20Sopenharmony_ci writel(tmp, host_mmio + PDC_SLEW_CTL); 11618c2ecf20Sopenharmony_ci} 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_cistatic int pdc_ata_init_one(struct pci_dev *pdev, 11648c2ecf20Sopenharmony_ci const struct pci_device_id *ent) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; 11678c2ecf20Sopenharmony_ci const struct ata_port_info *ppi[PDC_MAX_PORTS]; 11688c2ecf20Sopenharmony_ci struct ata_host *host; 11698c2ecf20Sopenharmony_ci struct pdc_host_priv *hpriv; 11708c2ecf20Sopenharmony_ci void __iomem *host_mmio; 11718c2ecf20Sopenharmony_ci int n_ports, i, rc; 11728c2ecf20Sopenharmony_ci int is_sataii_tx4; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* enable and acquire resources */ 11778c2ecf20Sopenharmony_ci rc = pcim_enable_device(pdev); 11788c2ecf20Sopenharmony_ci if (rc) 11798c2ecf20Sopenharmony_ci return rc; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci rc = pcim_iomap_regions(pdev, 1 << PDC_MMIO_BAR, DRV_NAME); 11828c2ecf20Sopenharmony_ci if (rc == -EBUSY) 11838c2ecf20Sopenharmony_ci pcim_pin_device(pdev); 11848c2ecf20Sopenharmony_ci if (rc) 11858c2ecf20Sopenharmony_ci return rc; 11868c2ecf20Sopenharmony_ci host_mmio = pcim_iomap_table(pdev)[PDC_MMIO_BAR]; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci /* determine port configuration and setup host */ 11898c2ecf20Sopenharmony_ci n_ports = 2; 11908c2ecf20Sopenharmony_ci if (pi->flags & PDC_FLAG_4_PORTS) 11918c2ecf20Sopenharmony_ci n_ports = 4; 11928c2ecf20Sopenharmony_ci for (i = 0; i < n_ports; i++) 11938c2ecf20Sopenharmony_ci ppi[i] = pi; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (pi->flags & PDC_FLAG_SATA_PATA) { 11968c2ecf20Sopenharmony_ci u8 tmp = readb(host_mmio + PDC_FLASH_CTL + 1); 11978c2ecf20Sopenharmony_ci if (!(tmp & 0x80)) 11988c2ecf20Sopenharmony_ci ppi[n_ports++] = pi + 1; 11998c2ecf20Sopenharmony_ci } 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 12028c2ecf20Sopenharmony_ci if (!host) { 12038c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to allocate host\n"); 12048c2ecf20Sopenharmony_ci return -ENOMEM; 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); 12078c2ecf20Sopenharmony_ci if (!hpriv) 12088c2ecf20Sopenharmony_ci return -ENOMEM; 12098c2ecf20Sopenharmony_ci spin_lock_init(&hpriv->hard_reset_lock); 12108c2ecf20Sopenharmony_ci host->private_data = hpriv; 12118c2ecf20Sopenharmony_ci host->iomap = pcim_iomap_table(pdev); 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); 12148c2ecf20Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 12158c2ecf20Sopenharmony_ci struct ata_port *ap = host->ports[i]; 12168c2ecf20Sopenharmony_ci unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4); 12178c2ecf20Sopenharmony_ci unsigned int ata_offset = 0x200 + ata_no * 0x80; 12188c2ecf20Sopenharmony_ci unsigned int scr_offset = 0x400 + ata_no * 0x100; 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci pdc_ata_setup_port(ap, host_mmio + ata_offset, host_mmio + scr_offset); 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio"); 12238c2ecf20Sopenharmony_ci ata_port_pbar_desc(ap, PDC_MMIO_BAR, ata_offset, "ata"); 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci /* initialize adapter */ 12278c2ecf20Sopenharmony_ci pdc_host_init(host); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); 12308c2ecf20Sopenharmony_ci if (rc) 12318c2ecf20Sopenharmony_ci return rc; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci /* start host, request IRQ and attach */ 12348c2ecf20Sopenharmony_ci pci_set_master(pdev); 12358c2ecf20Sopenharmony_ci return ata_host_activate(host, pdev->irq, pdc_interrupt, IRQF_SHARED, 12368c2ecf20Sopenharmony_ci &pdc_ata_sht); 12378c2ecf20Sopenharmony_ci} 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_cimodule_pci_driver(pdc_ata_pci_driver); 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jeff Garzik"); 12428c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver"); 12438c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 12448c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl); 12458c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 1246