1*8ab765f8Shastings /* $OpenBSD: sdhc.c,v 1.78 2024/10/19 21:10:03 hastings Exp $ */ 2aae4fe77Suwe 3aae4fe77Suwe /* 4aae4fe77Suwe * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> 5aae4fe77Suwe * 6aae4fe77Suwe * Permission to use, copy, modify, and distribute this software for any 7aae4fe77Suwe * purpose with or without fee is hereby granted, provided that the above 8aae4fe77Suwe * copyright notice and this permission notice appear in all copies. 9aae4fe77Suwe * 10aae4fe77Suwe * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11aae4fe77Suwe * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12aae4fe77Suwe * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13aae4fe77Suwe * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14aae4fe77Suwe * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15aae4fe77Suwe * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16aae4fe77Suwe * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17aae4fe77Suwe */ 18aae4fe77Suwe 19aae4fe77Suwe /* 20aae4fe77Suwe * SD Host Controller driver based on the SD Host Controller Standard 215e422abeSjsg * Simplified Specification Version 1.00 (www.sdcard.org). 22aae4fe77Suwe */ 23aae4fe77Suwe 24aae4fe77Suwe #include <sys/param.h> 25aae4fe77Suwe #include <sys/device.h> 26aae4fe77Suwe #include <sys/kernel.h> 27aae4fe77Suwe #include <sys/malloc.h> 28c2deed7fSkettenis #include <sys/proc.h> 29aae4fe77Suwe #include <sys/systm.h> 303f3abf14Scheloha #include <sys/time.h> 31aae4fe77Suwe 32aae4fe77Suwe #include <dev/sdmmc/sdhcreg.h> 33aae4fe77Suwe #include <dev/sdmmc/sdhcvar.h> 34aae4fe77Suwe #include <dev/sdmmc/sdmmcchip.h> 35aae4fe77Suwe #include <dev/sdmmc/sdmmcreg.h> 36aae4fe77Suwe #include <dev/sdmmc/sdmmcvar.h> 37402f30eeSpatrick #include <dev/sdmmc/sdmmc_ioreg.h> 38aae4fe77Suwe 393f3abf14Scheloha /* Timeouts in seconds */ 403f3abf14Scheloha #define SDHC_COMMAND_TIMEOUT 1 413f3abf14Scheloha #define SDHC_BUFFER_TIMEOUT 1 423f3abf14Scheloha #define SDHC_TRANSFER_TIMEOUT 1 433f3abf14Scheloha #define SDHC_DMA_TIMEOUT 3 44aae4fe77Suwe 45aae4fe77Suwe struct sdhc_host { 46aae4fe77Suwe struct sdhc_softc *sc; /* host controller device */ 47aae4fe77Suwe struct device *sdmmc; /* generic SD/MMC device */ 48aae4fe77Suwe bus_space_tag_t iot; /* host register set tag */ 49aae4fe77Suwe bus_space_handle_t ioh; /* host register set handle */ 50445e328eSkettenis u_int16_t version; /* specification version */ 51aae4fe77Suwe u_int clkbase; /* base clock frequency in KHz */ 52aae4fe77Suwe int maxblklen; /* maximum block length */ 53aae4fe77Suwe int flags; /* flags for this host */ 54aae4fe77Suwe u_int32_t ocr; /* OCR value from capabilities */ 55f50f4931Suwe u_int8_t regs[14]; /* host controller state */ 56a6fd99a7Suwe u_int16_t intr_status; /* soft interrupt status */ 57a6fd99a7Suwe u_int16_t intr_error_status; /* soft error status */ 58c6293583Skettenis 59c6293583Skettenis bus_dmamap_t adma_map; 60c6293583Skettenis bus_dma_segment_t adma_segs[1]; 61c6293583Skettenis caddr_t adma2; 6204b7fce9Skettenis 6304b7fce9Skettenis uint16_t block_size; 6404b7fce9Skettenis uint16_t block_count; 6504b7fce9Skettenis uint16_t transfer_mode; 66aae4fe77Suwe }; 67aae4fe77Suwe 68aae4fe77Suwe /* flag values */ 69aae4fe77Suwe #define SHF_USE_DMA 0x0001 70b60bffefSpatrick #define SHF_USE_DMA64 0x0002 7104b7fce9Skettenis #define SHF_USE_32BIT_ACCESS 0x0004 72aae4fe77Suwe 73aae4fe77Suwe #define HREAD1(hp, reg) \ 7404b7fce9Skettenis (sdhc_read_1((hp), (reg))) 75aae4fe77Suwe #define HREAD2(hp, reg) \ 7604b7fce9Skettenis (sdhc_read_2((hp), (reg))) 77aae4fe77Suwe #define HREAD4(hp, reg) \ 78aae4fe77Suwe (bus_space_read_4((hp)->iot, (hp)->ioh, (reg))) 79aae4fe77Suwe #define HWRITE1(hp, reg, val) \ 8004b7fce9Skettenis sdhc_write_1((hp), (reg), (val)) 81aae4fe77Suwe #define HWRITE2(hp, reg, val) \ 8204b7fce9Skettenis sdhc_write_2((hp), (reg), (val)) 83aae4fe77Suwe #define HWRITE4(hp, reg, val) \ 84aae4fe77Suwe bus_space_write_4((hp)->iot, (hp)->ioh, (reg), (val)) 85aae4fe77Suwe #define HCLR1(hp, reg, bits) \ 86aae4fe77Suwe HWRITE1((hp), (reg), HREAD1((hp), (reg)) & ~(bits)) 87aae4fe77Suwe #define HCLR2(hp, reg, bits) \ 88aae4fe77Suwe HWRITE2((hp), (reg), HREAD2((hp), (reg)) & ~(bits)) 89aae4fe77Suwe #define HSET1(hp, reg, bits) \ 90aae4fe77Suwe HWRITE1((hp), (reg), HREAD1((hp), (reg)) | (bits)) 91aae4fe77Suwe #define HSET2(hp, reg, bits) \ 92aae4fe77Suwe HWRITE2((hp), (reg), HREAD2((hp), (reg)) | (bits)) 93aae4fe77Suwe 94aae4fe77Suwe int sdhc_host_reset(sdmmc_chipset_handle_t); 95aae4fe77Suwe u_int32_t sdhc_host_ocr(sdmmc_chipset_handle_t); 96aae4fe77Suwe int sdhc_host_maxblklen(sdmmc_chipset_handle_t); 97aae4fe77Suwe int sdhc_card_detect(sdmmc_chipset_handle_t); 98aae4fe77Suwe int sdhc_bus_power(sdmmc_chipset_handle_t, u_int32_t); 99820e06f1Skettenis int sdhc_bus_clock(sdmmc_chipset_handle_t, int, int); 100b140af5cSkettenis int sdhc_bus_width(sdmmc_chipset_handle_t, int); 101b979651fSuwe void sdhc_card_intr_mask(sdmmc_chipset_handle_t, int); 102b979651fSuwe void sdhc_card_intr_ack(sdmmc_chipset_handle_t); 103820e06f1Skettenis int sdhc_signal_voltage(sdmmc_chipset_handle_t, int); 104a6fd99a7Suwe void sdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *); 105aae4fe77Suwe int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *); 106a6fd99a7Suwe int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t); 1075842cfcdSfgsch int sdhc_soft_reset(struct sdhc_host *, int); 108f3036462Sjmatthew int sdhc_wait_intr_cold(struct sdhc_host *, int, int); 109a6fd99a7Suwe int sdhc_wait_intr(struct sdhc_host *, int, int); 110a6fd99a7Suwe void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *); 111aae4fe77Suwe void sdhc_read_data(struct sdhc_host *, u_char *, int); 112aae4fe77Suwe void sdhc_write_data(struct sdhc_host *, u_char *, int); 113f3036462Sjmatthew int sdhc_hibernate_init(sdmmc_chipset_handle_t, void *); 114aae4fe77Suwe 115aae4fe77Suwe #ifdef SDHC_DEBUG 11637539bbbSuwe int sdhcdebug = 0; 11737539bbbSuwe #define DPRINTF(n,s) do { if ((n) <= sdhcdebug) printf s; } while (0) 118aae4fe77Suwe void sdhc_dump_regs(struct sdhc_host *); 119aae4fe77Suwe #else 12037539bbbSuwe #define DPRINTF(n,s) do {} while(0) 121aae4fe77Suwe #endif 122aae4fe77Suwe 123aae4fe77Suwe struct sdmmc_chip_functions sdhc_functions = { 124a62fc20aSkettenis .host_reset = sdhc_host_reset, 125a62fc20aSkettenis .host_ocr = sdhc_host_ocr, 126a62fc20aSkettenis .host_maxblklen = sdhc_host_maxblklen, 127a62fc20aSkettenis .card_detect = sdhc_card_detect, 128a62fc20aSkettenis .bus_power = sdhc_bus_power, 129a62fc20aSkettenis .bus_clock = sdhc_bus_clock, 130a62fc20aSkettenis .bus_width = sdhc_bus_width, 131a62fc20aSkettenis .exec_command = sdhc_exec_command, 132a62fc20aSkettenis .card_intr_mask = sdhc_card_intr_mask, 133a62fc20aSkettenis .card_intr_ack = sdhc_card_intr_ack, 134a62fc20aSkettenis .signal_voltage = sdhc_signal_voltage, 135a62fc20aSkettenis .hibernate_init = sdhc_hibernate_init, 136aae4fe77Suwe }; 137aae4fe77Suwe 138aae4fe77Suwe struct cfdriver sdhc_cd = { 139aae4fe77Suwe NULL, "sdhc", DV_DULL 140aae4fe77Suwe }; 141aae4fe77Suwe 142aae4fe77Suwe /* 14304b7fce9Skettenis * Some controllers live on a bus that only allows 32-bit 14404b7fce9Skettenis * transactions. In that case we use a RMW cycle for 8-bit and 16-bit 14504b7fce9Skettenis * register writes. However that doesn't work for the Transfer Mode 14604b7fce9Skettenis * register as this register lives in the same 32-bit word as the 14704b7fce9Skettenis * Command register and writing the Command register triggers SD 14804b7fce9Skettenis * command generation. We avoid this issue by using a shadow variable 14904b7fce9Skettenis * for the Transfer Mode register that we write out when we write the 15004b7fce9Skettenis * Command register. 15104b7fce9Skettenis * 152b3af768dSjsg * The Arasan controller integrated on the Broadcom SoCs 15304b7fce9Skettenis * used in the Raspberry Pi has an interesting bug where writing the 15404b7fce9Skettenis * same 32-bit register twice doesn't work. This means that we lose 15504b7fce9Skettenis * writes to the Block Sine and/or Block Count register. We work 15604b7fce9Skettenis * around that issue by using shadow variables as well. 15704b7fce9Skettenis */ 15804b7fce9Skettenis 15904b7fce9Skettenis uint8_t 16004b7fce9Skettenis sdhc_read_1(struct sdhc_host *hp, bus_size_t offset) 16104b7fce9Skettenis { 16204b7fce9Skettenis uint32_t reg; 16304b7fce9Skettenis 16404b7fce9Skettenis if (hp->flags & SHF_USE_32BIT_ACCESS) { 16504b7fce9Skettenis reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~3); 16604b7fce9Skettenis return (reg >> ((offset & 3) * 8)) & 0xff; 16704b7fce9Skettenis } 16804b7fce9Skettenis 16904b7fce9Skettenis return bus_space_read_1(hp->iot, hp->ioh, offset); 17004b7fce9Skettenis } 17104b7fce9Skettenis 17204b7fce9Skettenis uint16_t 17304b7fce9Skettenis sdhc_read_2(struct sdhc_host *hp, bus_size_t offset) 17404b7fce9Skettenis { 17504b7fce9Skettenis uint32_t reg; 17604b7fce9Skettenis 17704b7fce9Skettenis if (hp->flags & SHF_USE_32BIT_ACCESS) { 17804b7fce9Skettenis reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~2); 17904b7fce9Skettenis return (reg >> ((offset & 2) * 8)) & 0xffff; 18004b7fce9Skettenis } 18104b7fce9Skettenis 18204b7fce9Skettenis return bus_space_read_2(hp->iot, hp->ioh, offset); 18304b7fce9Skettenis } 18404b7fce9Skettenis 18504b7fce9Skettenis void 18604b7fce9Skettenis sdhc_write_1(struct sdhc_host *hp, bus_size_t offset, uint8_t value) 18704b7fce9Skettenis { 18804b7fce9Skettenis uint32_t reg; 18904b7fce9Skettenis 19004b7fce9Skettenis if (hp->flags & SHF_USE_32BIT_ACCESS) { 19104b7fce9Skettenis reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~3); 19204b7fce9Skettenis reg &= ~(0xff << ((offset & 3) * 8)); 19304b7fce9Skettenis reg |= (value << ((offset & 3) * 8)); 19404b7fce9Skettenis bus_space_write_4(hp->iot, hp->ioh, offset & ~3, reg); 19504b7fce9Skettenis return; 19604b7fce9Skettenis } 19704b7fce9Skettenis 19804b7fce9Skettenis bus_space_write_1(hp->iot, hp->ioh, offset, value); 19904b7fce9Skettenis } 20004b7fce9Skettenis 20104b7fce9Skettenis void 20204b7fce9Skettenis sdhc_write_2(struct sdhc_host *hp, bus_size_t offset, uint16_t value) 20304b7fce9Skettenis { 20404b7fce9Skettenis uint32_t reg; 20504b7fce9Skettenis 20604b7fce9Skettenis if (hp->flags & SHF_USE_32BIT_ACCESS) { 20704b7fce9Skettenis switch (offset) { 20804b7fce9Skettenis case SDHC_BLOCK_SIZE: 20904b7fce9Skettenis hp->block_size = value; 21004b7fce9Skettenis return; 21104b7fce9Skettenis case SDHC_BLOCK_COUNT: 21204b7fce9Skettenis hp->block_count = value; 21304b7fce9Skettenis return; 21404b7fce9Skettenis case SDHC_TRANSFER_MODE: 21504b7fce9Skettenis hp->transfer_mode = value; 21604b7fce9Skettenis return; 21704b7fce9Skettenis case SDHC_COMMAND: 21804b7fce9Skettenis bus_space_write_4(hp->iot, hp->ioh, SDHC_BLOCK_SIZE, 21904b7fce9Skettenis (hp->block_count << 16) | hp->block_size); 22004b7fce9Skettenis bus_space_write_4(hp->iot, hp->ioh, SDHC_TRANSFER_MODE, 22104b7fce9Skettenis (value << 16) | hp->transfer_mode); 22204b7fce9Skettenis return; 22304b7fce9Skettenis } 22404b7fce9Skettenis 22504b7fce9Skettenis reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~2); 22604b7fce9Skettenis reg &= ~(0xffff << ((offset & 2) * 8)); 22704b7fce9Skettenis reg |= (value << ((offset & 2) * 8)); 22804b7fce9Skettenis bus_space_write_4(hp->iot, hp->ioh, offset & ~2, reg); 22904b7fce9Skettenis return; 23004b7fce9Skettenis } 23104b7fce9Skettenis 23204b7fce9Skettenis bus_space_write_2(hp->iot, hp->ioh, offset, value); 23304b7fce9Skettenis } 23404b7fce9Skettenis 23504b7fce9Skettenis /* 236aae4fe77Suwe * Called by attachment driver. For each SD card slot there is one SD 237aae4fe77Suwe * host controller standard register set. (1.3) 238aae4fe77Suwe */ 239aae4fe77Suwe int 240aae4fe77Suwe sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot, 241bfa5fdb5Spatrick bus_space_handle_t ioh, bus_size_t iosize, int usedma, uint64_t capmask, 242bfa5fdb5Spatrick uint64_t capset) 243aae4fe77Suwe { 244aae4fe77Suwe struct sdmmcbus_attach_args saa; 245aae4fe77Suwe struct sdhc_host *hp; 246bfa5fdb5Spatrick uint32_t caps; 2474e9dcb19Skettenis int major, minor; 248c538fe19Sfgsch int error = 1; 249445e328eSkettenis int max_clock; 250aae4fe77Suwe 251aae4fe77Suwe /* Allocate one more host structure. */ 252aae4fe77Suwe sc->sc_nhosts++; 2532b585ff0Skrw hp = malloc(sizeof(*hp), M_DEVBUF, M_WAITOK | M_ZERO); 25481aa4bdcSfgsch sc->sc_host[sc->sc_nhosts - 1] = hp; 255aae4fe77Suwe 25604b7fce9Skettenis if (ISSET(sc->sc_flags, SDHC_F_32BIT_ACCESS)) 25704b7fce9Skettenis SET(hp->flags, SHF_USE_32BIT_ACCESS); 25804b7fce9Skettenis 259aae4fe77Suwe /* Fill in the new host structure. */ 260aae4fe77Suwe hp->sc = sc; 261aae4fe77Suwe hp->iot = iot; 262aae4fe77Suwe hp->ioh = ioh; 263aae4fe77Suwe 264445e328eSkettenis /* Store specification version. */ 26504b7fce9Skettenis hp->version = HREAD2(hp, SDHC_HOST_CTL_VERSION); 266445e328eSkettenis 267aae4fe77Suwe /* 268aae4fe77Suwe * Reset the host controller and enable interrupts. 269aae4fe77Suwe */ 270861ce88aSuwe (void)sdhc_host_reset(hp); 271aae4fe77Suwe 272aae4fe77Suwe /* Determine host capabilities. */ 273aae4fe77Suwe caps = HREAD4(hp, SDHC_CAPABILITIES); 274bfa5fdb5Spatrick caps &= ~capmask; 275bfa5fdb5Spatrick caps |= capset; 276aae4fe77Suwe 277aae4fe77Suwe /* Use DMA if the host system and the controller support it. */ 278b60bffefSpatrick if (usedma && ISSET(caps, SDHC_ADMA2_SUPP)) { 279aae4fe77Suwe SET(hp->flags, SHF_USE_DMA); 280b60bffefSpatrick if (ISSET(caps, SDHC_64BIT_DMA_SUPP)) 281b60bffefSpatrick SET(hp->flags, SHF_USE_DMA64); 282b60bffefSpatrick } 283aae4fe77Suwe 284aae4fe77Suwe /* 285aae4fe77Suwe * Determine the base clock frequency. (2.2.24) 286aae4fe77Suwe */ 287445e328eSkettenis if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) { 288445e328eSkettenis /* SDHC 3.0 supports 10-255 MHz. */ 289445e328eSkettenis max_clock = 255000; 290445e328eSkettenis if (SDHC_BASE_FREQ_KHZ_V3(caps) != 0) 291445e328eSkettenis hp->clkbase = SDHC_BASE_FREQ_KHZ_V3(caps); 292445e328eSkettenis } else { 293445e328eSkettenis /* SDHC 1.0/2.0 supports only 10-63 MHz. */ 294445e328eSkettenis max_clock = 63000; 295aae4fe77Suwe if (SDHC_BASE_FREQ_KHZ(caps) != 0) 296aae4fe77Suwe hp->clkbase = SDHC_BASE_FREQ_KHZ(caps); 297445e328eSkettenis } 298aae4fe77Suwe if (hp->clkbase == 0) { 2997b2b2895Skettenis /* Make sure we can clock down to 400 kHz. */ 3007b2b2895Skettenis max_clock = 400 * SDHC_SDCLK_DIV_MAX_V3; 3017b2b2895Skettenis hp->clkbase = sc->sc_clkbase; 3027b2b2895Skettenis } 3037b2b2895Skettenis if (hp->clkbase == 0) { 304aae4fe77Suwe /* The attachment driver must tell us. */ 305aae4fe77Suwe printf("%s: base clock frequency unknown\n", 306aae4fe77Suwe sc->sc_dev.dv_xname); 307aae4fe77Suwe goto err; 308445e328eSkettenis } else if (hp->clkbase < 10000 || hp->clkbase > max_clock) { 309aae4fe77Suwe printf("%s: base clock frequency out of range: %u MHz\n", 310db9033feSfgsch sc->sc_dev.dv_xname, hp->clkbase / 1000); 311aae4fe77Suwe goto err; 312aae4fe77Suwe } 313aae4fe77Suwe 3144e9dcb19Skettenis switch (SDHC_SPEC_VERSION(hp->version)) { 3154e9dcb19Skettenis case SDHC_SPEC_VERS_4_10: 3164e9dcb19Skettenis major = 4, minor = 10; 3174e9dcb19Skettenis break; 3184e9dcb19Skettenis case SDHC_SPEC_VERS_4_20: 3194e9dcb19Skettenis major = 4, minor = 20; 3204e9dcb19Skettenis break; 3214e9dcb19Skettenis default: 3224e9dcb19Skettenis major = SDHC_SPEC_VERSION(hp->version) + 1, minor = 0; 3234e9dcb19Skettenis break; 3244e9dcb19Skettenis } 3254e9dcb19Skettenis 3264e9dcb19Skettenis printf("%s: SDHC %d.%02d, %d MHz base clock\n", DEVNAME(sc), 3274e9dcb19Skettenis major, minor, hp->clkbase / 1000); 328e8385f59Skettenis 329aae4fe77Suwe /* 330aae4fe77Suwe * XXX Set the data timeout counter value according to 331aae4fe77Suwe * capabilities. (2.2.15) 332aae4fe77Suwe */ 333aae4fe77Suwe 334aae4fe77Suwe /* 335aae4fe77Suwe * Determine SD bus voltage levels supported by the controller. 336aae4fe77Suwe */ 337aae4fe77Suwe if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V)) 338b676d50fSkettenis SET(hp->ocr, MMC_OCR_1_65V_1_95V); 339aae4fe77Suwe if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V)) 340aae4fe77Suwe SET(hp->ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V); 341aae4fe77Suwe if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_3V)) 342aae4fe77Suwe SET(hp->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V); 343aae4fe77Suwe 344aae4fe77Suwe /* 345aae4fe77Suwe * Determine the maximum block length supported by the host 346aae4fe77Suwe * controller. (2.2.24) 347aae4fe77Suwe */ 348aae4fe77Suwe switch((caps >> SDHC_MAX_BLK_LEN_SHIFT) & SDHC_MAX_BLK_LEN_MASK) { 349aae4fe77Suwe case SDHC_MAX_BLK_LEN_512: 350aae4fe77Suwe hp->maxblklen = 512; 351aae4fe77Suwe break; 352aae4fe77Suwe case SDHC_MAX_BLK_LEN_1024: 353aae4fe77Suwe hp->maxblklen = 1024; 354aae4fe77Suwe break; 355aae4fe77Suwe case SDHC_MAX_BLK_LEN_2048: 356aae4fe77Suwe hp->maxblklen = 2048; 357aae4fe77Suwe break; 358aae4fe77Suwe default: 359aae4fe77Suwe hp->maxblklen = 1; 360aae4fe77Suwe break; 361aae4fe77Suwe } 362aae4fe77Suwe 363c6293583Skettenis if (ISSET(hp->flags, SHF_USE_DMA)) { 364c6293583Skettenis int rseg; 365c6293583Skettenis 366c6293583Skettenis /* Allocate ADMA2 descriptor memory */ 367c6293583Skettenis error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 368c6293583Skettenis PAGE_SIZE, hp->adma_segs, 1, &rseg, 369c6293583Skettenis BUS_DMA_WAITOK | BUS_DMA_ZERO); 370c6293583Skettenis if (error) 371c6293583Skettenis goto adma_done; 372c6293583Skettenis error = bus_dmamem_map(sc->sc_dmat, hp->adma_segs, rseg, 37312393d97Skettenis PAGE_SIZE, &hp->adma2, BUS_DMA_WAITOK | BUS_DMA_COHERENT); 374c6293583Skettenis if (error) { 375c6293583Skettenis bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg); 376c6293583Skettenis goto adma_done; 377c6293583Skettenis } 378c6293583Skettenis error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 379c6293583Skettenis 0, BUS_DMA_WAITOK, &hp->adma_map); 380c6293583Skettenis if (error) { 381c6293583Skettenis bus_dmamem_unmap(sc->sc_dmat, hp->adma2, PAGE_SIZE); 382c6293583Skettenis bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg); 383c6293583Skettenis goto adma_done; 384c6293583Skettenis } 385c6293583Skettenis error = bus_dmamap_load(sc->sc_dmat, hp->adma_map, 386c6293583Skettenis hp->adma2, PAGE_SIZE, NULL, 387c6293583Skettenis BUS_DMA_WAITOK | BUS_DMA_WRITE); 388c6293583Skettenis if (error) { 389c6293583Skettenis bus_dmamap_destroy(sc->sc_dmat, hp->adma_map); 390c6293583Skettenis bus_dmamem_unmap(sc->sc_dmat, hp->adma2, PAGE_SIZE); 391c6293583Skettenis bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg); 392c6293583Skettenis goto adma_done; 393c6293583Skettenis } 394c6293583Skettenis 395c6293583Skettenis adma_done: 396c6293583Skettenis if (error) { 397c6293583Skettenis printf("%s: can't allocate DMA descriptor table\n", 398c6293583Skettenis DEVNAME(hp->sc)); 399c6293583Skettenis CLR(hp->flags, SHF_USE_DMA); 400c6293583Skettenis } 401c6293583Skettenis } 402c6293583Skettenis 403aae4fe77Suwe /* 404aae4fe77Suwe * Attach the generic SD/MMC bus driver. (The bus driver must 405aae4fe77Suwe * not invoke any chipset functions before it is attached.) 406aae4fe77Suwe */ 407aae4fe77Suwe bzero(&saa, sizeof(saa)); 408aae4fe77Suwe saa.saa_busname = "sdmmc"; 409aae4fe77Suwe saa.sct = &sdhc_functions; 410aae4fe77Suwe saa.sch = hp; 411b140af5cSkettenis saa.caps = SMC_CAPS_4BIT_MODE; 412c6293583Skettenis saa.dmat = sc->sc_dmat; 413834ff46cSdlg saa.dma_boundary = sc->sc_dma_boundary; 414c6293583Skettenis if (ISSET(hp->flags, SHF_USE_DMA)) 415c6293583Skettenis saa.caps |= SMC_CAPS_DMA; 416aae4fe77Suwe 417829e5ee2Skettenis if (ISSET(caps, SDHC_HIGH_SPEED_SUPP)) 418829e5ee2Skettenis saa.caps |= SMC_CAPS_SD_HIGHSPEED; 419829e5ee2Skettenis if (ISSET(caps, SDHC_HIGH_SPEED_SUPP)) 420829e5ee2Skettenis saa.caps |= SMC_CAPS_MMC_HIGHSPEED; 421829e5ee2Skettenis 42282aad119Skettenis if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) { 423820e06f1Skettenis uint32_t caps2 = HREAD4(hp, SDHC_CAPABILITIES2); 424bfa5fdb5Spatrick caps2 &= ~(capmask >> 32); 425bfa5fdb5Spatrick caps2 |= capset >> 32; 426820e06f1Skettenis 42782aad119Skettenis if (ISSET(caps, SDHC_8BIT_MODE_SUPP)) 42882aad119Skettenis saa.caps |= SMC_CAPS_8BIT_MODE; 429820e06f1Skettenis 430820e06f1Skettenis if (ISSET(caps2, SDHC_DDR50_SUPP)) 431820e06f1Skettenis saa.caps |= SMC_CAPS_MMC_DDR52; 43282aad119Skettenis } 43382aad119Skettenis 434fd406f4dSstsp if (ISSET(sc->sc_flags, SDHC_F_NONREMOVABLE)) 435fd406f4dSstsp saa.caps |= SMC_CAPS_NONREMOVABLE; 436fd406f4dSstsp 437aae4fe77Suwe hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL); 438aae4fe77Suwe if (hp->sdmmc == NULL) { 439c538fe19Sfgsch error = 0; 440aae4fe77Suwe goto err; 441aae4fe77Suwe } 442aae4fe77Suwe 443aae4fe77Suwe return 0; 444aae4fe77Suwe 445aae4fe77Suwe err: 44687985770Sderaadt free(hp, M_DEVBUF, sizeof *hp); 44781aa4bdcSfgsch sc->sc_host[sc->sc_nhosts - 1] = NULL; 448aae4fe77Suwe sc->sc_nhosts--; 449c538fe19Sfgsch return (error); 450aae4fe77Suwe } 451aae4fe77Suwe 4522c6678e4Sderaadt int 4532c6678e4Sderaadt sdhc_activate(struct device *self, int act) 454aae4fe77Suwe { 4552c6678e4Sderaadt struct sdhc_softc *sc = (struct sdhc_softc *)self; 456f50f4931Suwe struct sdhc_host *hp; 457b7fbe345Sderaadt int n, i, rv = 0; 458aae4fe77Suwe 4592c6678e4Sderaadt switch (act) { 4602c6678e4Sderaadt case DVACT_SUSPEND: 46100c76a70Sderaadt rv = config_activate_children(self, act); 462f50f4931Suwe 463f50f4931Suwe /* Save the host controller state. */ 464f50f4931Suwe for (n = 0; n < sc->sc_nhosts; n++) { 46581aa4bdcSfgsch hp = sc->sc_host[n]; 466f50f4931Suwe for (i = 0; i < sizeof hp->regs; i++) 467f50f4931Suwe hp->regs[i] = HREAD1(hp, i); 468f50f4931Suwe } 469aae4fe77Suwe break; 4702c6678e4Sderaadt case DVACT_RESUME: 471f50f4931Suwe /* Restore the host controller state. */ 472f50f4931Suwe for (n = 0; n < sc->sc_nhosts; n++) { 47381aa4bdcSfgsch hp = sc->sc_host[n]; 474861ce88aSuwe (void)sdhc_host_reset(hp); 475f50f4931Suwe for (i = 0; i < sizeof hp->regs; i++) 476f50f4931Suwe HWRITE1(hp, i, hp->regs[i]); 477f50f4931Suwe } 478b7fbe345Sderaadt rv = config_activate_children(self, act); 479aae4fe77Suwe break; 48037ecb596Sderaadt case DVACT_POWERDOWN: 48137ecb596Sderaadt rv = config_activate_children(self, act); 48237ecb596Sderaadt sdhc_shutdown(self); 48337ecb596Sderaadt break; 48437ecb596Sderaadt default: 48537ecb596Sderaadt rv = config_activate_children(self, act); 48637ecb596Sderaadt break; 487aae4fe77Suwe } 488b7fbe345Sderaadt return (rv); 4892c6678e4Sderaadt } 4902c6678e4Sderaadt 491aae4fe77Suwe /* 492aae4fe77Suwe * Shutdown hook established by or called from attachment driver. 493aae4fe77Suwe */ 494aae4fe77Suwe void 495aae4fe77Suwe sdhc_shutdown(void *arg) 496aae4fe77Suwe { 497aae4fe77Suwe struct sdhc_softc *sc = arg; 498aae4fe77Suwe struct sdhc_host *hp; 499aae4fe77Suwe int i; 500aae4fe77Suwe 501aae4fe77Suwe /* XXX chip locks up if we don't disable it before reboot. */ 502aae4fe77Suwe for (i = 0; i < sc->sc_nhosts; i++) { 50381aa4bdcSfgsch hp = sc->sc_host[i]; 504861ce88aSuwe (void)sdhc_host_reset(hp); 505aae4fe77Suwe } 506aae4fe77Suwe } 507aae4fe77Suwe 508aae4fe77Suwe /* 509aae4fe77Suwe * Reset the host controller. Called during initialization, when 510861ce88aSuwe * cards are removed, upon resume, and during error recovery. 511aae4fe77Suwe */ 512aae4fe77Suwe int 513aae4fe77Suwe sdhc_host_reset(sdmmc_chipset_handle_t sch) 514aae4fe77Suwe { 515aae4fe77Suwe struct sdhc_host *hp = sch; 516aae4fe77Suwe u_int16_t imask; 5175842cfcdSfgsch int error; 518aae4fe77Suwe int s; 519aae4fe77Suwe 520aae4fe77Suwe s = splsdmmc(); 521aae4fe77Suwe 522aae4fe77Suwe /* Disable all interrupts. */ 523aae4fe77Suwe HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, 0); 524aae4fe77Suwe 525aae4fe77Suwe /* 526861ce88aSuwe * Reset the entire host controller and wait up to 100ms for 527861ce88aSuwe * the controller to clear the reset bit. 528aae4fe77Suwe */ 529f2fcfe5eSkrw if ((error = sdhc_soft_reset(hp, SDHC_RESET_ALL)) != 0) { 530f2fcfe5eSkrw splx(s); 5315842cfcdSfgsch return (error); 532f2fcfe5eSkrw } 533aae4fe77Suwe 534aae4fe77Suwe /* Set data timeout counter value to max for now. */ 535aae4fe77Suwe HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX); 536aae4fe77Suwe 537aae4fe77Suwe /* Enable interrupts. */ 538aae4fe77Suwe imask = SDHC_CARD_REMOVAL | SDHC_CARD_INSERTION | 539aae4fe77Suwe SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY | 540aae4fe77Suwe SDHC_DMA_INTERRUPT | SDHC_BLOCK_GAP_EVENT | 541b979651fSuwe SDHC_TRANSFER_COMPLETE | SDHC_COMMAND_COMPLETE; 542393d192eSuwe 543aae4fe77Suwe HWRITE2(hp, SDHC_NINTR_STATUS_EN, imask); 544aae4fe77Suwe HWRITE2(hp, SDHC_EINTR_STATUS_EN, SDHC_EINTR_STATUS_MASK); 545aae4fe77Suwe HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, imask); 546aae4fe77Suwe HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK); 547aae4fe77Suwe 548aae4fe77Suwe splx(s); 549861ce88aSuwe return 0; 550aae4fe77Suwe } 551aae4fe77Suwe 552aae4fe77Suwe u_int32_t 553aae4fe77Suwe sdhc_host_ocr(sdmmc_chipset_handle_t sch) 554aae4fe77Suwe { 555aae4fe77Suwe struct sdhc_host *hp = sch; 556aae4fe77Suwe return hp->ocr; 557aae4fe77Suwe } 558aae4fe77Suwe 559aae4fe77Suwe int 560aae4fe77Suwe sdhc_host_maxblklen(sdmmc_chipset_handle_t sch) 561aae4fe77Suwe { 562aae4fe77Suwe struct sdhc_host *hp = sch; 563aae4fe77Suwe return hp->maxblklen; 564aae4fe77Suwe } 565aae4fe77Suwe 566aae4fe77Suwe /* 567aae4fe77Suwe * Return non-zero if the card is currently inserted. 568aae4fe77Suwe */ 569aae4fe77Suwe int 570aae4fe77Suwe sdhc_card_detect(sdmmc_chipset_handle_t sch) 571aae4fe77Suwe { 572aae4fe77Suwe struct sdhc_host *hp = sch; 57388a093b3Skettenis 57488a093b3Skettenis if (hp->sc->sc_card_detect) 57588a093b3Skettenis return hp->sc->sc_card_detect(hp->sc); 57688a093b3Skettenis 577aae4fe77Suwe return ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED) ? 578aae4fe77Suwe 1 : 0; 579aae4fe77Suwe } 580aae4fe77Suwe 581aae4fe77Suwe /* 582aae4fe77Suwe * Set or change SD bus voltage and enable or disable SD bus power. 583aae4fe77Suwe * Return zero on success. 584aae4fe77Suwe */ 585aae4fe77Suwe int 586aae4fe77Suwe sdhc_bus_power(sdmmc_chipset_handle_t sch, u_int32_t ocr) 587aae4fe77Suwe { 588aae4fe77Suwe struct sdhc_host *hp = sch; 589aae4fe77Suwe u_int8_t vdd; 590aae4fe77Suwe int s; 591aae4fe77Suwe 592aae4fe77Suwe s = splsdmmc(); 593aae4fe77Suwe 594aae4fe77Suwe /* If power is disabled, reset the host and return now. */ 595aae4fe77Suwe if (ocr == 0) { 596*8ab765f8Shastings HWRITE1(hp, SDHC_POWER_CTL, 0); 597aae4fe77Suwe splx(s); 598861ce88aSuwe (void)sdhc_host_reset(hp); 599aae4fe77Suwe return 0; 600aae4fe77Suwe } 601aae4fe77Suwe 602aae4fe77Suwe /* 603aae4fe77Suwe * Select the maximum voltage according to capabilities. 604aae4fe77Suwe */ 605aae4fe77Suwe ocr &= hp->ocr; 606aae4fe77Suwe if (ISSET(ocr, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V)) 607aae4fe77Suwe vdd = SDHC_VOLTAGE_3_3V; 608aae4fe77Suwe else if (ISSET(ocr, MMC_OCR_2_9V_3_0V|MMC_OCR_3_0V_3_1V)) 609aae4fe77Suwe vdd = SDHC_VOLTAGE_3_0V; 610b676d50fSkettenis else if (ISSET(ocr, MMC_OCR_1_65V_1_95V)) 611aae4fe77Suwe vdd = SDHC_VOLTAGE_1_8V; 612aae4fe77Suwe else { 613aae4fe77Suwe /* Unsupported voltage level requested. */ 614aae4fe77Suwe splx(s); 615aae4fe77Suwe return EINVAL; 616aae4fe77Suwe } 617aae4fe77Suwe 618aae4fe77Suwe /* 619*8ab765f8Shastings * Return if no change to powered bus voltage. 620*8ab765f8Shastings */ 621*8ab765f8Shastings if (HREAD1(hp, SDHC_POWER_CTL) == 622*8ab765f8Shastings ((vdd << SDHC_VOLTAGE_SHIFT) | SDHC_BUS_POWER)) { 623*8ab765f8Shastings splx(s); 624*8ab765f8Shastings return 0; 625*8ab765f8Shastings } 626*8ab765f8Shastings 627*8ab765f8Shastings /* 628*8ab765f8Shastings * Disable bus power before voltage change. 629*8ab765f8Shastings */ 630*8ab765f8Shastings if (!(hp->sc->sc_flags & SDHC_F_NOPWR0)) 631*8ab765f8Shastings HWRITE1(hp, SDHC_POWER_CTL, 0); 632*8ab765f8Shastings 633*8ab765f8Shastings /* 634aae4fe77Suwe * Enable bus power. Wait at least 1 ms (or 74 clocks) plus 635aae4fe77Suwe * voltage ramp until power rises. 636aae4fe77Suwe */ 637aae4fe77Suwe HWRITE1(hp, SDHC_POWER_CTL, (vdd << SDHC_VOLTAGE_SHIFT) | 638aae4fe77Suwe SDHC_BUS_POWER); 639aae4fe77Suwe sdmmc_delay(10000); 640aae4fe77Suwe 641aae4fe77Suwe /* 642aae4fe77Suwe * The host system may not power the bus due to battery low, 643aae4fe77Suwe * etc. In that case, the host controller should clear the 644aae4fe77Suwe * bus power bit. 645aae4fe77Suwe */ 646aae4fe77Suwe if (!ISSET(HREAD1(hp, SDHC_POWER_CTL), SDHC_BUS_POWER)) { 647aae4fe77Suwe splx(s); 648aae4fe77Suwe return ENXIO; 649aae4fe77Suwe } 650aae4fe77Suwe 651aae4fe77Suwe splx(s); 652aae4fe77Suwe return 0; 653aae4fe77Suwe } 654aae4fe77Suwe 655aae4fe77Suwe /* 656aae4fe77Suwe * Return the smallest possible base clock frequency divisor value 657aae4fe77Suwe * for the CLOCK_CTL register to produce `freq' (KHz). 658aae4fe77Suwe */ 659aae4fe77Suwe static int 660aae4fe77Suwe sdhc_clock_divisor(struct sdhc_host *hp, u_int freq) 661aae4fe77Suwe { 662aae4fe77Suwe int div; 663aae4fe77Suwe 664e7a76d17Spatrick if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) { 665e7a76d17Spatrick if (hp->clkbase <= freq) 666e7a76d17Spatrick return 0; 667445e328eSkettenis 668e7a76d17Spatrick for (div = 2; div <= SDHC_SDCLK_DIV_MAX_V3; div += 2) 669aae4fe77Suwe if ((hp->clkbase / div) <= freq) 670aae4fe77Suwe return (div / 2); 671e7a76d17Spatrick } else { 672e7a76d17Spatrick for (div = 1; div <= SDHC_SDCLK_DIV_MAX; div *= 2) 673e7a76d17Spatrick if ((hp->clkbase / div) <= freq) 674e7a76d17Spatrick return (div / 2); 675e7a76d17Spatrick } 676e7a76d17Spatrick 677aae4fe77Suwe /* No divisor found. */ 678aae4fe77Suwe return -1; 679aae4fe77Suwe } 680aae4fe77Suwe 681aae4fe77Suwe /* 682aae4fe77Suwe * Set or change SDCLK frequency or disable the SD clock. 683aae4fe77Suwe * Return zero on success. 684aae4fe77Suwe */ 685aae4fe77Suwe int 686820e06f1Skettenis sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing) 687aae4fe77Suwe { 688aae4fe77Suwe struct sdhc_host *hp = sch; 689d03761f2Smglocker struct sdhc_softc *sc = hp->sc; 690aae4fe77Suwe int s; 691aae4fe77Suwe int div; 692445e328eSkettenis int sdclk; 693aae4fe77Suwe int timo; 694aae4fe77Suwe int error = 0; 695aae4fe77Suwe 696aae4fe77Suwe s = splsdmmc(); 697aae4fe77Suwe 698fa1cdcb1Spatrick if (hp->sc->sc_bus_clock_pre) 699fa1cdcb1Spatrick hp->sc->sc_bus_clock_pre(hp->sc, freq, timing); 700fa1cdcb1Spatrick 701aae4fe77Suwe #ifdef DIAGNOSTIC 702aae4fe77Suwe /* Must not stop the clock if commands are in progress. */ 703aae4fe77Suwe if (ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK) && 704aae4fe77Suwe sdhc_card_detect(hp)) 705aae4fe77Suwe printf("sdhc_sdclk_frequency_select: command in progress\n"); 706aae4fe77Suwe #endif 707aae4fe77Suwe 708aae4fe77Suwe /* 709aae4fe77Suwe * Stop SD clock before changing the frequency. 710aae4fe77Suwe */ 711aae4fe77Suwe HWRITE2(hp, SDHC_CLOCK_CTL, 0); 712aae4fe77Suwe if (freq == SDMMC_SDCLK_OFF) 713aae4fe77Suwe goto ret; 714aae4fe77Suwe 715d03761f2Smglocker if (!ISSET(sc->sc_flags, SDHC_F_NO_HS_BIT)) { 716820e06f1Skettenis if (timing == SDMMC_TIMING_LEGACY) 717820e06f1Skettenis HCLR1(hp, SDHC_HOST_CTL, SDHC_HIGH_SPEED); 718820e06f1Skettenis else 719820e06f1Skettenis HSET1(hp, SDHC_HOST_CTL, SDHC_HIGH_SPEED); 720d03761f2Smglocker } 721820e06f1Skettenis 722820e06f1Skettenis if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) { 723820e06f1Skettenis switch (timing) { 724820e06f1Skettenis case SDMMC_TIMING_MMC_DDR52: 725820e06f1Skettenis HCLR2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_MASK); 726820e06f1Skettenis HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_DDR50); 727820e06f1Skettenis break; 728820e06f1Skettenis } 729820e06f1Skettenis } 730820e06f1Skettenis 731aae4fe77Suwe /* 732aae4fe77Suwe * Set the minimum base clock frequency divisor. 733aae4fe77Suwe */ 734aae4fe77Suwe if ((div = sdhc_clock_divisor(hp, freq)) < 0) { 735aae4fe77Suwe /* Invalid base clock frequency or `freq' value. */ 736aae4fe77Suwe error = EINVAL; 737aae4fe77Suwe goto ret; 738aae4fe77Suwe } 739445e328eSkettenis if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) 740445e328eSkettenis sdclk = SDHC_SDCLK_DIV_V3(div); 741445e328eSkettenis else 742445e328eSkettenis sdclk = SDHC_SDCLK_DIV(div); 743445e328eSkettenis HWRITE2(hp, SDHC_CLOCK_CTL, sdclk); 744aae4fe77Suwe 745aae4fe77Suwe /* 746aae4fe77Suwe * Start internal clock. Wait 10ms for stabilization. 747aae4fe77Suwe */ 748aae4fe77Suwe HSET2(hp, SDHC_CLOCK_CTL, SDHC_INTCLK_ENABLE); 749aae4fe77Suwe for (timo = 1000; timo > 0; timo--) { 750aae4fe77Suwe if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL), SDHC_INTCLK_STABLE)) 751aae4fe77Suwe break; 752aae4fe77Suwe sdmmc_delay(10); 753aae4fe77Suwe } 754aae4fe77Suwe if (timo == 0) { 755aae4fe77Suwe error = ETIMEDOUT; 756aae4fe77Suwe goto ret; 757aae4fe77Suwe } 758aae4fe77Suwe 759aae4fe77Suwe /* 760aae4fe77Suwe * Enable SD clock. 761aae4fe77Suwe */ 762aae4fe77Suwe HSET2(hp, SDHC_CLOCK_CTL, SDHC_SDCLK_ENABLE); 763aae4fe77Suwe 764fa1cdcb1Spatrick if (hp->sc->sc_bus_clock_post) 765fa1cdcb1Spatrick hp->sc->sc_bus_clock_post(hp->sc, freq, timing); 766fa1cdcb1Spatrick 767aae4fe77Suwe ret: 768aae4fe77Suwe splx(s); 769aae4fe77Suwe return error; 770aae4fe77Suwe } 771aae4fe77Suwe 772b140af5cSkettenis int 773b140af5cSkettenis sdhc_bus_width(sdmmc_chipset_handle_t sch, int width) 774b140af5cSkettenis { 775b140af5cSkettenis struct sdhc_host *hp = (struct sdhc_host *)sch; 776b140af5cSkettenis int reg; 777b140af5cSkettenis int s; 778b140af5cSkettenis 779b140af5cSkettenis if (width != 1 && width != 4 && width != 8) 780820e06f1Skettenis return EINVAL; 781b140af5cSkettenis 782b140af5cSkettenis s = splsdmmc(); 783b140af5cSkettenis 784b140af5cSkettenis reg = HREAD1(hp, SDHC_HOST_CTL); 785b140af5cSkettenis reg &= ~SDHC_4BIT_MODE; 786b140af5cSkettenis if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) { 787b140af5cSkettenis reg &= ~SDHC_8BIT_MODE; 788b140af5cSkettenis } 789b140af5cSkettenis if (width == 4) { 790b140af5cSkettenis reg |= SDHC_4BIT_MODE; 791b140af5cSkettenis } else if (width == 8) { 792b140af5cSkettenis KASSERT(SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3); 793b140af5cSkettenis reg |= SDHC_8BIT_MODE; 794b140af5cSkettenis } 795b140af5cSkettenis HWRITE1(hp, SDHC_HOST_CTL, reg); 796b140af5cSkettenis 797b140af5cSkettenis splx(s); 798b140af5cSkettenis 799b140af5cSkettenis return 0; 800b140af5cSkettenis } 801b140af5cSkettenis 802b979651fSuwe void 803b979651fSuwe sdhc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable) 804b979651fSuwe { 805b979651fSuwe struct sdhc_host *hp = sch; 806b979651fSuwe 807b979651fSuwe if (enable) { 808b979651fSuwe HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); 809b979651fSuwe HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT); 810b979651fSuwe } else { 811b979651fSuwe HCLR2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT); 812b979651fSuwe HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); 813b979651fSuwe } 814b979651fSuwe } 815b979651fSuwe 816b979651fSuwe void 817b979651fSuwe sdhc_card_intr_ack(sdmmc_chipset_handle_t sch) 818b979651fSuwe { 819b979651fSuwe struct sdhc_host *hp = sch; 820b979651fSuwe 821b979651fSuwe HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); 822b979651fSuwe } 823aae4fe77Suwe 824aae4fe77Suwe int 825820e06f1Skettenis sdhc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage) 826820e06f1Skettenis { 827820e06f1Skettenis struct sdhc_host *hp = sch; 828820e06f1Skettenis 829c2deed7fSkettenis if (hp->sc->sc_signal_voltage) 830c2deed7fSkettenis return hp->sc->sc_signal_voltage(hp->sc, signal_voltage); 831c2deed7fSkettenis 832820e06f1Skettenis if (SDHC_SPEC_VERSION(hp->version) < SDHC_SPEC_V3) 833820e06f1Skettenis return EINVAL; 834820e06f1Skettenis 835820e06f1Skettenis switch (signal_voltage) { 836820e06f1Skettenis case SDMMC_SIGNAL_VOLTAGE_180: 837820e06f1Skettenis HSET2(hp, SDHC_HOST_CTL2, SDHC_1_8V_SIGNAL_EN); 838820e06f1Skettenis break; 839820e06f1Skettenis case SDMMC_SIGNAL_VOLTAGE_330: 840820e06f1Skettenis HCLR2(hp, SDHC_HOST_CTL2, SDHC_1_8V_SIGNAL_EN); 841820e06f1Skettenis break; 842820e06f1Skettenis default: 843820e06f1Skettenis return EINVAL; 844820e06f1Skettenis } 845820e06f1Skettenis 846820e06f1Skettenis /* Regulator output shall be stable within 5 ms. */ 847820e06f1Skettenis sdmmc_delay(5000); 848820e06f1Skettenis 849820e06f1Skettenis /* Host controller clears this bit if 1.8V signalling fails. */ 850820e06f1Skettenis if (signal_voltage == SDMMC_SIGNAL_VOLTAGE_180 && 851679ad45bSpatrick !ISSET(HREAD2(hp, SDHC_HOST_CTL2), SDHC_1_8V_SIGNAL_EN)) 852820e06f1Skettenis return EIO; 853820e06f1Skettenis 854820e06f1Skettenis return 0; 855820e06f1Skettenis } 856820e06f1Skettenis 857820e06f1Skettenis int 858aae4fe77Suwe sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value) 859aae4fe77Suwe { 860aae4fe77Suwe u_int32_t state; 861aae4fe77Suwe int timeout; 862aae4fe77Suwe 863aae4fe77Suwe for (timeout = 10; timeout > 0; timeout--) { 864aae4fe77Suwe if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask) 865aae4fe77Suwe == value) 866aae4fe77Suwe return 0; 867aae4fe77Suwe sdmmc_delay(10000); 868aae4fe77Suwe } 869a93f47f6Sjasper DPRINTF(0,("%s: timeout waiting for %x (state=%b)\n", DEVNAME(hp->sc), 870aae4fe77Suwe value, state, SDHC_PRESENT_STATE_BITS)); 871aae4fe77Suwe return ETIMEDOUT; 872aae4fe77Suwe } 873aae4fe77Suwe 874a6fd99a7Suwe void 875a6fd99a7Suwe sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 876a6fd99a7Suwe { 877a6fd99a7Suwe struct sdhc_host *hp = sch; 878a6fd99a7Suwe int error; 879a6fd99a7Suwe 880a6fd99a7Suwe /* 881a6fd99a7Suwe * Start the MMC command, or mark `cmd' as failed and return. 882a6fd99a7Suwe */ 883a6fd99a7Suwe error = sdhc_start_command(hp, cmd); 884a6fd99a7Suwe if (error != 0) { 885a6fd99a7Suwe cmd->c_error = error; 886a6fd99a7Suwe SET(cmd->c_flags, SCF_ITSDONE); 887a6fd99a7Suwe return; 888a6fd99a7Suwe } 889a6fd99a7Suwe 890a6fd99a7Suwe /* 891a6fd99a7Suwe * Wait until the command phase is done, or until the command 892a6fd99a7Suwe * is marked done for any other reason. 893a6fd99a7Suwe */ 894a6fd99a7Suwe if (!sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE, 895a6fd99a7Suwe SDHC_COMMAND_TIMEOUT)) { 896a6fd99a7Suwe cmd->c_error = ETIMEDOUT; 897a6fd99a7Suwe SET(cmd->c_flags, SCF_ITSDONE); 898a6fd99a7Suwe return; 899a6fd99a7Suwe } 900a6fd99a7Suwe 901a6fd99a7Suwe /* 902a6fd99a7Suwe * The host controller removes bits [0:7] from the response 903a6fd99a7Suwe * data (CRC) and we pass the data up unchanged to the bus 904a6fd99a7Suwe * driver (without padding). 905a6fd99a7Suwe */ 906a6fd99a7Suwe if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) { 907a6fd99a7Suwe if (ISSET(cmd->c_flags, SCF_RSP_136)) { 908a6fd99a7Suwe u_char *p = (u_char *)cmd->c_resp; 909a6fd99a7Suwe int i; 910a6fd99a7Suwe 911a6fd99a7Suwe for (i = 0; i < 15; i++) 912a6fd99a7Suwe *p++ = HREAD1(hp, SDHC_RESPONSE + i); 913a6fd99a7Suwe } else 914a6fd99a7Suwe cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE); 915a6fd99a7Suwe } 916a6fd99a7Suwe 917a6fd99a7Suwe /* 918a6fd99a7Suwe * If the command has data to transfer in any direction, 919a6fd99a7Suwe * execute the transfer now. 920a6fd99a7Suwe */ 921a6fd99a7Suwe if (cmd->c_error == 0 && cmd->c_data != NULL) 922a6fd99a7Suwe sdhc_transfer_data(hp, cmd); 923a6fd99a7Suwe 924a6fd99a7Suwe /* Turn off the LED. */ 925a6fd99a7Suwe HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON); 926a6fd99a7Suwe 92737539bbbSuwe DPRINTF(1,("%s: cmd %u done (flags=%#x error=%d)\n", 928a93f47f6Sjasper DEVNAME(hp->sc), cmd->c_opcode, cmd->c_flags, cmd->c_error)); 929a6fd99a7Suwe SET(cmd->c_flags, SCF_ITSDONE); 930a6fd99a7Suwe } 931a6fd99a7Suwe 932aae4fe77Suwe int 933aae4fe77Suwe sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd) 934aae4fe77Suwe { 935b60bffefSpatrick struct sdhc_adma2_descriptor32 *desc32 = (void *)hp->adma2; 936b60bffefSpatrick struct sdhc_adma2_descriptor64 *desc64 = (void *)hp->adma2; 937c6293583Skettenis struct sdhc_softc *sc = hp->sc; 938aae4fe77Suwe u_int16_t blksize = 0; 939aae4fe77Suwe u_int16_t blkcount = 0; 940aae4fe77Suwe u_int16_t mode; 941aae4fe77Suwe u_int16_t command; 942aae4fe77Suwe int error; 943c6293583Skettenis int seg; 944aae4fe77Suwe int s; 945aae4fe77Suwe 9461dd2d335Sians DPRINTF(1,("%s: start cmd %u arg=%#x data=%p dlen=%d flags=%#x\n", 9471dd2d335Sians DEVNAME(hp->sc), cmd->c_opcode, cmd->c_arg, cmd->c_data, 9481dd2d335Sians cmd->c_datalen, cmd->c_flags)); 949aae4fe77Suwe 950aae4fe77Suwe /* 951aae4fe77Suwe * The maximum block length for commands should be the minimum 952aae4fe77Suwe * of the host buffer size and the card buffer size. (1.7.2) 953aae4fe77Suwe */ 954aae4fe77Suwe 955aae4fe77Suwe /* Fragment the data into proper blocks. */ 956aae4fe77Suwe if (cmd->c_datalen > 0) { 957393d192eSuwe blksize = MIN(cmd->c_datalen, cmd->c_blklen); 958aae4fe77Suwe blkcount = cmd->c_datalen / blksize; 959aae4fe77Suwe if (cmd->c_datalen % blksize > 0) { 960aae4fe77Suwe /* XXX: Split this command. (1.7.4) */ 961aae4fe77Suwe printf("%s: data not a multiple of %d bytes\n", 962a93f47f6Sjasper DEVNAME(hp->sc), blksize); 963aae4fe77Suwe return EINVAL; 964aae4fe77Suwe } 965aae4fe77Suwe } 966aae4fe77Suwe 967aae4fe77Suwe /* Check limit imposed by 9-bit block count. (1.7.2) */ 968aae4fe77Suwe if (blkcount > SDHC_BLOCK_COUNT_MAX) { 969a93f47f6Sjasper printf("%s: too much data\n", DEVNAME(hp->sc)); 970aae4fe77Suwe return EINVAL; 971aae4fe77Suwe } 972aae4fe77Suwe 973aae4fe77Suwe /* Prepare transfer mode register value. (2.2.5) */ 974aae4fe77Suwe mode = 0; 975aae4fe77Suwe if (ISSET(cmd->c_flags, SCF_CMD_READ)) 976aae4fe77Suwe mode |= SDHC_READ_MODE; 977aae4fe77Suwe if (blkcount > 0) { 978aae4fe77Suwe mode |= SDHC_BLOCK_COUNT_ENABLE; 979aae4fe77Suwe if (blkcount > 1) { 980aae4fe77Suwe mode |= SDHC_MULTI_BLOCK_MODE; 981402f30eeSpatrick if (cmd->c_opcode != SD_IO_RW_EXTENDED) 982aae4fe77Suwe mode |= SDHC_AUTO_CMD12_ENABLE; 983aae4fe77Suwe } 984aae4fe77Suwe } 985c6293583Skettenis if (cmd->c_dmamap && cmd->c_datalen > 0 && 986c6293583Skettenis ISSET(hp->flags, SHF_USE_DMA)) 987aae4fe77Suwe mode |= SDHC_DMA_ENABLE; 988aae4fe77Suwe 989aae4fe77Suwe /* 990aae4fe77Suwe * Prepare command register value. (2.2.6) 991aae4fe77Suwe */ 992aae4fe77Suwe command = (cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) << 993aae4fe77Suwe SDHC_COMMAND_INDEX_SHIFT; 994aae4fe77Suwe 995aae4fe77Suwe if (ISSET(cmd->c_flags, SCF_RSP_CRC)) 996aae4fe77Suwe command |= SDHC_CRC_CHECK_ENABLE; 997aae4fe77Suwe if (ISSET(cmd->c_flags, SCF_RSP_IDX)) 998aae4fe77Suwe command |= SDHC_INDEX_CHECK_ENABLE; 999aae4fe77Suwe if (cmd->c_data != NULL) 1000aae4fe77Suwe command |= SDHC_DATA_PRESENT_SELECT; 1001aae4fe77Suwe 1002aae4fe77Suwe if (!ISSET(cmd->c_flags, SCF_RSP_PRESENT)) 1003aae4fe77Suwe command |= SDHC_NO_RESPONSE; 1004aae4fe77Suwe else if (ISSET(cmd->c_flags, SCF_RSP_136)) 1005aae4fe77Suwe command |= SDHC_RESP_LEN_136; 1006aae4fe77Suwe else if (ISSET(cmd->c_flags, SCF_RSP_BSY)) 1007aae4fe77Suwe command |= SDHC_RESP_LEN_48_CHK_BUSY; 1008aae4fe77Suwe else 1009aae4fe77Suwe command |= SDHC_RESP_LEN_48; 1010aae4fe77Suwe 1011aae4fe77Suwe /* Wait until command and data inhibit bits are clear. (1.5) */ 1012aae4fe77Suwe if ((error = sdhc_wait_state(hp, SDHC_CMD_INHIBIT_MASK, 0)) != 0) 1013aae4fe77Suwe return error; 1014aae4fe77Suwe 1015aae4fe77Suwe s = splsdmmc(); 1016aae4fe77Suwe 1017aae4fe77Suwe /* Alert the user not to remove the card. */ 1018aae4fe77Suwe HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON); 1019aae4fe77Suwe 1020c6293583Skettenis /* Set DMA start address if SHF_USE_DMA is set. */ 1021c6293583Skettenis if (cmd->c_dmamap && ISSET(hp->flags, SHF_USE_DMA)) { 1022c6293583Skettenis for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { 1023c6293583Skettenis bus_addr_t paddr = 1024c6293583Skettenis cmd->c_dmamap->dm_segs[seg].ds_addr; 1025c6293583Skettenis uint16_t len = 1026c6293583Skettenis cmd->c_dmamap->dm_segs[seg].ds_len == 65536 ? 1027c6293583Skettenis 0 : cmd->c_dmamap->dm_segs[seg].ds_len; 1028c6293583Skettenis uint16_t attr; 1029c6293583Skettenis 1030c6293583Skettenis attr = SDHC_ADMA2_VALID | SDHC_ADMA2_ACT_TRANS; 1031c6293583Skettenis if (seg == cmd->c_dmamap->dm_nsegs - 1) 1032c6293583Skettenis attr |= SDHC_ADMA2_END; 1033c6293583Skettenis 1034b60bffefSpatrick if (ISSET(hp->flags, SHF_USE_DMA64)) { 1035b60bffefSpatrick desc64[seg].attribute = htole16(attr); 1036b60bffefSpatrick desc64[seg].length = htole16(len); 1037b60bffefSpatrick desc64[seg].address_lo = 1038b60bffefSpatrick htole32((uint64_t)paddr & 0xffffffff); 1039b60bffefSpatrick desc64[seg].address_hi = 1040b60bffefSpatrick htole32((uint64_t)paddr >> 32); 1041b60bffefSpatrick } else { 1042b60bffefSpatrick desc32[seg].attribute = htole16(attr); 1043b60bffefSpatrick desc32[seg].length = htole16(len); 1044b60bffefSpatrick desc32[seg].address = htole32(paddr); 1045b60bffefSpatrick } 1046c6293583Skettenis } 1047c6293583Skettenis 1048b60bffefSpatrick if (ISSET(hp->flags, SHF_USE_DMA64)) 1049b60bffefSpatrick desc64[cmd->c_dmamap->dm_nsegs].attribute = htole16(0); 1050b60bffefSpatrick else 1051b60bffefSpatrick desc32[cmd->c_dmamap->dm_nsegs].attribute = htole16(0); 1052c6293583Skettenis 1053c6293583Skettenis bus_dmamap_sync(sc->sc_dmat, hp->adma_map, 0, PAGE_SIZE, 1054c6293583Skettenis BUS_DMASYNC_PREWRITE); 1055c6293583Skettenis 1056c6293583Skettenis HCLR1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT); 1057b60bffefSpatrick if (ISSET(hp->flags, SHF_USE_DMA64)) 1058b60bffefSpatrick HSET1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT_ADMA64); 1059b60bffefSpatrick else 1060b60bffefSpatrick HSET1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT_ADMA32); 1061c6293583Skettenis 1062c6293583Skettenis HWRITE4(hp, SDHC_ADMA_SYSTEM_ADDR, 1063c6293583Skettenis hp->adma_map->dm_segs[0].ds_addr); 1064cb39577eSpatrick } else 1065cb39577eSpatrick HCLR1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT); 1066aae4fe77Suwe 106737539bbbSuwe DPRINTF(1,("%s: cmd=%#x mode=%#x blksize=%d blkcount=%d\n", 1068a93f47f6Sjasper DEVNAME(hp->sc), command, mode, blksize, blkcount)); 1069f6697933Sfgsch 1070d80c3592Spatrick /* We're starting a new command, reset state. */ 1071d80c3592Spatrick hp->intr_status = 0; 1072d80c3592Spatrick 1073aae4fe77Suwe /* 1074aae4fe77Suwe * Start a CPU data transfer. Writing to the high order byte 1075aae4fe77Suwe * of the SDHC_COMMAND register triggers the SD command. (1.5) 1076aae4fe77Suwe */ 1077393d192eSuwe HWRITE2(hp, SDHC_TRANSFER_MODE, mode); 1078aae4fe77Suwe HWRITE2(hp, SDHC_BLOCK_SIZE, blksize); 1079aae4fe77Suwe HWRITE2(hp, SDHC_BLOCK_COUNT, blkcount); 1080aae4fe77Suwe HWRITE4(hp, SDHC_ARGUMENT, cmd->c_arg); 1081aae4fe77Suwe HWRITE2(hp, SDHC_COMMAND, command); 1082aae4fe77Suwe 1083aae4fe77Suwe splx(s); 1084aae4fe77Suwe return 0; 1085aae4fe77Suwe } 1086aae4fe77Suwe 1087aae4fe77Suwe void 1088a6fd99a7Suwe sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd) 1089aae4fe77Suwe { 109012393d97Skettenis struct sdhc_softc *sc = hp->sc; 1091aae4fe77Suwe u_char *datap = cmd->c_data; 1092aae4fe77Suwe int i, datalen; 1093aae4fe77Suwe int mask; 1094aae4fe77Suwe int error; 1095aae4fe77Suwe 1096c6293583Skettenis if (cmd->c_dmamap) { 1097c6293583Skettenis int status; 1098c6293583Skettenis 1099c6293583Skettenis error = 0; 1100c6293583Skettenis for (;;) { 1101c6293583Skettenis status = sdhc_wait_intr(hp, 1102c6293583Skettenis SDHC_DMA_INTERRUPT|SDHC_TRANSFER_COMPLETE, 1103c6293583Skettenis SDHC_DMA_TIMEOUT); 1104c6293583Skettenis if (status & SDHC_TRANSFER_COMPLETE) 1105c6293583Skettenis break; 1106c6293583Skettenis if (!status) { 1107c6293583Skettenis error = ETIMEDOUT; 1108c6293583Skettenis break; 1109c6293583Skettenis } 1110c6293583Skettenis } 1111c6293583Skettenis 111212393d97Skettenis bus_dmamap_sync(sc->sc_dmat, hp->adma_map, 0, PAGE_SIZE, 111312393d97Skettenis BUS_DMASYNC_POSTWRITE); 1114c6293583Skettenis goto done; 1115c6293583Skettenis } 1116c6293583Skettenis 1117aae4fe77Suwe mask = ISSET(cmd->c_flags, SCF_CMD_READ) ? 1118aae4fe77Suwe SDHC_BUFFER_READ_ENABLE : SDHC_BUFFER_WRITE_ENABLE; 1119aae4fe77Suwe error = 0; 1120aae4fe77Suwe datalen = cmd->c_datalen; 1121aae4fe77Suwe 1122a93f47f6Sjasper DPRINTF(1,("%s: resp=%#x datalen=%d\n", DEVNAME(hp->sc), 1123a6fd99a7Suwe MMC_R1(cmd->c_resp), datalen)); 1124aae4fe77Suwe 1125393d192eSuwe #ifdef SDHC_DEBUG 1126393d192eSuwe /* XXX I forgot why I wanted to know when this happens :-( */ 1127393d192eSuwe if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) && 1128393d192eSuwe ISSET(MMC_R1(cmd->c_resp), 0xcb00)) 1129393d192eSuwe printf("%s: CMD52/53 error response flags %#x\n", 1130a93f47f6Sjasper DEVNAME(hp->sc), MMC_R1(cmd->c_resp) & 0xff00); 1131393d192eSuwe #endif 1132393d192eSuwe 1133a6fd99a7Suwe while (datalen > 0) { 1134a6fd99a7Suwe if (!sdhc_wait_intr(hp, SDHC_BUFFER_READ_READY| 1135a6fd99a7Suwe SDHC_BUFFER_WRITE_READY, SDHC_BUFFER_TIMEOUT)) { 1136a6fd99a7Suwe error = ETIMEDOUT; 1137a6fd99a7Suwe break; 1138a6fd99a7Suwe } 1139a6fd99a7Suwe 1140a6fd99a7Suwe if ((error = sdhc_wait_state(hp, mask, mask)) != 0) 1141aae4fe77Suwe break; 1142aae4fe77Suwe 1143aae4fe77Suwe i = MIN(datalen, cmd->c_blklen); 1144aae4fe77Suwe if (ISSET(cmd->c_flags, SCF_CMD_READ)) 1145aae4fe77Suwe sdhc_read_data(hp, datap, i); 1146aae4fe77Suwe else 1147aae4fe77Suwe sdhc_write_data(hp, datap, i); 1148aae4fe77Suwe 1149aae4fe77Suwe datap += i; 1150aae4fe77Suwe datalen -= i; 1151aae4fe77Suwe } 1152aae4fe77Suwe 1153a6fd99a7Suwe if (error == 0 && !sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE, 1154a6fd99a7Suwe SDHC_TRANSFER_TIMEOUT)) 1155a6fd99a7Suwe error = ETIMEDOUT; 1156aae4fe77Suwe 1157c6293583Skettenis done: 1158a6fd99a7Suwe if (error != 0) 1159aae4fe77Suwe cmd->c_error = error; 1160a6fd99a7Suwe SET(cmd->c_flags, SCF_ITSDONE); 1161aae4fe77Suwe 116237539bbbSuwe DPRINTF(1,("%s: data transfer done (error=%d)\n", 1163a93f47f6Sjasper DEVNAME(hp->sc), cmd->c_error)); 1164aae4fe77Suwe } 1165aae4fe77Suwe 1166aae4fe77Suwe void 1167aae4fe77Suwe sdhc_read_data(struct sdhc_host *hp, u_char *datap, int datalen) 1168aae4fe77Suwe { 1169393d192eSuwe while (datalen > 3) { 1170393d192eSuwe *(u_int32_t *)datap = HREAD4(hp, SDHC_DATA); 11718371700fSmiod datap += 4; 1172aae4fe77Suwe datalen -= 4; 1173aae4fe77Suwe } 1174393d192eSuwe if (datalen > 0) { 1175393d192eSuwe u_int32_t rv = HREAD4(hp, SDHC_DATA); 1176393d192eSuwe do { 1177393d192eSuwe *datap++ = rv & 0xff; 1178393d192eSuwe rv = rv >> 8; 1179393d192eSuwe } while (--datalen > 0); 1180aae4fe77Suwe } 1181aae4fe77Suwe } 1182aae4fe77Suwe 1183aae4fe77Suwe void 1184aae4fe77Suwe sdhc_write_data(struct sdhc_host *hp, u_char *datap, int datalen) 1185aae4fe77Suwe { 1186393d192eSuwe while (datalen > 3) { 1187393d192eSuwe DPRINTF(3,("%08x\n", *(u_int32_t *)datap)); 1188ab8fb65aSgrange HWRITE4(hp, SDHC_DATA, *((u_int32_t *)datap)); 1189ab8fb65aSgrange datap += 4; 1190aae4fe77Suwe datalen -= 4; 1191aae4fe77Suwe } 1192393d192eSuwe if (datalen > 0) { 1193393d192eSuwe u_int32_t rv = *datap++; 1194393d192eSuwe if (datalen > 1) 1195393d192eSuwe rv |= *datap++ << 8; 1196393d192eSuwe if (datalen > 2) 1197393d192eSuwe rv |= *datap++ << 16; 1198393d192eSuwe DPRINTF(3,("rv %08x\n", rv)); 1199393d192eSuwe HWRITE4(hp, SDHC_DATA, rv); 1200aae4fe77Suwe } 1201aae4fe77Suwe } 1202aae4fe77Suwe 1203a6fd99a7Suwe /* Prepare for another command. */ 12045842cfcdSfgsch int 12055842cfcdSfgsch sdhc_soft_reset(struct sdhc_host *hp, int mask) 1206aae4fe77Suwe { 12075842cfcdSfgsch int timo; 12085842cfcdSfgsch 1209a93f47f6Sjasper DPRINTF(1,("%s: software reset reg=%#x\n", DEVNAME(hp->sc), mask)); 12105842cfcdSfgsch 12115842cfcdSfgsch HWRITE1(hp, SDHC_SOFTWARE_RESET, mask); 12125842cfcdSfgsch for (timo = 10; timo > 0; timo--) { 12135842cfcdSfgsch if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask)) 12145842cfcdSfgsch break; 1215a6fd99a7Suwe sdmmc_delay(10000); 121669c67381Sclaudio HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); 1217a6fd99a7Suwe } 12185842cfcdSfgsch if (timo == 0) { 1219a93f47f6Sjasper DPRINTF(1,("%s: timeout reg=%#x\n", DEVNAME(hp->sc), 12205842cfcdSfgsch HREAD1(hp, SDHC_SOFTWARE_RESET))); 12215842cfcdSfgsch HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); 12225842cfcdSfgsch return (ETIMEDOUT); 12235842cfcdSfgsch } 12245842cfcdSfgsch 12255842cfcdSfgsch return (0); 12265842cfcdSfgsch } 1227a6fd99a7Suwe 1228a6fd99a7Suwe int 12293f3abf14Scheloha sdhc_wait_intr_cold(struct sdhc_host *hp, int mask, int secs) 1230f3036462Sjmatthew { 12313f3abf14Scheloha int status, usecs; 1232f3036462Sjmatthew 1233f3036462Sjmatthew mask |= SDHC_ERROR_INTERRUPT; 12343f3abf14Scheloha usecs = secs * 1000000; 1235f3036462Sjmatthew status = hp->intr_status; 1236f3036462Sjmatthew while ((status & mask) == 0) { 1237f3036462Sjmatthew 1238f3036462Sjmatthew status = HREAD2(hp, SDHC_NINTR_STATUS); 1239f3036462Sjmatthew if (ISSET(status, SDHC_NINTR_STATUS_MASK)) { 1240f3036462Sjmatthew HWRITE2(hp, SDHC_NINTR_STATUS, status); 1241f3036462Sjmatthew if (ISSET(status, SDHC_ERROR_INTERRUPT)) { 1242f3036462Sjmatthew uint16_t error; 1243f3036462Sjmatthew error = HREAD2(hp, SDHC_EINTR_STATUS); 1244f3036462Sjmatthew HWRITE2(hp, SDHC_EINTR_STATUS, error); 1245f3036462Sjmatthew hp->intr_status |= status; 1246f3036462Sjmatthew 1247f3036462Sjmatthew if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR| 1248f3036462Sjmatthew SDHC_DATA_TIMEOUT_ERROR)) 1249f3036462Sjmatthew break; 1250f3036462Sjmatthew } 1251f3036462Sjmatthew 1252f3036462Sjmatthew if (ISSET(status, SDHC_BUFFER_READ_READY | 1253f3036462Sjmatthew SDHC_BUFFER_WRITE_READY | SDHC_COMMAND_COMPLETE | 1254f3036462Sjmatthew SDHC_TRANSFER_COMPLETE)) { 1255f3036462Sjmatthew hp->intr_status |= status; 1256f3036462Sjmatthew break; 1257f3036462Sjmatthew } 1258f3036462Sjmatthew 1259f3036462Sjmatthew if (ISSET(status, SDHC_CARD_INTERRUPT)) { 1260f3036462Sjmatthew HSET2(hp, SDHC_NINTR_STATUS_EN, 1261f3036462Sjmatthew SDHC_CARD_INTERRUPT); 1262f3036462Sjmatthew } 1263f3036462Sjmatthew 1264f3036462Sjmatthew continue; 1265f3036462Sjmatthew } 1266f3036462Sjmatthew 1267f3036462Sjmatthew delay(1); 12683f3abf14Scheloha if (usecs-- == 0) { 1269f3036462Sjmatthew status |= SDHC_ERROR_INTERRUPT; 1270f3036462Sjmatthew break; 1271f3036462Sjmatthew } 1272f3036462Sjmatthew } 1273f3036462Sjmatthew 1274f3036462Sjmatthew hp->intr_status &= ~(status & mask); 1275f3036462Sjmatthew return (status & mask); 1276f3036462Sjmatthew } 1277f3036462Sjmatthew 1278f3036462Sjmatthew int 12793f3abf14Scheloha sdhc_wait_intr(struct sdhc_host *hp, int mask, int secs) 1280a6fd99a7Suwe { 1281a6fd99a7Suwe int status; 1282aae4fe77Suwe int s; 1283aae4fe77Suwe 1284f3036462Sjmatthew if (cold) 12853f3abf14Scheloha return (sdhc_wait_intr_cold(hp, mask, secs)); 1286f3036462Sjmatthew 1287a6fd99a7Suwe mask |= SDHC_ERROR_INTERRUPT; 1288aae4fe77Suwe 1289aae4fe77Suwe s = splsdmmc(); 1290a6fd99a7Suwe status = hp->intr_status & mask; 1291a6fd99a7Suwe while (status == 0) { 12923f3abf14Scheloha if (tsleep_nsec(&hp->intr_status, PWAIT, "hcintr", 12933f3abf14Scheloha SEC_TO_NSEC(secs)) == EWOULDBLOCK) { 1294a6fd99a7Suwe status |= SDHC_ERROR_INTERRUPT; 1295a6fd99a7Suwe break; 1296aae4fe77Suwe } 1297a6fd99a7Suwe status = hp->intr_status & mask; 1298a6fd99a7Suwe } 1299a6fd99a7Suwe hp->intr_status &= ~status; 1300a6fd99a7Suwe 1301a93f47f6Sjasper DPRINTF(2,("%s: intr status %#x error %#x\n", DEVNAME(hp->sc), status, 1302a6fd99a7Suwe hp->intr_error_status)); 1303a6fd99a7Suwe 1304a6fd99a7Suwe /* Command timeout has higher priority than command complete. */ 1305a6fd99a7Suwe if (ISSET(status, SDHC_ERROR_INTERRUPT)) { 1306a6fd99a7Suwe hp->intr_error_status = 0; 13075842cfcdSfgsch (void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD); 1308a6fd99a7Suwe status = 0; 1309a6fd99a7Suwe } 1310a6fd99a7Suwe 1311aae4fe77Suwe splx(s); 1312a6fd99a7Suwe return status; 1313aae4fe77Suwe } 1314aae4fe77Suwe 1315aae4fe77Suwe /* 1316aae4fe77Suwe * Established by attachment driver at interrupt priority IPL_SDMMC. 1317aae4fe77Suwe */ 1318aae4fe77Suwe int 1319aae4fe77Suwe sdhc_intr(void *arg) 1320aae4fe77Suwe { 1321aae4fe77Suwe struct sdhc_softc *sc = arg; 1322aae4fe77Suwe int host; 1323a6fd99a7Suwe int done = 0; 1324aae4fe77Suwe 1325aae4fe77Suwe /* We got an interrupt, but we don't know from which slot. */ 1326aae4fe77Suwe for (host = 0; host < sc->sc_nhosts; host++) { 132781aa4bdcSfgsch struct sdhc_host *hp = sc->sc_host[host]; 1328aae4fe77Suwe u_int16_t status; 1329aae4fe77Suwe 1330aae4fe77Suwe if (hp == NULL) 1331aae4fe77Suwe continue; 1332aae4fe77Suwe 133356ce46e4Suwe /* Find out which interrupts are pending. */ 1334aae4fe77Suwe status = HREAD2(hp, SDHC_NINTR_STATUS); 133556ce46e4Suwe if (!ISSET(status, SDHC_NINTR_STATUS_MASK)) 133656ce46e4Suwe continue; /* no interrupt for us */ 133756ce46e4Suwe 133856ce46e4Suwe /* Acknowledge the interrupts we are about to handle. */ 1339a6fd99a7Suwe HWRITE2(hp, SDHC_NINTR_STATUS, status); 1340a93f47f6Sjasper DPRINTF(2,("%s: interrupt status=%b\n", DEVNAME(hp->sc), 1341a6fd99a7Suwe status, SDHC_NINTR_STATUS_BITS)); 1342a6fd99a7Suwe 1343a6fd99a7Suwe /* Claim this interrupt. */ 1344a6fd99a7Suwe done = 1; 1345aae4fe77Suwe 1346aae4fe77Suwe /* 1347a6fd99a7Suwe * Service error interrupts. 1348aae4fe77Suwe */ 1349aae4fe77Suwe if (ISSET(status, SDHC_ERROR_INTERRUPT)) { 1350aae4fe77Suwe u_int16_t error; 1351aae4fe77Suwe 1352a6fd99a7Suwe /* Acknowledge error interrupts. */ 1353aae4fe77Suwe error = HREAD2(hp, SDHC_EINTR_STATUS); 1354aae4fe77Suwe HWRITE2(hp, SDHC_EINTR_STATUS, error); 135537539bbbSuwe DPRINTF(2,("%s: error interrupt, status=%b\n", 1356a93f47f6Sjasper DEVNAME(hp->sc), error, SDHC_EINTR_STATUS_BITS)); 1357aae4fe77Suwe 1358aae4fe77Suwe if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR| 1359a6fd99a7Suwe SDHC_DATA_TIMEOUT_ERROR)) { 1360a6fd99a7Suwe hp->intr_error_status |= error; 1361a6fd99a7Suwe hp->intr_status |= status; 1362a6fd99a7Suwe wakeup(&hp->intr_status); 1363aae4fe77Suwe } 1364aae4fe77Suwe } 1365aae4fe77Suwe 1366a6fd99a7Suwe /* 1367a6fd99a7Suwe * Wake up the sdmmc event thread to scan for cards. 1368a6fd99a7Suwe */ 1369a6fd99a7Suwe if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) 1370a6fd99a7Suwe sdmmc_needs_discover(hp->sdmmc); 1371a6fd99a7Suwe 1372a6fd99a7Suwe /* 1373a6fd99a7Suwe * Wake up the blocking process to service command 1374a6fd99a7Suwe * related interrupt(s). 1375a6fd99a7Suwe */ 1376a6fd99a7Suwe if (ISSET(status, SDHC_BUFFER_READ_READY| 1377a6fd99a7Suwe SDHC_BUFFER_WRITE_READY|SDHC_COMMAND_COMPLETE| 1378a6fd99a7Suwe SDHC_TRANSFER_COMPLETE)) { 1379a6fd99a7Suwe hp->intr_status |= status; 1380a6fd99a7Suwe wakeup(&hp->intr_status); 1381a6fd99a7Suwe } 1382a6fd99a7Suwe 1383a6fd99a7Suwe /* 1384a6fd99a7Suwe * Service SD card interrupts. 1385a6fd99a7Suwe */ 1386aae4fe77Suwe if (ISSET(status, SDHC_CARD_INTERRUPT)) { 1387a93f47f6Sjasper DPRINTF(0,("%s: card interrupt\n", DEVNAME(hp->sc))); 1388aae4fe77Suwe HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT); 1389b979651fSuwe sdmmc_card_intr(hp->sdmmc); 1390aae4fe77Suwe } 1391aae4fe77Suwe } 1392aae4fe77Suwe return done; 1393aae4fe77Suwe } 1394aae4fe77Suwe 1395c6076839Skettenis void 1396c6076839Skettenis sdhc_needs_discover(struct sdhc_softc *sc) 1397c6076839Skettenis { 1398c6076839Skettenis int host; 1399c6076839Skettenis 1400c6076839Skettenis for (host = 0; host < sc->sc_nhosts; host++) 1401c6076839Skettenis sdmmc_needs_discover(sc->sc_host[host]->sdmmc); 1402c6076839Skettenis } 1403c6076839Skettenis 1404aae4fe77Suwe #ifdef SDHC_DEBUG 1405aae4fe77Suwe void 1406aae4fe77Suwe sdhc_dump_regs(struct sdhc_host *hp) 1407aae4fe77Suwe { 1408aae4fe77Suwe printf("0x%02x PRESENT_STATE: %b\n", SDHC_PRESENT_STATE, 1409aae4fe77Suwe HREAD4(hp, SDHC_PRESENT_STATE), SDHC_PRESENT_STATE_BITS); 1410aae4fe77Suwe printf("0x%02x POWER_CTL: %x\n", SDHC_POWER_CTL, 1411aae4fe77Suwe HREAD1(hp, SDHC_POWER_CTL)); 1412aae4fe77Suwe printf("0x%02x NINTR_STATUS: %x\n", SDHC_NINTR_STATUS, 1413aae4fe77Suwe HREAD2(hp, SDHC_NINTR_STATUS)); 1414aae4fe77Suwe printf("0x%02x EINTR_STATUS: %x\n", SDHC_EINTR_STATUS, 1415aae4fe77Suwe HREAD2(hp, SDHC_EINTR_STATUS)); 1416aae4fe77Suwe printf("0x%02x NINTR_STATUS_EN: %x\n", SDHC_NINTR_STATUS_EN, 1417aae4fe77Suwe HREAD2(hp, SDHC_NINTR_STATUS_EN)); 1418aae4fe77Suwe printf("0x%02x EINTR_STATUS_EN: %x\n", SDHC_EINTR_STATUS_EN, 1419aae4fe77Suwe HREAD2(hp, SDHC_EINTR_STATUS_EN)); 1420aae4fe77Suwe printf("0x%02x NINTR_SIGNAL_EN: %x\n", SDHC_NINTR_SIGNAL_EN, 1421aae4fe77Suwe HREAD2(hp, SDHC_NINTR_SIGNAL_EN)); 1422aae4fe77Suwe printf("0x%02x EINTR_SIGNAL_EN: %x\n", SDHC_EINTR_SIGNAL_EN, 1423aae4fe77Suwe HREAD2(hp, SDHC_EINTR_SIGNAL_EN)); 1424aae4fe77Suwe printf("0x%02x CAPABILITIES: %x\n", SDHC_CAPABILITIES, 1425aae4fe77Suwe HREAD4(hp, SDHC_CAPABILITIES)); 1426aae4fe77Suwe printf("0x%02x MAX_CAPABILITIES: %x\n", SDHC_MAX_CAPABILITIES, 1427aae4fe77Suwe HREAD4(hp, SDHC_MAX_CAPABILITIES)); 1428aae4fe77Suwe } 1429aae4fe77Suwe #endif 1430f3036462Sjmatthew 1431f3036462Sjmatthew int 1432f3036462Sjmatthew sdhc_hibernate_init(sdmmc_chipset_handle_t sch, void *fake_softc) 1433f3036462Sjmatthew { 1434f3036462Sjmatthew struct sdhc_host *hp, *fhp; 1435f3036462Sjmatthew fhp = fake_softc; 1436f3036462Sjmatthew hp = sch; 1437f3036462Sjmatthew *fhp = *hp; 1438f3036462Sjmatthew 1439f3036462Sjmatthew return (0); 1440f3036462Sjmatthew } 1441