xref: /openbmc/linux/drivers/ata/acard-ahci.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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