kernel: bump 4.14 to 4.14.125 (FS#2305 FS#2297)
[oweals/openwrt.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)