Skip to contentSkip to conversation

ata: ahci_xgene: Add support for 2nd HW version of APM X-Gene SoC AHCI SATA Host controller driver.

PATCH Superseded Suman Tripathi 2 participants 5 messages May 5, 2015

Subsystems (2)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v4 cover ata: ahci_xgene: Add support for 2nd HW version of APM X-Gene SoC AHCI SATA Host controller driver.

V2 change:
* Drop the MIDR based implementation.

V3 change:
* Implement the support for HOST_IRQ_STAT as edge trigger latch.

V4 change:
* Implement seperate irq handler for level and edge trigger latch.

---

Suman Tripathi (2):
libahci: Add support to handle HOST_IRQ_STAT as edge trigger latch.
ata: ahci_xgene: Add AHCI Support for 2nd HW version of APM X-Gene SoC
AHCI SATA Host controller.

 drivers/ata/ahci.h       |  2 ++
 drivers/ata/ahci_xgene.c | 90 ++++++++++++++++++++++++++++++++++++----------
 drivers/ata/libahci.c    | 93 ++++++++++++++++++++++++++++++++++++------------
 3 files changed, 145 insertions(+), 40 deletions(-)

--
1.8.2.1

#1 lore raw

PATCH v4 1/2 libahci: Add support to handle HOST_IRQ_STAT as edge trigger latch.

This patch adds the support to handle HOST_IRQ_STAT as edge trigger latch.

---
 drivers/ata/ahci.h    |  2 ++
 drivers/ata/libahci.c | 93 +++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 73 insertions(+), 22 deletions(-)
drivers/ata/ahci.h +2 -0
index 71262e0..2df2237 100644
@@ -238,6 +238,8 @@ enum {
 	AHCI_HFLAG_MULTI_MSI		= (1 << 16), /* multiple PCI MSIs */
 	AHCI_HFLAG_NO_DEVSLP		= (1 << 17), /* no device sleep */
 	AHCI_HFLAG_NO_FBS		= (1 << 18), /* no FBS */
+	AHCI_HFLAG_EDGE_TRIG_IRQ	= (1 << 19), /* HOST_IRQ_STAT behaves as
+							Edge Triggered */
 
 	/* ap->flags bits */
 
drivers/ata/libahci.c +71 -22

129 lines not on this page · raw message

--
1.8.2.1

#2 lore raw

PATCH v4 1/2 libahci: Add support to handle HOST_IRQ_STAT as edge trigger latch.

Hello, Suman.

Looks pretty. Some nitpicks.

drivers/ata/ahci.h enum { · line 242

Quoted 10 lines · Suman Tripathi
drivers/ata/ahci.h +2 -0
index 71262e0..2df2237 100644
@@ -238,6 +238,8 @@ enum {
 	AHCI_HFLAG_MULTI_MSI		= (1 << 16), /* multiple PCI MSIs */
 	AHCI_HFLAG_NO_DEVSLP		= (1 << 17), /* no device sleep */
 	AHCI_HFLAG_NO_FBS		= (1 << 18), /* no FBS */
+	AHCI_HFLAG_EDGE_TRIG_IRQ	= (1 << 19), /* HOST_IRQ_STAT behaves as
+							Edge Triggered */

Let's just name it ahci_HFLAG_EDGE_IRQ.

drivers/ata/ahci.h enum { · line 243

Quoted 1 line
drivers/ata/ahci.h +1 -0
+static irqreturn_t ahci_level_trig_intr(int irq, void *dev_instance)

ahci_single_level_irq_intr()

Quoted 1 line
drivers/ata/ahci.h +1 -0
+{

...

drivers/ata/ahci.h static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) · line 1888

Quoted 5 lines
drivers/ata/ahci.h +1 -0
@@ -1877,13 +1885,51 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
 	 * Also, use the unmasked value to clear interrupt as spurious
 	 * pending event on a dummy port might cause screaming IRQ.
 	 */
+

Extra newline which wasn't there before.

drivers/ata/ahci.h static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) · line 1898

Quoted 10 lines
drivers/ata/ahci.h +10 -0
+	writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+	spin_unlock(&host->lock);
+
+	VPRINTK("EXIT\n");
+
+	return IRQ_RETVAL(rc);
+}
+
+static irqreturn_t ahci_edge_trig_intr(int irq, void *dev_instance)

ahci_single_edge_irq_intr()

And let's please separate refactoring of intr routine and addition of edge irq handling into two patches.

Thanks.

Signature · 1 line
tejun
#3 lore raw

PATCH v4 1/2 libahci: Add support to handle HOST_IRQ_STAT as edge trigger latch.

Hi Tejun,

Quoted 5 lines · Tejun Heo

Hello, Suman.

Looks pretty. Some nitpicks.

On Tue, May 05, 2015 at 08:43:41PM +0530, Suman Tripathi wrote:

Quoted 12 lines

drivers/ata/ahci.h enum { · line 242

Quoted 10 lines
drivers/ata/ahci.h +2 -0
index 71262e0..2df2237 100644
@@ -238,6 +238,8 @@ enum {
      AHCI_HFLAG_MULTI_MSI            = (1 << 16), /* multiple PCI MSIs */
      AHCI_HFLAG_NO_DEVSLP            = (1 << 17), /* no device sleep */
      AHCI_HFLAG_NO_FBS               = (1 << 18), /* no FBS */
+     AHCI_HFLAG_EDGE_TRIG_IRQ        = (1 << 19), /* HOST_IRQ_STAT behaves as
+                                                     Edge Triggered */

Let's just name it ahci_HFLAG_EDGE_IRQ.

Sure

Quoted 6 lines

drivers/ata/ahci.h enum { · line 243

Quoted 2 lines
drivers/ata/ahci.h +1 -0
+static irqreturn_t ahci_level_trig_intr(int irq, void *dev_instance)

ahci_single_level_irq_intr()

drivers/ata/ahci.h enum { · line 244

Quoted 1 line
drivers/ata/ahci.h +1 -0
+{
Quoted 8 lines

...

drivers/ata/ahci.h static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) · line 1888

Quoted 5 lines
drivers/ata/ahci.h +1 -0
@@ -1877,13 +1885,51 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
       * Also, use the unmasked value to clear interrupt as spurious
       * pending event on a dummy port might cause screaming IRQ.
       */
+

Extra newline which wasn't there before.

sorry . Happened mistakenly

Quoted 13 lines

drivers/ata/ahci.h static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) · line 1898

Quoted 11 lines
drivers/ata/ahci.h +10 -0
+     writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+     spin_unlock(&host->lock);
+
+     VPRINTK("EXIT\n");
+
+     return IRQ_RETVAL(rc);
+}
+
+static irqreturn_t ahci_edge_trig_intr(int irq, void *dev_instance)

ahci_single_edge_irq_intr()

Sure.

Quoted 3 lines

And let's please separate refactoring of intr routine and addition of edge irq handling into two patches.

Okay

Quoted 5 lines

Thanks.

--
tejun

Signature · 3 lines
Thanks,
with regards,
Suman Tripathi
#4 lore raw

PATCH v4 2/2 ata: ahci_xgene: Add AHCI Support for 2nd HW version of APM X-Gene SoC AHCI SATA Host controller.

In reply to Suman Tripathi

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.

---
 drivers/ata/ahci_xgene.c | 90 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 72 insertions(+), 18 deletions(-)
drivers/ata/ahci_xgene.c +72 -18
index 2b78510..2ced663 100644
@@ -27,6 +27,7 @@
 #include <linux/platform_device.h>
 #include <linux/ahci_platform.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/phy/phy.h>
 #include "ahci.h"
@@ -84,6 +85,11 @@
 /* Max retry for link down */
 #define MAX_LINK_DOWN_RETRY 3
 
+enum xgene_ahci_version {
+	XGENE_AHCI_V1 = 1,
+	XGENE_AHCI_V2,
+};
+
 struct xgene_ahci_context {
 	struct ahci_host_priv *hpriv;
 	struct device *dev;
@@ -547,9 +553,6 @@ static struct ata_port_operations xgene_ahci_ops = {
 	.host_stop = xgene_ahci_host_stop,
 	.hardreset = xgene_ahci_hardreset,
 	.read_id = xgene_ahci_read_id,
-	.qc_issue = xgene_ahci_qc_issue,
-	.softreset = xgene_ahci_softreset,
-	.pmp_softreset = xgene_ahci_pmp_softreset
 };
 
 static const struct ata_port_info xgene_ahci_port_info = {
@@ -629,12 +632,30 @@ static struct scsi_host_template ahci_platform_sht = {
 	AHCI_SHT(DRV_NAME),
 };
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_ahci_acpi_match[] = {
+	{ "APMC0D0D", XGENE_AHCI_V1},
+	{ "APMC0D32", XGENE_AHCI_V2},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
+#endif
+
+static const struct of_device_id xgene_ahci_of_match[] = {
+	{.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
+	{.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
+	{},
+};
+MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
+
 static int xgene_ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
 	struct xgene_ahci_context *ctx;
 	struct resource *res;
+	const struct of_device_id *of_devid;
+	enum xgene_ahci_version version = XGENE_AHCI_V1;
 	int rc;
 
 	hpriv = ahci_platform_get_resources(pdev);
@@ -677,6 +698,37 @@ static int xgene_ahci_probe(struct platform_device *pdev)
 		ctx->csr_mux = csr;
 	}
 
+	of_devid = of_match_device(xgene_ahci_of_match, dev);
+	if (of_devid) {
+		if (of_devid->data)
+			version = (enum xgene_ahci_version) of_devid->data;
+	}
+#ifdef CONFIG_ACPI
+	else {
+		const struct acpi_device_id *acpi_id;
+		struct acpi_device_info *info;
+		acpi_status status;
+
+		acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev);
+		if (!acpi_id) {
+			dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n");
+			version = XGENE_AHCI_V1;
+		}
+
+		if (acpi_id->driver_data) {
+			version = (enum xgene_ahci_version) acpi_id->driver_data;
+			status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info);
+			if (ACPI_FAILURE(status)) {
+				dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n",
+					__func__);
+				version = XGENE_AHCI_V1;
+			}
+			if (info->valid & ACPI_VALID_CID)
+				version = XGENE_AHCI_V2;
+		}
+	}
+#endif
+
 	dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core,
 		hpriv->mmio);
 
@@ -704,7 +756,23 @@ static int xgene_ahci_probe(struct platform_device *pdev)
 	/* Configure the host controller */
 	xgene_ahci_hw_init(hpriv);
 skip_clk_phy:
-	hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ;
+
+	switch (version) {
+	case XGENE_AHCI_V1:
+		hpriv->flags = AHCI_HFLAG_NO_NCQ;
+		/*
+		 * Override the callbacks for storm ERRATA
+		 */
+		xgene_ahci_ops.qc_issue = xgene_ahci_qc_issue;
+		xgene_ahci_ops.softreset = xgene_ahci_softreset;
+		xgene_ahci_ops.pmp_softreset = xgene_ahci_pmp_softreset;
+		break;
+	case XGENE_AHCI_V2:
+		hpriv->flags |= AHCI_HFLAG_YES_FBS | AHCI_HFLAG_EDGE_TRIG_IRQ;
+		break;
+	default:
+		break;
+	}
 
 	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info,
 				     &ahci_platform_sht);
@@ -719,20 +787,6 @@ disable_resources:
 	return rc;
 }
 
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id xgene_ahci_acpi_match[] = {
-	{ "APMC0D0D", },
-	{ }
-};
-MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
-#endif
-
-static const struct of_device_id xgene_ahci_of_match[] = {
-	{.compatible = "apm,xgene-ahci"},
-	{},
-};
-MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
-
 static struct platform_driver xgene_ahci_driver = {
 	.probe = xgene_ahci_probe,
 	.remove = ata_platform_remove_one,

--
1.8.2.1