aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch')
-rw-r--r--target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch243
1 files changed, 232 insertions, 11 deletions
diff --git a/target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch b/target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch
index aaf677b564..779127058a 100644
--- a/target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch
+++ b/target/linux/layerscape/patches-4.14/801-sata-support-layerscape.patch
@@ -1,15 +1,33 @@
-From 918f966af1f0e42ff8ac298e1d7d02e67afcfab4 Mon Sep 17 00:00:00 2001
+From 71fb63c92eae3f9197e2343ed5ed3676440789e1 Mon Sep 17 00:00:00 2001
From: Biwen Li <biwen.li@nxp.com>
-Date: Tue, 30 Oct 2018 18:27:42 +0800
-Subject: [PATCH 18/40] sata: support layerscape
+Date: Wed, 17 Apr 2019 18:59:01 +0800
+Subject: [PATCH] sata: support layerscape
+
This is an integrated patch of sata for layerscape
-Signed-off-by: Tang Yuantian <andy.tang@nxp.com>
Signed-off-by: Biwen Li <biwen.li@nxp.com>
+Signed-off-by: Peng Ma <peng.ma@nxp.com>
+Signed-off-by: Tang Yuantian <andy.tang@nxp.com>
---
- drivers/ata/ahci_qoriq.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
+ drivers/ata/ahci.h | 7 ++
+ drivers/ata/ahci_qoriq.c | 168 ++++++++++++++++++++++++++++++++++++++
+ drivers/ata/libata-core.c | 3 +
+ 3 files changed, 178 insertions(+)
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -445,4 +445,11 @@ static inline int ahci_nr_ports(u32 cap)
+ return (cap & 0x1f) + 1;
+ }
+
++#ifdef CONFIG_AHCI_QORIQ
++extern void fsl_sata_errata_379364(struct ata_link *link);
++#else
++static void fsl_sata_errata_379364(struct ata_link *link)
++{}
++#endif
++
+ #endif /* _AHCI_H */
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -35,6 +35,8 @@
@@ -21,7 +39,190 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
#define AHCI_PORT_TRANS_CFG 0x08000029
#define AHCI_PORT_AXICC_CFG 0x3fffffff
-@@ -183,6 +185,8 @@ static int ahci_qoriq_phy_init(struct ah
+@@ -49,6 +51,27 @@
+ #define ECC_DIS_ARMV8_CH2 0x80000000
+ #define ECC_DIS_LS1088A 0x40000000
+
++/* errata for lx2160 */
++#define RCWSR29_BASE 0x1E00170
++#define SERDES2_BASE 0x1EB0000
++#define DEVICE_CONFIG_REG_BASE 0x1E00000
++#define SERDES2_LNAX_RX_CR(x) (0x840 + (0x100 * (x)))
++#define SERDES2_LNAX_RX_CBR(x) (0x8C0 + (0x100 * (x)))
++#define SYS_VER_REG 0xA4
++#define LN_RX_RST 0x80000010
++#define LN_RX_RST_DONE 0x3
++#define LN_RX_MASK 0xf
++#define LX2160A_VER1 0x1
++
++#define SERDES2_LNAA 0
++#define SERDES2_LNAB 1
++#define SERDES2_LNAC 2
++#define SERDES2_LNAD 3
++#define SERDES2_LNAE 4
++#define SERDES2_LNAF 5
++#define SERDES2_LNAG 6
++#define SERDES2_LNAH 7
++
+ enum ahci_qoriq_type {
+ AHCI_LS1021A,
+ AHCI_LS1043A,
+@@ -56,6 +79,7 @@ enum ahci_qoriq_type {
+ AHCI_LS1046A,
+ AHCI_LS1088A,
+ AHCI_LS2088A,
++ AHCI_LX2160A,
+ };
+
+ struct ahci_qoriq_priv {
+@@ -72,6 +96,7 @@ static const struct of_device_id ahci_qo
+ { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
+ { .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A},
+ { .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A},
++ { .compatible = "fsl,lx2160a-ahci", .data = (void *)AHCI_LX2160A},
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
+@@ -156,6 +181,138 @@ static struct scsi_host_template ahci_qo
+ AHCI_SHT(DRV_NAME),
+ };
+
++void fsl_sata_errata_379364(struct ata_link *link)
++{
++ struct ata_port *ap = link->ap;
++ struct ahci_host_priv *hpriv = ap->host->private_data;
++ struct ahci_qoriq_priv *qoriq_priv = hpriv->plat_data;
++ bool lx2160a_workaround = (qoriq_priv->type == AHCI_LX2160A);
++
++ int val = 0;
++ void __iomem *rcw_base = NULL;
++ void __iomem *serdes_base = NULL;
++ void __iomem *dev_con_base = NULL;
++
++ if (!lx2160a_workaround)
++ return;
++ else {
++ dev_con_base = ioremap(DEVICE_CONFIG_REG_BASE, PAGE_SIZE);
++ if (!dev_con_base) {
++ ata_link_err(link, "device config ioremap failed\n");
++ return;
++ }
++
++ val = (readl(dev_con_base + SYS_VER_REG) & GENMASK(7, 4)) >> 4;
++ if (val != LX2160A_VER1)
++ goto dev_unmap;
++
++ /*
++ * Add few msec delay.
++ * Check for corresponding serdes lane RST_DONE .
++ * apply lane reset.
++ */
++
++ serdes_base = ioremap(SERDES2_BASE, PAGE_SIZE);
++ if (!serdes_base) {
++ ata_link_err(link, "serdes ioremap failed\n");
++ goto dev_unmap;
++ }
++
++ rcw_base = ioremap(RCWSR29_BASE, PAGE_SIZE);
++ if (!rcw_base) {
++ ata_link_err(link, "rcw ioremap failed\n");
++ goto serdes_unmap;
++ }
++
++ ata_msleep(link->ap, 1);
++
++ val = (readl(rcw_base) & GENMASK(25, 21)) >> 21;
++
++ switch (val) {
++ case 1:
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAC)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAC));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAD)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAD));
++ break;
++
++ case 4:
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAG));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAH));
++ break;
++
++ case 5:
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAE)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAE));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAF)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAF));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAG));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAH));
++ break;
++
++ case 8:
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAC)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAC));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAD)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAD));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAE)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAE));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAF)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAF));
++ break;
++
++ case 12:
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAG));
++ if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
++ LN_RX_MASK) != LN_RX_RST_DONE)
++ writel(LN_RX_RST, serdes_base +
++ SERDES2_LNAX_RX_CR(SERDES2_LNAH));
++ break;
++
++ default:
++ break;
++ }
++ }
++
++ iounmap(rcw_base);
++serdes_unmap:
++ iounmap(serdes_base);
++dev_unmap:
++ iounmap(dev_con_base);
++}
++
++
+ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
+ {
+ struct ahci_qoriq_priv *qpriv = hpriv->plat_data;
+@@ -183,13 +340,18 @@ static int ahci_qoriq_phy_init(struct ah
writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
@@ -30,16 +231,17 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
-@@ -190,6 +194,8 @@ static int ahci_qoriq_phy_init(struct ah
+ break;
case AHCI_LS2080A:
++ case AHCI_LX2160A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2);
+ writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
-@@ -201,6 +207,8 @@ static int ahci_qoriq_phy_init(struct ah
+@@ -201,6 +363,8 @@ static int ahci_qoriq_phy_init(struct ah
writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
@@ -48,7 +250,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
-@@ -212,6 +220,8 @@ static int ahci_qoriq_phy_init(struct ah
+@@ -212,6 +376,8 @@ static int ahci_qoriq_phy_init(struct ah
writel(readl(qpriv->ecc_addr) | ECC_DIS_LS1088A,
qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
@@ -57,7 +259,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
-@@ -219,6 +229,8 @@ static int ahci_qoriq_phy_init(struct ah
+@@ -219,6 +385,8 @@ static int ahci_qoriq_phy_init(struct ah
case AHCI_LS2088A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
@@ -66,3 +268,22 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
if (qpriv->is_dmacoherent)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -76,6 +76,7 @@
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/libata.h>
+
++#include "ahci.h"
+ #include "libata.h"
+ #include "libata-transport.h"
+
+@@ -4119,6 +4120,8 @@ int sata_link_hardreset(struct ata_link
+ */
+ ata_msleep(link->ap, 1);
+
++ fsl_sata_errata_379364(link);
++
+ /* bring link back */
+ rc = sata_link_resume(link, timing, deadline);
+ if (rc)