1 From 71fb63c92eae3f9197e2343ed5ed3676440789e1 Mon Sep 17 00:00:00 2001
2 From: Biwen Li <biwen.li@nxp.com>
3 Date: Wed, 17 Apr 2019 18:59:01 +0800
4 Subject: [PATCH] sata: support layerscape
6 This is an integrated patch of sata for layerscape
8 Signed-off-by: Biwen Li <biwen.li@nxp.com>
9 Signed-off-by: Peng Ma <peng.ma@nxp.com>
10 Signed-off-by: Tang Yuantian <andy.tang@nxp.com>
12 drivers/ata/ahci.h | 7 ++
13 drivers/ata/ahci_qoriq.c | 168 ++++++++++++++++++++++++++++++++++++++
14 drivers/ata/libata-core.c | 3 +
15 3 files changed, 178 insertions(+)
17 --- a/drivers/ata/ahci.h
18 +++ b/drivers/ata/ahci.h
19 @@ -445,4 +445,11 @@ static inline int ahci_nr_ports(u32 cap)
20 return (cap & 0x1f) + 1;
23 +#ifdef CONFIG_AHCI_QORIQ
24 +extern void fsl_sata_errata_379364(struct ata_link *link);
26 +static void fsl_sata_errata_379364(struct ata_link *link)
31 --- a/drivers/ata/ahci_qoriq.c
32 +++ b/drivers/ata/ahci_qoriq.c
35 /* port register default value */
36 #define AHCI_PORT_PHY_1_CFG 0xa003fffe
37 +#define AHCI_PORT_PHY2_CFG 0x28184d1f
38 +#define AHCI_PORT_PHY3_CFG 0x0e081509
39 #define AHCI_PORT_TRANS_CFG 0x08000029
40 #define AHCI_PORT_AXICC_CFG 0x3fffffff
43 #define ECC_DIS_ARMV8_CH2 0x80000000
44 #define ECC_DIS_LS1088A 0x40000000
46 +/* errata for lx2160 */
47 +#define RCWSR29_BASE 0x1E00170
48 +#define SERDES2_BASE 0x1EB0000
49 +#define DEVICE_CONFIG_REG_BASE 0x1E00000
50 +#define SERDES2_LNAX_RX_CR(x) (0x840 + (0x100 * (x)))
51 +#define SERDES2_LNAX_RX_CBR(x) (0x8C0 + (0x100 * (x)))
52 +#define SYS_VER_REG 0xA4
53 +#define LN_RX_RST 0x80000010
54 +#define LN_RX_RST_DONE 0x3
55 +#define LN_RX_MASK 0xf
56 +#define LX2160A_VER1 0x1
58 +#define SERDES2_LNAA 0
59 +#define SERDES2_LNAB 1
60 +#define SERDES2_LNAC 2
61 +#define SERDES2_LNAD 3
62 +#define SERDES2_LNAE 4
63 +#define SERDES2_LNAF 5
64 +#define SERDES2_LNAG 6
65 +#define SERDES2_LNAH 7
67 enum ahci_qoriq_type {
70 @@ -56,6 +79,7 @@ enum ahci_qoriq_type {
77 struct ahci_qoriq_priv {
78 @@ -72,6 +96,7 @@ static const struct of_device_id ahci_qo
79 { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
80 { .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A},
81 { .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A},
82 + { .compatible = "fsl,lx2160a-ahci", .data = (void *)AHCI_LX2160A},
85 MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
86 @@ -156,6 +181,138 @@ static struct scsi_host_template ahci_qo
90 +void fsl_sata_errata_379364(struct ata_link *link)
92 + struct ata_port *ap = link->ap;
93 + struct ahci_host_priv *hpriv = ap->host->private_data;
94 + struct ahci_qoriq_priv *qoriq_priv = hpriv->plat_data;
95 + bool lx2160a_workaround = (qoriq_priv->type == AHCI_LX2160A);
98 + void __iomem *rcw_base = NULL;
99 + void __iomem *serdes_base = NULL;
100 + void __iomem *dev_con_base = NULL;
102 + if (!lx2160a_workaround)
105 + dev_con_base = ioremap(DEVICE_CONFIG_REG_BASE, PAGE_SIZE);
106 + if (!dev_con_base) {
107 + ata_link_err(link, "device config ioremap failed\n");
111 + val = (readl(dev_con_base + SYS_VER_REG) & GENMASK(7, 4)) >> 4;
112 + if (val != LX2160A_VER1)
116 + * Add few msec delay.
117 + * Check for corresponding serdes lane RST_DONE .
118 + * apply lane reset.
121 + serdes_base = ioremap(SERDES2_BASE, PAGE_SIZE);
122 + if (!serdes_base) {
123 + ata_link_err(link, "serdes ioremap failed\n");
127 + rcw_base = ioremap(RCWSR29_BASE, PAGE_SIZE);
129 + ata_link_err(link, "rcw ioremap failed\n");
133 + ata_msleep(link->ap, 1);
135 + val = (readl(rcw_base) & GENMASK(25, 21)) >> 21;
139 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAC)) &
140 + LN_RX_MASK) != LN_RX_RST_DONE)
141 + writel(LN_RX_RST, serdes_base +
142 + SERDES2_LNAX_RX_CR(SERDES2_LNAC));
143 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAD)) &
144 + LN_RX_MASK) != LN_RX_RST_DONE)
145 + writel(LN_RX_RST, serdes_base +
146 + SERDES2_LNAX_RX_CR(SERDES2_LNAD));
150 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
151 + LN_RX_MASK) != LN_RX_RST_DONE)
152 + writel(LN_RX_RST, serdes_base +
153 + SERDES2_LNAX_RX_CR(SERDES2_LNAG));
154 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
155 + LN_RX_MASK) != LN_RX_RST_DONE)
156 + writel(LN_RX_RST, serdes_base +
157 + SERDES2_LNAX_RX_CR(SERDES2_LNAH));
161 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAE)) &
162 + LN_RX_MASK) != LN_RX_RST_DONE)
163 + writel(LN_RX_RST, serdes_base +
164 + SERDES2_LNAX_RX_CR(SERDES2_LNAE));
165 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAF)) &
166 + LN_RX_MASK) != LN_RX_RST_DONE)
167 + writel(LN_RX_RST, serdes_base +
168 + SERDES2_LNAX_RX_CR(SERDES2_LNAF));
169 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
170 + LN_RX_MASK) != LN_RX_RST_DONE)
171 + writel(LN_RX_RST, serdes_base +
172 + SERDES2_LNAX_RX_CR(SERDES2_LNAG));
173 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
174 + LN_RX_MASK) != LN_RX_RST_DONE)
175 + writel(LN_RX_RST, serdes_base +
176 + SERDES2_LNAX_RX_CR(SERDES2_LNAH));
180 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAC)) &
181 + LN_RX_MASK) != LN_RX_RST_DONE)
182 + writel(LN_RX_RST, serdes_base +
183 + SERDES2_LNAX_RX_CR(SERDES2_LNAC));
184 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAD)) &
185 + LN_RX_MASK) != LN_RX_RST_DONE)
186 + writel(LN_RX_RST, serdes_base +
187 + SERDES2_LNAX_RX_CR(SERDES2_LNAD));
188 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAE)) &
189 + LN_RX_MASK) != LN_RX_RST_DONE)
190 + writel(LN_RX_RST, serdes_base +
191 + SERDES2_LNAX_RX_CR(SERDES2_LNAE));
192 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAF)) &
193 + LN_RX_MASK) != LN_RX_RST_DONE)
194 + writel(LN_RX_RST, serdes_base +
195 + SERDES2_LNAX_RX_CR(SERDES2_LNAF));
199 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAG)) &
200 + LN_RX_MASK) != LN_RX_RST_DONE)
201 + writel(LN_RX_RST, serdes_base +
202 + SERDES2_LNAX_RX_CR(SERDES2_LNAG));
203 + if ((readl(serdes_base + SERDES2_LNAX_RX_CBR(SERDES2_LNAH)) &
204 + LN_RX_MASK) != LN_RX_RST_DONE)
205 + writel(LN_RX_RST, serdes_base +
206 + SERDES2_LNAX_RX_CR(SERDES2_LNAH));
216 + iounmap(serdes_base);
218 + iounmap(dev_con_base);
222 static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
224 struct ahci_qoriq_priv *qpriv = hpriv->plat_data;
225 @@ -183,13 +340,18 @@ static int ahci_qoriq_phy_init(struct ah
226 writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
228 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
229 + writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2);
230 + writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3);
231 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
232 if (qpriv->is_dmacoherent)
233 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
238 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
239 + writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2);
240 + writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3);
241 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
242 if (qpriv->is_dmacoherent)
243 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
244 @@ -201,6 +363,8 @@ static int ahci_qoriq_phy_init(struct ah
245 writel(readl(qpriv->ecc_addr) | ECC_DIS_ARMV8_CH2,
247 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
248 + writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2);
249 + writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3);
250 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
251 if (qpriv->is_dmacoherent)
252 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
253 @@ -212,6 +376,8 @@ static int ahci_qoriq_phy_init(struct ah
254 writel(readl(qpriv->ecc_addr) | ECC_DIS_LS1088A,
256 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
257 + writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2);
258 + writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3);
259 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
260 if (qpriv->is_dmacoherent)
261 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
262 @@ -219,6 +385,8 @@ static int ahci_qoriq_phy_init(struct ah
265 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
266 + writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2);
267 + writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3);
268 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
269 if (qpriv->is_dmacoherent)
270 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
271 --- a/drivers/ata/libata-core.c
272 +++ b/drivers/ata/libata-core.c
274 #define CREATE_TRACE_POINTS
275 #include <trace/events/libata.h>
279 #include "libata-transport.h"
281 @@ -4119,6 +4120,8 @@ int sata_link_hardreset(struct ata_link
283 ata_msleep(link->ap, 1);
285 + fsl_sata_errata_379364(link);
287 /* bring link back */
288 rc = sata_link_resume(link, timing, deadline);