xref: /freebsd/sys/dev/sdhci/sdhci_acpi.c (revision 190cef3d52236565eb22e18b33e9e865ec634aa3)
1 /*-
2  * Copyright (c) 2017 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
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 ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32 #include <sys/kernel.h>
33 #include <sys/lock.h>
34 #include <sys/module.h>
35 #include <sys/mutex.h>
36 #include <sys/resource.h>
37 #include <sys/rman.h>
38 #include <sys/sysctl.h>
39 #include <sys/taskqueue.h>
40 
41 #include <machine/bus.h>
42 #include <machine/resource.h>
43 
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <dev/acpica/acpivar.h>
46 
47 #include <dev/mmc/bridge.h>
48 
49 #include <dev/sdhci/sdhci.h>
50 
51 #include "mmcbr_if.h"
52 #include "sdhci_if.h"
53 
54 static const struct sdhci_acpi_device {
55 	const char*	hid;
56 	int		uid;
57 	const char	*desc;
58 	u_int		quirks;
59 } sdhci_acpi_devices[] = {
60 	{ "80860F14",	1, "Intel Bay Trail/Braswell eMMC 4.5/4.5.1 Controller",
61 	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
62 	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
63 	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
64 	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
65 	{ "80860F14",	3, "Intel Bay Trail/Braswell SDXC Controller",
66 	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
67 	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
68 	{ "80860F16",	0, "Intel Bay Trail/Braswell SDXC Controller",
69 	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
70 	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
71 	{ "80865ACA",	0, "Intel Apollo Lake SDXC Controller",
72 	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
73 	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
74 	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
75 	{ "80865ACC",	0, "Intel Apollo Lake eMMC 5.0 Controller",
76 	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
77 	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
78 	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
79 	    SDHCI_QUIRK_MMC_DDR52 |
80 	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
81 	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
82 	{ NULL, 0, NULL, 0}
83 };
84 
85 static char *sdhci_ids[] = {
86 	"80860F14",
87 	"80860F16",
88 	"80865ACA",
89 	"80865ACC",
90 	NULL
91 };
92 
93 struct sdhci_acpi_softc {
94 	u_int		quirks;		/* Chip specific quirks */
95 	struct resource *irq_res;	/* IRQ resource */
96 	void		*intrhand;	/* Interrupt handle */
97 
98 	struct sdhci_slot slot;
99 	struct resource	*mem_res;	/* Memory resource */
100 };
101 
102 static void sdhci_acpi_intr(void *arg);
103 static int sdhci_acpi_detach(device_t dev);
104 
105 static uint8_t
106 sdhci_acpi_read_1(device_t dev, struct sdhci_slot *slot __unused,
107     bus_size_t off)
108 {
109 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
110 
111 	bus_barrier(sc->mem_res, 0, 0xFF,
112 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
113 	return bus_read_1(sc->mem_res, off);
114 }
115 
116 static void
117 sdhci_acpi_write_1(device_t dev, struct sdhci_slot *slot __unused,
118     bus_size_t off, uint8_t val)
119 {
120 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
121 
122 	bus_barrier(sc->mem_res, 0, 0xFF,
123 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
124 	bus_write_1(sc->mem_res, off, val);
125 }
126 
127 static uint16_t
128 sdhci_acpi_read_2(device_t dev, struct sdhci_slot *slot __unused,
129     bus_size_t off)
130 {
131 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
132 
133 	bus_barrier(sc->mem_res, 0, 0xFF,
134 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
135 	return bus_read_2(sc->mem_res, off);
136 }
137 
138 static void
139 sdhci_acpi_write_2(device_t dev, struct sdhci_slot *slot __unused,
140     bus_size_t off, uint16_t val)
141 {
142 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
143 
144 	bus_barrier(sc->mem_res, 0, 0xFF,
145 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
146 	bus_write_2(sc->mem_res, off, val);
147 }
148 
149 static uint32_t
150 sdhci_acpi_read_4(device_t dev, struct sdhci_slot *slot __unused,
151     bus_size_t off)
152 {
153 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
154 
155 	bus_barrier(sc->mem_res, 0, 0xFF,
156 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
157 	return bus_read_4(sc->mem_res, off);
158 }
159 
160 static void
161 sdhci_acpi_write_4(device_t dev, struct sdhci_slot *slot __unused,
162     bus_size_t off, uint32_t val)
163 {
164 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
165 
166 	bus_barrier(sc->mem_res, 0, 0xFF,
167 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
168 	bus_write_4(sc->mem_res, off, val);
169 }
170 
171 static void
172 sdhci_acpi_read_multi_4(device_t dev, struct sdhci_slot *slot __unused,
173     bus_size_t off, uint32_t *data, bus_size_t count)
174 {
175 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
176 
177 	bus_read_multi_stream_4(sc->mem_res, off, data, count);
178 }
179 
180 static void
181 sdhci_acpi_write_multi_4(device_t dev, struct sdhci_slot *slot __unused,
182     bus_size_t off, uint32_t *data, bus_size_t count)
183 {
184 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
185 
186 	bus_write_multi_stream_4(sc->mem_res, off, data, count);
187 }
188 
189 static const struct sdhci_acpi_device *
190 sdhci_acpi_find_device(device_t dev)
191 {
192 	const char *hid;
193 	int i, uid;
194 	ACPI_HANDLE handle;
195 	ACPI_STATUS status;
196 
197 	hid = ACPI_ID_PROBE(device_get_parent(dev), dev, sdhci_ids);
198 	if (hid == NULL)
199 		return (NULL);
200 
201 	handle = acpi_get_handle(dev);
202 	status = acpi_GetInteger(handle, "_UID", &uid);
203 	if (ACPI_FAILURE(status))
204 		uid = 0;
205 
206 	for (i = 0; sdhci_acpi_devices[i].hid != NULL; i++) {
207 		if (strcmp(sdhci_acpi_devices[i].hid, hid) != 0)
208 			continue;
209 		if ((sdhci_acpi_devices[i].uid != 0) &&
210 		    (sdhci_acpi_devices[i].uid != uid))
211 			continue;
212 		return (&sdhci_acpi_devices[i]);
213 	}
214 
215 	return (NULL);
216 }
217 
218 static int
219 sdhci_acpi_probe(device_t dev)
220 {
221 	const struct sdhci_acpi_device *acpi_dev;
222 
223 	acpi_dev = sdhci_acpi_find_device(dev);
224 	if (acpi_dev == NULL)
225 		return (ENXIO);
226 
227 	device_set_desc(dev, acpi_dev->desc);
228 
229 	return (BUS_PROBE_DEFAULT);
230 }
231 
232 static int
233 sdhci_acpi_attach(device_t dev)
234 {
235 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
236 	int rid, err;
237 	const struct sdhci_acpi_device *acpi_dev;
238 
239 	acpi_dev = sdhci_acpi_find_device(dev);
240 	if (acpi_dev == NULL)
241 		return (ENXIO);
242 
243 	sc->quirks = acpi_dev->quirks;
244 
245 	/* Allocate IRQ. */
246 	rid = 0;
247 	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
248 		RF_ACTIVE);
249 	if (sc->irq_res == NULL) {
250 		device_printf(dev, "can't allocate IRQ\n");
251 		return (ENOMEM);
252 	}
253 
254 	rid = 0;
255 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
256 	    &rid, RF_ACTIVE);
257 	if (sc->mem_res == NULL) {
258 		device_printf(dev, "can't allocate memory resource for slot\n");
259 		sdhci_acpi_detach(dev);
260 		return (ENOMEM);
261 	}
262 
263 	/*
264 	 * Intel Bay Trail and Braswell eMMC controllers share the same IDs,
265 	 * but while with these former DDR52 is affected by the VLI54 erratum,
266 	 * these latter require the timeout clock to be hardcoded to 1 MHz.
267 	 */
268 	if (strcmp(acpi_dev->hid, "80860F14") == 0 && acpi_dev->uid == 1 &&
269 	    SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES) == 0x446cc8b2 &&
270 	    SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES2) == 0x00000807)
271 		sc->quirks |= SDHCI_QUIRK_MMC_DDR52 |
272 		    SDHCI_QUIRK_DATA_TIMEOUT_1MHZ;
273 	sc->quirks &= ~sdhci_quirk_clear;
274 	sc->quirks |= sdhci_quirk_set;
275 	sc->slot.quirks = sc->quirks;
276 
277 	err = sdhci_init_slot(dev, &sc->slot, 0);
278 	if (err) {
279 		device_printf(dev, "failed to init slot\n");
280 		sdhci_acpi_detach(dev);
281 		return (err);
282 	}
283 
284 	/* Activate the interrupt */
285 	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
286 	    NULL, sdhci_acpi_intr, sc, &sc->intrhand);
287 	if (err) {
288 		device_printf(dev, "can't setup IRQ\n");
289 		sdhci_acpi_detach(dev);
290 		return (err);
291 	}
292 
293 	/* Process cards detection. */
294 	sdhci_start_slot(&sc->slot);
295 
296 	return (0);
297 }
298 
299 static int
300 sdhci_acpi_detach(device_t dev)
301 {
302 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
303 
304 	if (sc->intrhand)
305 		bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
306 	if (sc->irq_res)
307 		bus_release_resource(dev, SYS_RES_IRQ,
308 		    rman_get_rid(sc->irq_res), sc->irq_res);
309 
310 	if (sc->mem_res) {
311 		sdhci_cleanup_slot(&sc->slot);
312 		bus_release_resource(dev, SYS_RES_MEMORY,
313 		    rman_get_rid(sc->mem_res), sc->mem_res);
314 	}
315 
316 	return (0);
317 }
318 
319 static int
320 sdhci_acpi_shutdown(device_t dev)
321 {
322 
323 	return (0);
324 }
325 
326 static int
327 sdhci_acpi_suspend(device_t dev)
328 {
329 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
330 	int err;
331 
332 	err = bus_generic_suspend(dev);
333 	if (err)
334 		return (err);
335 	sdhci_generic_suspend(&sc->slot);
336 	return (0);
337 }
338 
339 static int
340 sdhci_acpi_resume(device_t dev)
341 {
342 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
343 	int err;
344 
345 	sdhci_generic_resume(&sc->slot);
346 	err = bus_generic_resume(dev);
347 	if (err)
348 		return (err);
349 	return (0);
350 }
351 
352 static void
353 sdhci_acpi_intr(void *arg)
354 {
355 	struct sdhci_acpi_softc *sc = (struct sdhci_acpi_softc *)arg;
356 
357 	sdhci_generic_intr(&sc->slot);
358 }
359 
360 static device_method_t sdhci_methods[] = {
361 	/* device_if */
362 	DEVMETHOD(device_probe, sdhci_acpi_probe),
363 	DEVMETHOD(device_attach, sdhci_acpi_attach),
364 	DEVMETHOD(device_detach, sdhci_acpi_detach),
365 	DEVMETHOD(device_shutdown, sdhci_acpi_shutdown),
366 	DEVMETHOD(device_suspend, sdhci_acpi_suspend),
367 	DEVMETHOD(device_resume, sdhci_acpi_resume),
368 
369 	/* Bus interface */
370 	DEVMETHOD(bus_read_ivar,	sdhci_generic_read_ivar),
371 	DEVMETHOD(bus_write_ivar,	sdhci_generic_write_ivar),
372 
373 	/* mmcbr_if */
374 	DEVMETHOD(mmcbr_update_ios,	sdhci_generic_update_ios),
375 	DEVMETHOD(mmcbr_switch_vccq,	sdhci_generic_switch_vccq),
376 	DEVMETHOD(mmcbr_tune,		sdhci_generic_tune),
377 	DEVMETHOD(mmcbr_retune,		sdhci_generic_retune),
378 	DEVMETHOD(mmcbr_request,	sdhci_generic_request),
379 	DEVMETHOD(mmcbr_get_ro,		sdhci_generic_get_ro),
380 	DEVMETHOD(mmcbr_acquire_host,   sdhci_generic_acquire_host),
381 	DEVMETHOD(mmcbr_release_host,   sdhci_generic_release_host),
382 
383 	/* SDHCI accessors */
384 	DEVMETHOD(sdhci_read_1,		sdhci_acpi_read_1),
385 	DEVMETHOD(sdhci_read_2,		sdhci_acpi_read_2),
386 	DEVMETHOD(sdhci_read_4,		sdhci_acpi_read_4),
387 	DEVMETHOD(sdhci_read_multi_4,	sdhci_acpi_read_multi_4),
388 	DEVMETHOD(sdhci_write_1,	sdhci_acpi_write_1),
389 	DEVMETHOD(sdhci_write_2,	sdhci_acpi_write_2),
390 	DEVMETHOD(sdhci_write_4,	sdhci_acpi_write_4),
391 	DEVMETHOD(sdhci_write_multi_4,	sdhci_acpi_write_multi_4),
392 	DEVMETHOD(sdhci_set_uhs_timing,	sdhci_generic_set_uhs_timing),
393 
394 	DEVMETHOD_END
395 };
396 
397 static driver_t sdhci_acpi_driver = {
398 	"sdhci_acpi",
399 	sdhci_methods,
400 	sizeof(struct sdhci_acpi_softc),
401 };
402 static devclass_t sdhci_acpi_devclass;
403 
404 DRIVER_MODULE(sdhci_acpi, acpi, sdhci_acpi_driver, sdhci_acpi_devclass, NULL,
405     NULL);
406 MODULE_DEPEND(sdhci_acpi, sdhci, 1, 1, 1);
407 
408 #ifndef MMCCAM
409 MMC_DECLARE_BRIDGE(sdhci_acpi);
410 #endif
411