OpenWrt – Rev 4

Subversion Repositories:
Rev:
From 4c3979602db05bca439bfc98db88dc14a8663db0 Mon Sep 17 00:00:00 2001
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Wed, 17 Jan 2018 15:14:57 +0800
Subject: [PATCH 13/30] ata: support layerscape

This is an integrated patch for layerscape sata support.

Signed-off-by: Tang Yuantian <Yuantian.Tang@nxp.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
 drivers/ata/ahci_qoriq.c | 63 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 56 insertions(+), 7 deletions(-)

--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -1,7 +1,7 @@
 /*
  * Freescale QorIQ AHCI SATA platform driver
  *
- * Copyright 2015 Freescale, Inc.
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
  *   Tang Yuantian <Yuantian.Tang@freescale.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -46,23 +46,32 @@
 #define LS1021A_AXICC_ADDR     0xC0
 
 #define SATA_ECC_DISABLE       0x00020000
+#define ECC_DIS_ARMV8_CH2      0x80000000
+#define ECC_DIS_LS1088A                0x40000000
 
 enum ahci_qoriq_type {
        AHCI_LS1021A,
        AHCI_LS1043A,
        AHCI_LS2080A,
+       AHCI_LS1046A,
+       AHCI_LS1088A,
+       AHCI_LS2088A,
 };
 
 struct ahci_qoriq_priv {
        struct ccsr_ahci *reg_base;
        enum ahci_qoriq_type type;
        void __iomem *ecc_addr;
+       bool is_dmacoherent;
 };
 
 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},
+       { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
+       { .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A},
+       { .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A},
        {},
 };
 MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
@@ -154,6 +163,8 @@ static int ahci_qoriq_phy_init(struct ah
 
        switch (qpriv->type) {
        case AHCI_LS1021A:
+               if (!qpriv->ecc_addr)
+                       return -EINVAL;
                writel(SATA_ECC_DISABLE, qpriv->ecc_addr);
                writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
                writel(LS1021A_PORT_PHY2, reg_base + PORT_PHY2);
@@ -161,19 +172,56 @@ static int ahci_qoriq_phy_init(struct ah
                writel(LS1021A_PORT_PHY4, reg_base + PORT_PHY4);
                writel(LS1021A_PORT_PHY5, reg_base + PORT_PHY5);
                writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
-               writel(AHCI_PORT_AXICC_CFG, reg_base + LS1021A_AXICC_ADDR);
+               if (qpriv->is_dmacoherent)
+                       writel(AHCI_PORT_AXICC_CFG,
+                                       reg_base + LS1021A_AXICC_ADDR);
                break;
 
        case AHCI_LS1043A:
+               if (!qpriv->ecc_addr)
+                       return -EINVAL;
+               writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
+                               qpriv->ecc_addr);
                writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
                writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
-               writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+               if (qpriv->is_dmacoherent)
+                       writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
                break;
 
        case AHCI_LS2080A:
                writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
                writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
-               writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+               if (qpriv->is_dmacoherent)
+                       writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+               break;
+
+       case AHCI_LS1046A:
+               if (!qpriv->ecc_addr)
+                       return -EINVAL;
+               writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
+                               qpriv->ecc_addr);
+               writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+               writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+               if (qpriv->is_dmacoherent)
+                       writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+               break;
+
+       case AHCI_LS1088A:
+               if (!qpriv->ecc_addr)
+                       return -EINVAL;
+               writel(readl(qpriv->ecc_addr) | ECC_DIS_LS1088A,
+                      qpriv->ecc_addr);
+               writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+               writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+               if (qpriv->is_dmacoherent)
+                       writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+               break;
+
+       case AHCI_LS2088A:
+               writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+               writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+               if (qpriv->is_dmacoherent)
+                       writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
                break;
        }
 
@@ -204,13 +252,14 @@ static int ahci_qoriq_probe(struct platf
 
        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");
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                       "sata-ecc");
+       if (res) {
                qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res);
                if (IS_ERR(qoriq_priv->ecc_addr))
                        return PTR_ERR(qoriq_priv->ecc_addr);
        }
+       qoriq_priv->is_dmacoherent = of_dma_is_coherent(np);
 
        rc = ahci_platform_enable_resources(hpriv);
        if (rc)