diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 14:32:54 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 14:32:54 -0800 |
commit | 11eaaadb3ea376c6c194491c2e9bddd647f9d253 (patch) | |
tree | 461f130ddbf07737128a1bb115775e41bce22643 /drivers | |
parent | e25ac7ddaae0e798f794cdaf9109bc71246110cd (diff) | |
parent | 159b5bb46492e4dcef2070b12861030bc360402b (diff) | |
download | linux-11eaaadb3ea376c6c194491c2e9bddd647f9d253.tar.bz2 |
Merge branch 'for-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata updates from Tejun Heo:
"Most are ahci and other device specific additions. Dan cleaned up
ahci IRQ handling to prepare for future MSIX changes. On the libata
core side, Vinayak updated SG handling so that NCQ commands can be
issued through SG_IO and Christoph cleaned up code a bit. There's one
merge from for-4.3-fixes to include a pata_macio commit that didn't
get pushed out"
* 'for-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
ahci: add new Intel device IDs
ahci: Add Marvell 88se91a2 device id
ahci: cleanup ahci_host_activate_multi_irqs
ahci: ahci_host_activate: kill IRQF_SHARED
devicetree: bindings: Fixed a few typos
ahci: qoriq: Disable NCQ on ls2080a SoC
ahci: qoriq: Rename LS2085A SoC support code to LS2080A
libata: enable LBA flag in taskfile for ata_scsi_pass_thru()
libata: add support for NCQ commands for SG interface
ahci: qoriq: Fix a compiling warning
pata_it821x: use "const char *" for string literals
libata: only call ->done once all per-tag ressources are released
libata: cleanup ata_scsi_qc_complete
ata: ahci: find eSATA ports and flag them as removable
libata: samsung_cf: fix handling platform_get_irq result
ata: pata_macio: Fix module autoload for OF platform driver
ata: pata_pxa: dmaengine conversion
ahci: added a new driver for supporting Freescale AHCI sata
devicetree:bindings: add devicetree bindings for Freescale AHCI
Revert "ahci: added support for Freescale AHCI sata"
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/Kconfig | 9 | ||||
-rw-r--r-- | drivers/ata/Makefile | 1 | ||||
-rw-r--r-- | drivers/ata/ahci.c | 12 | ||||
-rw-r--r-- | drivers/ata/ahci.h | 2 | ||||
-rw-r--r-- | drivers/ata/ahci_platform.c | 1 | ||||
-rw-r--r-- | drivers/ata/ahci_qoriq.c | 279 | ||||
-rw-r--r-- | drivers/ata/libahci.c | 30 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 59 | ||||
-rw-r--r-- | drivers/ata/pata_it821x.c | 6 | ||||
-rw-r--r-- | drivers/ata/pata_macio.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_pxa.c | 171 | ||||
-rw-r--r-- | drivers/ata/pata_samsung_cf.c | 2 |
12 files changed, 411 insertions, 162 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 15e40ee62a94..6aaa3f81755b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -175,6 +175,15 @@ config AHCI_XGENE help This option enables support for APM X-Gene SoC SATA host controller. +config AHCI_QORIQ + tristate "Freescale QorIQ AHCI SATA support" + depends on OF + help + This option enables support for the Freescale QorIQ AHCI SoC's + onboard AHCI SATA. + + If unsure, say N. + config SATA_FSL tristate "Freescale 3.0Gbps SATA support" depends on FSL_SOC diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index af70919f7dde..af45effac18c 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_TEGRA) += ahci_tegra.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_XGENE) += ahci_xgene.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_QORIQ) += ahci_qoriq.o libahci.o libahci_platform.o # SFF w/ custom DMA obj-$(CONFIG_PDC_ADMA) += pdc_adma.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a46660204e3a..ff02bb4218fc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -314,6 +314,16 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ + { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ + { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ @@ -489,6 +499,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ + .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 5b8e8a0fab48..45586c1dbbdc 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -181,6 +181,8 @@ enum { PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ + PORT_CMD_ESP = (1 << 21), /* External Sata Port */ + PORT_CMD_HPCP = (1 << 18), /* HotPlug Capable Port */ PORT_CMD_PMP = (1 << 17), /* PMP attached */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 1befb114c384..04975b851c23 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -76,7 +76,6 @@ static const struct of_device_id ahci_of_match[] = { { .compatible = "ibm,476gtr-ahci", }, { .compatible = "snps,dwc-ahci", }, { .compatible = "hisilicon,hisi-ahci", }, - { .compatible = "fsl,qoriq-ahci", }, {}, }; MODULE_DEVICE_TABLE(of, ahci_of_match); diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c new file mode 100644 index 000000000000..d0f9de96e4ea --- /dev/null +++ b/drivers/ata/ahci_qoriq.c @@ -0,0 +1,279 @@ +/* + * Freescale QorIQ AHCI SATA platform driver + * + * Copyright 2015 Freescale, Inc. + * Tang Yuantian <Yuantian.Tang@freescale.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pm.h> +#include <linux/ahci_platform.h> +#include <linux/device.h> +#include <linux/of_address.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/libata.h> +#include "ahci.h" + +#define DRV_NAME "ahci-qoriq" + +/* port register definition */ +#define PORT_PHY1 0xA8 +#define PORT_PHY2 0xAC +#define PORT_PHY3 0xB0 +#define PORT_PHY4 0xB4 +#define PORT_PHY5 0xB8 +#define PORT_TRANS 0xC8 + +/* port register default value */ +#define AHCI_PORT_PHY_1_CFG 0xa003fffe +#define AHCI_PORT_PHY_2_CFG 0x28183411 +#define AHCI_PORT_PHY_3_CFG 0x0e081004 +#define AHCI_PORT_PHY_4_CFG 0x00480811 +#define AHCI_PORT_PHY_5_CFG 0x192c96a4 +#define AHCI_PORT_TRANS_CFG 0x08000025 + +#define SATA_ECC_DISABLE 0x00020000 + +enum ahci_qoriq_type { + AHCI_LS1021A, + AHCI_LS1043A, + AHCI_LS2080A, +}; + +struct ahci_qoriq_priv { + struct ccsr_ahci *reg_base; + enum ahci_qoriq_type type; + void __iomem *ecc_addr; +}; + +static const struct of_device_id ahci_qoriq_of_match[] = { + { .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A}, + { .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A}, + { .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A}, + {}, +}; +MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match); + +static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); + void __iomem *port_mmio = ahci_port_base(link->ap); + u32 px_cmd, px_is, px_val; + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; + struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_qoriq_priv *qoriq_priv = hpriv->plat_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; + int rc; + bool ls1021a_workaround = (qoriq_priv->type == AHCI_LS1021A); + + DPRINTK("ENTER\n"); + + ahci_stop_engine(ap); + + /* + * There is a errata on ls1021a Rev1.0 and Rev2.0 which is: + * A-009042: The device detection initialization sequence + * mistakenly resets some registers. + * + * Workaround for this is: + * The software should read and store PxCMD and PxIS values + * before issuing the device detection initialization sequence. + * After the sequence is complete, software should restore the + * PxCMD and PxIS with the stored values. + */ + if (ls1021a_workaround) { + px_cmd = readl(port_mmio + PORT_CMD); + px_is = readl(port_mmio + PORT_IRQ_STAT); + } + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); + tf.command = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + rc = sata_link_hardreset(link, timing, deadline, &online, + ahci_check_ready); + + /* restore the PxCMD and PxIS on ls1021 */ + if (ls1021a_workaround) { + px_val = readl(port_mmio + PORT_CMD); + if (px_val != px_cmd) + writel(px_cmd, port_mmio + PORT_CMD); + + px_val = readl(port_mmio + PORT_IRQ_STAT); + if (px_val != px_is) + writel(px_is, port_mmio + PORT_IRQ_STAT); + } + + hpriv->start_engine(ap); + + if (online) + *class = ahci_dev_classify(ap); + + DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); + return rc; +} + +static struct ata_port_operations ahci_qoriq_ops = { + .inherits = &ahci_ops, + .hardreset = ahci_qoriq_hardreset, +}; + +static struct ata_port_info ahci_qoriq_port_info = { + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_qoriq_ops, +}; + +static struct scsi_host_template ahci_qoriq_sht = { + AHCI_SHT(DRV_NAME), +}; + +static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) +{ + struct ahci_qoriq_priv *qpriv = hpriv->plat_data; + void __iomem *reg_base = hpriv->mmio; + + switch (qpriv->type) { + case AHCI_LS1021A: + writel(SATA_ECC_DISABLE, qpriv->ecc_addr); + writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); + writel(AHCI_PORT_PHY_2_CFG, reg_base + PORT_PHY2); + writel(AHCI_PORT_PHY_3_CFG, reg_base + PORT_PHY3); + writel(AHCI_PORT_PHY_4_CFG, reg_base + PORT_PHY4); + writel(AHCI_PORT_PHY_5_CFG, reg_base + PORT_PHY5); + writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + break; + + case AHCI_LS1043A: + case AHCI_LS2080A: + writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); + break; + } + + return 0; +} + +static int ahci_qoriq_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct ahci_host_priv *hpriv; + struct ahci_qoriq_priv *qoriq_priv; + const struct of_device_id *of_id; + struct resource *res; + int rc; + + hpriv = ahci_platform_get_resources(pdev); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + + of_id = of_match_node(ahci_qoriq_of_match, np); + if (!of_id) + return -ENODEV; + + qoriq_priv = devm_kzalloc(dev, sizeof(*qoriq_priv), GFP_KERNEL); + if (!qoriq_priv) + return -ENOMEM; + + qoriq_priv->type = (enum ahci_qoriq_type)of_id->data; + + if (qoriq_priv->type == AHCI_LS1021A) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "sata-ecc"); + qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(qoriq_priv->ecc_addr)) + return PTR_ERR(qoriq_priv->ecc_addr); + } + + rc = ahci_platform_enable_resources(hpriv); + if (rc) + return rc; + + hpriv->plat_data = qoriq_priv; + rc = ahci_qoriq_phy_init(hpriv); + if (rc) + goto disable_resources; + + /* Workaround for ls2080a */ + if (qoriq_priv->type == AHCI_LS2080A) { + hpriv->flags |= AHCI_HFLAG_NO_NCQ; + ahci_qoriq_port_info.flags &= ~ATA_FLAG_NCQ; + } + + rc = ahci_platform_init_host(pdev, hpriv, &ahci_qoriq_port_info, + &ahci_qoriq_sht); + if (rc) + goto disable_resources; + + return 0; + +disable_resources: + ahci_platform_disable_resources(hpriv); + + return rc; +} + +#ifdef CONFIG_PM_SLEEP +static int ahci_qoriq_resume(struct device *dev) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; + int rc; + + rc = ahci_platform_enable_resources(hpriv); + if (rc) + return rc; + + rc = ahci_qoriq_phy_init(hpriv); + if (rc) + goto disable_resources; + + rc = ahci_platform_resume_host(dev); + if (rc) + goto disable_resources; + + /* We resumed so update PM runtime state */ + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; + +disable_resources: + ahci_platform_disable_resources(hpriv); + + return rc; +} +#endif + +static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend, + ahci_qoriq_resume); + +static struct platform_driver ahci_qoriq_driver = { + .probe = ahci_qoriq_probe, + .remove = ata_platform_remove_one, + .driver = { + .name = DRV_NAME, + .of_match_table = ahci_qoriq_of_match, + .pm = &ahci_qoriq_pm_ops, + }, +}; +module_platform_driver(ahci_qoriq_driver); + +MODULE_DESCRIPTION("Freescale QorIQ AHCI SATA platform driver"); +MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index d256a66158be..096064cd6c52 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1117,6 +1117,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, int port_no, void __iomem *mmio, void __iomem *port_mmio) { + struct ahci_host_priv *hpriv = ap->host->private_data; const char *emsg = NULL; int rc; u32 tmp; @@ -1138,6 +1139,12 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, writel(tmp, port_mmio + PORT_IRQ_STAT); writel(1 << port_no, mmio + HOST_IRQ_STAT); + + /* mark esata ports */ + tmp = readl(port_mmio + PORT_CMD); + if ((tmp & PORT_CMD_HPCP) || + ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))) + ap->pflags |= ATA_PFLAG_EXTERNAL; } void ahci_init_controller(struct ata_host *host) @@ -2486,28 +2493,13 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq, rc = devm_request_threaded_irq(host->dev, irq + i, ahci_multi_irqs_intr, - ahci_port_thread_fn, IRQF_SHARED, + ahci_port_thread_fn, 0, pp->irq_desc, host->ports[i]); if (rc) - goto out_free_irqs; - } - - for (i = 0; i < host->n_ports; i++) + return rc; ata_port_desc(host->ports[i], "irq %d", irq + i); - - rc = ata_host_register(host, sht); - if (rc) - goto out_free_all_irqs; - - return 0; - -out_free_all_irqs: - i = host->n_ports; -out_free_irqs: - for (i--; i >= 0; i--) - devm_free_irq(host->dev, irq + i, host->ports[i]); - - return rc; + } + return ata_host_register(host, sht); } /** diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0d7f0da3a269..8b3a7861fa44 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1757,6 +1757,15 @@ nothing_to_do: return 1; } +static void ata_qc_done(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + void (*done)(struct scsi_cmnd *) = qc->scsidone; + + ata_qc_free(qc); + done(cmd); +} + static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -1774,28 +1783,17 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE */ if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && - ((cdb[2] & 0x20) || need_sense)) { + ((cdb[2] & 0x20) || need_sense)) ata_gen_passthru_sense(qc); - } else { - if (!need_sense) { - cmd->result = SAM_STAT_GOOD; - } else { - /* TODO: decide which descriptor format to use - * for 48b LBA devices and call that here - * instead of the fixed desc, which is only - * good for smaller LBA (and maybe CHS?) - * devices. - */ - ata_gen_ata_sense(qc); - } - } + else if (need_sense) + ata_gen_ata_sense(qc); + else + cmd->result = SAM_STAT_GOOD; if (need_sense && !ap->ops->error_handler) ata_dump_status(ap->print_id, &qc->result_tf); - qc->scsidone(cmd); - - ata_qc_free(qc); + ata_qc_done(qc); } /** @@ -2015,8 +2013,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) VPRINTK("ENTER\n"); - /* set scsi removable (RMB) bit per ata bit */ - if (ata_id_removable(args->id)) + /* set scsi removable (RMB) bit per ata bit, or if the + * AHCI port says it's external (Hotplug-capable, eSATA). + */ + if (ata_id_removable(args->id) || + (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL)) hdr[1] |= (1 << 7); if (args->dev->class == ATA_DEV_ZAC) { @@ -2594,8 +2595,7 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) ata_gen_passthru_sense(qc); } - qc->scsidone(qc->scsicmd); - ata_qc_free(qc); + ata_qc_done(qc); } /* is it pointless to prefer PIO for "safety reasons"? */ @@ -2690,8 +2690,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) qc->dev->sdev->locked = 0; qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; - qc->scsidone(cmd); - ata_qc_free(qc); + ata_qc_done(qc); return; } @@ -2735,8 +2734,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) cmd->result = SAM_STAT_GOOD; } - qc->scsidone(cmd); - ata_qc_free(qc); + ata_qc_done(qc); } /** * atapi_xlat - Initialize PACKET taskfile @@ -2914,12 +2912,14 @@ ata_scsi_map_proto(u8 byte1) case 5: /* PIO Data-out */ return ATA_PROT_PIO; + case 12: /* FPDMA */ + return ATA_PROT_NCQ; + case 0: /* Hard Reset */ case 1: /* SRST */ case 8: /* Device Diagnostic */ case 9: /* Device Reset */ case 7: /* DMA Queued */ - case 12: /* FPDMA */ case 15: /* Return Response Info */ default: /* Reserved */ break; @@ -2947,6 +2947,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; + /* enable LBA */ + tf->flags |= ATA_TFLAG_LBA; + /* * 12 and 16 byte CDBs use different offsets to * provide the various register values. @@ -2992,6 +2995,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->command = cdb[9]; } + /* For NCQ commands with FPDMA protocol, copy the tag value */ + if (tf->protocol == ATA_PROT_NCQ) + tf->nsect = qc->tag << 3; + /* enforce correct master/slave bit */ tf->device = dev->devno ? tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index a5088ecb349f..7a21edf89e72 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -604,9 +604,9 @@ static void it821x_display_disk(int n, u8 *buf) { unsigned char id[41]; int mode = 0; - char *mtype = ""; + const char *mtype = ""; char mbuf[8]; - char *cbl = "(40 wire cable)"; + const char *cbl = "(40 wire cable)"; static const char *types[5] = { "RAID0", "RAID1", "RAID 0+1", "JBOD", "DISK" @@ -903,7 +903,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) }; const struct ata_port_info *ppi[] = { NULL, NULL }; - static char *mode[2] = { "pass through", "smart" }; + static const char *mode[2] = { "pass through", "smart" }; int rc; rc = pcim_enable_device(pdev); diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index b0028588ff1c..e3d4b059fcd1 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -1344,6 +1344,7 @@ static struct of_device_id pata_macio_match[] = }, {}, }; +MODULE_DEVICE_TABLE(of, pata_macio_match); static struct macio_driver pata_macio_driver = { diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c index c36b3e6531d8..f6c46e9a4dc0 100644 --- a/drivers/ata/pata_pxa.c +++ b/drivers/ata/pata_pxa.c @@ -24,79 +24,36 @@ #include <linux/ata.h> #include <linux/libata.h> #include <linux/platform_device.h> +#include <linux/dmaengine.h> +#include <linux/dma/pxa-dma.h> #include <linux/gpio.h> #include <linux/slab.h> #include <linux/completion.h> #include <scsi/scsi_host.h> -#include <mach/pxa2xx-regs.h> #include <linux/platform_data/ata-pxa.h> -#include <mach/dma.h> #define DRV_NAME "pata_pxa" #define DRV_VERSION "0.1" struct pata_pxa_data { - uint32_t dma_channel; - struct pxa_dma_desc *dma_desc; - dma_addr_t dma_desc_addr; - uint32_t dma_desc_id; - - /* DMA IO physical address */ - uint32_t dma_io_addr; - /* PXA DREQ<0:2> pin selector */ - uint32_t dma_dreq; - /* DMA DCSR register value */ - uint32_t dma_dcsr; - + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; struct completion dma_done; }; /* - * Setup the DMA descriptors. The size is transfer capped at 4k per descriptor, - * if the transfer is longer, it is split into multiple chained descriptors. + * DMA interrupt handler. */ -static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc) +static void pxa_ata_dma_irq(void *d) { - struct pata_pxa_data *pd = qc->ap->private_data; - - uint32_t cpu_len, seg_len; - dma_addr_t cpu_addr; - - cpu_addr = sg_dma_address(sg); - cpu_len = sg_dma_len(sg); - - do { - seg_len = (cpu_len > 0x1000) ? 0x1000 : cpu_len; - - pd->dma_desc[pd->dma_desc_id].ddadr = pd->dma_desc_addr + - ((pd->dma_desc_id + 1) * sizeof(struct pxa_dma_desc)); - - pd->dma_desc[pd->dma_desc_id].dcmd = DCMD_BURST32 | - DCMD_WIDTH2 | (DCMD_LENGTH & seg_len); - - if (qc->tf.flags & ATA_TFLAG_WRITE) { - pd->dma_desc[pd->dma_desc_id].dsadr = cpu_addr; - pd->dma_desc[pd->dma_desc_id].dtadr = pd->dma_io_addr; - pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCSRCADDR | - DCMD_FLOWTRG; - } else { - pd->dma_desc[pd->dma_desc_id].dsadr = pd->dma_io_addr; - pd->dma_desc[pd->dma_desc_id].dtadr = cpu_addr; - pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCTRGADDR | - DCMD_FLOWSRC; - } - - cpu_len -= seg_len; - cpu_addr += seg_len; - pd->dma_desc_id++; + struct pata_pxa_data *pd = d; + enum dma_status status; - } while (cpu_len); - - /* Should not happen */ - if (seg_len & 0x1f) - DALGN |= (1 << pd->dma_dreq); + status = dmaengine_tx_status(pd->dma_chan, pd->dma_cookie, NULL); + if (status == DMA_ERROR || status == DMA_COMPLETE) + complete(&pd->dma_done); } /* @@ -105,28 +62,22 @@ static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc) static void pxa_qc_prep(struct ata_queued_cmd *qc) { struct pata_pxa_data *pd = qc->ap->private_data; - int si = 0; - struct scatterlist *sg; + struct dma_async_tx_descriptor *tx; + enum dma_transfer_direction dir; if (!(qc->flags & ATA_QCFLAG_DMAMAP)) return; - pd->dma_desc_id = 0; - - DCSR(pd->dma_channel) = 0; - DALGN &= ~(1 << pd->dma_dreq); - - for_each_sg(qc->sg, sg, qc->n_elem, si) - pxa_load_dmac(sg, qc); - - pd->dma_desc[pd->dma_desc_id - 1].ddadr = DDADR_STOP; - - /* Fire IRQ only at the end of last block */ - pd->dma_desc[pd->dma_desc_id - 1].dcmd |= DCMD_ENDIRQEN; - - DDADR(pd->dma_channel) = pd->dma_desc_addr; - DRCMR(pd->dma_dreq) = DRCMR_MAPVLD | pd->dma_channel; - + dir = (qc->dma_dir == DMA_TO_DEVICE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); + tx = dmaengine_prep_slave_sg(pd->dma_chan, qc->sg, qc->n_elem, dir, + DMA_PREP_INTERRUPT); + if (!tx) { + ata_dev_err(qc->dev, "prep_slave_sg() failed\n"); + return; + } + tx->callback = pxa_ata_dma_irq; + tx->callback_param = pd; + pd->dma_cookie = dmaengine_submit(tx); } /* @@ -145,7 +96,7 @@ static void pxa_bmdma_start(struct ata_queued_cmd *qc) { struct pata_pxa_data *pd = qc->ap->private_data; init_completion(&pd->dma_done); - DCSR(pd->dma_channel) = DCSR_RUN; + dma_async_issue_pending(pd->dma_chan); } /* @@ -154,12 +105,14 @@ static void pxa_bmdma_start(struct ata_queued_cmd *qc) static void pxa_bmdma_stop(struct ata_queued_cmd *qc) { struct pata_pxa_data *pd = qc->ap->private_data; + enum dma_status status; - if ((DCSR(pd->dma_channel) & DCSR_RUN) && - wait_for_completion_timeout(&pd->dma_done, HZ)) - dev_err(qc->ap->dev, "Timeout waiting for DMA completion!"); + status = dmaengine_tx_status(pd->dma_chan, pd->dma_cookie, NULL); + if (status != DMA_ERROR && status != DMA_COMPLETE && + wait_for_completion_timeout(&pd->dma_done, HZ)) + ata_dev_err(qc->dev, "Timeout waiting for DMA completion!"); - DCSR(pd->dma_channel) = 0; + dmaengine_terminate_all(pd->dma_chan); } /* @@ -170,8 +123,11 @@ static unsigned char pxa_bmdma_status(struct ata_port *ap) { struct pata_pxa_data *pd = ap->private_data; unsigned char ret = ATA_DMA_INTR; + struct dma_tx_state state; + enum dma_status status; - if (pd->dma_dcsr & DCSR_BUSERR) + status = dmaengine_tx_status(pd->dma_chan, pd->dma_cookie, &state); + if (status != DMA_COMPLETE) ret |= ATA_DMA_ERR; return ret; @@ -213,21 +169,6 @@ static struct ata_port_operations pxa_ata_port_ops = { .qc_prep = pxa_qc_prep, }; -/* - * DMA interrupt handler. - */ -static void pxa_ata_dma_irq(int dma, void *port) -{ - struct ata_port *ap = port; - struct pata_pxa_data *pd = ap->private_data; - - pd->dma_dcsr = DCSR(dma); - DCSR(dma) = pd->dma_dcsr; - - if (pd->dma_dcsr & DCSR_STOPSTATE) - complete(&pd->dma_done); -} - static int pxa_ata_probe(struct platform_device *pdev) { struct ata_host *host; @@ -238,6 +179,9 @@ static int pxa_ata_probe(struct platform_device *pdev) struct resource *dma_res; struct resource *irq_res; struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev); + struct dma_slave_config config; + dma_cap_mask_t mask; + struct pxad_param param; int ret = 0; /* @@ -333,29 +277,32 @@ static int pxa_ata_probe(struct platform_device *pdev) return -ENOMEM; ap->private_data = data; - data->dma_dreq = pdata->dma_dreq; - data->dma_io_addr = dma_res->start; - /* - * Allocate space for the DMA descriptors - */ - data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE, - &data->dma_desc_addr, GFP_KERNEL); - if (!data->dma_desc) - return -EINVAL; + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + param.prio = PXAD_PRIO_LOWEST; + param.drcmr = pdata->dma_dreq; + memset(&config, 0, sizeof(config)); + config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + config.src_addr = dma_res->start; + config.dst_addr = dma_res->start; + config.src_maxburst = 32; + config.dst_maxburst = 32; /* * Request the DMA channel */ - data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW, - pxa_ata_dma_irq, ap); - if (data->dma_channel < 0) + data->dma_chan = + dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶m, &pdev->dev, "data"); + if (!data->dma_chan) return -EBUSY; - - /* - * Stop and clear the DMA channel - */ - DCSR(data->dma_channel) = 0; + ret = dmaengine_slave_config(data->dma_chan, &config); + if (ret < 0) { + dev_err(&pdev->dev, "dma configuration failed: %d\n", ret); + return ret; + } /* * Activate the ATA host @@ -363,7 +310,7 @@ static int pxa_ata_probe(struct platform_device *pdev) ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt, pdata->irq_flags, &pxa_ata_sht); if (ret) - pxa_free_dma(data->dma_channel); + dma_release_channel(data->dma_chan); return ret; } @@ -373,7 +320,7 @@ static int pxa_ata_remove(struct platform_device *pdev) struct ata_host *host = platform_get_drvdata(pdev); struct pata_pxa_data *data = host->ports[0]->private_data; - pxa_free_dma(data->dma_channel); + dma_release_channel(data->dma_chan); ata_host_detach(host); diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index cbb5a471eb9d..f6facd686f94 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c @@ -70,7 +70,7 @@ struct s3c_ide_info { struct clk *clk; void __iomem *ide_addr; void __iomem *sfr_addr; - unsigned int irq; + int irq; enum s3c_cpu_type cpu_type; unsigned int fifo_status_reg; }; |