aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorSuman Tripathi <stripathi@apm.com>2015-05-11 04:36:15 -0400
committerTejun Heo <tj@kernel.org>2015-05-11 07:26:48 -0400
commitc9802a4be6611520dd99d91d0d9c4efcaa0fa281 (patch)
tree1fa844c8d02e752f3a16a9bff3610934c51419d8 /drivers/ata
parent5903b1643f41ccc0cb3a0cde1d12b1c942914317 (diff)
ata: ahci_xgene: Add AHCI Support for 2nd HW version of APM X-Gene SoC AHCI SATA Host controller.
This patch enables full AHCI feature support for APM X-Gene SoC SATA host controller. The following errata's are removed: 1. 2a0bdff6b95 ("ahci-xgene: fix the dma state machine lockup for the IDENTIFY DEVICE PIO mode command") 2. 09c32aaa368 ("ahci_xgene: Fix the dma state machine lockup for the ATA_CMD_SMART PIO mode command") 3. 1540035da71 ("ahci_xgene: Implement the xgene_ahci_poll_reg_val to support PMP") 4. a3a84bc7c88 ("ahci_xgene: Implement the workaround to support PMP enumeration and discovery") 5. 1102407bb71 ("ahci_xgene: Fix the DMA state machine lockup for the ATA_CMD_PACKET PIO mode command") 6. 72f79f9e35b ("ahci_xgene: Removing NCQ support from the APM X-Gene SoC AHCI SATA Host Controller driver") In addition, enable PMP support for APM X-Gene SoC and enable FBS support for second generation APM X-Gene SoC. Signed-off-by: Suman Tripathi <stripathi@apm.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci_xgene.c105
1 files changed, 86 insertions, 19 deletions
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 2b78510d94dd..2add250d1555 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -27,6 +27,7 @@
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/ahci_platform.h> 28#include <linux/ahci_platform.h>
29#include <linux/of_address.h> 29#include <linux/of_address.h>
30#include <linux/of_device.h>
30#include <linux/of_irq.h> 31#include <linux/of_irq.h>
31#include <linux/phy/phy.h> 32#include <linux/phy/phy.h>
32#include "ahci.h" 33#include "ahci.h"
@@ -84,6 +85,11 @@
84/* Max retry for link down */ 85/* Max retry for link down */
85#define MAX_LINK_DOWN_RETRY 3 86#define MAX_LINK_DOWN_RETRY 3
86 87
88enum xgene_ahci_version {
89 XGENE_AHCI_V1 = 1,
90 XGENE_AHCI_V2,
91};
92
87struct xgene_ahci_context { 93struct xgene_ahci_context {
88 struct ahci_host_priv *hpriv; 94 struct ahci_host_priv *hpriv;
89 struct device *dev; 95 struct device *dev;
@@ -542,7 +548,7 @@ softreset_retry:
542 return rc; 548 return rc;
543} 549}
544 550
545static struct ata_port_operations xgene_ahci_ops = { 551static struct ata_port_operations xgene_ahci_v1_ops = {
546 .inherits = &ahci_ops, 552 .inherits = &ahci_ops,
547 .host_stop = xgene_ahci_host_stop, 553 .host_stop = xgene_ahci_host_stop,
548 .hardreset = xgene_ahci_hardreset, 554 .hardreset = xgene_ahci_hardreset,
@@ -552,11 +558,25 @@ static struct ata_port_operations xgene_ahci_ops = {
552 .pmp_softreset = xgene_ahci_pmp_softreset 558 .pmp_softreset = xgene_ahci_pmp_softreset
553}; 559};
554 560
555static const struct ata_port_info xgene_ahci_port_info = { 561static const struct ata_port_info xgene_ahci_v1_port_info = {
556 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP, 562 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP,
557 .pio_mask = ATA_PIO4, 563 .pio_mask = ATA_PIO4,
558 .udma_mask = ATA_UDMA6, 564 .udma_mask = ATA_UDMA6,
559 .port_ops = &xgene_ahci_ops, 565 .port_ops = &xgene_ahci_v1_ops,
566};
567
568static struct ata_port_operations xgene_ahci_v2_ops = {
569 .inherits = &ahci_ops,
570 .host_stop = xgene_ahci_host_stop,
571 .hardreset = xgene_ahci_hardreset,
572 .read_id = xgene_ahci_read_id,
573};
574
575static const struct ata_port_info xgene_ahci_v2_port_info = {
576 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP,
577 .pio_mask = ATA_PIO4,
578 .udma_mask = ATA_UDMA6,
579 .port_ops = &xgene_ahci_v2_ops,
560}; 580};
561 581
562static int xgene_ahci_hw_init(struct ahci_host_priv *hpriv) 582static int xgene_ahci_hw_init(struct ahci_host_priv *hpriv)
@@ -629,12 +649,32 @@ static struct scsi_host_template ahci_platform_sht = {
629 AHCI_SHT(DRV_NAME), 649 AHCI_SHT(DRV_NAME),
630}; 650};
631 651
652#ifdef CONFIG_ACPI
653static const struct acpi_device_id xgene_ahci_acpi_match[] = {
654 { "APMC0D0D", XGENE_AHCI_V1},
655 { "APMC0D32", XGENE_AHCI_V2},
656 {},
657};
658MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
659#endif
660
661static const struct of_device_id xgene_ahci_of_match[] = {
662 {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
663 {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
664 {},
665};
666MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
667
632static int xgene_ahci_probe(struct platform_device *pdev) 668static int xgene_ahci_probe(struct platform_device *pdev)
633{ 669{
634 struct device *dev = &pdev->dev; 670 struct device *dev = &pdev->dev;
635 struct ahci_host_priv *hpriv; 671 struct ahci_host_priv *hpriv;
636 struct xgene_ahci_context *ctx; 672 struct xgene_ahci_context *ctx;
637 struct resource *res; 673 struct resource *res;
674 const struct of_device_id *of_devid;
675 enum xgene_ahci_version version = XGENE_AHCI_V1;
676 const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
677 &xgene_ahci_v2_port_info };
638 int rc; 678 int rc;
639 679
640 hpriv = ahci_platform_get_resources(pdev); 680 hpriv = ahci_platform_get_resources(pdev);
@@ -677,6 +717,37 @@ static int xgene_ahci_probe(struct platform_device *pdev)
677 ctx->csr_mux = csr; 717 ctx->csr_mux = csr;
678 } 718 }
679 719
720 of_devid = of_match_device(xgene_ahci_of_match, dev);
721 if (of_devid) {
722 if (of_devid->data)
723 version = (enum xgene_ahci_version) of_devid->data;
724 }
725#ifdef CONFIG_ACPI
726 else {
727 const struct acpi_device_id *acpi_id;
728 struct acpi_device_info *info;
729 acpi_status status;
730
731 acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev);
732 if (!acpi_id) {
733 dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n");
734 version = XGENE_AHCI_V1;
735 }
736
737 if (acpi_id->driver_data) {
738 version = (enum xgene_ahci_version) acpi_id->driver_data;
739 status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info);
740 if (ACPI_FAILURE(status)) {
741 dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n",
742 __func__);
743 version = XGENE_AHCI_V1;
744 }
745 if (info->valid & ACPI_VALID_CID)
746 version = XGENE_AHCI_V2;
747 }
748 }
749#endif
750
680 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core, 751 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core,
681 hpriv->mmio); 752 hpriv->mmio);
682 753
@@ -704,9 +775,19 @@ static int xgene_ahci_probe(struct platform_device *pdev)
704 /* Configure the host controller */ 775 /* Configure the host controller */
705 xgene_ahci_hw_init(hpriv); 776 xgene_ahci_hw_init(hpriv);
706skip_clk_phy: 777skip_clk_phy:
707 hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ;
708 778
709 rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info, 779 switch (version) {
780 case XGENE_AHCI_V1:
781 hpriv->flags = AHCI_HFLAG_NO_NCQ;
782 break;
783 case XGENE_AHCI_V2:
784 hpriv->flags |= AHCI_HFLAG_YES_FBS | AHCI_HFLAG_EDGE_IRQ;
785 break;
786 default:
787 break;
788 }
789
790 rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1],
710 &ahci_platform_sht); 791 &ahci_platform_sht);
711 if (rc) 792 if (rc)
712 goto disable_resources; 793 goto disable_resources;
@@ -719,20 +800,6 @@ disable_resources:
719 return rc; 800 return rc;
720} 801}
721 802
722#ifdef CONFIG_ACPI
723static const struct acpi_device_id xgene_ahci_acpi_match[] = {
724 { "APMC0D0D", },
725 { }
726};
727MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
728#endif
729
730static const struct of_device_id xgene_ahci_of_match[] = {
731 {.compatible = "apm,xgene-ahci"},
732 {},
733};
734MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
735
736static struct platform_driver xgene_ahci_driver = { 803static struct platform_driver xgene_ahci_driver = {
737 .probe = xgene_ahci_probe, 804 .probe = xgene_ahci_probe,
738 .remove = ata_platform_remove_one, 805 .remove = ata_platform_remove_one,