imx_ahcisata.c revision 1.1 1 /* $NetBSD: imx_ahcisata.c,v 1.1 2020/12/23 14:42:38 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2019 Genetec Corporation. All rights reserved.
5 * Written by Hashimoto Kenichi for Genetec Corporation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: imx_ahcisata.c,v 1.1 2020/12/23 14:42:38 skrll Exp $");
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/intr.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38
39 #include <dev/ata/atavar.h>
40 #include <dev/ic/ahcisatavar.h>
41
42 #include <arm/nxp/imx_ahcisatareg.h>
43 #include <arm/nxp/imx6_iomuxreg.h>
44 #include <arm/nxp/imx6_ccmreg.h>
45 #include <arm/nxp/imx6_ccmvar.h>
46
47 #include <dev/fdt/fdtvar.h>
48
49 static int imx_ahcisata_match(device_t, cfdata_t, void *);
50 static void imx_ahcisata_attach(device_t, device_t, void *);
51
52 struct imx_ahcisata_softc {
53 struct ahci_softc sc;
54
55 device_t sc_dev;
56 bus_space_tag_t sc_iot;
57 bus_space_handle_t sc_ioh;
58 bus_space_handle_t sc_gpr_ioh;
59 void *sc_ih;
60
61 u_int sc_tx_level;
62 u_int sc_tx_boost;
63 u_int sc_tx_atten;
64 u_int sc_rx_eq;
65 u_int sc_ss;
66
67 struct clk *sc_clk_sata;
68 struct clk *sc_clk_sata_ref;
69 struct clk *sc_clk_ahb;
70 };
71
72 static int imx_ahcisata_init(struct imx_ahcisata_softc *);
73 static int imx_ahcisata_phy_ctrl(struct imx_ahcisata_softc *, uint32_t, int);
74 static int imx_ahcisata_phy_addr(struct imx_ahcisata_softc *, uint32_t);
75 static int imx_ahcisata_phy_write(struct imx_ahcisata_softc *, uint32_t, uint16_t);
76 static int imx_ahcisata_phy_read(struct imx_ahcisata_softc *, uint32_t);
77 static int imx_ahcisata_init_clocks(struct imx_ahcisata_softc *);
78
79 CFATTACH_DECL_NEW(imx_ahcisata, sizeof(struct imx_ahcisata_softc),
80 imx_ahcisata_match, imx_ahcisata_attach, NULL, NULL);
81
82 static int
83 imx_ahcisata_match(device_t parent, cfdata_t cf, void *aux)
84 {
85 const char * const compatible[] = { "fsl,imx6q-ahci", NULL };
86 struct fdt_attach_args * const faa = aux;
87
88 return of_match_compatible(faa->faa_phandle, compatible);
89 }
90
91 static void
92 imx_ahcisata_attach(device_t parent, device_t self, void *aux)
93 {
94 struct imx_ahcisata_softc * const sc = device_private(self);
95 struct fdt_attach_args * const faa = aux;
96 const int phandle = faa->faa_phandle;
97 bus_addr_t ahci_addr;
98 bus_size_t ahci_size;
99 bus_addr_t addr;
100 bus_size_t size;
101 char intrstr[128];
102 int error;
103
104 if (fdtbus_get_reg(phandle, 0, &ahci_addr, &ahci_size) != 0) {
105 aprint_error(": couldn't get ahci registers\n");
106 return;
107 }
108
109 if (of_getprop_uint32(phandle, "fsl,transmit-level-mV", &sc->sc_tx_level) != 0)
110 sc->sc_tx_level = 1104;
111 if (of_getprop_uint32(phandle, "fsl,transmit-boost-mdB", &sc->sc_tx_boost) != 0)
112 sc->sc_tx_boost = 3330;
113 if (of_getprop_uint32(phandle, "fsl,transmit-atten-16ths", &sc->sc_tx_atten) != 0)
114 sc->sc_tx_atten = 9;
115 if (of_getprop_uint32(phandle, "fsl,receive-eq-mdB", &sc->sc_rx_eq) != 0)
116 sc->sc_rx_eq = 3000;
117 if (of_getprop_bool(phandle, "fsl,no-spread-spectrum") == false)
118 sc->sc_ss = 1;
119 else
120 sc->sc_ss = 0;
121
122 sc->sc_clk_sata = fdtbus_clock_get(phandle, "sata");
123 if (sc->sc_clk_sata == NULL) {
124 aprint_error(": couldn't get clock sata\n");
125 return;
126 }
127 sc->sc_clk_sata_ref = fdtbus_clock_get(phandle, "sata_ref");
128 if (sc->sc_clk_sata_ref == NULL) {
129 aprint_error(": couldn't get clock sata_ref\n");
130 return;
131 }
132 sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb");
133 if (sc->sc_clk_ahb == NULL) {
134 aprint_error(": couldn't get clock ahb\n");
135 return;
136 }
137
138 aprint_naive("\n");
139 aprint_normal(": AHCI Controller\n");
140
141 aprint_debug_dev(self, "tx level %d [mV]\n", sc->sc_tx_level);
142 aprint_debug_dev(self, "tx boost %d [mdB]\n", sc->sc_tx_boost);
143 aprint_debug_dev(self, "tx atten %d [16ths]\n", sc->sc_tx_atten);
144 aprint_debug_dev(self, "rx eq %d [mdB]\n", sc->sc_rx_eq);
145 aprint_debug_dev(self, "ss %d\n", sc->sc_ss);
146
147 sc->sc_dev = self;
148
149 sc->sc.sc_atac.atac_dev = self;
150 sc->sc.sc_ahci_ports = 1;
151 sc->sc.sc_dmat = faa->faa_dmat;
152 sc->sc.sc_ahcit = faa->faa_bst;
153 sc->sc.sc_ahcis = ahci_size;
154 error = bus_space_map(sc->sc.sc_ahcit, ahci_addr, ahci_size, 0,
155 &sc->sc.sc_ahcih);
156 if (error) {
157 aprint_error(": couldn't map ahci registers: %d\n", error);
158 return;
159 }
160
161 sc->sc_iot = sc->sc.sc_ahcit;
162 sc->sc_ioh = sc->sc.sc_ahcih;
163
164 const int gpr_phandle = OF_finddevice("/soc/aips-bus/iomuxc-gpr");
165 fdtbus_get_reg(gpr_phandle, 0, &addr, &size);
166 if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_gpr_ioh)) {
167 aprint_error_dev(self, "Cannot map registers\n");
168 return;
169 }
170
171 if (imx_ahcisata_init_clocks(sc) != 0) {
172 aprint_error_dev(self, "couldn't init clocks\n");
173 return;
174 }
175
176 if (imx_ahcisata_init(sc) != 0) {
177 aprint_error_dev(self, "couldn't init ahci\n");
178 return;
179 }
180
181 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
182 aprint_error_dev(self, "failed to decode interrupt\n");
183 return;
184 }
185
186 sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, 0,
187 ahci_intr, &sc->sc);
188 if (sc->sc_ih == NULL) {
189 aprint_error_dev(self, "failed to establish interrupt on %s\n",
190 intrstr);
191 return;
192 }
193 aprint_normal_dev(self, "interrupting on %s\n", intrstr);
194
195 ahci_attach(&sc->sc);
196 }
197
198 static int
199 imx_ahcisata_phy_ctrl(struct imx_ahcisata_softc *sc, uint32_t bitmask, int on)
200 {
201 uint32_t v;
202 int timeout;
203
204 v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR);
205 if (on)
206 v |= bitmask;
207 else
208 v &= ~bitmask;
209 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, v);
210
211 for (timeout = 5000; timeout > 0; --timeout) {
212 v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
213 if (!!(v & SATA_P0PHYSR_CR_ACK) == !!on)
214 break;
215 delay(100);
216 }
217
218 if (timeout > 0)
219 return 0;
220
221 return -1;
222 }
223
224 static int
225 imx_ahcisata_phy_addr(struct imx_ahcisata_softc *sc, uint32_t addr)
226 {
227 delay(100);
228
229 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, addr);
230
231 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 1) != 0)
232 return -1;
233 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 0) != 0)
234 return -1;
235
236 return 0;
237 }
238
239 static int
240 imx_ahcisata_phy_write(struct imx_ahcisata_softc *sc, uint32_t addr,
241 uint16_t data)
242 {
243 if (imx_ahcisata_phy_addr(sc, addr) != 0)
244 return -1;
245
246 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, data);
247
248 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 1) != 0)
249 return -1;
250 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 0) != 0)
251 return -1;
252
253 if ((addr == SATA_PHY_CLOCK_RESET) && data) {
254 /* we can't check ACK after RESET */
255 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR,
256 data | SATA_P0PHYCR_CR_WRITE);
257 return 0;
258 }
259
260 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 1) != 0)
261 return -1;
262 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 0) != 0)
263 return -1;
264
265 return 0;
266 }
267
268 static int
269 imx_ahcisata_phy_read(struct imx_ahcisata_softc *sc, uint32_t addr)
270 {
271 uint32_t v;
272
273 if (imx_ahcisata_phy_addr(sc, addr) != 0)
274 return -1;
275
276 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 1) != 0)
277 return -1;
278
279 v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
280
281 if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 0) != 0)
282 return -1;
283
284 return SATA_P0PHYSR_CR_DATA_OUT(v);
285 }
286
287 const static int tx_level[] = {
288 937,
289 947,
290 957,
291 966,
292 976,
293 986,
294 996,
295 1005,
296 1015,
297 1025,
298 1035,
299 1045,
300 1054,
301 1064,
302 1074,
303 1084,
304 1094,
305 1104,
306 1113,
307 1123,
308 1133,
309 1143,
310 1152,
311 1162,
312 1172,
313 1182,
314 1191,
315 1201,
316 1211,
317 1221,
318 1230,
319 1240,
320 };
321
322 const static int tx_boots[] = {
323 0,
324 370,
325 740,
326 1110,
327 1480,
328 1850,
329 2220,
330 2590,
331 2960,
332 3330,
333 3700,
334 4070,
335 4440,
336 4810,
337 5280,
338 5750,
339 };
340
341 const static int tx_atten[] = {
342 16,
343 14,
344 12,
345 10,
346 9,
347 8,
348 };
349
350 const static int rx_eq[] = {
351 500,
352 1000,
353 1500,
354 2000,
355 2500,
356 3000,
357 3500,
358 4000,
359 };
360
361 static int
362 imx_ahcisata_search_regval(const int *values, int count, int val)
363 {
364 for (int i = 0; i < count; i++)
365 if (values[i] == val)
366 return i;
367
368 return -1;
369 }
370
371 static int
372 imx_ahcisata_init(struct imx_ahcisata_softc *sc)
373 {
374 uint32_t v;
375 int timeout;
376 int pllstat;
377
378 v = bus_space_read_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13);
379 /* clear */
380 v &= ~(IOMUX_GPR13_SATA_PHY_8 |
381 IOMUX_GPR13_SATA_PHY_7 |
382 IOMUX_GPR13_SATA_PHY_6 |
383 IOMUX_GPR13_SATA_SPEED |
384 IOMUX_GPR13_SATA_PHY_5 |
385 IOMUX_GPR13_SATA_PHY_4 |
386 IOMUX_GPR13_SATA_PHY_3 |
387 IOMUX_GPR13_SATA_PHY_2 |
388 IOMUX_GPR13_SATA_PHY_1 |
389 IOMUX_GPR13_SATA_PHY_0);
390 /* setting */
391 struct {
392 const int *array;
393 int count;
394 int val;
395 int def_val;
396 int mask;
397 } gpr13_sata_phy_settings[] = {
398 { tx_level, __arraycount(tx_level), sc->sc_tx_level,
399 0x11, IOMUX_GPR13_SATA_PHY_2 },
400 { tx_boots, __arraycount(tx_boots), sc->sc_tx_boost,
401 0x09, IOMUX_GPR13_SATA_PHY_3 },
402 { tx_atten, __arraycount(tx_atten), sc->sc_tx_atten,
403 0x04, IOMUX_GPR13_SATA_PHY_4 },
404 { rx_eq, __arraycount(rx_eq), sc->sc_rx_eq,
405 0x05, IOMUX_GPR13_SATA_PHY_8 }
406 };
407 for (int i = 0; i < __arraycount(gpr13_sata_phy_settings); i++) {
408 int val;
409 val = imx_ahcisata_search_regval(
410 gpr13_sata_phy_settings[i].array,
411 gpr13_sata_phy_settings[i].count,
412 gpr13_sata_phy_settings[i].val);
413 if (val == -1)
414 val = gpr13_sata_phy_settings[i].def_val;
415 v |= __SHIFTIN(val, gpr13_sata_phy_settings[i].mask);
416 }
417 v |= __SHIFTIN(0x12, IOMUX_GPR13_SATA_PHY_7); /* Rx SATA2m */
418 v |= __SHIFTIN(3, IOMUX_GPR13_SATA_PHY_6); /* Rx DPLL mode */
419 v |= __SHIFTIN(1, IOMUX_GPR13_SATA_SPEED); /* 3.0GHz */
420 v |= __SHIFTIN(sc->sc_ss, IOMUX_GPR13_SATA_PHY_5);
421 v |= __SHIFTIN(1, IOMUX_GPR13_SATA_PHY_1); /* PLL clock enable */
422 bus_space_write_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13, v);
423
424 /* phy reset */
425 if (imx_ahcisata_phy_write(sc, SATA_PHY_CLOCK_RESET,
426 SATA_PHY_CLOCK_RESET_RST) < 0) {
427 aprint_error_dev(sc->sc_dev, "cannot reset PHY\n");
428 return -1;
429 }
430
431 for (timeout = 50; timeout > 0; --timeout) {
432 delay(100);
433 pllstat = imx_ahcisata_phy_read(sc, SATA_PHY_LANE0_OUT_STAT);
434 if (pllstat < 0) {
435 aprint_error_dev(sc->sc_dev,
436 "cannot read LANE0 status\n");
437 break;
438 }
439 if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE)
440 break;
441 }
442 if (timeout <= 0)
443 return -1;
444
445 /* Support Staggered Spin-up */
446 v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP);
447 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, v | SATA_CAP_SSS);
448
449 /* Ports Implmented. must set 1 */
450 v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_PI);
451 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, v | SATA_PI_PI);
452
453 /* set 1ms-timer = AHB clock / 1000 */
454 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS,
455 clk_get_rate(sc->sc_clk_ahb) / 1000);
456
457 return 0;
458 }
459
460 static int
461 imx_ahcisata_init_clocks(struct imx_ahcisata_softc *sc)
462 {
463 int error;
464
465 error = clk_enable(sc->sc_clk_sata);
466 if (error) {
467 aprint_error_dev(sc->sc_dev, "couldn't enable sata: %d\n", error);
468 return error;
469 }
470 error = clk_enable(sc->sc_clk_sata_ref);
471 if (error) {
472 aprint_error_dev(sc->sc_dev, "couldn't enable sata-ref: %d\n", error);
473 return error;
474 }
475 error = clk_enable(sc->sc_clk_ahb);
476 if (error) {
477 aprint_error_dev(sc->sc_dev, "couldn't enable anb: %d\n", error);
478 return error;
479 }
480
481 return 0;
482 }
483