1311911Sgonzo/*- 2311911Sgonzo * Copyright (c) 2017 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3311911Sgonzo * All rights reserved. 4311911Sgonzo * 5311911Sgonzo * Redistribution and use in source and binary forms, with or without 6311911Sgonzo * modification, are permitted provided that the following conditions 7311911Sgonzo * are met: 8311911Sgonzo * 1. Redistributions of source code must retain the above copyright 9311911Sgonzo * notice, this list of conditions and the following disclaimer. 10311911Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11311911Sgonzo * notice, this list of conditions and the following disclaimer in the 12311911Sgonzo * documentation and/or other materials provided with the distribution. 13311911Sgonzo * 14311911Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15311911Sgonzo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16311911Sgonzo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17311911Sgonzo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18311911Sgonzo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19311911Sgonzo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20311911Sgonzo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21311911Sgonzo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22311911Sgonzo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23311911Sgonzo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24311911Sgonzo */ 25311911Sgonzo 26311911Sgonzo#include <sys/cdefs.h> 27311911Sgonzo__FBSDID("$FreeBSD: stable/10/sys/dev/sdhci/sdhci_acpi.c 343505 2019-01-27 19:05:18Z marius $"); 28311911Sgonzo 29311911Sgonzo#include <sys/param.h> 30311911Sgonzo#include <sys/systm.h> 31311911Sgonzo#include <sys/bus.h> 32311911Sgonzo#include <sys/kernel.h> 33311911Sgonzo#include <sys/lock.h> 34311911Sgonzo#include <sys/module.h> 35311911Sgonzo#include <sys/mutex.h> 36311911Sgonzo#include <sys/resource.h> 37311911Sgonzo#include <sys/rman.h> 38311911Sgonzo#include <sys/sysctl.h> 39311911Sgonzo#include <sys/taskqueue.h> 40311911Sgonzo 41311911Sgonzo#include <machine/bus.h> 42311911Sgonzo#include <machine/resource.h> 43311911Sgonzo 44311911Sgonzo#include <contrib/dev/acpica/include/acpi.h> 45311911Sgonzo#include <dev/acpica/acpivar.h> 46311911Sgonzo 47311911Sgonzo#include <dev/mmc/bridge.h> 48340764Smarius#include <dev/mmc/mmcreg.h> 49311911Sgonzo 50318198Smarius#include <dev/sdhci/sdhci.h> 51318198Smarius 52311911Sgonzo#include "mmcbr_if.h" 53311911Sgonzo#include "sdhci_if.h" 54311911Sgonzo 55340764Smarius#define SDHCI_AMD_RESET_DLL_REG 0x908 56340764Smarius 57311911Sgonzostatic const struct sdhci_acpi_device { 58311911Sgonzo const char* hid; 59311911Sgonzo int uid; 60311911Sgonzo const char *desc; 61311911Sgonzo u_int quirks; 62311911Sgonzo} sdhci_acpi_devices[] = { 63318497Smarius { "80860F14", 1, "Intel Bay Trail/Braswell eMMC 4.5/4.5.1 Controller", 64318198Smarius SDHCI_QUIRK_INTEL_POWER_UP_RESET | 65318495Smarius SDHCI_QUIRK_WAIT_WHILE_BUSY | 66318495Smarius SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | 67318495Smarius SDHCI_QUIRK_PRESET_VALUE_BROKEN }, 68318497Smarius { "80860F14", 3, "Intel Bay Trail/Braswell SDXC Controller", 69318495Smarius SDHCI_QUIRK_WAIT_WHILE_BUSY | 70318495Smarius SDHCI_QUIRK_PRESET_VALUE_BROKEN }, 71318497Smarius { "80860F16", 0, "Intel Bay Trail/Braswell SDXC Controller", 72318495Smarius SDHCI_QUIRK_WAIT_WHILE_BUSY | 73318495Smarius SDHCI_QUIRK_PRESET_VALUE_BROKEN }, 74318497Smarius { "80865ACA", 0, "Intel Apollo Lake SDXC Controller", 75318497Smarius SDHCI_QUIRK_BROKEN_DMA | /* APL18 erratum */ 76318497Smarius SDHCI_QUIRK_WAIT_WHILE_BUSY | 77318497Smarius SDHCI_QUIRK_PRESET_VALUE_BROKEN }, 78318497Smarius { "80865ACC", 0, "Intel Apollo Lake eMMC 5.0 Controller", 79318497Smarius SDHCI_QUIRK_BROKEN_DMA | /* APL18 erratum */ 80318497Smarius SDHCI_QUIRK_INTEL_POWER_UP_RESET | 81318497Smarius SDHCI_QUIRK_WAIT_WHILE_BUSY | 82318497Smarius SDHCI_QUIRK_MMC_DDR52 | 83318497Smarius SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | 84318497Smarius SDHCI_QUIRK_PRESET_VALUE_BROKEN }, 85340764Smarius { "AMDI0040", 0, "AMD eMMC 5.0 Controller", 86340764Smarius SDHCI_QUIRK_32BIT_DMA_SIZE | 87340764Smarius SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 }, 88311911Sgonzo { NULL, 0, NULL, 0} 89311911Sgonzo}; 90311911Sgonzo 91311911Sgonzostatic char *sdhci_ids[] = { 92311911Sgonzo "80860F14", 93311911Sgonzo "80860F16", 94318497Smarius "80865ACA", 95318497Smarius "80865ACC", 96340764Smarius "AMDI0040", 97311911Sgonzo NULL 98311911Sgonzo}; 99311911Sgonzo 100311911Sgonzostruct sdhci_acpi_softc { 101340764Smarius struct sdhci_slot slot; 102340764Smarius struct resource *mem_res; /* Memory resource */ 103311911Sgonzo struct resource *irq_res; /* IRQ resource */ 104318198Smarius void *intrhand; /* Interrupt handle */ 105340764Smarius const struct sdhci_acpi_device *acpi_dev; 106311911Sgonzo}; 107311911Sgonzo 108311911Sgonzostatic void sdhci_acpi_intr(void *arg); 109311911Sgonzostatic int sdhci_acpi_detach(device_t dev); 110311911Sgonzo 111311911Sgonzostatic uint8_t 112318198Smariussdhci_acpi_read_1(device_t dev, struct sdhci_slot *slot __unused, 113318198Smarius bus_size_t off) 114311911Sgonzo{ 115311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 116311911Sgonzo 117311911Sgonzo bus_barrier(sc->mem_res, 0, 0xFF, 118311911Sgonzo BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 119311911Sgonzo return bus_read_1(sc->mem_res, off); 120311911Sgonzo} 121311911Sgonzo 122311911Sgonzostatic void 123318198Smariussdhci_acpi_write_1(device_t dev, struct sdhci_slot *slot __unused, 124318198Smarius bus_size_t off, uint8_t val) 125311911Sgonzo{ 126311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 127311911Sgonzo 128311911Sgonzo bus_barrier(sc->mem_res, 0, 0xFF, 129311911Sgonzo BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 130311911Sgonzo bus_write_1(sc->mem_res, off, val); 131311911Sgonzo} 132311911Sgonzo 133311911Sgonzostatic uint16_t 134318198Smariussdhci_acpi_read_2(device_t dev, struct sdhci_slot *slot __unused, 135318198Smarius bus_size_t off) 136311911Sgonzo{ 137311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 138311911Sgonzo 139311911Sgonzo bus_barrier(sc->mem_res, 0, 0xFF, 140311911Sgonzo BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 141311911Sgonzo return bus_read_2(sc->mem_res, off); 142311911Sgonzo} 143311911Sgonzo 144311911Sgonzostatic void 145318198Smariussdhci_acpi_write_2(device_t dev, struct sdhci_slot *slot __unused, 146318198Smarius bus_size_t off, uint16_t val) 147311911Sgonzo{ 148311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 149311911Sgonzo 150311911Sgonzo bus_barrier(sc->mem_res, 0, 0xFF, 151311911Sgonzo BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 152311911Sgonzo bus_write_2(sc->mem_res, off, val); 153311911Sgonzo} 154311911Sgonzo 155311911Sgonzostatic uint32_t 156318198Smariussdhci_acpi_read_4(device_t dev, struct sdhci_slot *slot __unused, 157318198Smarius bus_size_t off) 158311911Sgonzo{ 159311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 160311911Sgonzo 161311911Sgonzo bus_barrier(sc->mem_res, 0, 0xFF, 162311911Sgonzo BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 163311911Sgonzo return bus_read_4(sc->mem_res, off); 164311911Sgonzo} 165311911Sgonzo 166311911Sgonzostatic void 167318198Smariussdhci_acpi_write_4(device_t dev, struct sdhci_slot *slot __unused, 168318198Smarius bus_size_t off, uint32_t val) 169311911Sgonzo{ 170311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 171311911Sgonzo 172311911Sgonzo bus_barrier(sc->mem_res, 0, 0xFF, 173311911Sgonzo BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 174311911Sgonzo bus_write_4(sc->mem_res, off, val); 175311911Sgonzo} 176311911Sgonzo 177311911Sgonzostatic void 178318198Smariussdhci_acpi_read_multi_4(device_t dev, struct sdhci_slot *slot __unused, 179311911Sgonzo bus_size_t off, uint32_t *data, bus_size_t count) 180311911Sgonzo{ 181311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 182311911Sgonzo 183311911Sgonzo bus_read_multi_stream_4(sc->mem_res, off, data, count); 184311911Sgonzo} 185311911Sgonzo 186311911Sgonzostatic void 187318198Smariussdhci_acpi_write_multi_4(device_t dev, struct sdhci_slot *slot __unused, 188311911Sgonzo bus_size_t off, uint32_t *data, bus_size_t count) 189311911Sgonzo{ 190311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 191311911Sgonzo 192311911Sgonzo bus_write_multi_stream_4(sc->mem_res, off, data, count); 193311911Sgonzo} 194311911Sgonzo 195340764Smariusstatic void 196340764Smariussdhci_acpi_set_uhs_timing(device_t dev, struct sdhci_slot *slot) 197340764Smarius{ 198340764Smarius const struct sdhci_acpi_softc *sc; 199340764Smarius const struct sdhci_acpi_device *acpi_dev; 200340764Smarius const struct mmc_ios *ios; 201340764Smarius device_t bus; 202340764Smarius uint16_t old_timing; 203340764Smarius enum mmc_bus_timing timing; 204340764Smarius 205340764Smarius bus = slot->bus; 206340764Smarius old_timing = SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2); 207340764Smarius old_timing &= SDHCI_CTRL2_UHS_MASK; 208340764Smarius sdhci_generic_set_uhs_timing(dev, slot); 209340764Smarius 210340764Smarius sc = device_get_softc(dev); 211340764Smarius acpi_dev = sc->acpi_dev; 212340764Smarius /* 213340764Smarius * AMDI0040 controllers require SDHCI_CTRL2_SAMPLING_CLOCK to be 214340764Smarius * disabled when switching from HS200 to high speed and to always 215340764Smarius * be turned on again when tuning for HS400. In the later case, 216340764Smarius * an AMD-specific DLL reset additionally is needed. 217340764Smarius */ 218340764Smarius if (strcmp(acpi_dev->hid, "AMDI0040") == 0 && acpi_dev->uid == 0) { 219340764Smarius ios = &slot->host.ios; 220340764Smarius timing = ios->timing; 221340764Smarius if (old_timing == SDHCI_CTRL2_UHS_SDR104 && 222340764Smarius timing == bus_timing_hs) 223340764Smarius SDHCI_WRITE_2(bus, slot, SDHCI_HOST_CONTROL2, 224340764Smarius SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2) & 225340764Smarius ~SDHCI_CTRL2_SAMPLING_CLOCK); 226340764Smarius if (ios->clock > SD_SDR50_MAX && 227340764Smarius old_timing != SDHCI_CTRL2_MMC_HS400 && 228340764Smarius timing == bus_timing_mmc_hs400) { 229340764Smarius SDHCI_WRITE_2(bus, slot, SDHCI_HOST_CONTROL2, 230340764Smarius SDHCI_READ_2(bus, slot, SDHCI_HOST_CONTROL2) | 231340764Smarius SDHCI_CTRL2_SAMPLING_CLOCK); 232340764Smarius SDHCI_WRITE_4(bus, slot, SDHCI_AMD_RESET_DLL_REG, 233340764Smarius 0x40003210); 234340764Smarius DELAY(20); 235340764Smarius SDHCI_WRITE_4(bus, slot, SDHCI_AMD_RESET_DLL_REG, 236340764Smarius 0x40033210); 237340764Smarius } 238340764Smarius } 239340764Smarius} 240340764Smarius 241311911Sgonzostatic const struct sdhci_acpi_device * 242311911Sgonzosdhci_acpi_find_device(device_t dev) 243311911Sgonzo{ 244311911Sgonzo const char *hid; 245311911Sgonzo int i, uid; 246311911Sgonzo ACPI_HANDLE handle; 247311911Sgonzo ACPI_STATUS status; 248311911Sgonzo 249311911Sgonzo hid = ACPI_ID_PROBE(device_get_parent(dev), dev, sdhci_ids); 250311911Sgonzo if (hid == NULL) 251311911Sgonzo return (NULL); 252311911Sgonzo 253311911Sgonzo handle = acpi_get_handle(dev); 254311911Sgonzo status = acpi_GetInteger(handle, "_UID", &uid); 255311911Sgonzo if (ACPI_FAILURE(status)) 256311911Sgonzo uid = 0; 257311911Sgonzo 258311911Sgonzo for (i = 0; sdhci_acpi_devices[i].hid != NULL; i++) { 259311911Sgonzo if (strcmp(sdhci_acpi_devices[i].hid, hid) != 0) 260311911Sgonzo continue; 261311911Sgonzo if ((sdhci_acpi_devices[i].uid != 0) && 262311911Sgonzo (sdhci_acpi_devices[i].uid != uid)) 263311911Sgonzo continue; 264318198Smarius return (&sdhci_acpi_devices[i]); 265311911Sgonzo } 266311911Sgonzo 267311911Sgonzo return (NULL); 268311911Sgonzo} 269311911Sgonzo 270311911Sgonzostatic int 271311911Sgonzosdhci_acpi_probe(device_t dev) 272311911Sgonzo{ 273311911Sgonzo const struct sdhci_acpi_device *acpi_dev; 274311911Sgonzo 275311911Sgonzo acpi_dev = sdhci_acpi_find_device(dev); 276311911Sgonzo if (acpi_dev == NULL) 277311911Sgonzo return (ENXIO); 278311911Sgonzo 279311911Sgonzo device_set_desc(dev, acpi_dev->desc); 280311911Sgonzo 281311911Sgonzo return (BUS_PROBE_DEFAULT); 282311911Sgonzo} 283311911Sgonzo 284311911Sgonzostatic int 285311911Sgonzosdhci_acpi_attach(device_t dev) 286311911Sgonzo{ 287311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 288311911Sgonzo int rid, err; 289340764Smarius u_int quirks; 290311911Sgonzo const struct sdhci_acpi_device *acpi_dev; 291311911Sgonzo 292311911Sgonzo acpi_dev = sdhci_acpi_find_device(dev); 293311911Sgonzo if (acpi_dev == NULL) 294311911Sgonzo return (ENXIO); 295311911Sgonzo 296340764Smarius sc->acpi_dev = acpi_dev; 297340764Smarius quirks = acpi_dev->quirks; 298311911Sgonzo 299311911Sgonzo /* Allocate IRQ. */ 300311911Sgonzo rid = 0; 301311911Sgonzo sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 302311911Sgonzo RF_ACTIVE); 303311911Sgonzo if (sc->irq_res == NULL) { 304311911Sgonzo device_printf(dev, "can't allocate IRQ\n"); 305311911Sgonzo return (ENOMEM); 306311911Sgonzo } 307311911Sgonzo 308311911Sgonzo rid = 0; 309311911Sgonzo sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 310311911Sgonzo &rid, RF_ACTIVE); 311311911Sgonzo if (sc->mem_res == NULL) { 312311911Sgonzo device_printf(dev, "can't allocate memory resource for slot\n"); 313311911Sgonzo sdhci_acpi_detach(dev); 314311911Sgonzo return (ENOMEM); 315311911Sgonzo } 316318198Smarius 317338636Smarius /* 318338636Smarius * Intel Bay Trail and Braswell eMMC controllers share the same IDs, 319338636Smarius * but while with these former DDR52 is affected by the VLI54 erratum, 320338636Smarius * these latter require the timeout clock to be hardcoded to 1 MHz. 321338636Smarius */ 322318497Smarius if (strcmp(acpi_dev->hid, "80860F14") == 0 && acpi_dev->uid == 1 && 323318497Smarius SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES) == 0x446cc8b2 && 324318497Smarius SDHCI_READ_4(dev, &sc->slot, SDHCI_CAPABILITIES2) == 0x00000807) 325340764Smarius quirks |= SDHCI_QUIRK_MMC_DDR52 | SDHCI_QUIRK_DATA_TIMEOUT_1MHZ; 326340764Smarius quirks &= ~sdhci_quirk_clear; 327340764Smarius quirks |= sdhci_quirk_set; 328340764Smarius sc->slot.quirks = quirks; 329311911Sgonzo 330311911Sgonzo err = sdhci_init_slot(dev, &sc->slot, 0); 331311911Sgonzo if (err) { 332311911Sgonzo device_printf(dev, "failed to init slot\n"); 333311911Sgonzo sdhci_acpi_detach(dev); 334311911Sgonzo return (err); 335311911Sgonzo } 336311911Sgonzo 337311911Sgonzo /* Activate the interrupt */ 338311911Sgonzo err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 339311911Sgonzo NULL, sdhci_acpi_intr, sc, &sc->intrhand); 340311911Sgonzo if (err) { 341311911Sgonzo device_printf(dev, "can't setup IRQ\n"); 342311911Sgonzo sdhci_acpi_detach(dev); 343311911Sgonzo return (err); 344311911Sgonzo } 345311911Sgonzo 346311911Sgonzo /* Process cards detection. */ 347311911Sgonzo sdhci_start_slot(&sc->slot); 348311911Sgonzo 349311911Sgonzo return (0); 350311911Sgonzo} 351311911Sgonzo 352311911Sgonzostatic int 353311911Sgonzosdhci_acpi_detach(device_t dev) 354311911Sgonzo{ 355311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 356311911Sgonzo 357311911Sgonzo if (sc->intrhand) 358311911Sgonzo bus_teardown_intr(dev, sc->irq_res, sc->intrhand); 359311911Sgonzo if (sc->irq_res) 360311911Sgonzo bus_release_resource(dev, SYS_RES_IRQ, 361311911Sgonzo rman_get_rid(sc->irq_res), sc->irq_res); 362311911Sgonzo 363311911Sgonzo if (sc->mem_res) { 364311911Sgonzo sdhci_cleanup_slot(&sc->slot); 365311911Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, 366311911Sgonzo rman_get_rid(sc->mem_res), sc->mem_res); 367311911Sgonzo } 368311911Sgonzo 369311911Sgonzo return (0); 370311911Sgonzo} 371311911Sgonzo 372311911Sgonzostatic int 373311911Sgonzosdhci_acpi_shutdown(device_t dev) 374311911Sgonzo{ 375311911Sgonzo 376311911Sgonzo return (0); 377311911Sgonzo} 378311911Sgonzo 379311911Sgonzostatic int 380311911Sgonzosdhci_acpi_suspend(device_t dev) 381311911Sgonzo{ 382311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 383311911Sgonzo int err; 384311911Sgonzo 385311911Sgonzo err = bus_generic_suspend(dev); 386311911Sgonzo if (err) 387311911Sgonzo return (err); 388311911Sgonzo sdhci_generic_suspend(&sc->slot); 389311911Sgonzo return (0); 390311911Sgonzo} 391311911Sgonzo 392311911Sgonzostatic int 393311911Sgonzosdhci_acpi_resume(device_t dev) 394311911Sgonzo{ 395311911Sgonzo struct sdhci_acpi_softc *sc = device_get_softc(dev); 396311911Sgonzo int err; 397311911Sgonzo 398311911Sgonzo sdhci_generic_resume(&sc->slot); 399311911Sgonzo err = bus_generic_resume(dev); 400311911Sgonzo if (err) 401311911Sgonzo return (err); 402311911Sgonzo return (0); 403311911Sgonzo} 404311911Sgonzo 405311911Sgonzostatic void 406311911Sgonzosdhci_acpi_intr(void *arg) 407311911Sgonzo{ 408311911Sgonzo struct sdhci_acpi_softc *sc = (struct sdhci_acpi_softc *)arg; 409311911Sgonzo 410311911Sgonzo sdhci_generic_intr(&sc->slot); 411311911Sgonzo} 412311911Sgonzo 413311911Sgonzostatic device_method_t sdhci_methods[] = { 414311911Sgonzo /* device_if */ 415311911Sgonzo DEVMETHOD(device_probe, sdhci_acpi_probe), 416311911Sgonzo DEVMETHOD(device_attach, sdhci_acpi_attach), 417311911Sgonzo DEVMETHOD(device_detach, sdhci_acpi_detach), 418311911Sgonzo DEVMETHOD(device_shutdown, sdhci_acpi_shutdown), 419311911Sgonzo DEVMETHOD(device_suspend, sdhci_acpi_suspend), 420311911Sgonzo DEVMETHOD(device_resume, sdhci_acpi_resume), 421311911Sgonzo 422311911Sgonzo /* Bus interface */ 423311911Sgonzo DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), 424311911Sgonzo DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), 425311911Sgonzo 426311911Sgonzo /* mmcbr_if */ 427318198Smarius DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), 428318495Smarius DEVMETHOD(mmcbr_switch_vccq, sdhci_generic_switch_vccq), 429322120Smarius DEVMETHOD(mmcbr_tune, sdhci_generic_tune), 430322120Smarius DEVMETHOD(mmcbr_retune, sdhci_generic_retune), 431318198Smarius DEVMETHOD(mmcbr_request, sdhci_generic_request), 432318198Smarius DEVMETHOD(mmcbr_get_ro, sdhci_generic_get_ro), 433311911Sgonzo DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), 434311911Sgonzo DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), 435311911Sgonzo 436318495Smarius /* SDHCI accessors */ 437311911Sgonzo DEVMETHOD(sdhci_read_1, sdhci_acpi_read_1), 438311911Sgonzo DEVMETHOD(sdhci_read_2, sdhci_acpi_read_2), 439311911Sgonzo DEVMETHOD(sdhci_read_4, sdhci_acpi_read_4), 440311911Sgonzo DEVMETHOD(sdhci_read_multi_4, sdhci_acpi_read_multi_4), 441311911Sgonzo DEVMETHOD(sdhci_write_1, sdhci_acpi_write_1), 442311911Sgonzo DEVMETHOD(sdhci_write_2, sdhci_acpi_write_2), 443311911Sgonzo DEVMETHOD(sdhci_write_4, sdhci_acpi_write_4), 444311911Sgonzo DEVMETHOD(sdhci_write_multi_4, sdhci_acpi_write_multi_4), 445340764Smarius DEVMETHOD(sdhci_set_uhs_timing, sdhci_acpi_set_uhs_timing), 446311911Sgonzo 447311911Sgonzo DEVMETHOD_END 448311911Sgonzo}; 449311911Sgonzo 450311911Sgonzostatic driver_t sdhci_acpi_driver = { 451311911Sgonzo "sdhci_acpi", 452311911Sgonzo sdhci_methods, 453311911Sgonzo sizeof(struct sdhci_acpi_softc), 454311911Sgonzo}; 455311911Sgonzostatic devclass_t sdhci_acpi_devclass; 456311911Sgonzo 457311911SgonzoDRIVER_MODULE(sdhci_acpi, acpi, sdhci_acpi_driver, sdhci_acpi_devclass, NULL, 458311911Sgonzo NULL); 459343505SmariusSDHCI_DEPEND(sdhci_acpi); 460318198SmariusMMC_DECLARE_BRIDGE(sdhci_acpi); 461