From c0a85758a669b430c0a6af825e71d18a54ef88d0 Mon Sep 17 00:00:00 2001
From: Anthony Foiani <anthony.foiani@gmail.com>
Date: Mon, 29 Apr 2013 23:44:14 -0600
Subject: [PATCH] sata: fsl: allow device tree to limit sata speed.

There used to be an "orphan" config symbol (CONFIG_MPC8315_DS) that
would artificially limit SATA speed to generation 1 (1.5Gbps).

Since that config symbol got lost whenever any sort of configuration
was done, we instead extract the limitation from the device tree.

Signed-off-by: Anthony Foiani <anthony.foiani@gmail.com>
---
 .../devicetree/bindings/powerpc/fsl/board.txt      | 23 +++++++++++
 drivers/ata/sata_fsl.c                             | 44 ++++++++++++++++++----
 2 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/board.txt b/Documentation/devicetree/bindings/powerpc/fsl/board.txt
index 380914e..6a30398 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/board.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/board.txt
@@ -67,3 +67,26 @@ Example:
 			gpio-controller;
 		};
 	};
+
+* Maximum SATA Generation workaround
+
+Some boards advertise SATA speeds that they cannot actually achieve.
+Previously, this was dealt with via the orphaned config symbol
+CONFIG_MPC8315_DS.  We now have a device tree property
+"fsl,sata-max-gen" to control this.  It should live within the "sata"
+block.
+
+Example:
+
+		sata@18000 {
+			compatible = "fsl,mpc8315-sata", "fsl,pq-sata";
+			reg = <0x18000 0x1000>;
+			cell-index = <1>;
+			interrupts = <44 0x8>;
+			interrupt-parent = <&ipic>;
+			fsl,sata-max-gen = <1>;
+		};
+
+By default, there is no limitation; if a value is given, it indicates
+the maximum "generation" that should be negotiated.  Gen 1 is 1.5Gbps,
+Gen 2 is 3.0Gbps.
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index d6577b9..6d3ec47 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -274,6 +274,17 @@ struct sata_fsl_port_priv {
 };
 
 /*
+ * speed negotiation.
+ */
+
+enum {
+	SCR_SPEED_NEG_MASK	= 0xf0,
+	SCR_SPEED_NEG_UNLIMITED	= 0x00,
+	SCR_SPEED_NEG_GEN_1	= 0x10, /* 1.5Gbps max */
+	SCR_SPEED_NEG_GEN_2	= 0x20  /* 3.0Gbps max */
+};
+
+/*
  * ata_port->host_set private data
  */
 struct sata_fsl_host_priv {
@@ -282,6 +293,7 @@ struct sata_fsl_host_priv {
 	void __iomem *csr_base;
 	int irq;
 	int data_snoop;
+	u32 speed_neg;
 	struct device_attribute intr_coalescing;
 };
 
@@ -726,19 +738,23 @@ static int sata_fsl_port_start(struct ata_port *ap)
 	VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
 	VPRINTK("CHBA  = 0x%x\n", ioread32(hcr_base + CHBA));
 
-#ifdef CONFIG_MPC8315_DS
 	/*
 	 * Workaround for 8315DS board 3gbps link-up issue,
 	 * currently limit SATA port to GEN1 speed
 	 */
-	sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
-	temp &= ~(0xF << 4);
-	temp |= (0x1 << 4);
-	sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp);
+	if ( host_priv->speed_neg != SCR_SPEED_NEG_UNLIMITED )
+	{
 
-	sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
-	dev_warn(dev, "scr_control, speed limited to %x\n", temp);
-#endif
+		u32 orig;
+		sata_fsl_scr_read(&ap->link, SCR_CONTROL, &orig);
+		temp = ( ( orig                 & ~SCR_SPEED_NEG_MASK ) |
+			 ( host_priv->speed_neg &  SCR_SPEED_NEG_MASK ) );
+		sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp);
+
+		sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
+		dev_warn(dev, "speed limited, scr_control 0x%x -> 0x%x\n",
+			 orig, temp);
+	}
 
 	return 0;
 }
@@ -1437,6 +1453,18 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	else
 		host_priv->data_snoop = DATA_SNOOP_ENABLE_V1;
 
+	if (!of_property_read_u32(ofdev->dev.of_node, "fsl,sata-max-gen",
+				  &temp))
+	{
+		switch (temp)
+		{
+		case 1: host_priv->speed_neg = SCR_SPEED_NEG_GEN_1; break;
+		case 2: host_priv->speed_neg = SCR_SPEED_NEG_GEN_2; break;
+		}
+		dev_warn(&ofdev->dev, "speed limit set to gen %u (0x%x)\n",
+			 temp, host_priv->speed_neg);
+	}
+
 	/* allocate host structure */
 	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
 	if (!host) {
-- 
1.8.1.4

