1 From 73f7122003fca0d08142370e5b6c25783a7b43e9 Mon Sep 17 00:00:00 2001
2 From: Peng Ma <peng.ma@nxp.com>
3 Date: Wed, 15 May 2019 05:52:44 +0000
4 Subject: [PATCH] ahci: qoriq: workaround for errata A-379364 on lx2160a
6 There is a erratum on lx2160a which is: "SATA link is
7 going down sometime during sata initialization"
8 The workaround for it is to reset the lane. This patch
9 implements this workaround.
10 This erratum only exists on lx2160 Rev1, will be addressed
13 Signed-off-by: Peng Ma <peng.ma@nxp.com>
15 drivers/ata/ahci_qoriq.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++
16 1 file changed, 144 insertions(+)
18 --- a/drivers/ata/ahci_qoriq.c
19 +++ b/drivers/ata/ahci_qoriq.c
21 #define ECC_DIS_ARMV8_CH2 0x80000000
22 #define ECC_DIS_LS1088A 0x40000000
24 +/* errata for lx2160 */
25 +#define RCWSR29_BASE 0x1E00170
26 +#define SERDES2_BASE 0x1EB0000
27 +#define DEVICE_CONFIG_REG_BASE 0x1E00000
28 +#define SERDES2_LNAX_RX_CR(x) (0x840 + (0x100 * (x)))
29 +#define SERDES2_LNAX_RX_CBR(x) (0x8C0 + (0x100 * (x)))
30 +#define SYS_VER_REG 0xA4
31 +#define LN_RX_RST 0x80000010
32 +#define LN_RX_RST_DONE 0x3
33 +#define LN_RX_MASK 0xf
34 +#define LX2160A_VER1 0x1
36 +#define SERDES2_LNAA 0
37 +#define SERDES2_LNAB 1
38 +#define SERDES2_LNAC 2
39 +#define SERDES2_LNAD 3
40 +#define SERDES2_LNAE 4
41 +#define SERDES2_LNAF 5
42 +#define SERDES2_LNAG 6
43 +#define SERDES2_LNAH 7
45 enum ahci_qoriq_type {
48 @@ -87,6 +108,126 @@ static const struct acpi_device_id ahci_
50 MODULE_DEVICE_TABLE(acpi, ahci_qoriq_acpi_match);
52 +static void fsl_sata_errata_379364(bool select)
55 + void __iomem *rcw_base = NULL;
56 + void __iomem *serdes_base = NULL;
57 + void __iomem *dev_con_base = NULL;
60 + dev_con_base = ioremap(DEVICE_CONFIG_REG_BASE, PAGE_SIZE);
64 + val = (readl(dev_con_base + SYS_VER_REG) & GENMASK(7, 4)) >> 4;
65 + if (val != LX2160A_VER1)
69 + * Add few msec delay.
70 + * Check for corresponding serdes lane RST_DONE .
74 + serdes_base = ioremap(SERDES2_BASE, PAGE_SIZE);
78 + rcw_base = ioremap(RCWSR29_BASE, PAGE_SIZE);
84 + val = (readl(rcw_base) & GENMASK(25, 21)) >> 21;
88 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAC)) &
89 + LN_RX_MASK) != LN_RX_RST_DONE)
90 + writel(LN_RX_RST, serdes_base +
91 + SERDES2_LNAX_RX_CR(SERDES2_LNAC));
92 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAD)) &
93 + LN_RX_MASK) != LN_RX_RST_DONE)
94 + writel(LN_RX_RST, serdes_base +
95 + SERDES2_LNAX_RX_CR(SERDES2_LNAD));
99 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
100 + LN_RX_MASK) != LN_RX_RST_DONE)
101 + writel(LN_RX_RST, serdes_base +
102 + SERDES2_LNAX_RX_CR(SERDES2_LNAG));
103 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
104 + LN_RX_MASK) != LN_RX_RST_DONE)
105 + writel(LN_RX_RST, serdes_base +
106 + SERDES2_LNAX_RX_CR(SERDES2_LNAH));
110 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAE)) &
111 + LN_RX_MASK) != LN_RX_RST_DONE)
112 + writel(LN_RX_RST, serdes_base +
113 + SERDES2_LNAX_RX_CR(SERDES2_LNAE));
114 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAF)) &
115 + LN_RX_MASK) != LN_RX_RST_DONE)
116 + writel(LN_RX_RST, serdes_base +
117 + SERDES2_LNAX_RX_CR(SERDES2_LNAF));
118 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
119 + LN_RX_MASK) != LN_RX_RST_DONE)
120 + writel(LN_RX_RST, serdes_base +
121 + SERDES2_LNAX_RX_CR(SERDES2_LNAG));
122 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
123 + LN_RX_MASK) != LN_RX_RST_DONE)
124 + writel(LN_RX_RST, serdes_base +
125 + SERDES2_LNAX_RX_CR(SERDES2_LNAH));
129 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAC)) &
130 + LN_RX_MASK) != LN_RX_RST_DONE)
131 + writel(LN_RX_RST, serdes_base +
132 + SERDES2_LNAX_RX_CR(SERDES2_LNAC));
133 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAD)) &
134 + LN_RX_MASK) != LN_RX_RST_DONE)
135 + writel(LN_RX_RST, serdes_base +
136 + SERDES2_LNAX_RX_CR(SERDES2_LNAD));
137 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAE)) &
138 + LN_RX_MASK) != LN_RX_RST_DONE)
139 + writel(LN_RX_RST, serdes_base +
140 + SERDES2_LNAX_RX_CR(SERDES2_LNAE));
141 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAF)) &
142 + LN_RX_MASK) != LN_RX_RST_DONE)
143 + writel(LN_RX_RST, serdes_base +
144 + SERDES2_LNAX_RX_CR(SERDES2_LNAF));
148 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
149 + LN_RX_MASK) != LN_RX_RST_DONE)
150 + writel(LN_RX_RST, serdes_base +
151 + SERDES2_LNAX_RX_CR(SERDES2_LNAG));
152 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
153 + LN_RX_MASK) != LN_RX_RST_DONE)
154 + writel(LN_RX_RST, serdes_base +
155 + SERDES2_LNAX_RX_CR(SERDES2_LNAH));
167 + iounmap(serdes_base);
169 + iounmap(dev_con_base);
172 static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
173 unsigned long deadline)
175 @@ -102,6 +243,7 @@ static int ahci_qoriq_hardreset(struct a
178 bool ls1021a_workaround = (qoriq_priv->type == AHCI_LS1021A);
179 + bool lx2160a_workaround = (qoriq_priv->type == AHCI_LX2160A);
183 @@ -128,6 +270,8 @@ static int ahci_qoriq_hardreset(struct a
184 tf.command = ATA_BUSY;
185 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
187 + fsl_sata_errata_379364(lx2160a_workaround);
189 rc = sata_link_hardreset(link, timing, deadline, &online,