sdhci_acpi.c revision 343504
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: stable/11/sys/dev/sdhci/sdhci_acpi.c 343504 2019-01-27 19:04:28Z marius $");
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#include <dev/mmc/mmcreg.h>
49
50#include <dev/sdhci/sdhci.h>
51
52#include "mmcbr_if.h"
53#include "sdhci_if.h"
54
55#define	SDHCI_AMD_RESET_DLL_REG	0x908
56
57static const struct sdhci_acpi_device {
58	const char*	hid;
59	int		uid;
60	const char	*desc;
61	u_int		quirks;
62} sdhci_acpi_devices[] = {
63	{ "80860F14",	1, "Intel Bay Trail/Braswell eMMC 4.5/4.5.1 Controller",
64	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
65	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
66	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
67	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
68	{ "80860F14",	3, "Intel Bay Trail/Braswell SDXC Controller",
69	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
70	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
71	{ "80860F16",	0, "Intel Bay Trail/Braswell SDXC Controller",
72	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
73	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
74	{ "80865ACA",	0, "Intel Apollo Lake SDXC Controller",
75	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
76	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
77	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
78	{ "80865ACC",	0, "Intel Apollo Lake eMMC 5.0 Controller",
79	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
80	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
81	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
82	    SDHCI_QUIRK_MMC_DDR52 |
83	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
84	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
85	{ "AMDI0040",	0, "AMD eMMC 5.0 Controller",
86	    SDHCI_QUIRK_32BIT_DMA_SIZE |
87	    SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 },
88	{ NULL, 0, NULL, 0}
89};
90
91static char *sdhci_ids[] = {
92	"80860F14",
93	"80860F16",
94	"80865ACA",
95	"80865ACC",
96	"AMDI0040",
97	NULL
98};
99
100struct sdhci_acpi_softc {
101	struct sdhci_slot slot;
102	struct resource	*mem_res;	/* Memory resource */
103	struct resource *irq_res;	/* IRQ resource */
104	void		*intrhand;	/* Interrupt handle */
105	const struct sdhci_acpi_device *acpi_dev;
106};
107
108static void sdhci_acpi_intr(void *arg);
109static int sdhci_acpi_detach(device_t dev);
110
111static uint8_t
112sdhci_acpi_read_1(device_t dev, struct sdhci_slot *slot __unused,
113    bus_size_t off)
114{
115	struct sdhci_acpi_softc *sc = device_get_softc(dev);
116
117	bus_barrier(sc->mem_res, 0, 0xFF,
118	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
119	return bus_read_1(sc->mem_res, off);
120}
121
122static void
123sdhci_acpi_write_1(device_t dev, struct sdhci_slot *slot __unused,
124    bus_size_t off, uint8_t val)
125{
126	struct sdhci_acpi_softc *sc = device_get_softc(dev);
127
128	bus_barrier(sc->mem_res, 0, 0xFF,
129	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
130	bus_write_1(sc->mem_res, off, val);
131}
132
133static uint16_t
134sdhci_acpi_read_2(device_t dev, struct sdhci_slot *slot __unused,
135    bus_size_t off)
136{
137	struct sdhci_acpi_softc *sc = device_get_softc(dev);
138
139	bus_barrier(sc->mem_res, 0, 0xFF,
140	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
141	return bus_read_2(sc->mem_res, off);
142}
143
144static void
145sdhci_acpi_write_2(device_t dev, struct sdhci_slot *slot __unused,
146    bus_size_t off, uint16_t val)
147{
148	struct sdhci_acpi_softc *sc = device_get_softc(dev);
149
150	bus_barrier(sc->mem_res, 0, 0xFF,
151	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
152	bus_write_2(sc->mem_res, off, val);
153}
154
155static uint32_t
156sdhci_acpi_read_4(device_t dev, struct sdhci_slot *slot __unused,
157    bus_size_t off)
158{
159	struct sdhci_acpi_softc *sc = device_get_softc(dev);
160
161	bus_barrier(sc->mem_res, 0, 0xFF,
162	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
163	return bus_read_4(sc->mem_res, off);
164}
165
166static void
167sdhci_acpi_write_4(device_t dev, struct sdhci_slot *slot __unused,
168    bus_size_t off, uint32_t val)
169{
170	struct sdhci_acpi_softc *sc = device_get_softc(dev);
171
172	bus_barrier(sc->mem_res, 0, 0xFF,
173	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
174	bus_write_4(sc->mem_res, off, val);
175}
176
177static void
178sdhci_acpi_read_multi_4(device_t dev, struct sdhci_slot *slot __unused,
179    bus_size_t off, uint32_t *data, bus_size_t count)
180{
181	struct sdhci_acpi_softc *sc = device_get_softc(dev);
182
183	bus_read_multi_stream_4(sc->mem_res, off, data, count);
184}
185
186static void
187sdhci_acpi_write_multi_4(device_t dev, struct sdhci_slot *slot __unused,
188    bus_size_t off, uint32_t *data, bus_size_t count)
189{
190	struct sdhci_acpi_softc *sc = device_get_softc(dev);
191
192	bus_write_multi_stream_4(sc->mem_res, off, data, count);
193}
194
195static void
196sdhci_acpi_set_uhs_timing(device_t dev, struct sdhci_slot *slot)
197{
198	const struct sdhci_acpi_softc *sc;
199	const struct sdhci_acpi_device *acpi_dev;
200	const struct mmc_ios *ios;
201	device_t bus;
202	uint16_t old_timing;
203	enum mmc_bus_timing timing;
204
205	bus = slot->bus;
206	old_timing = SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2);
207	old_timing &= SDHCI_CTRL2_UHS_MASK;
208	sdhci_generic_set_uhs_timing(dev, slot);
209
210	sc = device_get_softc(dev);
211	acpi_dev = sc->acpi_dev;
212	/*
213	 * AMDI0040 controllers require SDHCI_CTRL2_SAMPLING_CLOCK to be
214	 * disabled when switching from HS200 to high speed and to always
215	 * be turned on again when tuning for HS400.  In the later case,
216	 * an AMD-specific DLL reset additionally is needed.
217	 */
218	if (strcmp(acpi_dev->hid, "AMDI0040") == 0 && acpi_dev->uid == 0) {
219		ios = &slot->host.ios;
220		timing = ios->timing;
221		if (old_timing == SDHCI_CTRL2_UHS_SDR104 &&
222		    timing == bus_timing_hs)
223			SDHCI_WRITE_2(bus, slot, SDHCI_HOST_CONTROL2,
224			    SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2) &
225			    ~SDHCI_CTRL2_SAMPLING_CLOCK);
226		if (ios->clock > SD_SDR50_MAX &&
227		    old_timing != SDHCI_CTRL2_MMC_HS400 &&
228		    timing == bus_timing_mmc_hs400) {
229			SDHCI_WRITE_2(bus, slot, SDHCI_HOST_CONTROL2,
230			    SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2) |
231			    SDHCI_CTRL2_SAMPLING_CLOCK);
232			SDHCI_WRITE_4(bus, slot, SDHCI_AMD_RESET_DLL_REG,
233			    0x40003210);
234			DELAY(20);
235			SDHCI_WRITE_4(bus, slot, SDHCI_AMD_RESET_DLL_REG,
236			    0x40033210);
237		}
238	}
239}
240
241static const struct sdhci_acpi_device *
242sdhci_acpi_find_device(device_t dev)
243{
244	const char *hid;
245	int i, uid;
246	ACPI_HANDLE handle;
247	ACPI_STATUS status;
248
249	hid = ACPI_ID_PROBE(device_get_parent(dev), dev, sdhci_ids);
250	if (hid == NULL)
251		return (NULL);
252
253	handle = acpi_get_handle(dev);
254	status = acpi_GetInteger(handle, "_UID", &uid);
255	if (ACPI_FAILURE(status))
256		uid = 0;
257
258	for (i = 0; sdhci_acpi_devices[i].hid != NULL; i++) {
259		if (strcmp(sdhci_acpi_devices[i].hid, hid) != 0)
260			continue;
261		if ((sdhci_acpi_devices[i].uid != 0) &&
262		    (sdhci_acpi_devices[i].uid != uid))
263			continue;
264		return (&sdhci_acpi_devices[i]);
265	}
266
267	return (NULL);
268}
269
270static int
271sdhci_acpi_probe(device_t dev)
272{
273	const struct sdhci_acpi_device *acpi_dev;
274
275	acpi_dev = sdhci_acpi_find_device(dev);
276	if (acpi_dev == NULL)
277		return (ENXIO);
278
279	device_set_desc(dev, acpi_dev->desc);
280
281	return (BUS_PROBE_DEFAULT);
282}
283
284static int
285sdhci_acpi_attach(device_t dev)
286{
287	struct sdhci_acpi_softc *sc = device_get_softc(dev);
288	int rid, err;
289	u_int quirks;
290	const struct sdhci_acpi_device *acpi_dev;
291
292	acpi_dev = sdhci_acpi_find_device(dev);
293	if (acpi_dev == NULL)
294		return (ENXIO);
295
296	sc->acpi_dev = acpi_dev;
297	quirks = acpi_dev->quirks;
298
299	/* Allocate IRQ. */
300	rid = 0;
301	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
302		RF_ACTIVE);
303	if (sc->irq_res == NULL) {
304		device_printf(dev, "can't allocate IRQ\n");
305		return (ENOMEM);
306	}
307
308	rid = 0;
309	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
310	    &rid, RF_ACTIVE);
311	if (sc->mem_res == NULL) {
312		device_printf(dev, "can't allocate memory resource for slot\n");
313		sdhci_acpi_detach(dev);
314		return (ENOMEM);
315	}
316
317	/*
318	 * Intel Bay Trail and Braswell eMMC controllers share the same IDs,
319	 * but while with these former DDR52 is affected by the VLI54 erratum,
320	 * these latter require the timeout clock to be hardcoded to 1 MHz.
321	 */
322	if (strcmp(acpi_dev->hid, "80860F14") == 0 && acpi_dev->uid == 1 &&
323	    SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES) == 0x446cc8b2 &&
324	    SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES2) == 0x00000807)
325		quirks |= SDHCI_QUIRK_MMC_DDR52 | SDHCI_QUIRK_DATA_TIMEOUT_1MHZ;
326	quirks &= ~sdhci_quirk_clear;
327	quirks |= sdhci_quirk_set;
328	sc->slot.quirks = quirks;
329
330	err = sdhci_init_slot(dev, &sc->slot, 0);
331	if (err) {
332		device_printf(dev, "failed to init slot\n");
333		sdhci_acpi_detach(dev);
334		return (err);
335	}
336
337	/* Activate the interrupt */
338	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
339	    NULL, sdhci_acpi_intr, sc, &sc->intrhand);
340	if (err) {
341		device_printf(dev, "can't setup IRQ\n");
342		sdhci_acpi_detach(dev);
343		return (err);
344	}
345
346	/* Process cards detection. */
347	sdhci_start_slot(&sc->slot);
348
349	return (0);
350}
351
352static int
353sdhci_acpi_detach(device_t dev)
354{
355	struct sdhci_acpi_softc *sc = device_get_softc(dev);
356
357	if (sc->intrhand)
358		bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
359	if (sc->irq_res)
360		bus_release_resource(dev, SYS_RES_IRQ,
361		    rman_get_rid(sc->irq_res), sc->irq_res);
362
363	if (sc->mem_res) {
364		sdhci_cleanup_slot(&sc->slot);
365		bus_release_resource(dev, SYS_RES_MEMORY,
366		    rman_get_rid(sc->mem_res), sc->mem_res);
367	}
368
369	return (0);
370}
371
372static int
373sdhci_acpi_shutdown(device_t dev)
374{
375
376	return (0);
377}
378
379static int
380sdhci_acpi_suspend(device_t dev)
381{
382	struct sdhci_acpi_softc *sc = device_get_softc(dev);
383	int err;
384
385	err = bus_generic_suspend(dev);
386	if (err)
387		return (err);
388	sdhci_generic_suspend(&sc->slot);
389	return (0);
390}
391
392static int
393sdhci_acpi_resume(device_t dev)
394{
395	struct sdhci_acpi_softc *sc = device_get_softc(dev);
396	int err;
397
398	sdhci_generic_resume(&sc->slot);
399	err = bus_generic_resume(dev);
400	if (err)
401		return (err);
402	return (0);
403}
404
405static void
406sdhci_acpi_intr(void *arg)
407{
408	struct sdhci_acpi_softc *sc = (struct sdhci_acpi_softc *)arg;
409
410	sdhci_generic_intr(&sc->slot);
411}
412
413static device_method_t sdhci_methods[] = {
414	/* device_if */
415	DEVMETHOD(device_probe, sdhci_acpi_probe),
416	DEVMETHOD(device_attach, sdhci_acpi_attach),
417	DEVMETHOD(device_detach, sdhci_acpi_detach),
418	DEVMETHOD(device_shutdown, sdhci_acpi_shutdown),
419	DEVMETHOD(device_suspend, sdhci_acpi_suspend),
420	DEVMETHOD(device_resume, sdhci_acpi_resume),
421
422	/* Bus interface */
423	DEVMETHOD(bus_read_ivar,	sdhci_generic_read_ivar),
424	DEVMETHOD(bus_write_ivar,	sdhci_generic_write_ivar),
425
426	/* mmcbr_if */
427	DEVMETHOD(mmcbr_update_ios,	sdhci_generic_update_ios),
428	DEVMETHOD(mmcbr_switch_vccq,	sdhci_generic_switch_vccq),
429	DEVMETHOD(mmcbr_tune,		sdhci_generic_tune),
430	DEVMETHOD(mmcbr_retune,		sdhci_generic_retune),
431	DEVMETHOD(mmcbr_request,	sdhci_generic_request),
432	DEVMETHOD(mmcbr_get_ro,		sdhci_generic_get_ro),
433	DEVMETHOD(mmcbr_acquire_host,   sdhci_generic_acquire_host),
434	DEVMETHOD(mmcbr_release_host,   sdhci_generic_release_host),
435
436	/* SDHCI accessors */
437	DEVMETHOD(sdhci_read_1,		sdhci_acpi_read_1),
438	DEVMETHOD(sdhci_read_2,		sdhci_acpi_read_2),
439	DEVMETHOD(sdhci_read_4,		sdhci_acpi_read_4),
440	DEVMETHOD(sdhci_read_multi_4,	sdhci_acpi_read_multi_4),
441	DEVMETHOD(sdhci_write_1,	sdhci_acpi_write_1),
442	DEVMETHOD(sdhci_write_2,	sdhci_acpi_write_2),
443	DEVMETHOD(sdhci_write_4,	sdhci_acpi_write_4),
444	DEVMETHOD(sdhci_write_multi_4,	sdhci_acpi_write_multi_4),
445	DEVMETHOD(sdhci_set_uhs_timing,	sdhci_acpi_set_uhs_timing),
446
447	DEVMETHOD_END
448};
449
450static driver_t sdhci_acpi_driver = {
451	"sdhci_acpi",
452	sdhci_methods,
453	sizeof(struct sdhci_acpi_softc),
454};
455static devclass_t sdhci_acpi_devclass;
456
457DRIVER_MODULE(sdhci_acpi, acpi, sdhci_acpi_driver, sdhci_acpi_devclass, NULL,
458    NULL);
459SDHCI_DEPEND(sdhci_acpi);
460MMC_DECLARE_BRIDGE(sdhci_acpi);
461