18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci/* 48c2ecf20Sopenharmony_ci * acard-ahci.c - ACard AHCI SATA support 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Maintained by: Tejun Heo <tj@kernel.org> 78c2ecf20Sopenharmony_ci * Please ALWAYS copy linux-ide@vger.kernel.org 88c2ecf20Sopenharmony_ci * on emails. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright 2010 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 * AHCI hardware documentation: 168c2ecf20Sopenharmony_ci * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 178c2ecf20Sopenharmony_ci * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <linux/kernel.h> 218c2ecf20Sopenharmony_ci#include <linux/module.h> 228c2ecf20Sopenharmony_ci#include <linux/pci.h> 238c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 248c2ecf20Sopenharmony_ci#include <linux/delay.h> 258c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 268c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 278c2ecf20Sopenharmony_ci#include <linux/device.h> 288c2ecf20Sopenharmony_ci#include <linux/dmi.h> 298c2ecf20Sopenharmony_ci#include <linux/gfp.h> 308c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 318c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h> 328c2ecf20Sopenharmony_ci#include <linux/libata.h> 338c2ecf20Sopenharmony_ci#include "ahci.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define DRV_NAME "acard-ahci" 368c2ecf20Sopenharmony_ci#define DRV_VERSION "1.0" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci Received FIS structure limited to 80h. 408c2ecf20Sopenharmony_ci*/ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define ACARD_AHCI_RX_FIS_SZ 128 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cienum { 458c2ecf20Sopenharmony_ci AHCI_PCI_BAR = 5, 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cienum board_ids { 498c2ecf20Sopenharmony_ci board_acard_ahci, 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistruct acard_sg { 538c2ecf20Sopenharmony_ci __le32 addr; 548c2ecf20Sopenharmony_ci __le32 addr_hi; 558c2ecf20Sopenharmony_ci __le32 reserved; 568c2ecf20Sopenharmony_ci __le32 size; /* bit 31 (EOT) max==0x10000 (64k) */ 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc); 608c2ecf20Sopenharmony_cistatic bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc); 618c2ecf20Sopenharmony_cistatic int acard_ahci_port_start(struct ata_port *ap); 628c2ecf20Sopenharmony_cistatic int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 658c2ecf20Sopenharmony_cistatic int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 668c2ecf20Sopenharmony_cistatic int acard_ahci_pci_device_resume(struct pci_dev *pdev); 678c2ecf20Sopenharmony_ci#endif 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic struct scsi_host_template acard_ahci_sht = { 708c2ecf20Sopenharmony_ci AHCI_SHT("acard-ahci"), 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic struct ata_port_operations acard_ops = { 748c2ecf20Sopenharmony_ci .inherits = &ahci_ops, 758c2ecf20Sopenharmony_ci .qc_prep = acard_ahci_qc_prep, 768c2ecf20Sopenharmony_ci .qc_fill_rtf = acard_ahci_qc_fill_rtf, 778c2ecf20Sopenharmony_ci .port_start = acard_ahci_port_start, 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic const struct ata_port_info acard_ahci_port_info[] = { 838c2ecf20Sopenharmony_ci [board_acard_ahci] = 848c2ecf20Sopenharmony_ci { 858c2ecf20Sopenharmony_ci AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 868c2ecf20Sopenharmony_ci .flags = AHCI_FLAG_COMMON, 878c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 888c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 898c2ecf20Sopenharmony_ci .port_ops = &acard_ops, 908c2ecf20Sopenharmony_ci }, 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic const struct pci_device_id acard_ahci_pci_tbl[] = { 948c2ecf20Sopenharmony_ci /* ACard */ 958c2ecf20Sopenharmony_ci { PCI_VDEVICE(ARTOP, 0x000d), board_acard_ahci }, /* ATP8620 */ 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci { } /* terminate list */ 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic struct pci_driver acard_ahci_pci_driver = { 1018c2ecf20Sopenharmony_ci .name = DRV_NAME, 1028c2ecf20Sopenharmony_ci .id_table = acard_ahci_pci_tbl, 1038c2ecf20Sopenharmony_ci .probe = acard_ahci_init_one, 1048c2ecf20Sopenharmony_ci .remove = ata_pci_remove_one, 1058c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 1068c2ecf20Sopenharmony_ci .suspend = acard_ahci_pci_device_suspend, 1078c2ecf20Sopenharmony_ci .resume = acard_ahci_pci_device_resume, 1088c2ecf20Sopenharmony_ci#endif 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 1128c2ecf20Sopenharmony_cistatic int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 1158c2ecf20Sopenharmony_ci struct ahci_host_priv *hpriv = host->private_data; 1168c2ecf20Sopenharmony_ci void __iomem *mmio = hpriv->mmio; 1178c2ecf20Sopenharmony_ci u32 ctl; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (mesg.event & PM_EVENT_SUSPEND && 1208c2ecf20Sopenharmony_ci hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 1218c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 1228c2ecf20Sopenharmony_ci "BIOS update required for suspend/resume\n"); 1238c2ecf20Sopenharmony_ci return -EIO; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (mesg.event & PM_EVENT_SLEEP) { 1278c2ecf20Sopenharmony_ci /* AHCI spec rev1.1 section 8.3.3: 1288c2ecf20Sopenharmony_ci * Software must disable interrupts prior to requesting a 1298c2ecf20Sopenharmony_ci * transition of the HBA to D3 state. 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci ctl = readl(mmio + HOST_CTL); 1328c2ecf20Sopenharmony_ci ctl &= ~HOST_IRQ_EN; 1338c2ecf20Sopenharmony_ci writel(ctl, mmio + HOST_CTL); 1348c2ecf20Sopenharmony_ci readl(mmio + HOST_CTL); /* flush */ 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return ata_pci_device_suspend(pdev, mesg); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int acard_ahci_pci_device_resume(struct pci_dev *pdev) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 1438c2ecf20Sopenharmony_ci int rc; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci rc = ata_pci_device_do_resume(pdev); 1468c2ecf20Sopenharmony_ci if (rc) 1478c2ecf20Sopenharmony_ci return rc; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 1508c2ecf20Sopenharmony_ci rc = ahci_reset_controller(host); 1518c2ecf20Sopenharmony_ci if (rc) 1528c2ecf20Sopenharmony_ci return rc; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci ahci_init_controller(host); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci ata_host_resume(host); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci#endif 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic void acard_ahci_pci_print_info(struct ata_host *host) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(host->dev); 1668c2ecf20Sopenharmony_ci u16 cc; 1678c2ecf20Sopenharmony_ci const char *scc_s; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci pci_read_config_word(pdev, 0x0a, &cc); 1708c2ecf20Sopenharmony_ci if (cc == PCI_CLASS_STORAGE_IDE) 1718c2ecf20Sopenharmony_ci scc_s = "IDE"; 1728c2ecf20Sopenharmony_ci else if (cc == PCI_CLASS_STORAGE_SATA) 1738c2ecf20Sopenharmony_ci scc_s = "SATA"; 1748c2ecf20Sopenharmony_ci else if (cc == PCI_CLASS_STORAGE_RAID) 1758c2ecf20Sopenharmony_ci scc_s = "RAID"; 1768c2ecf20Sopenharmony_ci else 1778c2ecf20Sopenharmony_ci scc_s = "unknown"; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci ahci_print_info(host, scc_s); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic unsigned int acard_ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct scatterlist *sg; 1858c2ecf20Sopenharmony_ci struct acard_sg *acard_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; 1868c2ecf20Sopenharmony_ci unsigned int si, last_si = 0; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* 1918c2ecf20Sopenharmony_ci * Next, the S/G list. 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_ci for_each_sg(qc->sg, sg, qc->n_elem, si) { 1948c2ecf20Sopenharmony_ci dma_addr_t addr = sg_dma_address(sg); 1958c2ecf20Sopenharmony_ci u32 sg_len = sg_dma_len(sg); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* 1988c2ecf20Sopenharmony_ci * ACard note: 1998c2ecf20Sopenharmony_ci * We must set an end-of-table (EOT) bit, 2008c2ecf20Sopenharmony_ci * and the segment cannot exceed 64k (0x10000) 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_ci acard_sg[si].addr = cpu_to_le32(addr & 0xffffffff); 2038c2ecf20Sopenharmony_ci acard_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16); 2048c2ecf20Sopenharmony_ci acard_sg[si].size = cpu_to_le32(sg_len); 2058c2ecf20Sopenharmony_ci last_si = si; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci acard_sg[last_si].size |= cpu_to_le32(1 << 31); /* set EOT */ 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci return si; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 2168c2ecf20Sopenharmony_ci struct ahci_port_priv *pp = ap->private_data; 2178c2ecf20Sopenharmony_ci int is_atapi = ata_is_atapi(qc->tf.protocol); 2188c2ecf20Sopenharmony_ci void *cmd_tbl; 2198c2ecf20Sopenharmony_ci u32 opts; 2208c2ecf20Sopenharmony_ci const u32 cmd_fis_len = 5; /* five dwords */ 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* 2238c2ecf20Sopenharmony_ci * Fill in command table information. First, the header, 2248c2ecf20Sopenharmony_ci * a SATA Register - Host to Device command FIS. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci cmd_tbl = pp->cmd_tbl + qc->hw_tag * AHCI_CMD_TBL_SZ; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl); 2298c2ecf20Sopenharmony_ci if (is_atapi) { 2308c2ecf20Sopenharmony_ci memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); 2318c2ecf20Sopenharmony_ci memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (qc->flags & ATA_QCFLAG_DMAMAP) 2358c2ecf20Sopenharmony_ci acard_ahci_fill_sg(qc, cmd_tbl); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* 2388c2ecf20Sopenharmony_ci * Fill in command slot information. 2398c2ecf20Sopenharmony_ci * 2408c2ecf20Sopenharmony_ci * ACard note: prd table length not filled in 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci opts = cmd_fis_len | (qc->dev->link->pmp << 12); 2438c2ecf20Sopenharmony_ci if (qc->tf.flags & ATA_TFLAG_WRITE) 2448c2ecf20Sopenharmony_ci opts |= AHCI_CMD_WRITE; 2458c2ecf20Sopenharmony_ci if (is_atapi) 2468c2ecf20Sopenharmony_ci opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci ahci_fill_cmd_slot(pp, qc->hw_tag, opts); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci return AC_ERR_OK; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct ahci_port_priv *pp = qc->ap->private_data; 2568c2ecf20Sopenharmony_ci u8 *rx_fis = pp->rx_fis; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (pp->fbs_enabled) 2598c2ecf20Sopenharmony_ci rx_fis += qc->dev->link->pmp * ACARD_AHCI_RX_FIS_SZ; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* 2628c2ecf20Sopenharmony_ci * After a successful execution of an ATA PIO data-in command, 2638c2ecf20Sopenharmony_ci * the device doesn't send D2H Reg FIS to update the TF and 2648c2ecf20Sopenharmony_ci * the host should take TF and E_Status from the preceding PIO 2658c2ecf20Sopenharmony_ci * Setup FIS. 2668c2ecf20Sopenharmony_ci */ 2678c2ecf20Sopenharmony_ci if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && 2688c2ecf20Sopenharmony_ci !(qc->flags & ATA_QCFLAG_FAILED)) { 2698c2ecf20Sopenharmony_ci ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); 2708c2ecf20Sopenharmony_ci qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15]; 2718c2ecf20Sopenharmony_ci } else 2728c2ecf20Sopenharmony_ci ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci return true; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic int acard_ahci_port_start(struct ata_port *ap) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci struct ahci_host_priv *hpriv = ap->host->private_data; 2808c2ecf20Sopenharmony_ci struct device *dev = ap->host->dev; 2818c2ecf20Sopenharmony_ci struct ahci_port_priv *pp; 2828c2ecf20Sopenharmony_ci void *mem; 2838c2ecf20Sopenharmony_ci dma_addr_t mem_dma; 2848c2ecf20Sopenharmony_ci size_t dma_sz, rx_fis_sz; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 2878c2ecf20Sopenharmony_ci if (!pp) 2888c2ecf20Sopenharmony_ci return -ENOMEM; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* check FBS capability */ 2918c2ecf20Sopenharmony_ci if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) { 2928c2ecf20Sopenharmony_ci void __iomem *port_mmio = ahci_port_base(ap); 2938c2ecf20Sopenharmony_ci u32 cmd = readl(port_mmio + PORT_CMD); 2948c2ecf20Sopenharmony_ci if (cmd & PORT_CMD_FBSCP) 2958c2ecf20Sopenharmony_ci pp->fbs_supported = true; 2968c2ecf20Sopenharmony_ci else if (hpriv->flags & AHCI_HFLAG_YES_FBS) { 2978c2ecf20Sopenharmony_ci dev_info(dev, "port %d can do FBS, forcing FBSCP\n", 2988c2ecf20Sopenharmony_ci ap->port_no); 2998c2ecf20Sopenharmony_ci pp->fbs_supported = true; 3008c2ecf20Sopenharmony_ci } else 3018c2ecf20Sopenharmony_ci dev_warn(dev, "port %d is not capable of FBS\n", 3028c2ecf20Sopenharmony_ci ap->port_no); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (pp->fbs_supported) { 3068c2ecf20Sopenharmony_ci dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ; 3078c2ecf20Sopenharmony_ci rx_fis_sz = ACARD_AHCI_RX_FIS_SZ * 16; 3088c2ecf20Sopenharmony_ci } else { 3098c2ecf20Sopenharmony_ci dma_sz = AHCI_PORT_PRIV_DMA_SZ; 3108c2ecf20Sopenharmony_ci rx_fis_sz = ACARD_AHCI_RX_FIS_SZ; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); 3148c2ecf20Sopenharmony_ci if (!mem) 3158c2ecf20Sopenharmony_ci return -ENOMEM; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* 3188c2ecf20Sopenharmony_ci * First item in chunk of DMA memory: 32-slot command table, 3198c2ecf20Sopenharmony_ci * 32 bytes each in size 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_ci pp->cmd_slot = mem; 3228c2ecf20Sopenharmony_ci pp->cmd_slot_dma = mem_dma; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci mem += AHCI_CMD_SLOT_SZ; 3258c2ecf20Sopenharmony_ci mem_dma += AHCI_CMD_SLOT_SZ; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* 3288c2ecf20Sopenharmony_ci * Second item: Received-FIS area 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci pp->rx_fis = mem; 3318c2ecf20Sopenharmony_ci pp->rx_fis_dma = mem_dma; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci mem += rx_fis_sz; 3348c2ecf20Sopenharmony_ci mem_dma += rx_fis_sz; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* 3378c2ecf20Sopenharmony_ci * Third item: data area for storing a single command 3388c2ecf20Sopenharmony_ci * and its scatter-gather table 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_ci pp->cmd_tbl = mem; 3418c2ecf20Sopenharmony_ci pp->cmd_tbl_dma = mem_dma; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* 3448c2ecf20Sopenharmony_ci * Save off initial list of interrupts to be enabled. 3458c2ecf20Sopenharmony_ci * This could be changed later 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ci pp->intr_mask = DEF_PORT_IRQ; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci ap->private_data = pp; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* engage engines, captain */ 3528c2ecf20Sopenharmony_ci return ahci_port_resume(ap); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci unsigned int board_id = ent->driver_data; 3588c2ecf20Sopenharmony_ci struct ata_port_info pi = acard_ahci_port_info[board_id]; 3598c2ecf20Sopenharmony_ci const struct ata_port_info *ppi[] = { &pi, NULL }; 3608c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 3618c2ecf20Sopenharmony_ci struct ahci_host_priv *hpriv; 3628c2ecf20Sopenharmony_ci struct ata_host *host; 3638c2ecf20Sopenharmony_ci int n_ports, i, rc; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci /* acquire resources */ 3728c2ecf20Sopenharmony_ci rc = pcim_enable_device(pdev); 3738c2ecf20Sopenharmony_ci if (rc) 3748c2ecf20Sopenharmony_ci return rc; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* AHCI controllers often implement SFF compatible interface. 3778c2ecf20Sopenharmony_ci * Grab all PCI BARs just in case. 3788c2ecf20Sopenharmony_ci */ 3798c2ecf20Sopenharmony_ci rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); 3808c2ecf20Sopenharmony_ci if (rc == -EBUSY) 3818c2ecf20Sopenharmony_ci pcim_pin_device(pdev); 3828c2ecf20Sopenharmony_ci if (rc) 3838c2ecf20Sopenharmony_ci return rc; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 3868c2ecf20Sopenharmony_ci if (!hpriv) 3878c2ecf20Sopenharmony_ci return -ENOMEM; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci hpriv->irq = pdev->irq; 3908c2ecf20Sopenharmony_ci hpriv->flags |= (unsigned long)pi.private_data; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) 3938c2ecf20Sopenharmony_ci pci_enable_msi(pdev); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* save initial config */ 3988c2ecf20Sopenharmony_ci ahci_save_initial_config(&pdev->dev, hpriv); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci /* prepare host */ 4018c2ecf20Sopenharmony_ci if (hpriv->cap & HOST_CAP_NCQ) 4028c2ecf20Sopenharmony_ci pi.flags |= ATA_FLAG_NCQ; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci if (hpriv->cap & HOST_CAP_PMP) 4058c2ecf20Sopenharmony_ci pi.flags |= ATA_FLAG_PMP; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci ahci_set_em_messages(hpriv, &pi); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci /* CAP.NP sometimes indicate the index of the last enabled 4108c2ecf20Sopenharmony_ci * port, at other times, that of the last possible port, so 4118c2ecf20Sopenharmony_ci * determining the maximum port number requires looking at 4128c2ecf20Sopenharmony_ci * both CAP.NP and port_map. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 4178c2ecf20Sopenharmony_ci if (!host) 4188c2ecf20Sopenharmony_ci return -ENOMEM; 4198c2ecf20Sopenharmony_ci host->private_data = hpriv; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 4228c2ecf20Sopenharmony_ci host->flags |= ATA_HOST_PARALLEL_SCAN; 4238c2ecf20Sopenharmony_ci else 4248c2ecf20Sopenharmony_ci printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 4278c2ecf20Sopenharmony_ci struct ata_port *ap = host->ports[i]; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); 4308c2ecf20Sopenharmony_ci ata_port_pbar_desc(ap, AHCI_PCI_BAR, 4318c2ecf20Sopenharmony_ci 0x100 + ap->port_no * 0x80, "port"); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* set initial link pm policy */ 4348c2ecf20Sopenharmony_ci /* 4358c2ecf20Sopenharmony_ci ap->pm_policy = NOT_AVAILABLE; 4368c2ecf20Sopenharmony_ci */ 4378c2ecf20Sopenharmony_ci /* disabled/not-implemented port */ 4388c2ecf20Sopenharmony_ci if (!(hpriv->port_map & (1 << i))) 4398c2ecf20Sopenharmony_ci ap->ops = &ata_dummy_port_ops; 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci /* initialize adapter */ 4438c2ecf20Sopenharmony_ci rc = dma_set_mask_and_coherent(&pdev->dev, 4448c2ecf20Sopenharmony_ci DMA_BIT_MASK((hpriv->cap & HOST_CAP_64) ? 64 : 32)); 4458c2ecf20Sopenharmony_ci if (rc) { 4468c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "DMA enable failed\n"); 4478c2ecf20Sopenharmony_ci return rc; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci rc = ahci_reset_controller(host); 4518c2ecf20Sopenharmony_ci if (rc) 4528c2ecf20Sopenharmony_ci return rc; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci ahci_init_controller(host); 4558c2ecf20Sopenharmony_ci acard_ahci_pci_print_info(host); 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci pci_set_master(pdev); 4588c2ecf20Sopenharmony_ci return ahci_host_activate(host, &acard_ahci_sht); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cimodule_pci_driver(acard_ahci_pci_driver); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jeff Garzik"); 4648c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ACard AHCI SATA low-level driver"); 4658c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4668c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, acard_ahci_pci_tbl); 4678c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 468