xref: /netbsd-src/sys/arch/arm/nxp/imx_ahcisata.c (revision 183889cba7f5563a43fd45def3b2e1a8611f85dc)
1 /*	$NetBSD: imx_ahcisata.c,v 1.4 2022/02/06 20:20:19 andvar 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.4 2022/02/06 20:20:19 andvar 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 const struct device_compatible_entry compat_data[] = {
83 	{ .compat = "fsl,imx6q-ahci" },
84 	DEVICE_COMPAT_EOL
85 };
86 
87 static int
imx_ahcisata_match(device_t parent,cfdata_t cf,void * aux)88 imx_ahcisata_match(device_t parent, cfdata_t cf, void *aux)
89 {
90 	struct fdt_attach_args * const faa = aux;
91 
92 	return of_compatible_match(faa->faa_phandle, compat_data);
93 }
94 
95 static void
imx_ahcisata_attach(device_t parent,device_t self,void * aux)96 imx_ahcisata_attach(device_t parent, device_t self, void *aux)
97 {
98 	struct imx_ahcisata_softc * const sc = device_private(self);
99 	struct fdt_attach_args * const faa = aux;
100 	const int phandle = faa->faa_phandle;
101 	bus_addr_t ahci_addr;
102 	bus_size_t ahci_size;
103 	bus_addr_t addr;
104 	bus_size_t size;
105 	char intrstr[128];
106 	int error;
107 
108 	if (fdtbus_get_reg(phandle, 0, &ahci_addr, &ahci_size) != 0) {
109 		aprint_error(": couldn't get ahci registers\n");
110 		return;
111 	}
112 
113 	if (of_getprop_uint32(phandle, "fsl,transmit-level-mV", &sc->sc_tx_level) != 0)
114 		sc->sc_tx_level = 1104;
115 	if (of_getprop_uint32(phandle, "fsl,transmit-boost-mdB", &sc->sc_tx_boost) != 0)
116 		sc->sc_tx_boost = 3330;
117 	if (of_getprop_uint32(phandle, "fsl,transmit-atten-16ths", &sc->sc_tx_atten) != 0)
118 		sc->sc_tx_atten = 9;
119 	if (of_getprop_uint32(phandle, "fsl,receive-eq-mdB", &sc->sc_rx_eq) != 0)
120 		sc->sc_rx_eq = 3000;
121 	if (of_getprop_bool(phandle, "fsl,no-spread-spectrum") == false)
122 		sc->sc_ss = 1;
123 	else
124 		sc->sc_ss = 0;
125 
126 	sc->sc_clk_sata = fdtbus_clock_get(phandle, "sata");
127 	if (sc->sc_clk_sata == NULL) {
128 		aprint_error(": couldn't get clock sata\n");
129 		return;
130 	}
131 	sc->sc_clk_sata_ref = fdtbus_clock_get(phandle, "sata_ref");
132 	if (sc->sc_clk_sata_ref == NULL) {
133 		aprint_error(": couldn't get clock sata_ref\n");
134 		return;
135 	}
136 	sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb");
137 	if (sc->sc_clk_ahb == NULL) {
138 		aprint_error(": couldn't get clock ahb\n");
139 		return;
140 	}
141 
142 	aprint_naive("\n");
143 	aprint_normal(": AHCI Controller\n");
144 
145 	aprint_debug_dev(self, "tx level %d [mV]\n", sc->sc_tx_level);
146 	aprint_debug_dev(self, "tx boost %d [mdB]\n", sc->sc_tx_boost);
147 	aprint_debug_dev(self, "tx atten %d [16ths]\n", sc->sc_tx_atten);
148 	aprint_debug_dev(self, "rx eq    %d [mdB]\n", sc->sc_rx_eq);
149 	aprint_debug_dev(self, "ss       %d\n", sc->sc_ss);
150 
151 	sc->sc_dev = self;
152 
153 	sc->sc.sc_atac.atac_dev = self;
154 	sc->sc.sc_ahci_ports = 1;
155 	sc->sc.sc_dmat = faa->faa_dmat;
156 	sc->sc.sc_ahcit = faa->faa_bst;
157 	sc->sc.sc_ahcis = ahci_size;
158 	error = bus_space_map(sc->sc.sc_ahcit, ahci_addr, ahci_size, 0,
159 	    &sc->sc.sc_ahcih);
160 	if (error) {
161 		aprint_error(": couldn't map ahci registers: %d\n", error);
162 		return;
163 	}
164 
165 	sc->sc_iot = sc->sc.sc_ahcit;
166 	sc->sc_ioh = sc->sc.sc_ahcih;
167 
168 	const int gpr_phandle = OF_finddevice("/soc/aips-bus/iomuxc-gpr");
169 	fdtbus_get_reg(gpr_phandle, 0, &addr, &size);
170 	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_gpr_ioh)) {
171 		aprint_error_dev(self, "Cannot map registers\n");
172 		return;
173 	}
174 
175 	if (imx_ahcisata_init_clocks(sc) != 0) {
176 		aprint_error_dev(self, "couldn't init clocks\n");
177 		return;
178 	}
179 
180 	if (imx_ahcisata_init(sc) != 0) {
181 		aprint_error_dev(self, "couldn't init ahci\n");
182 		return;
183 	}
184 
185 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
186 		aprint_error_dev(self, "failed to decode interrupt\n");
187 		return;
188 	}
189 
190 	sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0,
191 	    ahci_intr, &sc->sc, device_xname(self));
192 	if (sc->sc_ih == NULL) {
193 		aprint_error_dev(self, "failed to establish interrupt on %s\n",
194 		    intrstr);
195 		return;
196 	}
197 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
198 
199 	ahci_attach(&sc->sc);
200 }
201 
202 static int
imx_ahcisata_phy_ctrl(struct imx_ahcisata_softc * sc,uint32_t bitmask,int on)203 imx_ahcisata_phy_ctrl(struct imx_ahcisata_softc *sc, uint32_t bitmask, int on)
204 {
205 	uint32_t v;
206 	int timeout;
207 
208 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR);
209 	if (on)
210 		v |= bitmask;
211 	else
212 		v &= ~bitmask;
213 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, v);
214 
215 	for (timeout = 5000; timeout > 0; --timeout) {
216 		v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
217 		if (!!(v & SATA_P0PHYSR_CR_ACK) == !!on)
218 			break;
219 		delay(100);
220 	}
221 
222 	if (timeout > 0)
223 		return 0;
224 
225 	return -1;
226 }
227 
228 static int
imx_ahcisata_phy_addr(struct imx_ahcisata_softc * sc,uint32_t addr)229 imx_ahcisata_phy_addr(struct imx_ahcisata_softc *sc, uint32_t addr)
230 {
231 	delay(100);
232 
233 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, addr);
234 
235 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 1) != 0)
236 		return -1;
237 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 0) != 0)
238 		return -1;
239 
240 	return 0;
241 }
242 
243 static int
imx_ahcisata_phy_write(struct imx_ahcisata_softc * sc,uint32_t addr,uint16_t data)244 imx_ahcisata_phy_write(struct imx_ahcisata_softc *sc, uint32_t addr,
245                         uint16_t data)
246 {
247 	if (imx_ahcisata_phy_addr(sc, addr) != 0)
248 		return -1;
249 
250 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, data);
251 
252 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 1) != 0)
253 		return -1;
254 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 0) != 0)
255 		return -1;
256 
257 	if ((addr == SATA_PHY_CLOCK_RESET) && data) {
258 		/* we can't check ACK after RESET */
259 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR,
260 		    data | SATA_P0PHYCR_CR_WRITE);
261 		return 0;
262 	}
263 
264 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 1) != 0)
265 		return -1;
266 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 0) != 0)
267 		return -1;
268 
269 	return 0;
270 }
271 
272 static int
imx_ahcisata_phy_read(struct imx_ahcisata_softc * sc,uint32_t addr)273 imx_ahcisata_phy_read(struct imx_ahcisata_softc *sc, uint32_t addr)
274 {
275 	uint32_t v;
276 
277 	if (imx_ahcisata_phy_addr(sc, addr) != 0)
278 		return -1;
279 
280 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 1) != 0)
281 		return -1;
282 
283 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
284 
285 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 0) != 0)
286 		return -1;
287 
288 	return SATA_P0PHYSR_CR_DATA_OUT(v);
289 }
290 
291 const static int tx_level[] = {
292 	 937,
293 	 947,
294 	 957,
295 	 966,
296 	 976,
297 	 986,
298 	 996,
299 	1005,
300 	1015,
301 	1025,
302 	1035,
303 	1045,
304 	1054,
305 	1064,
306 	1074,
307 	1084,
308 	1094,
309 	1104,
310 	1113,
311 	1123,
312 	1133,
313 	1143,
314 	1152,
315 	1162,
316 	1172,
317 	1182,
318 	1191,
319 	1201,
320 	1211,
321 	1221,
322 	1230,
323 	1240,
324 };
325 
326 const static int tx_boots[] = {
327 	   0,
328 	 370,
329 	 740,
330 	1110,
331 	1480,
332 	1850,
333 	2220,
334 	2590,
335 	2960,
336 	3330,
337 	3700,
338 	4070,
339 	4440,
340 	4810,
341 	5280,
342 	5750,
343 };
344 
345 const static int tx_atten[] = {
346 	  16,
347 	  14,
348 	  12,
349 	  10,
350 	   9,
351 	   8,
352 };
353 
354 const static int rx_eq[] = {
355 	 500,
356 	1000,
357 	1500,
358 	2000,
359 	2500,
360 	3000,
361 	3500,
362 	4000,
363 };
364 
365 static int
imx_ahcisata_search_regval(const int * values,int count,int val)366 imx_ahcisata_search_regval(const int *values, int count, int val)
367 {
368 	for (int i = 0; i < count; i++)
369 		if (values[i] == val)
370 			return i;
371 
372 	return -1;
373 }
374 
375 static int
imx_ahcisata_init(struct imx_ahcisata_softc * sc)376 imx_ahcisata_init(struct imx_ahcisata_softc *sc)
377 {
378 	uint32_t v;
379 	int timeout;
380 	int pllstat;
381 
382 	v = bus_space_read_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13);
383 	/* clear */
384 	v &= ~(IOMUX_GPR13_SATA_PHY_8 |
385 	    IOMUX_GPR13_SATA_PHY_7 |
386 	    IOMUX_GPR13_SATA_PHY_6 |
387 	    IOMUX_GPR13_SATA_SPEED |
388 	    IOMUX_GPR13_SATA_PHY_5 |
389 	    IOMUX_GPR13_SATA_PHY_4 |
390 	    IOMUX_GPR13_SATA_PHY_3 |
391 	    IOMUX_GPR13_SATA_PHY_2 |
392 	    IOMUX_GPR13_SATA_PHY_1 |
393 	    IOMUX_GPR13_SATA_PHY_0);
394 	/* setting */
395 	struct {
396 		const int *array;
397 		int count;
398 		int val;
399 		int def_val;
400 		int mask;
401 	} gpr13_sata_phy_settings[] = {
402 		{ tx_level, __arraycount(tx_level), sc->sc_tx_level,
403 		  0x11, IOMUX_GPR13_SATA_PHY_2 },
404 		{ tx_boots, __arraycount(tx_boots), sc->sc_tx_boost,
405 		  0x09, IOMUX_GPR13_SATA_PHY_3 },
406 		{ tx_atten, __arraycount(tx_atten), sc->sc_tx_atten,
407 		  0x04, IOMUX_GPR13_SATA_PHY_4 },
408 		{ rx_eq, __arraycount(rx_eq), sc->sc_rx_eq,
409 		  0x05, IOMUX_GPR13_SATA_PHY_8 }
410 	};
411 	for (int i = 0; i < __arraycount(gpr13_sata_phy_settings); i++) {
412 		int val;
413 		val = imx_ahcisata_search_regval(
414 			gpr13_sata_phy_settings[i].array,
415 			gpr13_sata_phy_settings[i].count,
416 			gpr13_sata_phy_settings[i].val);
417 		if (val == -1)
418 			val = gpr13_sata_phy_settings[i].def_val;
419 		v |= __SHIFTIN(val, gpr13_sata_phy_settings[i].mask);
420 	}
421 	v |= __SHIFTIN(0x12, IOMUX_GPR13_SATA_PHY_7);	/* Rx SATA2m */
422 	v |= __SHIFTIN(3, IOMUX_GPR13_SATA_PHY_6);	/* Rx DPLL mode */
423 	v |= __SHIFTIN(1, IOMUX_GPR13_SATA_SPEED);	/* 3.0GHz */
424 	v |= __SHIFTIN(sc->sc_ss, IOMUX_GPR13_SATA_PHY_5);
425 	v |= __SHIFTIN(1, IOMUX_GPR13_SATA_PHY_1);	/* PLL clock enable */
426 	bus_space_write_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13, v);
427 
428 	/* phy reset */
429 	if (imx_ahcisata_phy_write(sc, SATA_PHY_CLOCK_RESET,
430 	    SATA_PHY_CLOCK_RESET_RST) < 0) {
431 		aprint_error_dev(sc->sc_dev, "cannot reset PHY\n");
432 		return -1;
433 	}
434 
435 	for (timeout = 50; timeout > 0; --timeout) {
436 		delay(100);
437 		pllstat = imx_ahcisata_phy_read(sc, SATA_PHY_LANE0_OUT_STAT);
438 		if (pllstat < 0) {
439 			aprint_error_dev(sc->sc_dev,
440 			    "cannot read LANE0 status\n");
441 			break;
442 		}
443 		if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE)
444 			break;
445 	}
446 	if (timeout <= 0)
447 		return -1;
448 
449 	/* Support Staggered Spin-up */
450 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP);
451 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, v | SATA_CAP_SSS);
452 
453 	/* Ports Implemented. must set 1 */
454 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_PI);
455 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, v | SATA_PI_PI);
456 
457 	/* set 1ms-timer = AHB clock / 1000 */
458 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS,
459 	    clk_get_rate(sc->sc_clk_ahb) / 1000);
460 
461 	return 0;
462 }
463 
464 static int
imx_ahcisata_init_clocks(struct imx_ahcisata_softc * sc)465 imx_ahcisata_init_clocks(struct imx_ahcisata_softc *sc)
466 {
467 	int error;
468 
469 	error = clk_enable(sc->sc_clk_sata);
470 	if (error) {
471 		aprint_error_dev(sc->sc_dev, "couldn't enable sata: %d\n", error);
472 		return error;
473 	}
474 	error = clk_enable(sc->sc_clk_sata_ref);
475 	if (error) {
476 		aprint_error_dev(sc->sc_dev, "couldn't enable sata-ref: %d\n", error);
477 		return error;
478 	}
479 	error = clk_enable(sc->sc_clk_ahb);
480 	if (error) {
481 		aprint_error_dev(sc->sc_dev, "couldn't enable anb: %d\n", error);
482 		return error;
483 	}
484 
485 	return 0;
486 }
487