xref: /freebsd/sys/arm/freescale/imx/imx6_ahci.c (revision 3078531de10dcae44b253a35125c949ff4235284)
1 /*-
2  * Copyright (c) 2017 Rogiel Sulzbach <rogiel@allogica.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/rman.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 
38 #include <machine/bus.h>
39 #include <dev/ofw/ofw_bus.h>
40 #include <dev/ofw/ofw_bus_subr.h>
41 
42 #include <dev/ahci/ahci.h>
43 #include <arm/freescale/imx/imx_iomuxreg.h>
44 #include <arm/freescale/imx/imx_iomuxvar.h>
45 #include <arm/freescale/imx/imx_ccmvar.h>
46 
47 #define	SATA_TIMER1MS				0x000000e0
48 
49 #define	SATA_P0PHYCR				0x00000178
50 #define	  SATA_P0PHYCR_CR_READ			  (1 << 19)
51 #define	  SATA_P0PHYCR_CR_WRITE			  (1 << 18)
52 #define	  SATA_P0PHYCR_CR_CAP_DATA		  (1 << 17)
53 #define	  SATA_P0PHYCR_CR_CAP_ADDR		  (1 << 16)
54 #define	  SATA_P0PHYCR_CR_DATA_IN(v)		  ((v) & 0xffff)
55 
56 #define	SATA_P0PHYSR				0x0000017c
57 #define	  SATA_P0PHYSR_CR_ACK			  (1 << 18)
58 #define	  SATA_P0PHYSR_CR_DATA_OUT(v)		  ((v) & 0xffff)
59 
60 /* phy registers */
61 #define	SATA_PHY_CLOCK_RESET			0x7f3f
62 #define	  SATA_PHY_CLOCK_RESET_RST		  (1 << 0)
63 
64 #define	SATA_PHY_LANE0_OUT_STAT			0x2003
65 #define	  SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE	  (1 << 1)
66 
67 static struct ofw_compat_data compat_data[] = {
68 	{"fsl,imx6q-ahci", true},
69 	{NULL,             false}
70 };
71 
72 static int
73 imx6_ahci_phy_ctrl(struct ahci_controller* sc, uint32_t bitmask, bool on)
74 {
75 	uint32_t v;
76 	int timeout;
77 	bool state;
78 
79 	v = ATA_INL(sc->r_mem, SATA_P0PHYCR);
80 	if (on) {
81 		v |= bitmask;
82 	} else {
83 		v &= ~bitmask;
84 	}
85 	ATA_OUTL(sc->r_mem, SATA_P0PHYCR, v);
86 
87 	for (timeout = 5000; timeout > 0; --timeout) {
88 		v = ATA_INL(sc->r_mem, SATA_P0PHYSR);
89 		state = (v & SATA_P0PHYSR_CR_ACK) == SATA_P0PHYSR_CR_ACK;
90 		if(state == on) {
91 			break;
92 		}
93 		DELAY(100);
94 	}
95 
96 	if (timeout > 0) {
97 		return (0);
98 	}
99 
100 	return (ETIMEDOUT);
101 }
102 
103 static int
104 imx6_ahci_phy_addr(struct ahci_controller* sc, uint32_t addr)
105 {
106 	int error;
107 
108 	DELAY(100);
109 
110 	ATA_OUTL(sc->r_mem, SATA_P0PHYCR, addr);
111 
112 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, true);
113 	if (error != 0) {
114 		device_printf(sc->dev,
115 		    "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=1\n",
116 		    __FUNCTION__);
117 		return (error);
118 	}
119 
120 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, false);
121 	if (error != 0) {
122 		device_printf(sc->dev,
123 		    "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=0\n",
124 		    __FUNCTION__);
125 		return (error);
126 	}
127 
128 	return (0);
129 }
130 
131 static int
132 imx6_ahci_phy_write(struct ahci_controller* sc, uint32_t addr,
133 		    uint16_t data)
134 {
135 	int error;
136 
137 	error = imx6_ahci_phy_addr(sc, addr);
138 	if (error != 0) {
139 		device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n",
140 		    __FUNCTION__);
141 		return (error);
142 	}
143 
144 	ATA_OUTL(sc->r_mem, SATA_P0PHYCR, data);
145 
146 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, true);
147 	if (error != 0) {
148 		device_printf(sc->dev,
149 		    "%s: error on SATA_P0PHYCR_CR_CAP_DATA=1\n", __FUNCTION__);
150 		return (error);
151 	}
152 	if (imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, false) != 0) {
153 		device_printf(sc->dev,
154 		    "%s: error on SATA_P0PHYCR_CR_CAP_DATA=0\n", __FUNCTION__);
155 		return (error);
156 	}
157 
158 	if ((addr == SATA_PHY_CLOCK_RESET) && data) {
159 		/* we can't check ACK after RESET */
160 		ATA_OUTL(sc->r_mem, SATA_P0PHYCR,
161 		    SATA_P0PHYCR_CR_DATA_IN(data) | SATA_P0PHYCR_CR_WRITE);
162 		return (0);
163 	}
164 
165 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, true);
166 	if (error != 0) {
167 		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=1\n",
168 		    __FUNCTION__);
169 		return (error);
170 	}
171 
172 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, false);
173 	if (error != 0) {
174 		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=0\n",
175 		    __FUNCTION__);
176 		return (error);
177 	}
178 
179 	return (0);
180 }
181 
182 static int
183 imx6_ahci_phy_read(struct ahci_controller* sc, uint32_t addr, uint16_t* val)
184 {
185 	int error;
186 	uint32_t v;
187 
188 	error = imx6_ahci_phy_addr(sc, addr);
189 	if (error != 0) {
190 		device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n",
191 		    __FUNCTION__);
192 		return (error);
193 	}
194 
195 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, true);
196 	if (error != 0) {
197 		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=1\n",
198 		    __FUNCTION__);
199 		return (error);
200 	}
201 
202 	v = ATA_INL(sc->r_mem, SATA_P0PHYSR);
203 
204 	error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, false);
205 	if (error != 0) {
206 		device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=0\n",
207 		    __FUNCTION__);
208 		return (error);
209 	}
210 
211 	*val = SATA_P0PHYSR_CR_DATA_OUT(v);
212 	return (0);
213 }
214 
215 static int
216 imx6_ahci_probe(device_t dev)
217 {
218 
219 	if (!ofw_bus_status_okay(dev)) {
220 		return (ENXIO);
221 	}
222 
223 	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
224 		return (ENXIO);
225 	}
226 	device_set_desc(dev, "i.MX6 Integrated AHCI controller");
227 
228 	return (BUS_PROBE_DEFAULT);
229 }
230 
231 static int
232 imx6_ahci_attach(device_t dev)
233 {
234 	struct ahci_controller* ctlr;
235 	uint16_t pllstat;
236 	uint32_t v;
237 	int error, timeout;
238 
239 	ctlr = device_get_softc(dev);
240 
241 	/* Power up the controller and phy. */
242 	error = imx6_ccm_sata_enable();
243 	if (error != 0) {
244 		device_printf(dev, "error enabling controller and phy\n");
245 		return (error);
246 	}
247 
248 	ctlr->vendorid = 0;
249 	ctlr->deviceid = 0;
250 	ctlr->subvendorid = 0;
251 	ctlr->subdeviceid = 0;
252 	ctlr->numirqs = 1;
253 	ctlr->r_rid = 0;
254 	if ((ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
255 	    &ctlr->r_rid, RF_ACTIVE)) == NULL) {
256 		return (ENXIO);
257 	}
258 
259 	v = imx_iomux_gpr_get(IOMUX_GPR13);
260 	/* Clear out existing values; these numbers are bitmasks. */
261 	v &= ~(IOMUX_GPR13_SATA_PHY_8(7) 	|
262 	       IOMUX_GPR13_SATA_PHY_7(0x1f) 	|
263 	       IOMUX_GPR13_SATA_PHY_6(7) 	|
264 	       IOMUX_GPR13_SATA_SPEED(1) 	|
265 	       IOMUX_GPR13_SATA_PHY_5(1) 	|
266 	       IOMUX_GPR13_SATA_PHY_4(7) 	|
267 	       IOMUX_GPR13_SATA_PHY_3(0xf) 	|
268 	       IOMUX_GPR13_SATA_PHY_2(0x1f) 	|
269 	       IOMUX_GPR13_SATA_PHY_1(1) 	|
270 	       IOMUX_GPR13_SATA_PHY_0(1));
271 	/* setting */
272 	v |= IOMUX_GPR13_SATA_PHY_8(5) 		|     /* Rx 3.0db */
273 	     IOMUX_GPR13_SATA_PHY_7(0x12) 	|     /* Rx SATA2m */
274 	     IOMUX_GPR13_SATA_PHY_6(3) 		|     /* Rx DPLL mode */
275 	     IOMUX_GPR13_SATA_SPEED(1) 		|     /* 3.0GHz */
276 	     IOMUX_GPR13_SATA_PHY_5(0) 		|     /* SpreadSpectram */
277 	     IOMUX_GPR13_SATA_PHY_4(4) 		|     /* Tx Attenuation 9/16 */
278 	     IOMUX_GPR13_SATA_PHY_3(0) 		|     /* Tx Boost 0db */
279 	     IOMUX_GPR13_SATA_PHY_2(0x11) 	|     /* Tx Level 1.104V */
280 	     IOMUX_GPR13_SATA_PHY_1(1);               /* PLL clock enable */
281 	imx_iomux_gpr_set(IOMUX_GPR13, v);
282 
283 	/* phy reset */
284 	error = imx6_ahci_phy_write(ctlr, SATA_PHY_CLOCK_RESET,
285 	    SATA_PHY_CLOCK_RESET_RST);
286 	if (error != 0) {
287 		device_printf(dev, "cannot reset PHY\n");
288 		goto fail;
289 	}
290 
291 	for (timeout = 50; timeout > 0; --timeout) {
292 		DELAY(100);
293 		error = imx6_ahci_phy_read(ctlr, SATA_PHY_LANE0_OUT_STAT,
294 		    &pllstat);
295 		if (error != 0) {
296 			device_printf(dev, "cannot read LANE0 status\n");
297 			goto fail;
298 		}
299 		if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE) {
300 			break;
301 		}
302 	}
303 	if (timeout <= 0) {
304 		device_printf(dev, "time out reading LANE0 status\n");
305 		error = ETIMEDOUT;
306 		goto fail;
307 	}
308 
309 	/* Support Staggered Spin-up */
310 	v = ATA_INL(ctlr->r_mem, AHCI_CAP);
311 	ATA_OUTL(ctlr->r_mem, AHCI_CAP, v | AHCI_CAP_SSS);
312 
313 	/* Ports Implemented. must set 1 */
314 	v = ATA_INL(ctlr->r_mem, AHCI_PI);
315 	ATA_OUTL(ctlr->r_mem, AHCI_PI, v | (1 << 0));
316 
317 	/* set 1ms-timer = AHB clock / 1000 */
318 	ATA_OUTL(ctlr->r_mem, SATA_TIMER1MS,
319 		 imx_ccm_ahb_hz() / 1000);
320 
321 	/*
322 	 * Note: ahci_attach will release ctlr->r_mem on errors automatically
323 	 */
324 	return (ahci_attach(dev));
325 
326 fail:
327 	bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
328 	return (error);
329 }
330 
331 static int
332 imx6_ahci_detach(device_t dev)
333 {
334 
335 	return (ahci_detach(dev));
336 }
337 
338 static device_method_t imx6_ahci_ata_methods[] = {
339 	/* device probe, attach and detach methods */
340 	DEVMETHOD(device_probe,  imx6_ahci_probe),
341 	DEVMETHOD(device_attach, imx6_ahci_attach),
342 	DEVMETHOD(device_detach, imx6_ahci_detach),
343 
344 	/* ahci bus methods */
345 	DEVMETHOD(bus_print_child,        ahci_print_child),
346 	DEVMETHOD(bus_alloc_resource,     ahci_alloc_resource),
347 	DEVMETHOD(bus_release_resource,   ahci_release_resource),
348 	DEVMETHOD(bus_setup_intr,         ahci_setup_intr),
349 	DEVMETHOD(bus_teardown_intr,      ahci_teardown_intr),
350 	DEVMETHOD(bus_child_location,	  ahci_child_location),
351 
352 	DEVMETHOD_END
353 };
354 
355 static driver_t ahci_ata_driver = {
356 	"ahci",
357 	imx6_ahci_ata_methods,
358 	sizeof(struct ahci_controller)
359 };
360 
361 DRIVER_MODULE(imx6_ahci, simplebus, ahci_ata_driver, 0, 0);
362 MODULE_DEPEND(imx6_ahci, ahci, 1, 1, 1);
363 SIMPLEBUS_PNP_INFO(compat_data)
364