1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
202cdfcf0SDavid Milburn
302cdfcf0SDavid Milburn /*
402cdfcf0SDavid Milburn * acard-ahci.c - ACard AHCI SATA support
502cdfcf0SDavid Milburn *
68c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org>
702cdfcf0SDavid Milburn * Please ALWAYS copy linux-ide@vger.kernel.org
802cdfcf0SDavid Milburn * on emails.
902cdfcf0SDavid Milburn *
1002cdfcf0SDavid Milburn * Copyright 2010 Red Hat, Inc.
1102cdfcf0SDavid Milburn *
1202cdfcf0SDavid Milburn * libata documentation is available via 'make {ps|pdf}docs',
1319285f3cSMauro Carvalho Chehab * as Documentation/driver-api/libata.rst
1402cdfcf0SDavid Milburn *
1502cdfcf0SDavid Milburn * AHCI hardware documentation:
1602cdfcf0SDavid Milburn * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
1702cdfcf0SDavid Milburn * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
1802cdfcf0SDavid Milburn */
1902cdfcf0SDavid Milburn
2002cdfcf0SDavid Milburn #include <linux/kernel.h>
2102cdfcf0SDavid Milburn #include <linux/module.h>
2202cdfcf0SDavid Milburn #include <linux/pci.h>
2302cdfcf0SDavid Milburn #include <linux/blkdev.h>
2402cdfcf0SDavid Milburn #include <linux/delay.h>
2502cdfcf0SDavid Milburn #include <linux/interrupt.h>
2602cdfcf0SDavid Milburn #include <linux/dma-mapping.h>
2702cdfcf0SDavid Milburn #include <linux/device.h>
2802cdfcf0SDavid Milburn #include <linux/dmi.h>
2902cdfcf0SDavid Milburn #include <linux/gfp.h>
3002cdfcf0SDavid Milburn #include <scsi/scsi_host.h>
3102cdfcf0SDavid Milburn #include <scsi/scsi_cmnd.h>
3202cdfcf0SDavid Milburn #include <linux/libata.h>
3302cdfcf0SDavid Milburn #include "ahci.h"
3402cdfcf0SDavid Milburn
3502cdfcf0SDavid Milburn #define DRV_NAME "acard-ahci"
3602cdfcf0SDavid Milburn #define DRV_VERSION "1.0"
3702cdfcf0SDavid Milburn
3802cdfcf0SDavid Milburn /*
3902cdfcf0SDavid Milburn Received FIS structure limited to 80h.
4002cdfcf0SDavid Milburn */
4102cdfcf0SDavid Milburn
4202cdfcf0SDavid Milburn #define ACARD_AHCI_RX_FIS_SZ 128
4302cdfcf0SDavid Milburn
4402cdfcf0SDavid Milburn enum {
4502cdfcf0SDavid Milburn AHCI_PCI_BAR = 5,
4602cdfcf0SDavid Milburn };
4702cdfcf0SDavid Milburn
4802cdfcf0SDavid Milburn enum board_ids {
4902cdfcf0SDavid Milburn board_acard_ahci,
5002cdfcf0SDavid Milburn };
5102cdfcf0SDavid Milburn
5202cdfcf0SDavid Milburn struct acard_sg {
5302cdfcf0SDavid Milburn __le32 addr;
5402cdfcf0SDavid Milburn __le32 addr_hi;
5502cdfcf0SDavid Milburn __le32 reserved;
5602cdfcf0SDavid Milburn __le32 size; /* bit 31 (EOT) max==0x10000 (64k) */
5702cdfcf0SDavid Milburn };
5802cdfcf0SDavid Milburn
5995364f36SJiri Slaby static enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc);
60931139afSDamien Le Moal static void acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
6102cdfcf0SDavid Milburn static int acard_ahci_port_start(struct ata_port *ap);
6202cdfcf0SDavid Milburn static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
6302cdfcf0SDavid Milburn
6458eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
6502cdfcf0SDavid Milburn static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
6602cdfcf0SDavid Milburn static int acard_ahci_pci_device_resume(struct pci_dev *pdev);
6702cdfcf0SDavid Milburn #endif
6802cdfcf0SDavid Milburn
69*25df73d9SBart Van Assche static const struct scsi_host_template acard_ahci_sht = {
7002cdfcf0SDavid Milburn AHCI_SHT("acard-ahci"),
7102cdfcf0SDavid Milburn };
7202cdfcf0SDavid Milburn
7302cdfcf0SDavid Milburn static struct ata_port_operations acard_ops = {
7402cdfcf0SDavid Milburn .inherits = &ahci_ops,
7502cdfcf0SDavid Milburn .qc_prep = acard_ahci_qc_prep,
7602cdfcf0SDavid Milburn .qc_fill_rtf = acard_ahci_qc_fill_rtf,
7702cdfcf0SDavid Milburn .port_start = acard_ahci_port_start,
7802cdfcf0SDavid Milburn };
7902cdfcf0SDavid Milburn
8002cdfcf0SDavid Milburn #define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
8102cdfcf0SDavid Milburn
8202cdfcf0SDavid Milburn static const struct ata_port_info acard_ahci_port_info[] = {
8302cdfcf0SDavid Milburn [board_acard_ahci] =
8402cdfcf0SDavid Milburn {
8502cdfcf0SDavid Milburn AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ),
8602cdfcf0SDavid Milburn .flags = AHCI_FLAG_COMMON,
8702cdfcf0SDavid Milburn .pio_mask = ATA_PIO4,
8802cdfcf0SDavid Milburn .udma_mask = ATA_UDMA6,
8902cdfcf0SDavid Milburn .port_ops = &acard_ops,
9002cdfcf0SDavid Milburn },
9102cdfcf0SDavid Milburn };
9202cdfcf0SDavid Milburn
9302cdfcf0SDavid Milburn static const struct pci_device_id acard_ahci_pci_tbl[] = {
9402cdfcf0SDavid Milburn /* ACard */
9502cdfcf0SDavid Milburn { PCI_VDEVICE(ARTOP, 0x000d), board_acard_ahci }, /* ATP8620 */
9602cdfcf0SDavid Milburn
9702cdfcf0SDavid Milburn { } /* terminate list */
9802cdfcf0SDavid Milburn };
9902cdfcf0SDavid Milburn
10002cdfcf0SDavid Milburn static struct pci_driver acard_ahci_pci_driver = {
10102cdfcf0SDavid Milburn .name = DRV_NAME,
10202cdfcf0SDavid Milburn .id_table = acard_ahci_pci_tbl,
10302cdfcf0SDavid Milburn .probe = acard_ahci_init_one,
10402cdfcf0SDavid Milburn .remove = ata_pci_remove_one,
10558eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
10602cdfcf0SDavid Milburn .suspend = acard_ahci_pci_device_suspend,
10702cdfcf0SDavid Milburn .resume = acard_ahci_pci_device_resume,
10802cdfcf0SDavid Milburn #endif
10902cdfcf0SDavid Milburn };
11002cdfcf0SDavid Milburn
11158eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
acard_ahci_pci_device_suspend(struct pci_dev * pdev,pm_message_t mesg)11202cdfcf0SDavid Milburn static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
11302cdfcf0SDavid Milburn {
1140a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev);
11502cdfcf0SDavid Milburn struct ahci_host_priv *hpriv = host->private_data;
11602cdfcf0SDavid Milburn void __iomem *mmio = hpriv->mmio;
11702cdfcf0SDavid Milburn u32 ctl;
11802cdfcf0SDavid Milburn
11902cdfcf0SDavid Milburn if (mesg.event & PM_EVENT_SUSPEND &&
12002cdfcf0SDavid Milburn hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
121a44fec1fSJoe Perches dev_err(&pdev->dev,
12202cdfcf0SDavid Milburn "BIOS update required for suspend/resume\n");
12302cdfcf0SDavid Milburn return -EIO;
12402cdfcf0SDavid Milburn }
12502cdfcf0SDavid Milburn
12602cdfcf0SDavid Milburn if (mesg.event & PM_EVENT_SLEEP) {
12702cdfcf0SDavid Milburn /* AHCI spec rev1.1 section 8.3.3:
12802cdfcf0SDavid Milburn * Software must disable interrupts prior to requesting a
12902cdfcf0SDavid Milburn * transition of the HBA to D3 state.
13002cdfcf0SDavid Milburn */
13102cdfcf0SDavid Milburn ctl = readl(mmio + HOST_CTL);
13202cdfcf0SDavid Milburn ctl &= ~HOST_IRQ_EN;
13302cdfcf0SDavid Milburn writel(ctl, mmio + HOST_CTL);
13402cdfcf0SDavid Milburn readl(mmio + HOST_CTL); /* flush */
13502cdfcf0SDavid Milburn }
13602cdfcf0SDavid Milburn
13702cdfcf0SDavid Milburn return ata_pci_device_suspend(pdev, mesg);
13802cdfcf0SDavid Milburn }
13902cdfcf0SDavid Milburn
acard_ahci_pci_device_resume(struct pci_dev * pdev)14002cdfcf0SDavid Milburn static int acard_ahci_pci_device_resume(struct pci_dev *pdev)
14102cdfcf0SDavid Milburn {
1420a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev);
14302cdfcf0SDavid Milburn int rc;
14402cdfcf0SDavid Milburn
14502cdfcf0SDavid Milburn rc = ata_pci_device_do_resume(pdev);
14602cdfcf0SDavid Milburn if (rc)
14702cdfcf0SDavid Milburn return rc;
14802cdfcf0SDavid Milburn
14902cdfcf0SDavid Milburn if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
15002cdfcf0SDavid Milburn rc = ahci_reset_controller(host);
15102cdfcf0SDavid Milburn if (rc)
15202cdfcf0SDavid Milburn return rc;
15302cdfcf0SDavid Milburn
15402cdfcf0SDavid Milburn ahci_init_controller(host);
15502cdfcf0SDavid Milburn }
15602cdfcf0SDavid Milburn
15702cdfcf0SDavid Milburn ata_host_resume(host);
15802cdfcf0SDavid Milburn
15902cdfcf0SDavid Milburn return 0;
16002cdfcf0SDavid Milburn }
16102cdfcf0SDavid Milburn #endif
16202cdfcf0SDavid Milburn
acard_ahci_pci_print_info(struct ata_host * host)16302cdfcf0SDavid Milburn static void acard_ahci_pci_print_info(struct ata_host *host)
16402cdfcf0SDavid Milburn {
16502cdfcf0SDavid Milburn struct pci_dev *pdev = to_pci_dev(host->dev);
16602cdfcf0SDavid Milburn u16 cc;
16702cdfcf0SDavid Milburn const char *scc_s;
16802cdfcf0SDavid Milburn
16902cdfcf0SDavid Milburn pci_read_config_word(pdev, 0x0a, &cc);
17002cdfcf0SDavid Milburn if (cc == PCI_CLASS_STORAGE_IDE)
17102cdfcf0SDavid Milburn scc_s = "IDE";
17202cdfcf0SDavid Milburn else if (cc == PCI_CLASS_STORAGE_SATA)
17302cdfcf0SDavid Milburn scc_s = "SATA";
17402cdfcf0SDavid Milburn else if (cc == PCI_CLASS_STORAGE_RAID)
17502cdfcf0SDavid Milburn scc_s = "RAID";
17602cdfcf0SDavid Milburn else
17702cdfcf0SDavid Milburn scc_s = "unknown";
17802cdfcf0SDavid Milburn
17902cdfcf0SDavid Milburn ahci_print_info(host, scc_s);
18002cdfcf0SDavid Milburn }
18102cdfcf0SDavid Milburn
acard_ahci_fill_sg(struct ata_queued_cmd * qc,void * cmd_tbl)18202cdfcf0SDavid Milburn static unsigned int acard_ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
18302cdfcf0SDavid Milburn {
18402cdfcf0SDavid Milburn struct scatterlist *sg;
18502cdfcf0SDavid Milburn struct acard_sg *acard_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
18602cdfcf0SDavid Milburn unsigned int si, last_si = 0;
18702cdfcf0SDavid Milburn
18802cdfcf0SDavid Milburn /*
18902cdfcf0SDavid Milburn * Next, the S/G list.
19002cdfcf0SDavid Milburn */
19102cdfcf0SDavid Milburn for_each_sg(qc->sg, sg, qc->n_elem, si) {
19202cdfcf0SDavid Milburn dma_addr_t addr = sg_dma_address(sg);
19302cdfcf0SDavid Milburn u32 sg_len = sg_dma_len(sg);
19402cdfcf0SDavid Milburn
19502cdfcf0SDavid Milburn /*
19602cdfcf0SDavid Milburn * ACard note:
19702cdfcf0SDavid Milburn * We must set an end-of-table (EOT) bit,
19802cdfcf0SDavid Milburn * and the segment cannot exceed 64k (0x10000)
19902cdfcf0SDavid Milburn */
20002cdfcf0SDavid Milburn acard_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
20102cdfcf0SDavid Milburn acard_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
20202cdfcf0SDavid Milburn acard_sg[si].size = cpu_to_le32(sg_len);
20302cdfcf0SDavid Milburn last_si = si;
20402cdfcf0SDavid Milburn }
20502cdfcf0SDavid Milburn
20602cdfcf0SDavid Milburn acard_sg[last_si].size |= cpu_to_le32(1 << 31); /* set EOT */
20702cdfcf0SDavid Milburn
20802cdfcf0SDavid Milburn return si;
20902cdfcf0SDavid Milburn }
21002cdfcf0SDavid Milburn
acard_ahci_qc_prep(struct ata_queued_cmd * qc)21195364f36SJiri Slaby static enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc)
21202cdfcf0SDavid Milburn {
21302cdfcf0SDavid Milburn struct ata_port *ap = qc->ap;
21402cdfcf0SDavid Milburn struct ahci_port_priv *pp = ap->private_data;
21502cdfcf0SDavid Milburn int is_atapi = ata_is_atapi(qc->tf.protocol);
21602cdfcf0SDavid Milburn void *cmd_tbl;
21702cdfcf0SDavid Milburn u32 opts;
21802cdfcf0SDavid Milburn const u32 cmd_fis_len = 5; /* five dwords */
21902cdfcf0SDavid Milburn
22002cdfcf0SDavid Milburn /*
22102cdfcf0SDavid Milburn * Fill in command table information. First, the header,
22202cdfcf0SDavid Milburn * a SATA Register - Host to Device command FIS.
22302cdfcf0SDavid Milburn */
2244e5b6260SJens Axboe cmd_tbl = pp->cmd_tbl + qc->hw_tag * AHCI_CMD_TBL_SZ;
22502cdfcf0SDavid Milburn
22602cdfcf0SDavid Milburn ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
22702cdfcf0SDavid Milburn if (is_atapi) {
22802cdfcf0SDavid Milburn memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
22902cdfcf0SDavid Milburn memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
23002cdfcf0SDavid Milburn }
23102cdfcf0SDavid Milburn
23202cdfcf0SDavid Milburn if (qc->flags & ATA_QCFLAG_DMAMAP)
2337e053d3eSAlex Shi acard_ahci_fill_sg(qc, cmd_tbl);
23402cdfcf0SDavid Milburn
23502cdfcf0SDavid Milburn /*
23602cdfcf0SDavid Milburn * Fill in command slot information.
23702cdfcf0SDavid Milburn *
23802cdfcf0SDavid Milburn * ACard note: prd table length not filled in
23902cdfcf0SDavid Milburn */
24002cdfcf0SDavid Milburn opts = cmd_fis_len | (qc->dev->link->pmp << 12);
24102cdfcf0SDavid Milburn if (qc->tf.flags & ATA_TFLAG_WRITE)
24202cdfcf0SDavid Milburn opts |= AHCI_CMD_WRITE;
24302cdfcf0SDavid Milburn if (is_atapi)
24402cdfcf0SDavid Milburn opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
24502cdfcf0SDavid Milburn
2464e5b6260SJens Axboe ahci_fill_cmd_slot(pp, qc->hw_tag, opts);
24795364f36SJiri Slaby
24895364f36SJiri Slaby return AC_ERR_OK;
24902cdfcf0SDavid Milburn }
25002cdfcf0SDavid Milburn
acard_ahci_qc_fill_rtf(struct ata_queued_cmd * qc)251931139afSDamien Le Moal static void acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
25202cdfcf0SDavid Milburn {
25302cdfcf0SDavid Milburn struct ahci_port_priv *pp = qc->ap->private_data;
25402cdfcf0SDavid Milburn u8 *rx_fis = pp->rx_fis;
25502cdfcf0SDavid Milburn
25602cdfcf0SDavid Milburn if (pp->fbs_enabled)
25702cdfcf0SDavid Milburn rx_fis += qc->dev->link->pmp * ACARD_AHCI_RX_FIS_SZ;
25802cdfcf0SDavid Milburn
25902cdfcf0SDavid Milburn /*
26002cdfcf0SDavid Milburn * After a successful execution of an ATA PIO data-in command,
26102cdfcf0SDavid Milburn * the device doesn't send D2H Reg FIS to update the TF and
26202cdfcf0SDavid Milburn * the host should take TF and E_Status from the preceding PIO
26302cdfcf0SDavid Milburn * Setup FIS.
26402cdfcf0SDavid Milburn */
26502cdfcf0SDavid Milburn if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
26687629312SNiklas Cassel !(qc->flags & ATA_QCFLAG_EH)) {
26702cdfcf0SDavid Milburn ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
268efcef265SSergey Shtylyov qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15];
26902cdfcf0SDavid Milburn } else
27002cdfcf0SDavid Milburn ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
27102cdfcf0SDavid Milburn }
27202cdfcf0SDavid Milburn
acard_ahci_port_start(struct ata_port * ap)27302cdfcf0SDavid Milburn static int acard_ahci_port_start(struct ata_port *ap)
27402cdfcf0SDavid Milburn {
27502cdfcf0SDavid Milburn struct ahci_host_priv *hpriv = ap->host->private_data;
27602cdfcf0SDavid Milburn struct device *dev = ap->host->dev;
27702cdfcf0SDavid Milburn struct ahci_port_priv *pp;
27802cdfcf0SDavid Milburn void *mem;
27902cdfcf0SDavid Milburn dma_addr_t mem_dma;
28002cdfcf0SDavid Milburn size_t dma_sz, rx_fis_sz;
28102cdfcf0SDavid Milburn
28202cdfcf0SDavid Milburn pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
28302cdfcf0SDavid Milburn if (!pp)
28402cdfcf0SDavid Milburn return -ENOMEM;
28502cdfcf0SDavid Milburn
28602cdfcf0SDavid Milburn /* check FBS capability */
28702cdfcf0SDavid Milburn if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) {
28802cdfcf0SDavid Milburn void __iomem *port_mmio = ahci_port_base(ap);
28902cdfcf0SDavid Milburn u32 cmd = readl(port_mmio + PORT_CMD);
29002cdfcf0SDavid Milburn if (cmd & PORT_CMD_FBSCP)
29102cdfcf0SDavid Milburn pp->fbs_supported = true;
29202cdfcf0SDavid Milburn else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
293a44fec1fSJoe Perches dev_info(dev, "port %d can do FBS, forcing FBSCP\n",
29402cdfcf0SDavid Milburn ap->port_no);
29502cdfcf0SDavid Milburn pp->fbs_supported = true;
29602cdfcf0SDavid Milburn } else
297a44fec1fSJoe Perches dev_warn(dev, "port %d is not capable of FBS\n",
29802cdfcf0SDavid Milburn ap->port_no);
29902cdfcf0SDavid Milburn }
30002cdfcf0SDavid Milburn
30102cdfcf0SDavid Milburn if (pp->fbs_supported) {
30202cdfcf0SDavid Milburn dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ;
30302cdfcf0SDavid Milburn rx_fis_sz = ACARD_AHCI_RX_FIS_SZ * 16;
30402cdfcf0SDavid Milburn } else {
30502cdfcf0SDavid Milburn dma_sz = AHCI_PORT_PRIV_DMA_SZ;
30602cdfcf0SDavid Milburn rx_fis_sz = ACARD_AHCI_RX_FIS_SZ;
30702cdfcf0SDavid Milburn }
30802cdfcf0SDavid Milburn
30902cdfcf0SDavid Milburn mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL);
31002cdfcf0SDavid Milburn if (!mem)
31102cdfcf0SDavid Milburn return -ENOMEM;
31202cdfcf0SDavid Milburn
31302cdfcf0SDavid Milburn /*
31402cdfcf0SDavid Milburn * First item in chunk of DMA memory: 32-slot command table,
31502cdfcf0SDavid Milburn * 32 bytes each in size
31602cdfcf0SDavid Milburn */
31702cdfcf0SDavid Milburn pp->cmd_slot = mem;
31802cdfcf0SDavid Milburn pp->cmd_slot_dma = mem_dma;
31902cdfcf0SDavid Milburn
32002cdfcf0SDavid Milburn mem += AHCI_CMD_SLOT_SZ;
32102cdfcf0SDavid Milburn mem_dma += AHCI_CMD_SLOT_SZ;
32202cdfcf0SDavid Milburn
32302cdfcf0SDavid Milburn /*
32402cdfcf0SDavid Milburn * Second item: Received-FIS area
32502cdfcf0SDavid Milburn */
32602cdfcf0SDavid Milburn pp->rx_fis = mem;
32702cdfcf0SDavid Milburn pp->rx_fis_dma = mem_dma;
32802cdfcf0SDavid Milburn
32902cdfcf0SDavid Milburn mem += rx_fis_sz;
33002cdfcf0SDavid Milburn mem_dma += rx_fis_sz;
33102cdfcf0SDavid Milburn
33202cdfcf0SDavid Milburn /*
33302cdfcf0SDavid Milburn * Third item: data area for storing a single command
33402cdfcf0SDavid Milburn * and its scatter-gather table
33502cdfcf0SDavid Milburn */
33602cdfcf0SDavid Milburn pp->cmd_tbl = mem;
33702cdfcf0SDavid Milburn pp->cmd_tbl_dma = mem_dma;
33802cdfcf0SDavid Milburn
33902cdfcf0SDavid Milburn /*
34002cdfcf0SDavid Milburn * Save off initial list of interrupts to be enabled.
34102cdfcf0SDavid Milburn * This could be changed later
34202cdfcf0SDavid Milburn */
34302cdfcf0SDavid Milburn pp->intr_mask = DEF_PORT_IRQ;
34402cdfcf0SDavid Milburn
34502cdfcf0SDavid Milburn ap->private_data = pp;
34602cdfcf0SDavid Milburn
34702cdfcf0SDavid Milburn /* engage engines, captain */
34802cdfcf0SDavid Milburn return ahci_port_resume(ap);
34902cdfcf0SDavid Milburn }
35002cdfcf0SDavid Milburn
acard_ahci_init_one(struct pci_dev * pdev,const struct pci_device_id * ent)35102cdfcf0SDavid Milburn static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
35202cdfcf0SDavid Milburn {
35302cdfcf0SDavid Milburn unsigned int board_id = ent->driver_data;
35402cdfcf0SDavid Milburn struct ata_port_info pi = acard_ahci_port_info[board_id];
35502cdfcf0SDavid Milburn const struct ata_port_info *ppi[] = { &pi, NULL };
35602cdfcf0SDavid Milburn struct device *dev = &pdev->dev;
35702cdfcf0SDavid Milburn struct ahci_host_priv *hpriv;
35802cdfcf0SDavid Milburn struct ata_host *host;
35902cdfcf0SDavid Milburn int n_ports, i, rc;
36002cdfcf0SDavid Milburn
361f68b3afeSJeff Garzik WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
36202cdfcf0SDavid Milburn
36306296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION);
36402cdfcf0SDavid Milburn
36502cdfcf0SDavid Milburn /* acquire resources */
36602cdfcf0SDavid Milburn rc = pcim_enable_device(pdev);
36702cdfcf0SDavid Milburn if (rc)
36802cdfcf0SDavid Milburn return rc;
36902cdfcf0SDavid Milburn
37002cdfcf0SDavid Milburn /* AHCI controllers often implement SFF compatible interface.
37102cdfcf0SDavid Milburn * Grab all PCI BARs just in case.
37202cdfcf0SDavid Milburn */
37302cdfcf0SDavid Milburn rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
37402cdfcf0SDavid Milburn if (rc == -EBUSY)
37502cdfcf0SDavid Milburn pcim_pin_device(pdev);
37602cdfcf0SDavid Milburn if (rc)
37702cdfcf0SDavid Milburn return rc;
37802cdfcf0SDavid Milburn
37902cdfcf0SDavid Milburn hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
38002cdfcf0SDavid Milburn if (!hpriv)
38102cdfcf0SDavid Milburn return -ENOMEM;
38221bfd1aaSRobert Richter
38321bfd1aaSRobert Richter hpriv->irq = pdev->irq;
38402cdfcf0SDavid Milburn hpriv->flags |= (unsigned long)pi.private_data;
38502cdfcf0SDavid Milburn
38602cdfcf0SDavid Milburn if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
38702cdfcf0SDavid Milburn pci_enable_msi(pdev);
38802cdfcf0SDavid Milburn
38902cdfcf0SDavid Milburn hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
39002cdfcf0SDavid Milburn
39102cdfcf0SDavid Milburn /* save initial config */
392725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv);
39302cdfcf0SDavid Milburn
39402cdfcf0SDavid Milburn /* prepare host */
39502cdfcf0SDavid Milburn if (hpriv->cap & HOST_CAP_NCQ)
39602cdfcf0SDavid Milburn pi.flags |= ATA_FLAG_NCQ;
39702cdfcf0SDavid Milburn
39802cdfcf0SDavid Milburn if (hpriv->cap & HOST_CAP_PMP)
39902cdfcf0SDavid Milburn pi.flags |= ATA_FLAG_PMP;
40002cdfcf0SDavid Milburn
40102cdfcf0SDavid Milburn ahci_set_em_messages(hpriv, &pi);
40202cdfcf0SDavid Milburn
40302cdfcf0SDavid Milburn /* CAP.NP sometimes indicate the index of the last enabled
40402cdfcf0SDavid Milburn * port, at other times, that of the last possible port, so
40502cdfcf0SDavid Milburn * determining the maximum port number requires looking at
40602cdfcf0SDavid Milburn * both CAP.NP and port_map.
40702cdfcf0SDavid Milburn */
40802cdfcf0SDavid Milburn n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
40902cdfcf0SDavid Milburn
41002cdfcf0SDavid Milburn host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
41102cdfcf0SDavid Milburn if (!host)
41202cdfcf0SDavid Milburn return -ENOMEM;
41302cdfcf0SDavid Milburn host->private_data = hpriv;
41402cdfcf0SDavid Milburn
41502cdfcf0SDavid Milburn if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
41602cdfcf0SDavid Milburn host->flags |= ATA_HOST_PARALLEL_SCAN;
41702cdfcf0SDavid Milburn else
41802cdfcf0SDavid Milburn printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
41902cdfcf0SDavid Milburn
42002cdfcf0SDavid Milburn for (i = 0; i < host->n_ports; i++) {
42102cdfcf0SDavid Milburn struct ata_port *ap = host->ports[i];
42202cdfcf0SDavid Milburn
42302cdfcf0SDavid Milburn ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
42402cdfcf0SDavid Milburn ata_port_pbar_desc(ap, AHCI_PCI_BAR,
42502cdfcf0SDavid Milburn 0x100 + ap->port_no * 0x80, "port");
42602cdfcf0SDavid Milburn
42702cdfcf0SDavid Milburn /* set initial link pm policy */
42802cdfcf0SDavid Milburn /*
42902cdfcf0SDavid Milburn ap->pm_policy = NOT_AVAILABLE;
43002cdfcf0SDavid Milburn */
43102cdfcf0SDavid Milburn /* disabled/not-implemented port */
43202cdfcf0SDavid Milburn if (!(hpriv->port_map & (1 << i)))
43302cdfcf0SDavid Milburn ap->ops = &ata_dummy_port_ops;
43402cdfcf0SDavid Milburn }
43502cdfcf0SDavid Milburn
43602cdfcf0SDavid Milburn /* initialize adapter */
437759ad097SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev,
438759ad097SChristoph Hellwig DMA_BIT_MASK((hpriv->cap & HOST_CAP_64) ? 64 : 32));
439759ad097SChristoph Hellwig if (rc) {
440759ad097SChristoph Hellwig dev_err(&pdev->dev, "DMA enable failed\n");
44102cdfcf0SDavid Milburn return rc;
442759ad097SChristoph Hellwig }
44302cdfcf0SDavid Milburn
44402cdfcf0SDavid Milburn rc = ahci_reset_controller(host);
44502cdfcf0SDavid Milburn if (rc)
44602cdfcf0SDavid Milburn return rc;
44702cdfcf0SDavid Milburn
44802cdfcf0SDavid Milburn ahci_init_controller(host);
44902cdfcf0SDavid Milburn acard_ahci_pci_print_info(host);
45002cdfcf0SDavid Milburn
45102cdfcf0SDavid Milburn pci_set_master(pdev);
45221bfd1aaSRobert Richter return ahci_host_activate(host, &acard_ahci_sht);
45302cdfcf0SDavid Milburn }
45402cdfcf0SDavid Milburn
4552fc75da0SAxel Lin module_pci_driver(acard_ahci_pci_driver);
45602cdfcf0SDavid Milburn
45702cdfcf0SDavid Milburn MODULE_AUTHOR("Jeff Garzik");
45802cdfcf0SDavid Milburn MODULE_DESCRIPTION("ACard AHCI SATA low-level driver");
45902cdfcf0SDavid Milburn MODULE_LICENSE("GPL");
46002cdfcf0SDavid Milburn MODULE_DEVICE_TABLE(pci, acard_ahci_pci_tbl);
46102cdfcf0SDavid Milburn MODULE_VERSION(DRV_VERSION);
462