xref: /dragonfly/sys/dev/disk/sdhci/sdhci_acpi.c (revision df21e16d)
121f9f90cSImre Vadász /*-
221f9f90cSImre Vadász  * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org>
321f9f90cSImre Vadász  * All rights reserved.
421f9f90cSImre Vadász  *
521f9f90cSImre Vadász  * Redistribution and use in source and binary forms, with or without
621f9f90cSImre Vadász  * modification, are permitted provided that the following conditions
721f9f90cSImre Vadász  * are met:
821f9f90cSImre Vadász  * 1. Redistributions of source code must retain the above copyright
921f9f90cSImre Vadász  *    notice, this list of conditions and the following disclaimer.
1021f9f90cSImre Vadász  * 2. Redistributions in binary form must reproduce the above copyright
1121f9f90cSImre Vadász  *    notice, this list of conditions and the following disclaimer in the
1221f9f90cSImre Vadász  *    documentation and/or other materials provided with the distribution.
1321f9f90cSImre Vadász  *
1421f9f90cSImre Vadász  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1521f9f90cSImre Vadász  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1621f9f90cSImre Vadász  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1721f9f90cSImre Vadász  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1821f9f90cSImre Vadász  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1921f9f90cSImre Vadász  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2021f9f90cSImre Vadász  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2121f9f90cSImre Vadász  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2221f9f90cSImre Vadász  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2321f9f90cSImre Vadász  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2421f9f90cSImre Vadász  */
2521f9f90cSImre Vadász 
2621f9f90cSImre Vadász #include <sys/param.h>
2721f9f90cSImre Vadász #include <sys/systm.h>
2821f9f90cSImre Vadász #include <sys/bus.h>
2921f9f90cSImre Vadász #include <sys/kernel.h>
3021f9f90cSImre Vadász #include <sys/module.h>
3121f9f90cSImre Vadász #include <sys/resource.h>
3221f9f90cSImre Vadász #include <sys/rman.h>
3321f9f90cSImre Vadász #include <sys/taskqueue.h>
3421f9f90cSImre Vadász 
3521f9f90cSImre Vadász #include "acpi.h"
3621f9f90cSImre Vadász #include "opt_acpi.h"
3721f9f90cSImre Vadász #include <dev/acpica/acpivar.h>
3821f9f90cSImre Vadász 
3921f9f90cSImre Vadász #include <bus/pci/pcivar.h>
4021f9f90cSImre Vadász 
4121f9f90cSImre Vadász #include <bus/mmc/bridge.h>
4221f9f90cSImre Vadász 
434d3ae590SImre Vadász #include <dev/disk/sdhci/sdhci.h>
444d3ae590SImre Vadász 
4521f9f90cSImre Vadász #include "mmcbr_if.h"
4621f9f90cSImre Vadász #include "sdhci_if.h"
4721f9f90cSImre Vadász 
4821f9f90cSImre Vadász ACPI_MODULE_NAME("sdhci_acpi");
4921f9f90cSImre Vadász 
5021f9f90cSImre Vadász struct sdhci_acpi_softc {
5121f9f90cSImre Vadász 	device_t	dev;		/* Controller device */
5221f9f90cSImre Vadász 	ACPI_HANDLE	handle;
5321f9f90cSImre Vadász 	struct resource *irq_res;	/* IRQ resource */
5421f9f90cSImre Vadász 	void 		*intrhand;	/* Interrupt handle */
5521f9f90cSImre Vadász 
5621f9f90cSImre Vadász 	struct sdhci_slot slot;
5721f9f90cSImre Vadász 	struct resource	*mem_res;	/* Memory resource */
5821f9f90cSImre Vadász };
5921f9f90cSImre Vadász 
6021f9f90cSImre Vadász static uint8_t
sdhci_acpi_read_1(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off)6170a02aadSImre Vadász sdhci_acpi_read_1(device_t dev, struct sdhci_slot *slot __unused,
6270a02aadSImre Vadász     bus_size_t off)
6321f9f90cSImre Vadász {
6421f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
6521f9f90cSImre Vadász 
6621f9f90cSImre Vadász 	bus_barrier(sc->mem_res, 0, 0xFF,
6721f9f90cSImre Vadász 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
6821f9f90cSImre Vadász 	return bus_read_1(sc->mem_res, off);
6921f9f90cSImre Vadász }
7021f9f90cSImre Vadász 
7121f9f90cSImre Vadász static void
sdhci_acpi_write_1(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off,uint8_t val)7270a02aadSImre Vadász sdhci_acpi_write_1(device_t dev, struct sdhci_slot *slot __unused,
7370a02aadSImre Vadász     bus_size_t off, uint8_t val)
7421f9f90cSImre Vadász {
7521f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
7621f9f90cSImre Vadász 
7721f9f90cSImre Vadász 	bus_barrier(sc->mem_res, 0, 0xFF,
7821f9f90cSImre Vadász 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
7921f9f90cSImre Vadász 	bus_write_1(sc->mem_res, off, val);
8021f9f90cSImre Vadász }
8121f9f90cSImre Vadász 
8221f9f90cSImre Vadász static uint16_t
sdhci_acpi_read_2(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off)8370a02aadSImre Vadász sdhci_acpi_read_2(device_t dev, struct sdhci_slot *slot __unused,
8470a02aadSImre Vadász     bus_size_t off)
8521f9f90cSImre Vadász {
8621f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
8721f9f90cSImre Vadász 
8821f9f90cSImre Vadász 	bus_barrier(sc->mem_res, 0, 0xFF,
8921f9f90cSImre Vadász 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
9021f9f90cSImre Vadász 	return bus_read_2(sc->mem_res, off);
9121f9f90cSImre Vadász }
9221f9f90cSImre Vadász 
9321f9f90cSImre Vadász static void
sdhci_acpi_write_2(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off,uint16_t val)9470a02aadSImre Vadász sdhci_acpi_write_2(device_t dev, struct sdhci_slot *slot __unused,
9570a02aadSImre Vadász     bus_size_t off, uint16_t val)
9621f9f90cSImre Vadász {
9721f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
9821f9f90cSImre Vadász 
9921f9f90cSImre Vadász 	bus_barrier(sc->mem_res, 0, 0xFF,
10021f9f90cSImre Vadász 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
10121f9f90cSImre Vadász 	bus_write_2(sc->mem_res, off, val);
10221f9f90cSImre Vadász }
10321f9f90cSImre Vadász 
10421f9f90cSImre Vadász static uint32_t
sdhci_acpi_read_4(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off)10570a02aadSImre Vadász sdhci_acpi_read_4(device_t dev, struct sdhci_slot *slot __unused,
10670a02aadSImre Vadász     bus_size_t off)
10721f9f90cSImre Vadász {
10821f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
10921f9f90cSImre Vadász 
11021f9f90cSImre Vadász 	bus_barrier(sc->mem_res, 0, 0xFF,
11121f9f90cSImre Vadász 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
11221f9f90cSImre Vadász 	return bus_read_4(sc->mem_res, off);
11321f9f90cSImre Vadász }
11421f9f90cSImre Vadász 
11521f9f90cSImre Vadász static void
sdhci_acpi_write_4(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off,uint32_t val)11670a02aadSImre Vadász sdhci_acpi_write_4(device_t dev, struct sdhci_slot *slot __unused,
11770a02aadSImre Vadász     bus_size_t off, uint32_t val)
11821f9f90cSImre Vadász {
11921f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
12021f9f90cSImre Vadász 
12121f9f90cSImre Vadász 	bus_barrier(sc->mem_res, 0, 0xFF,
12221f9f90cSImre Vadász 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
12321f9f90cSImre Vadász 	bus_write_4(sc->mem_res, off, val);
12421f9f90cSImre Vadász }
12521f9f90cSImre Vadász 
12621f9f90cSImre Vadász static void
sdhci_acpi_read_multi_4(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off,uint32_t * data,bus_size_t count)12770a02aadSImre Vadász sdhci_acpi_read_multi_4(device_t dev, struct sdhci_slot *slot __unused,
12821f9f90cSImre Vadász     bus_size_t off, uint32_t *data, bus_size_t count)
12921f9f90cSImre Vadász {
13021f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
13121f9f90cSImre Vadász 
13221f9f90cSImre Vadász 	bus_read_multi_stream_4(sc->mem_res, off, data, count);
13321f9f90cSImre Vadász }
13421f9f90cSImre Vadász 
13521f9f90cSImre Vadász static void
sdhci_acpi_write_multi_4(device_t dev,struct sdhci_slot * slot __unused,bus_size_t off,uint32_t * data,bus_size_t count)13670a02aadSImre Vadász sdhci_acpi_write_multi_4(device_t dev, struct sdhci_slot *slot __unused,
13721f9f90cSImre Vadász     bus_size_t off, uint32_t *data, bus_size_t count)
13821f9f90cSImre Vadász {
13921f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
14021f9f90cSImre Vadász 
14121f9f90cSImre Vadász 	bus_write_multi_stream_4(sc->mem_res, off, data, count);
14221f9f90cSImre Vadász }
14321f9f90cSImre Vadász 
14421f9f90cSImre Vadász static void sdhci_acpi_intr(void *arg);
14521f9f90cSImre Vadász 
1467ba10b88SImre Vadász #define INTEL_ATOM_QUIRKS_SDCARD					\
1477ba10b88SImre Vadász 	SDHCI_QUIRK_WHITELIST_ADMA2 | SDHCI_QUIRK_WAIT_WHILE_BUSY
1487ba10b88SImre Vadász #define INTEL_ATOM_QUIRKS_EMMC						\
1497ba10b88SImre Vadász 	INTEL_ATOM_QUIRKS_SDCARD | SDHCI_QUIRK_MMC_DDR52 |		\
1507ba10b88SImre Vadász 	SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | SDHCI_QUIRK_PRESET_VALUE_BROKEN
1517ba10b88SImre Vadász 
15285ccd313SImre Vadász static struct {
15385ccd313SImre Vadász 	char *hid;
1547ba10b88SImre Vadász 	char *uid;
15585ccd313SImre Vadász 	u_int quirks;
15685ccd313SImre Vadász } sdhci_devices[] = {
1577ba10b88SImre Vadász 	/* The Intel Atom integrated controllers work fine with ADMA2. */
1587ba10b88SImre Vadász 	/* Bay Trail / Braswell */
1597ba10b88SImre Vadász 	{"80860F14", "1", INTEL_ATOM_QUIRKS_EMMC},
1607ba10b88SImre Vadász 	{"80860F14", "3", INTEL_ATOM_QUIRKS_SDCARD},
1617ba10b88SImre Vadász 	{"80860F16", NULL, INTEL_ATOM_QUIRKS_SDCARD},
1627ba10b88SImre Vadász 	/* Apollo Lake */
163ffb8e567SImre Vadász 	{"80865ACA", NULL,
164ffb8e567SImre Vadász 	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
165ffb8e567SImre Vadász 	    INTEL_ATOM_QUIRKS_SDCARD},
166ffb8e567SImre Vadász 	{"80865ACC", NULL,
167ffb8e567SImre Vadász 	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
168ffb8e567SImre Vadász 	    INTEL_ATOM_QUIRKS_EMMC},
16985ccd313SImre Vadász };
17085ccd313SImre Vadász 
17185ccd313SImre Vadász static char *sdhci_ids[] = {
17285ccd313SImre Vadász 	"80860F14",
17385ccd313SImre Vadász 	"80860F16",
1747ba10b88SImre Vadász 	"80865ACA",
1757ba10b88SImre Vadász 	"80865ACC",
17685ccd313SImre Vadász 	NULL
17785ccd313SImre Vadász };
17885ccd313SImre Vadász 
17921f9f90cSImre Vadász static int
sdhci_acpi_probe(device_t dev)18021f9f90cSImre Vadász sdhci_acpi_probe(device_t dev)
18121f9f90cSImre Vadász {
18285ccd313SImre Vadász 	if (acpi_disabled("sdhci"))
18385ccd313SImre Vadász 		return (ENXIO);
18421f9f90cSImre Vadász 
18585ccd313SImre Vadász 	if (ACPI_ID_PROBE(device_get_parent(dev), dev, sdhci_ids) == NULL)
18621f9f90cSImre Vadász 		return (ENXIO);
18721f9f90cSImre Vadász 
18821f9f90cSImre Vadász 	device_set_desc(dev, "SDHCI controller");
18921f9f90cSImre Vadász 	return (0);
19021f9f90cSImre Vadász }
19121f9f90cSImre Vadász 
19221f9f90cSImre Vadász static int
sdhci_acpi_attach(device_t dev)19321f9f90cSImre Vadász sdhci_acpi_attach(device_t dev)
19421f9f90cSImre Vadász {
19521f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
19685ccd313SImre Vadász 	char *id;
19785ccd313SImre Vadász 	int err, i, rid, quirks;
19885ccd313SImre Vadász 
19985ccd313SImre Vadász 	id = ACPI_ID_PROBE(device_get_parent(dev), dev, sdhci_ids);
20085ccd313SImre Vadász 	if (id == NULL)
20185ccd313SImre Vadász 		return (ENXIO);
20221f9f90cSImre Vadász 
20321f9f90cSImre Vadász 	sc->dev = dev;
20421f9f90cSImre Vadász 	sc->handle = acpi_get_handle(dev);
20521f9f90cSImre Vadász 
20685ccd313SImre Vadász 	quirks = 0;
20785ccd313SImre Vadász 	for (i = 0; i < NELEM(sdhci_devices); i++) {
2087ba10b88SImre Vadász 		if (strcmp(sdhci_devices[i].hid, id) == 0 &&
2097ba10b88SImre Vadász 		    (sdhci_devices[i].uid == NULL ||
2107ba10b88SImre Vadász 		     acpi_MatchUid(sc->handle, sdhci_devices[i].uid))) {
21185ccd313SImre Vadász 			quirks = sdhci_devices[i].quirks;
21285ccd313SImre Vadász 			break;
21385ccd313SImre Vadász 		}
21485ccd313SImre Vadász 	}
2157ba10b88SImre Vadász 	quirks &= ~sdhci_quirk_clear;
2167ba10b88SImre Vadász 	quirks |= sdhci_quirk_set;
21785ccd313SImre Vadász 
21821f9f90cSImre Vadász 	/* Allocate IRQ. */
21921f9f90cSImre Vadász 	rid = 0;
22021f9f90cSImre Vadász 	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
22121f9f90cSImre Vadász 		RF_SHAREABLE);
22221f9f90cSImre Vadász 	if (sc->irq_res == NULL) {
22321f9f90cSImre Vadász 		device_printf(dev, "Can't allocate IRQ\n");
22421f9f90cSImre Vadász 		err = ENOMEM;
22521f9f90cSImre Vadász 		goto error;
22621f9f90cSImre Vadász 	}
22721f9f90cSImre Vadász 
22821f9f90cSImre Vadász 	/* Allocate memory. */
22921f9f90cSImre Vadász 	rid = 0;
23021f9f90cSImre Vadász 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
23121f9f90cSImre Vadász 	    RF_ACTIVE);
23221f9f90cSImre Vadász 	if (sc->mem_res == NULL) {
23321f9f90cSImre Vadász 		device_printf(dev, "Can't allocate memory for slot %d\n", 0);
23421f9f90cSImre Vadász 		err = ENOMEM;
23521f9f90cSImre Vadász 		goto error;
23621f9f90cSImre Vadász 	}
23721f9f90cSImre Vadász 
23821f9f90cSImre Vadász 	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
23985ccd313SImre Vadász 
24085ccd313SImre Vadász 	sc->slot.quirks = quirks;
24121f9f90cSImre Vadász 	if (sdhci_init_slot(dev, &sc->slot, 0) != 0) {
24221f9f90cSImre Vadász 		device_printf(dev, "sdhci initialization failed\n");
24321f9f90cSImre Vadász 		pci_set_powerstate(dev, PCI_POWERSTATE_D3);
24421f9f90cSImre Vadász 		err = ENXIO;
24521f9f90cSImre Vadász 		goto error;
24621f9f90cSImre Vadász 	}
24721f9f90cSImre Vadász 
24821f9f90cSImre Vadász 	device_printf(dev, "%d slot(s) allocated\n", 1);
24921f9f90cSImre Vadász 	/* Activate the interrupt */
25021f9f90cSImre Vadász 	err = bus_setup_intr(dev, sc->irq_res, INTR_MPSAFE,
25121f9f90cSImre Vadász 	    sdhci_acpi_intr, sc, &sc->intrhand, NULL);
25221f9f90cSImre Vadász 	if (err)
25321f9f90cSImre Vadász 		device_printf(dev, "Can't setup IRQ\n");
25421f9f90cSImre Vadász 
25521f9f90cSImre Vadász 	/* Process cards detection. */
25621f9f90cSImre Vadász 	sdhci_start_slot(&sc->slot);
25721f9f90cSImre Vadász 
25821f9f90cSImre Vadász 	return (0);
25921f9f90cSImre Vadász 
26021f9f90cSImre Vadász error:
26121f9f90cSImre Vadász 	if (sc->irq_res != NULL) {
26221f9f90cSImre Vadász 		bus_release_resource(dev, SYS_RES_IRQ,
26321f9f90cSImre Vadász 		    rman_get_rid(sc->irq_res), sc->irq_res);
26421f9f90cSImre Vadász 	}
26521f9f90cSImre Vadász 	if (sc->mem_res != NULL) {
26621f9f90cSImre Vadász 		bus_release_resource(dev, SYS_RES_MEMORY,
26721f9f90cSImre Vadász 		    rman_get_rid(sc->mem_res), sc->mem_res);
26821f9f90cSImre Vadász 	}
26921f9f90cSImre Vadász 	return (err);
27021f9f90cSImre Vadász }
27121f9f90cSImre Vadász 
27221f9f90cSImre Vadász static int
sdhci_acpi_detach(device_t dev)27321f9f90cSImre Vadász sdhci_acpi_detach(device_t dev)
27421f9f90cSImre Vadász {
27521f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
27621f9f90cSImre Vadász 
27721f9f90cSImre Vadász 	bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
27821f9f90cSImre Vadász 	bus_release_resource(dev, SYS_RES_IRQ,
27921f9f90cSImre Vadász 	    rman_get_rid(sc->irq_res), sc->irq_res);
28021f9f90cSImre Vadász 
28121f9f90cSImre Vadász 	sdhci_cleanup_slot(&sc->slot);
28221f9f90cSImre Vadász 	bus_release_resource(dev, SYS_RES_MEMORY,
28321f9f90cSImre Vadász 	    rman_get_rid(sc->mem_res), sc->mem_res);
28421f9f90cSImre Vadász 	pci_set_powerstate(dev, PCI_POWERSTATE_D3);
28521f9f90cSImre Vadász 	return (0);
28621f9f90cSImre Vadász }
28721f9f90cSImre Vadász 
28821f9f90cSImre Vadász static int
sdhci_acpi_suspend(device_t dev)28921f9f90cSImre Vadász sdhci_acpi_suspend(device_t dev)
29021f9f90cSImre Vadász {
29121f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
29221f9f90cSImre Vadász 	int err;
29321f9f90cSImre Vadász 
29421f9f90cSImre Vadász 	err = bus_generic_suspend(dev);
29521f9f90cSImre Vadász 	if (err)
29621f9f90cSImre Vadász 		return (err);
29721f9f90cSImre Vadász 	sdhci_generic_suspend(&sc->slot);
29821f9f90cSImre Vadász 	return (0);
29921f9f90cSImre Vadász }
30021f9f90cSImre Vadász 
30121f9f90cSImre Vadász static int
sdhci_acpi_resume(device_t dev)30221f9f90cSImre Vadász sdhci_acpi_resume(device_t dev)
30321f9f90cSImre Vadász {
30421f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = device_get_softc(dev);
30521f9f90cSImre Vadász 
30621f9f90cSImre Vadász 	sdhci_generic_resume(&sc->slot);
30721f9f90cSImre Vadász 	return (bus_generic_resume(dev));
30821f9f90cSImre Vadász }
30921f9f90cSImre Vadász 
31021f9f90cSImre Vadász static void
sdhci_acpi_intr(void * arg)31121f9f90cSImre Vadász sdhci_acpi_intr(void *arg)
31221f9f90cSImre Vadász {
31321f9f90cSImre Vadász 	struct sdhci_acpi_softc *sc = (struct sdhci_acpi_softc *)arg;
31421f9f90cSImre Vadász 
31521f9f90cSImre Vadász 	sdhci_generic_intr(&sc->slot);
31621f9f90cSImre Vadász }
31721f9f90cSImre Vadász 
31821f9f90cSImre Vadász static device_method_t sdhci_methods[] = {
31921f9f90cSImre Vadász 	/* device_if */
32021f9f90cSImre Vadász 	DEVMETHOD(device_probe, sdhci_acpi_probe),
32121f9f90cSImre Vadász 	DEVMETHOD(device_attach, sdhci_acpi_attach),
32221f9f90cSImre Vadász 	DEVMETHOD(device_detach, sdhci_acpi_detach),
32321f9f90cSImre Vadász 	DEVMETHOD(device_suspend, sdhci_acpi_suspend),
32421f9f90cSImre Vadász 	DEVMETHOD(device_resume, sdhci_acpi_resume),
32521f9f90cSImre Vadász 
32621f9f90cSImre Vadász 	/* Bus interface */
32721f9f90cSImre Vadász 	DEVMETHOD(bus_read_ivar,	sdhci_generic_read_ivar),
32821f9f90cSImre Vadász 	DEVMETHOD(bus_write_ivar,	sdhci_generic_write_ivar),
32921f9f90cSImre Vadász 
33021f9f90cSImre Vadász 	/* mmcbr_if */
33121f9f90cSImre Vadász 	DEVMETHOD(mmcbr_update_ios,	sdhci_generic_update_ios),
3327ba10b88SImre Vadász 	DEVMETHOD(mmcbr_switch_vccq,	sdhci_generic_switch_vccq),
33321f9f90cSImre Vadász 	DEVMETHOD(mmcbr_request,	sdhci_generic_request),
33421f9f90cSImre Vadász 	DEVMETHOD(mmcbr_get_ro,		sdhci_generic_get_ro),
33521f9f90cSImre Vadász 	DEVMETHOD(mmcbr_acquire_host,	sdhci_generic_acquire_host),
33621f9f90cSImre Vadász 	DEVMETHOD(mmcbr_release_host,	sdhci_generic_release_host),
33721f9f90cSImre Vadász 
3387ba10b88SImre Vadász 	/* SDHCI accessors */
33921f9f90cSImre Vadász 	DEVMETHOD(sdhci_read_1,		sdhci_acpi_read_1),
34021f9f90cSImre Vadász 	DEVMETHOD(sdhci_read_2,		sdhci_acpi_read_2),
34121f9f90cSImre Vadász 	DEVMETHOD(sdhci_read_4,		sdhci_acpi_read_4),
34221f9f90cSImre Vadász 	DEVMETHOD(sdhci_read_multi_4,	sdhci_acpi_read_multi_4),
34321f9f90cSImre Vadász 	DEVMETHOD(sdhci_write_1,	sdhci_acpi_write_1),
34421f9f90cSImre Vadász 	DEVMETHOD(sdhci_write_2,	sdhci_acpi_write_2),
34521f9f90cSImre Vadász 	DEVMETHOD(sdhci_write_4,	sdhci_acpi_write_4),
34621f9f90cSImre Vadász 	DEVMETHOD(sdhci_write_multi_4,	sdhci_acpi_write_multi_4),
3477ba10b88SImre Vadász 	DEVMETHOD(sdhci_set_uhs_timing,	sdhci_generic_set_uhs_timing),
34821f9f90cSImre Vadász 
34921f9f90cSImre Vadász 	DEVMETHOD_END
35021f9f90cSImre Vadász };
35121f9f90cSImre Vadász 
35221f9f90cSImre Vadász static driver_t sdhci_acpi_driver = {
35321f9f90cSImre Vadász 	"sdhci_acpi",
35421f9f90cSImre Vadász 	sdhci_methods,
35521f9f90cSImre Vadász 	sizeof(struct sdhci_acpi_softc),
356*df21e16dSImre Vadász 	.gpri = KOBJ_GPRI_ACPI
35721f9f90cSImre Vadász };
35821f9f90cSImre Vadász static devclass_t sdhci_acpi_devclass;
35921f9f90cSImre Vadász 
36021f9f90cSImre Vadász DRIVER_MODULE(sdhci_acpi, acpi, sdhci_acpi_driver, sdhci_acpi_devclass, NULL,
36121f9f90cSImre Vadász     NULL);
36221f9f90cSImre Vadász MODULE_DEPEND(sdhci_acpi, sdhci, 1, 1, 1);
363