779127058ac141d3b8411f66c9b3df8df7ac0e82
[openwrt/staging/adrian.git] / target / linux / layerscape / patches-4.14 / 801-sata-support-layerscape.patch
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
5
6 This is an integrated patch of sata for layerscape
7
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>
11 ---
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(+)
16
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;
21 }
22
23 +#ifdef CONFIG_AHCI_QORIQ
24 +extern void fsl_sata_errata_379364(struct ata_link *link);
25 +#else
26 +static void fsl_sata_errata_379364(struct ata_link *link)
27 +{}
28 +#endif
29 +
30 #endif /* _AHCI_H */
31 --- a/drivers/ata/ahci_qoriq.c
32 +++ b/drivers/ata/ahci_qoriq.c
33 @@ -35,6 +35,8 @@
34
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
41
42 @@ -49,6 +51,27 @@
43 #define ECC_DIS_ARMV8_CH2 0x80000000
44 #define ECC_DIS_LS1088A 0x40000000
45
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
57 +
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
66 +
67 enum ahci_qoriq_type {
68 AHCI_LS1021A,
69 AHCI_LS1043A,
70 @@ -56,6 +79,7 @@ enum ahci_qoriq_type {
71 AHCI_LS1046A,
72 AHCI_LS1088A,
73 AHCI_LS2088A,
74 + AHCI_LX2160A,
75 };
76
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},
83 {},
84 };
85 MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
86 @@ -156,6 +181,138 @@ static struct scsi_host_template ahci_qo
87 AHCI_SHT(DRV_NAME),
88 };
89
90 +void fsl_sata_errata_379364(struct ata_link *link)
91 +{
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);
96 +
97 + int val = 0;
98 + void __iomem *rcw_base = NULL;
99 + void __iomem *serdes_base = NULL;
100 + void __iomem *dev_con_base = NULL;
101 +
102 + if (!lx2160a_workaround)
103 + return;
104 + else {
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");
108 + return;
109 + }
110 +
111 + val = (readl(dev_con_base + SYS_VER_REG) & GENMASK(7, 4)) >> 4;
112 + if (val != LX2160A_VER1)
113 + goto dev_unmap;
114 +
115 + /*
116 + * Add few msec delay.
117 + * Check for corresponding serdes lane RST_DONE .
118 + * apply lane reset.
119 + */
120 +
121 + serdes_base = ioremap(SERDES2_BASE, PAGE_SIZE);
122 + if (!serdes_base) {
123 + ata_link_err(link, "serdes ioremap failed\n");
124 + goto dev_unmap;
125 + }
126 +
127 + rcw_base = ioremap(RCWSR29_BASE, PAGE_SIZE);
128 + if (!rcw_base) {
129 + ata_link_err(link, "rcw ioremap failed\n");
130 + goto serdes_unmap;
131 + }
132 +
133 + ata_msleep(link->ap, 1);
134 +
135 + val = (readl(rcw_base) & GENMASK(25, 21)) >> 21;
136 +
137 + switch (val) {
138 + case 1:
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));
147 + break;
148 +
149 + case 4:
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));
158 + break;
159 +
160 + case 5:
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));
177 + break;
178 +
179 + case 8:
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));
196 + break;
197 +
198 + case 12:
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));
207 + break;
208 +
209 + default:
210 + break;
211 + }
212 + }
213 +
214 + iounmap(rcw_base);
215 +serdes_unmap:
216 + iounmap(serdes_base);
217 +dev_unmap:
218 + iounmap(dev_con_base);
219 +}
220 +
221 +
222 static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
223 {
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,
227 qpriv->ecc_addr);
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);
234 break;
235
236 case AHCI_LS2080A:
237 + case AHCI_LX2160A:
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,
246 qpriv->ecc_addr);
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,
255 qpriv->ecc_addr);
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
263
264 case AHCI_LS2088A:
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
273 @@ -76,6 +76,7 @@
274 #define CREATE_TRACE_POINTS
275 #include <trace/events/libata.h>
276
277 +#include "ahci.h"
278 #include "libata.h"
279 #include "libata-transport.h"
280
281 @@ -4119,6 +4120,8 @@ int sata_link_hardreset(struct ata_link
282 */
283 ata_msleep(link->ap, 1);
284
285 + fsl_sata_errata_379364(link);
286 +
287 /* bring link back */
288 rc = sata_link_resume(link, timing, deadline);
289 if (rc)