ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 815-sata-0002-ahci-qoriq-workaround-for-errata-A-379364-on-lx2160a.patch
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
5
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
11 on Rev2 and later.
12
13 Signed-off-by: Peng Ma <peng.ma@nxp.com>
14 ---
15  drivers/ata/ahci_qoriq.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++
16  1 file changed, 144 insertions(+)
17
18 --- a/drivers/ata/ahci_qoriq.c
19 +++ b/drivers/ata/ahci_qoriq.c
20 @@ -48,6 +48,27 @@
21  #define ECC_DIS_ARMV8_CH2      0x80000000
22  #define ECC_DIS_LS1088A                0x40000000
23  
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
35 +
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
44 +
45  enum ahci_qoriq_type {
46         AHCI_LS1021A,
47         AHCI_LS1028A,
48 @@ -87,6 +108,126 @@ static const struct acpi_device_id ahci_
49  };
50  MODULE_DEVICE_TABLE(acpi, ahci_qoriq_acpi_match);
51  
52 +static void fsl_sata_errata_379364(bool select)
53 +{
54 +       int val = 0;
55 +       void __iomem *rcw_base = NULL;
56 +       void __iomem *serdes_base = NULL;
57 +       void __iomem *dev_con_base = NULL;
58 +
59 +       if (select) {
60 +               dev_con_base = ioremap(DEVICE_CONFIG_REG_BASE, PAGE_SIZE);
61 +               if (!dev_con_base)
62 +                       return;
63 +
64 +               val = (readl(dev_con_base + SYS_VER_REG) & GENMASK(7, 4)) >> 4;
65 +               if (val != LX2160A_VER1)
66 +                       goto dev_unmap;
67 +
68 +               /*
69 +                * Add few msec delay.
70 +                * Check for corresponding serdes lane RST_DONE .
71 +                * apply lane reset.
72 +                */
73 +
74 +               serdes_base = ioremap(SERDES2_BASE, PAGE_SIZE);
75 +               if (!serdes_base)
76 +                       goto dev_unmap;
77 +
78 +               rcw_base = ioremap(RCWSR29_BASE, PAGE_SIZE);
79 +               if (!rcw_base)
80 +                       goto serdes_unmap;
81 +
82 +               msleep(20);
83 +
84 +               val = (readl(rcw_base) & GENMASK(25, 21)) >> 21;
85 +
86 +               switch (val) {
87 +               case 1:
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));
96 +                       break;
97 +
98 +               case 4:
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));
107 +                       break;
108 +
109 +               case 5:
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));
126 +                       break;
127 +
128 +               case 8:
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));
145 +                       break;
146 +
147 +               case 12:
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));
156 +                       break;
157 +
158 +               default:
159 +                       break;
160 +               }
161 +       } else {
162 +               return;
163 +       }
164 +
165 +       iounmap(rcw_base);
166 +serdes_unmap:
167 +       iounmap(serdes_base);
168 +dev_unmap:
169 +       iounmap(dev_con_base);
170 +}
171 +
172  static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
173                           unsigned long deadline)
174  {
175 @@ -102,6 +243,7 @@ static int ahci_qoriq_hardreset(struct a
176         bool online;
177         int rc;
178         bool ls1021a_workaround = (qoriq_priv->type == AHCI_LS1021A);
179 +       bool lx2160a_workaround = (qoriq_priv->type == AHCI_LX2160A);
180  
181         DPRINTK("ENTER\n");
182  
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);
186  
187 +       fsl_sata_errata_379364(lx2160a_workaround);
188 +
189         rc = sata_link_hardreset(link, timing, deadline, &online,
190                                  ahci_check_ready);
191