diff mbox

[v2,01/10] ata: ahci_brcmstb: add quick for broken ncq

Message ID 1445928491-7320-2-git-send-email-jaedon.shin@gmail.com
State Not Applicable
Delegated to: David Miller
Headers show

Commit Message

Jaedon Shin Oct. 27, 2015, 6:48 a.m. UTC
Add quick for bronken ncq. The chipsets (eg. BCM7439A0, BCM7445A0 and
BCM7445B0) need a workaround disabling NCQ. and it may need the
MIPS-based set-top box platforms.

Signed-off-by: Jaedon Shin <jaedon.shin@gmail.com>
---
 .../devicetree/bindings/ata/brcm,sata-brcmstb.txt  |  3 ++
 drivers/ata/ahci_brcmstb.c                         | 42 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)

Comments

Florian Fainelli Oct. 27, 2015, 3:46 p.m. UTC | #1
On 26/10/15 23:48, Jaedon Shin wrote:
> Add quick for bronken ncq. The chipsets (eg. BCM7439A0, BCM7445A0 and
> BCM7445B0) need a workaround disabling NCQ. and it may need the
> MIPS-based set-top box platforms.

None of these chips are production chips, so at this point, disabling
NCQ should be done based on the compatible string we probed the driver
with, not using a specific property.

There are more comments below

> 
> Signed-off-by: Jaedon Shin <jaedon.shin@gmail.com>
> ---

[snip]

>  
> +static void brcm_sata_quick(struct platform_device *pdev,
> +			    struct brcm_ahci_priv *priv)
> +{
> +	void __iomem *ahci;
> +	struct resource *res;
> +	u32 reg;
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
> +	ahci = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(ahci))
> +		return;
> +
> +	if (priv->quicks & BRCM_AHCI_QUICK_NONCQ) {
> +		reg  = readl(priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
> +		reg |= OVERRIDE_HWINIT;
> +		writel(reg, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
> +
> +		/* Clear out the NCQ bit so the AHCI driver will not issue
> +		 * FPDMA/NCQ commands.
> +		 */
> +		reg = readl(ahci + HOST_CAP);
> +		reg &= ~HOST_CAP_NCQ;
> +		writel(reg, ahci + HOST_CAP);
> +
> +		reg = readl(priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
> +		reg &= ~OVERRIDE_HWINIT;
> +		writel(reg, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
> +	}

In the original BSP, the NCQ disabling occurs prior to initializing the
SATA controller endianess. We would want to keep doing that in the same
order, and use brcm_sata_readreg() and brcm_sata_writereg() which take
care of doing these accesses in the native endianess of the system.

Reference is here:

https://github.com/Broadcom/stblinux-3.3/blob/master/linux/drivers/brcmstb/bchip.c#L254

> +
> +	devm_iounmap(&pdev->dev, ahci);
> +	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
> +}
> +
>  #ifdef CONFIG_PM_SLEEP
>  static int brcm_ahci_suspend(struct device *dev)
>  {
> @@ -256,7 +294,11 @@ static int brcm_ahci_probe(struct platform_device *pdev)
>  	if (IS_ERR(priv->top_ctrl))
>  		return PTR_ERR(priv->top_ctrl);
>  
> +	if (of_property_read_bool(dev->of_node, "brcm,broken-ncq"))
> +		priv->quicks |= BRCM_AHCI_QUICK_NONCQ;
> +
>  	brcm_sata_init(priv);
> +	brcm_sata_quick(pdev, priv);
Florian
--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt b/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt
index 20ac9bbfa1fd..4650c0aff6b3 100644
--- a/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt
+++ b/Documentation/devicetree/bindings/ata/brcm,sata-brcmstb.txt
@@ -10,6 +10,9 @@  Required properties:
 - reg-names          : "ahci" and "top-ctrl"
 - interrupts         : interrupt mapping for SATA IRQ
 
+Optional properties:
+- brcm,broken-ncq    : if present, NCQ is unusable
+
 Also see ahci-platform.txt.
 
 Example:
diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c
index 14b7305d2ba0..a2df76698adb 100644
--- a/drivers/ata/ahci_brcmstb.c
+++ b/drivers/ata/ahci_brcmstb.c
@@ -69,10 +69,15 @@ 
 	(DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) |		\
 	(MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
 
+enum brcm_ahci_quicks {
+	BRCM_AHCI_QUICK_NONCQ		= BIT(0),
+};
+
 struct brcm_ahci_priv {
 	struct device *dev;
 	void __iomem *top_ctrl;
 	u32 port_mask;
+	u32 quicks;
 };
 
 static const struct ata_port_info ahci_brcm_port_info = {
@@ -209,6 +214,39 @@  static void brcm_sata_init(struct brcm_ahci_priv *priv)
 			   priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
 }
 
+static void brcm_sata_quick(struct platform_device *pdev,
+			    struct brcm_ahci_priv *priv)
+{
+	void __iomem *ahci;
+	struct resource *res;
+	u32 reg;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
+	ahci = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ahci))
+		return;
+
+	if (priv->quicks & BRCM_AHCI_QUICK_NONCQ) {
+		reg  = readl(priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+		reg |= OVERRIDE_HWINIT;
+		writel(reg, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+
+		/* Clear out the NCQ bit so the AHCI driver will not issue
+		 * FPDMA/NCQ commands.
+		 */
+		reg = readl(ahci + HOST_CAP);
+		reg &= ~HOST_CAP_NCQ;
+		writel(reg, ahci + HOST_CAP);
+
+		reg = readl(priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+		reg &= ~OVERRIDE_HWINIT;
+		writel(reg, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+	}
+
+	devm_iounmap(&pdev->dev, ahci);
+	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int brcm_ahci_suspend(struct device *dev)
 {
@@ -256,7 +294,11 @@  static int brcm_ahci_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->top_ctrl))
 		return PTR_ERR(priv->top_ctrl);
 
+	if (of_property_read_bool(dev->of_node, "brcm,broken-ncq"))
+		priv->quicks |= BRCM_AHCI_QUICK_NONCQ;
+
 	brcm_sata_init(priv);
+	brcm_sata_quick(pdev, priv);
 
 	priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
 	if (!priv->port_mask)