1184138Smav/*- 2184138Smav * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org> 3322120Smarius * Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org> 4184138Smav * All rights reserved. 5184138Smav * 6184138Smav * Redistribution and use in source and binary forms, with or without 7184138Smav * modification, are permitted provided that the following conditions 8184138Smav * are met: 9184138Smav * 1. Redistributions of source code must retain the above copyright 10184138Smav * notice, this list of conditions and the following disclaimer. 11184138Smav * 2. Redistributions in binary form must reproduce the above copyright 12184138Smav * notice, this list of conditions and the following disclaimer in the 13184138Smav * documentation and/or other materials provided with the distribution. 14184138Smav * 15184138Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16184138Smav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17184138Smav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18184138Smav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19184138Smav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20184138Smav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21184138Smav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22184138Smav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23184138Smav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24184138Smav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25184138Smav */ 26184138Smav 27184138Smav#include <sys/cdefs.h> 28184138Smav__FBSDID("$FreeBSD: stable/10/sys/dev/sdhci/sdhci.c 343505 2019-01-27 19:05:18Z marius $"); 29184138Smav 30184138Smav#include <sys/param.h> 31184138Smav#include <sys/systm.h> 32184138Smav#include <sys/bus.h> 33266200Sian#include <sys/callout.h> 34184138Smav#include <sys/conf.h> 35184138Smav#include <sys/kernel.h> 36322120Smarius#include <sys/kobj.h> 37343505Smarius#include <sys/libkern.h> 38184138Smav#include <sys/lock.h> 39322120Smarius#include <sys/malloc.h> 40184138Smav#include <sys/module.h> 41184138Smav#include <sys/mutex.h> 42184138Smav#include <sys/resource.h> 43184138Smav#include <sys/rman.h> 44187876Smav#include <sys/sysctl.h> 45184138Smav#include <sys/taskqueue.h> 46184138Smav 47184138Smav#include <machine/bus.h> 48184138Smav#include <machine/resource.h> 49184138Smav#include <machine/stdarg.h> 50184138Smav 51184138Smav#include <dev/mmc/bridge.h> 52184138Smav#include <dev/mmc/mmcreg.h> 53184138Smav#include <dev/mmc/mmcbrvar.h> 54184138Smav 55322120Smarius#include <dev/sdhci/sdhci.h> 56322120Smarius 57184138Smav#include "mmcbr_if.h" 58241600Sgonzo#include "sdhci_if.h" 59184138Smav 60271051SmariusSYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver"); 61184138Smav 62271051Smariusstatic int sdhci_debug; 63187876SmavTUNABLE_INT("hw.sdhci.debug", &sdhci_debug); 64318198SmariusSYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RWTUN, &sdhci_debug, 0, 65318198Smarius "Debug level"); 66318495Smariusu_int sdhci_quirk_clear = 0; 67318495SmariusSYSCTL_INT(_hw_sdhci, OID_AUTO, quirk_clear, CTLFLAG_RWTUN, &sdhci_quirk_clear, 68318495Smarius 0, "Mask of quirks to clear"); 69318495Smariusu_int sdhci_quirk_set = 0; 70318495SmariusSYSCTL_INT(_hw_sdhci, OID_AUTO, quirk_set, CTLFLAG_RWTUN, &sdhci_quirk_set, 0, 71318495Smarius "Mask of quirks to set"); 72187876Smav 73318198Smarius#define RD1(slot, off) SDHCI_READ_1((slot)->bus, (slot), (off)) 74318198Smarius#define RD2(slot, off) SDHCI_READ_2((slot)->bus, (slot), (off)) 75318198Smarius#define RD4(slot, off) SDHCI_READ_4((slot)->bus, (slot), (off)) 76318198Smarius#define RD_MULTI_4(slot, off, ptr, count) \ 77241600Sgonzo SDHCI_READ_MULTI_4((slot)->bus, (slot), (off), (ptr), (count)) 78184138Smav 79318198Smarius#define WR1(slot, off, val) SDHCI_WRITE_1((slot)->bus, (slot), (off), (val)) 80318198Smarius#define WR2(slot, off, val) SDHCI_WRITE_2((slot)->bus, (slot), (off), (val)) 81318198Smarius#define WR4(slot, off, val) SDHCI_WRITE_4((slot)->bus, (slot), (off), (val)) 82318198Smarius#define WR_MULTI_4(slot, off, ptr, count) \ 83241600Sgonzo SDHCI_WRITE_MULTI_4((slot)->bus, (slot), (off), (ptr), (count)) 84184138Smav 85338634Smariusstatic void sdhci_acmd_irq(struct sdhci_slot *slot, uint16_t acmd_err); 86322120Smariusstatic void sdhci_card_poll(void *arg); 87322120Smariusstatic void sdhci_card_task(void *arg, int pending); 88338634Smariusstatic void sdhci_cmd_irq(struct sdhci_slot *slot, uint32_t intmask); 89338634Smariusstatic void sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask); 90322120Smariusstatic int sdhci_exec_tuning(struct sdhci_slot *slot, bool reset); 91338634Smariusstatic void sdhci_handle_card_present_locked(struct sdhci_slot *slot, 92338634Smarius bool is_present); 93338634Smariusstatic void sdhci_finish_command(struct sdhci_slot *slot); 94338634Smariusstatic void sdhci_init(struct sdhci_slot *slot); 95338634Smariusstatic void sdhci_read_block_pio(struct sdhci_slot *slot); 96338634Smariusstatic void sdhci_req_done(struct sdhci_slot *slot); 97322120Smariusstatic void sdhci_req_wakeup(struct mmc_request *req); 98338634Smariusstatic void sdhci_reset(struct sdhci_slot *slot, uint8_t mask); 99322120Smariusstatic void sdhci_retune(void *arg); 100184138Smavstatic void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock); 101338634Smariusstatic void sdhci_set_power(struct sdhci_slot *slot, u_char power); 102338634Smariusstatic void sdhci_set_transfer_mode(struct sdhci_slot *slot, 103343505Smarius const struct mmc_data *data); 104184138Smavstatic void sdhci_start(struct sdhci_slot *slot); 105338634Smariusstatic void sdhci_timeout(void *arg); 106338634Smariusstatic void sdhci_start_command(struct sdhci_slot *slot, 107338634Smarius struct mmc_command *cmd); 108343505Smariusstatic void sdhci_start_data(struct sdhci_slot *slot, 109343505Smarius const struct mmc_data *data); 110338634Smariusstatic void sdhci_write_block_pio(struct sdhci_slot *slot); 111338634Smariusstatic void sdhci_transfer_pio(struct sdhci_slot *slot); 112184138Smav 113184138Smav/* helper routines */ 114343505Smariusstatic int sdhci_dma_alloc(struct sdhci_slot *slot); 115343505Smariusstatic void sdhci_dma_free(struct sdhci_slot *slot); 116318495Smariusstatic void sdhci_dumpregs(struct sdhci_slot *slot); 117338634Smariusstatic void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, 118338634Smarius int error); 119343505Smariusstatic int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...) 120318495Smarius __printflike(2, 3); 121343505Smariusstatic uint32_t sdhci_tuning_intmask(const struct sdhci_slot *slot); 122318495Smarius 123318198Smarius#define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx) 124184138Smav#define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx) 125318198Smarius#define SDHCI_LOCK_INIT(_slot) \ 126184138Smav mtx_init(&_slot->mtx, "SD slot mtx", "sdhci", MTX_DEF) 127318198Smarius#define SDHCI_LOCK_DESTROY(_slot) mtx_destroy(&_slot->mtx); 128318198Smarius#define SDHCI_ASSERT_LOCKED(_slot) mtx_assert(&_slot->mtx, MA_OWNED); 129318198Smarius#define SDHCI_ASSERT_UNLOCKED(_slot) mtx_assert(&_slot->mtx, MA_NOTOWNED); 130184138Smav 131243689Sgonzo#define SDHCI_DEFAULT_MAX_FREQ 50 132243689Sgonzo 133246886Sgonzo#define SDHCI_200_MAX_DIVIDER 256 134246886Sgonzo#define SDHCI_300_MAX_DIVIDER 2046 135246886Sgonzo 136312245Sian#define SDHCI_CARD_PRESENT_TICKS (hz / 5) 137312245Sian#define SDHCI_INSERT_DELAY_TICKS (hz / 2) 138312245Sian 139312245Sian/* 140312245Sian * Broadcom BCM577xx Controller Constants 141312245Sian */ 142318198Smarius/* Maximum divider supported by the default clock source. */ 143318198Smarius#define BCM577XX_DEFAULT_MAX_DIVIDER 256 144318198Smarius/* Alternative clock's base frequency. */ 145318198Smarius#define BCM577XX_ALT_CLOCK_BASE 63000000 146312245Sian 147318198Smarius#define BCM577XX_HOST_CONTROL 0x198 148318198Smarius#define BCM577XX_CTRL_CLKSEL_MASK 0xFFFFCFFF 149318198Smarius#define BCM577XX_CTRL_CLKSEL_SHIFT 12 150318198Smarius#define BCM577XX_CTRL_CLKSEL_DEFAULT 0x0 151318198Smarius#define BCM577XX_CTRL_CLKSEL_64MHZ 0x3 152312245Sian 153241600Sgonzostatic void 154241600Sgonzosdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 155241600Sgonzo{ 156318198Smarius 157241600Sgonzo if (error != 0) { 158241600Sgonzo printf("getaddr: error %d\n", error); 159241600Sgonzo return; 160241600Sgonzo } 161241600Sgonzo *(bus_addr_t *)arg = segs[0].ds_addr; 162241600Sgonzo} 163241600Sgonzo 164184138Smavstatic int 165343505Smariusslot_printf(const struct sdhci_slot *slot, const char * fmt, ...) 166184138Smav{ 167184138Smav va_list ap; 168184138Smav int retval; 169184138Smav 170318198Smarius retval = printf("%s-slot%d: ", 171241600Sgonzo device_get_nameunit(slot->bus), slot->num); 172184138Smav 173184138Smav va_start(ap, fmt); 174184138Smav retval += vprintf(fmt, ap); 175184138Smav va_end(ap); 176184138Smav return (retval); 177184138Smav} 178184138Smav 179184138Smavstatic void 180184138Smavsdhci_dumpregs(struct sdhci_slot *slot) 181184138Smav{ 182318198Smarius 183184138Smav slot_printf(slot, 184184138Smav "============== REGISTER DUMP ==============\n"); 185184138Smav 186184138Smav slot_printf(slot, "Sys addr: 0x%08x | Version: 0x%08x\n", 187184138Smav RD4(slot, SDHCI_DMA_ADDRESS), RD2(slot, SDHCI_HOST_VERSION)); 188184138Smav slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n", 189184138Smav RD2(slot, SDHCI_BLOCK_SIZE), RD2(slot, SDHCI_BLOCK_COUNT)); 190184138Smav slot_printf(slot, "Argument: 0x%08x | Trn mode: 0x%08x\n", 191184138Smav RD4(slot, SDHCI_ARGUMENT), RD2(slot, SDHCI_TRANSFER_MODE)); 192184138Smav slot_printf(slot, "Present: 0x%08x | Host ctl: 0x%08x\n", 193184138Smav RD4(slot, SDHCI_PRESENT_STATE), RD1(slot, SDHCI_HOST_CONTROL)); 194184138Smav slot_printf(slot, "Power: 0x%08x | Blk gap: 0x%08x\n", 195184138Smav RD1(slot, SDHCI_POWER_CONTROL), RD1(slot, SDHCI_BLOCK_GAP_CONTROL)); 196184138Smav slot_printf(slot, "Wake-up: 0x%08x | Clock: 0x%08x\n", 197184138Smav RD1(slot, SDHCI_WAKE_UP_CONTROL), RD2(slot, SDHCI_CLOCK_CONTROL)); 198184138Smav slot_printf(slot, "Timeout: 0x%08x | Int stat: 0x%08x\n", 199184138Smav RD1(slot, SDHCI_TIMEOUT_CONTROL), RD4(slot, SDHCI_INT_STATUS)); 200184138Smav slot_printf(slot, "Int enab: 0x%08x | Sig enab: 0x%08x\n", 201184138Smav RD4(slot, SDHCI_INT_ENABLE), RD4(slot, SDHCI_SIGNAL_ENABLE)); 202322120Smarius slot_printf(slot, "AC12 err: 0x%08x | Host ctl2:0x%08x\n", 203318200Smarius RD2(slot, SDHCI_ACMD12_ERR), RD2(slot, SDHCI_HOST_CONTROL2)); 204318200Smarius slot_printf(slot, "Caps: 0x%08x | Caps2: 0x%08x\n", 205318200Smarius RD4(slot, SDHCI_CAPABILITIES), RD4(slot, SDHCI_CAPABILITIES2)); 206318200Smarius slot_printf(slot, "Max curr: 0x%08x | ADMA err: 0x%08x\n", 207318200Smarius RD4(slot, SDHCI_MAX_CURRENT), RD1(slot, SDHCI_ADMA_ERR)); 208322120Smarius slot_printf(slot, "ADMA addr:0x%08x | Slot int: 0x%08x\n", 209318200Smarius RD4(slot, SDHCI_ADMA_ADDRESS_LO), RD2(slot, SDHCI_SLOT_INT_STATUS)); 210184138Smav 211184138Smav slot_printf(slot, 212184138Smav "===========================================\n"); 213184138Smav} 214184138Smav 215184138Smavstatic void 216184138Smavsdhci_reset(struct sdhci_slot *slot, uint8_t mask) 217184138Smav{ 218184138Smav int timeout; 219318198Smarius uint32_t clock; 220184138Smav 221241600Sgonzo if (slot->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 222312245Sian if (!SDHCI_GET_CARD_PRESENT(slot->bus, slot)) 223184138Smav return; 224184138Smav } 225184138Smav 226184138Smav /* Some controllers need this kick or reset won't work. */ 227184138Smav if ((mask & SDHCI_RESET_ALL) == 0 && 228241600Sgonzo (slot->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)) { 229184138Smav /* This is to force an update */ 230184138Smav clock = slot->clock; 231184138Smav slot->clock = 0; 232184138Smav sdhci_set_clock(slot, clock); 233184138Smav } 234184138Smav 235185661Smav if (mask & SDHCI_RESET_ALL) { 236184138Smav slot->clock = 0; 237185661Smav slot->power = 0; 238185661Smav } 239184138Smav 240276287Sian WR1(slot, SDHCI_SOFTWARE_RESET, mask); 241276287Sian 242276287Sian if (slot->quirks & SDHCI_QUIRK_WAITFOR_RESET_ASSERTED) { 243276287Sian /* 244276287Sian * Resets on TI OMAPs and AM335x are incompatible with SDHCI 245276287Sian * specification. The reset bit has internal propagation delay, 246276287Sian * so a fast read after write returns 0 even if reset process is 247318198Smarius * in progress. The workaround is to poll for 1 before polling 248276287Sian * for 0. In the worst case, if we miss seeing it asserted the 249276287Sian * time we spent waiting is enough to ensure the reset finishes. 250276287Sian */ 251276287Sian timeout = 10000; 252276287Sian while ((RD1(slot, SDHCI_SOFTWARE_RESET) & mask) != mask) { 253276287Sian if (timeout <= 0) 254276287Sian break; 255276287Sian timeout--; 256276287Sian DELAY(1); 257276287Sian } 258276287Sian } 259276287Sian 260184138Smav /* Wait max 100 ms */ 261276287Sian timeout = 10000; 262184138Smav /* Controller clears the bits when it's done */ 263276287Sian while (RD1(slot, SDHCI_SOFTWARE_RESET) & mask) { 264276287Sian if (timeout <= 0) { 265276287Sian slot_printf(slot, "Reset 0x%x never completed.\n", 266276287Sian mask); 267184138Smav sdhci_dumpregs(slot); 268184138Smav return; 269184138Smav } 270184138Smav timeout--; 271276287Sian DELAY(10); 272184138Smav } 273184138Smav} 274184138Smav 275322120Smariusstatic uint32_t 276343505Smariussdhci_tuning_intmask(const struct sdhci_slot *slot) 277322120Smarius{ 278322120Smarius uint32_t intmask; 279322120Smarius 280322120Smarius intmask = 0; 281331035Smarius if (slot->opt & SDHCI_TUNING_ENABLED) { 282322120Smarius intmask |= SDHCI_INT_TUNEERR; 283322120Smarius if (slot->retune_mode == SDHCI_RETUNE_MODE_2 || 284322120Smarius slot->retune_mode == SDHCI_RETUNE_MODE_3) 285322120Smarius intmask |= SDHCI_INT_RETUNE; 286322120Smarius } 287322120Smarius return (intmask); 288322120Smarius} 289322120Smarius 290184138Smavstatic void 291184138Smavsdhci_init(struct sdhci_slot *slot) 292184138Smav{ 293184138Smav 294184138Smav sdhci_reset(slot, SDHCI_RESET_ALL); 295184138Smav 296184138Smav /* Enable interrupts. */ 297184138Smav slot->intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 298184138Smav SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | 299184138Smav SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | 300184138Smav SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | 301184138Smav SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE | 302184138Smav SDHCI_INT_ACMD12ERR; 303312245Sian 304312245Sian if (!(slot->quirks & SDHCI_QUIRK_POLL_CARD_PRESENT) && 305312245Sian !(slot->opt & SDHCI_NON_REMOVABLE)) { 306312245Sian slot->intmask |= SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; 307312245Sian } 308312245Sian 309331035Smarius WR4(slot, SDHCI_INT_ENABLE, slot->intmask); 310184138Smav WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 311184138Smav} 312184138Smav 313184138Smavstatic void 314184138Smavsdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) 315184138Smav{ 316312245Sian uint32_t clk_base; 317312245Sian uint32_t clk_sel; 318184138Smav uint32_t res; 319184138Smav uint16_t clk; 320242320Sgonzo uint16_t div; 321184138Smav int timeout; 322184138Smav 323184138Smav if (clock == slot->clock) 324184138Smav return; 325184138Smav slot->clock = clock; 326184138Smav 327184138Smav /* Turn off the clock. */ 328266751Sian clk = RD2(slot, SDHCI_CLOCK_CONTROL); 329266751Sian WR2(slot, SDHCI_CLOCK_CONTROL, clk & ~SDHCI_CLOCK_CARD_EN); 330318198Smarius /* If no clock requested - leave it so. */ 331184138Smav if (clock == 0) 332184138Smav return; 333318198Smarius 334312245Sian /* Determine the clock base frequency */ 335312245Sian clk_base = slot->max_clk; 336312245Sian if (slot->quirks & SDHCI_QUIRK_BCM577XX_400KHZ_CLKSRC) { 337318198Smarius clk_sel = RD2(slot, BCM577XX_HOST_CONTROL) & 338318198Smarius BCM577XX_CTRL_CLKSEL_MASK; 339254423Sian 340318198Smarius /* 341318198Smarius * Select clock source appropriate for the requested frequency. 342318198Smarius */ 343312245Sian if ((clk_base / BCM577XX_DEFAULT_MAX_DIVIDER) > clock) { 344312245Sian clk_base = BCM577XX_ALT_CLOCK_BASE; 345318198Smarius clk_sel |= (BCM577XX_CTRL_CLKSEL_64MHZ << 346318198Smarius BCM577XX_CTRL_CLKSEL_SHIFT); 347312245Sian } else { 348318198Smarius clk_sel |= (BCM577XX_CTRL_CLKSEL_DEFAULT << 349318198Smarius BCM577XX_CTRL_CLKSEL_SHIFT); 350312245Sian } 351318198Smarius 352312245Sian WR2(slot, BCM577XX_HOST_CONTROL, clk_sel); 353312245Sian } 354312245Sian 355254423Sian /* Recalculate timeout clock frequency based on the new sd clock. */ 356254423Sian if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) 357254423Sian slot->timeout_clk = slot->clock / 1000; 358254423Sian 359242320Sgonzo if (slot->version < SDHCI_SPEC_300) { 360242320Sgonzo /* Looking for highest freq <= clock. */ 361312245Sian res = clk_base; 362246886Sgonzo for (div = 1; div < SDHCI_200_MAX_DIVIDER; div <<= 1) { 363242320Sgonzo if (res <= clock) 364242320Sgonzo break; 365242320Sgonzo res >>= 1; 366242320Sgonzo } 367242320Sgonzo /* Divider 1:1 is 0x00, 2:1 is 0x01, 256:1 is 0x80 ... */ 368242320Sgonzo div >>= 1; 369318198Smarius } else { 370318198Smarius /* Version 3.0 divisors are multiples of two up to 1023 * 2 */ 371312245Sian if (clock >= clk_base) 372246886Sgonzo div = 0; 373242320Sgonzo else { 374318198Smarius for (div = 2; div < SDHCI_300_MAX_DIVIDER; div += 2) { 375318198Smarius if ((clk_base / div) <= clock) 376242320Sgonzo break; 377242320Sgonzo } 378242320Sgonzo } 379242320Sgonzo div >>= 1; 380242320Sgonzo } 381242320Sgonzo 382242320Sgonzo if (bootverbose || sdhci_debug) 383318198Smarius slot_printf(slot, "Divider %d for freq %d (base %d)\n", 384312245Sian div, clock, clk_base); 385242320Sgonzo 386184138Smav /* Now we have got divider, set it. */ 387242320Sgonzo clk = (div & SDHCI_DIVIDER_MASK) << SDHCI_DIVIDER_SHIFT; 388242320Sgonzo clk |= ((div >> SDHCI_DIVIDER_MASK_LEN) & SDHCI_DIVIDER_HI_MASK) 389242320Sgonzo << SDHCI_DIVIDER_HI_SHIFT; 390242320Sgonzo 391184138Smav WR2(slot, SDHCI_CLOCK_CONTROL, clk); 392184138Smav /* Enable clock. */ 393184138Smav clk |= SDHCI_CLOCK_INT_EN; 394184138Smav WR2(slot, SDHCI_CLOCK_CONTROL, clk); 395184138Smav /* Wait up to 10 ms until it stabilize. */ 396184138Smav timeout = 10; 397184138Smav while (!((clk = RD2(slot, SDHCI_CLOCK_CONTROL)) 398184138Smav & SDHCI_CLOCK_INT_STABLE)) { 399184138Smav if (timeout == 0) { 400318198Smarius slot_printf(slot, 401184138Smav "Internal clock never stabilised.\n"); 402184138Smav sdhci_dumpregs(slot); 403184138Smav return; 404184138Smav } 405184138Smav timeout--; 406184138Smav DELAY(1000); 407184138Smav } 408184138Smav /* Pass clock signal to the bus. */ 409184138Smav clk |= SDHCI_CLOCK_CARD_EN; 410184138Smav WR2(slot, SDHCI_CLOCK_CONTROL, clk); 411184138Smav} 412184138Smav 413184138Smavstatic void 414184138Smavsdhci_set_power(struct sdhci_slot *slot, u_char power) 415184138Smav{ 416320899Smarius int i; 417184138Smav uint8_t pwr; 418184138Smav 419184138Smav if (slot->power == power) 420184138Smav return; 421241600Sgonzo 422184138Smav slot->power = power; 423184138Smav 424184138Smav /* Turn off the power. */ 425184138Smav pwr = 0; 426184138Smav WR1(slot, SDHCI_POWER_CONTROL, pwr); 427318198Smarius /* If power down requested - leave it so. */ 428184138Smav if (power == 0) 429184138Smav return; 430184138Smav /* Set voltage. */ 431184138Smav switch (1 << power) { 432184138Smav case MMC_OCR_LOW_VOLTAGE: 433184138Smav pwr |= SDHCI_POWER_180; 434184138Smav break; 435184138Smav case MMC_OCR_290_300: 436184138Smav case MMC_OCR_300_310: 437184138Smav pwr |= SDHCI_POWER_300; 438184138Smav break; 439184138Smav case MMC_OCR_320_330: 440184138Smav case MMC_OCR_330_340: 441184138Smav pwr |= SDHCI_POWER_330; 442184138Smav break; 443184138Smav } 444184138Smav WR1(slot, SDHCI_POWER_CONTROL, pwr); 445320899Smarius /* 446320899Smarius * Turn on VDD1 power. Note that at least some Intel controllers can 447320899Smarius * fail to enable bus power on the first try after transiting from D3 448322120Smarius * to D0, so we give them up to 2 ms. 449320899Smarius */ 450184138Smav pwr |= SDHCI_POWER_ON; 451320899Smarius for (i = 0; i < 20; i++) { 452320899Smarius WR1(slot, SDHCI_POWER_CONTROL, pwr); 453320899Smarius if (RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON) 454320899Smarius break; 455320899Smarius DELAY(100); 456320899Smarius } 457320899Smarius if (!(RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON)) 458320899Smarius slot_printf(slot, "Bus power failed to enable"); 459312400Smarius 460312400Smarius if (slot->quirks & SDHCI_QUIRK_INTEL_POWER_UP_RESET) { 461312400Smarius WR1(slot, SDHCI_POWER_CONTROL, pwr | 0x10); 462312400Smarius DELAY(10); 463312400Smarius WR1(slot, SDHCI_POWER_CONTROL, pwr); 464312400Smarius DELAY(300); 465312400Smarius } 466184138Smav} 467184138Smav 468184138Smavstatic void 469184138Smavsdhci_read_block_pio(struct sdhci_slot *slot) 470184138Smav{ 471184138Smav uint32_t data; 472184138Smav char *buffer; 473184138Smav size_t left; 474184138Smav 475184138Smav buffer = slot->curcmd->data->data; 476184138Smav buffer += slot->offset; 477184138Smav /* Transfer one block at a time. */ 478184138Smav left = min(512, slot->curcmd->data->len - slot->offset); 479184138Smav slot->offset += left; 480184138Smav 481184138Smav /* If we are too fast, broken controllers return zeroes. */ 482241600Sgonzo if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) 483184138Smav DELAY(10); 484254512Srpaulo /* Handle unaligned and aligned buffer cases. */ 485184138Smav if ((intptr_t)buffer & 3) { 486184138Smav while (left > 3) { 487184138Smav data = RD4(slot, SDHCI_BUFFER); 488184138Smav buffer[0] = data; 489184138Smav buffer[1] = (data >> 8); 490184138Smav buffer[2] = (data >> 16); 491184138Smav buffer[3] = (data >> 24); 492184138Smav buffer += 4; 493184138Smav left -= 4; 494184138Smav } 495184138Smav } else { 496241600Sgonzo RD_MULTI_4(slot, SDHCI_BUFFER, 497184138Smav (uint32_t *)buffer, left >> 2); 498184138Smav left &= 3; 499184138Smav } 500184138Smav /* Handle uneven size case. */ 501184138Smav if (left > 0) { 502184138Smav data = RD4(slot, SDHCI_BUFFER); 503184138Smav while (left > 0) { 504184138Smav *(buffer++) = data; 505184138Smav data >>= 8; 506184138Smav left--; 507184138Smav } 508184138Smav } 509184138Smav} 510184138Smav 511184138Smavstatic void 512184138Smavsdhci_write_block_pio(struct sdhci_slot *slot) 513184138Smav{ 514184138Smav uint32_t data = 0; 515184138Smav char *buffer; 516184138Smav size_t left; 517184138Smav 518184138Smav buffer = slot->curcmd->data->data; 519184138Smav buffer += slot->offset; 520184138Smav /* Transfer one block at a time. */ 521184138Smav left = min(512, slot->curcmd->data->len - slot->offset); 522184138Smav slot->offset += left; 523184138Smav 524254512Srpaulo /* Handle unaligned and aligned buffer cases. */ 525184138Smav if ((intptr_t)buffer & 3) { 526184138Smav while (left > 3) { 527184138Smav data = buffer[0] + 528184138Smav (buffer[1] << 8) + 529184138Smav (buffer[2] << 16) + 530184138Smav (buffer[3] << 24); 531184138Smav left -= 4; 532184138Smav buffer += 4; 533184138Smav WR4(slot, SDHCI_BUFFER, data); 534184138Smav } 535184138Smav } else { 536241600Sgonzo WR_MULTI_4(slot, SDHCI_BUFFER, 537184138Smav (uint32_t *)buffer, left >> 2); 538184138Smav left &= 3; 539184138Smav } 540184138Smav /* Handle uneven size case. */ 541184138Smav if (left > 0) { 542184138Smav while (left > 0) { 543184138Smav data <<= 8; 544184138Smav data += *(buffer++); 545184138Smav left--; 546184138Smav } 547184138Smav WR4(slot, SDHCI_BUFFER, data); 548184138Smav } 549184138Smav} 550184138Smav 551184138Smavstatic void 552184138Smavsdhci_transfer_pio(struct sdhci_slot *slot) 553184138Smav{ 554184138Smav 555184138Smav /* Read as many blocks as possible. */ 556184138Smav if (slot->curcmd->data->flags & MMC_DATA_READ) { 557184138Smav while (RD4(slot, SDHCI_PRESENT_STATE) & 558184138Smav SDHCI_DATA_AVAILABLE) { 559184138Smav sdhci_read_block_pio(slot); 560184138Smav if (slot->offset >= slot->curcmd->data->len) 561184138Smav break; 562184138Smav } 563184138Smav } else { 564184138Smav while (RD4(slot, SDHCI_PRESENT_STATE) & 565184138Smav SDHCI_SPACE_AVAILABLE) { 566184138Smav sdhci_write_block_pio(slot); 567184138Smav if (slot->offset >= slot->curcmd->data->len) 568184138Smav break; 569184138Smav } 570184138Smav } 571184138Smav} 572184138Smav 573184138Smavstatic void 574318198Smariussdhci_card_task(void *arg, int pending __unused) 575184138Smav{ 576184138Smav struct sdhci_slot *slot = arg; 577318198Smarius device_t d; 578184138Smav 579184138Smav SDHCI_LOCK(slot); 580312245Sian if (SDHCI_GET_CARD_PRESENT(slot->bus, slot)) { 581184138Smav if (slot->dev == NULL) { 582184138Smav /* If card is present - attach mmc bus. */ 583312245Sian if (bootverbose || sdhci_debug) 584312245Sian slot_printf(slot, "Card inserted\n"); 585322120Smarius d = slot->dev = device_add_child(slot->bus, "mmc", -1); 586184138Smav SDHCI_UNLOCK(slot); 587322120Smarius if (d) { 588322120Smarius device_set_ivars(d, slot); 589322120Smarius (void)device_probe_and_attach(d); 590322120Smarius } 591184138Smav } else 592184138Smav SDHCI_UNLOCK(slot); 593184138Smav } else { 594184138Smav if (slot->dev != NULL) { 595184138Smav /* If no card present - detach mmc bus. */ 596312245Sian if (bootverbose || sdhci_debug) 597312245Sian slot_printf(slot, "Card removed\n"); 598318198Smarius d = slot->dev; 599184138Smav slot->dev = NULL; 600322120Smarius slot->intmask &= ~sdhci_tuning_intmask(slot); 601331035Smarius WR4(slot, SDHCI_INT_ENABLE, slot->intmask); 602322120Smarius WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 603322120Smarius slot->opt &= ~SDHCI_TUNING_ENABLED; 604184138Smav SDHCI_UNLOCK(slot); 605322120Smarius callout_drain(&slot->retune_callout); 606241600Sgonzo device_delete_child(slot->bus, d); 607184138Smav } else 608184138Smav SDHCI_UNLOCK(slot); 609184138Smav } 610184138Smav} 611184138Smav 612312245Sianstatic void 613312245Siansdhci_handle_card_present_locked(struct sdhci_slot *slot, bool is_present) 614312245Sian{ 615312245Sian bool was_present; 616312245Sian 617312245Sian /* 618312245Sian * If there was no card and now there is one, schedule the task to 619312245Sian * create the child device after a short delay. The delay is to 620312245Sian * debounce the card insert (sometimes the card detect pin stabilizes 621312245Sian * before the other pins have made good contact). 622312245Sian * 623312245Sian * If there was a card present and now it's gone, immediately schedule 624312245Sian * the task to delete the child device. No debouncing -- gone is gone, 625312245Sian * because once power is removed, a full card re-init is needed, and 626312245Sian * that happens by deleting and recreating the child device. 627312245Sian */ 628312245Sian was_present = slot->dev != NULL; 629312245Sian if (!was_present && is_present) { 630312245Sian taskqueue_enqueue_timeout(taskqueue_swi_giant, 631312245Sian &slot->card_delayed_task, -SDHCI_INSERT_DELAY_TICKS); 632312245Sian } else if (was_present && !is_present) { 633312245Sian taskqueue_enqueue(taskqueue_swi_giant, &slot->card_task); 634312245Sian } 635312245Sian} 636312245Sian 637312245Sianvoid 638312245Siansdhci_handle_card_present(struct sdhci_slot *slot, bool is_present) 639312245Sian{ 640312245Sian 641312245Sian SDHCI_LOCK(slot); 642312245Sian sdhci_handle_card_present_locked(slot, is_present); 643312245Sian SDHCI_UNLOCK(slot); 644312245Sian} 645312245Sian 646318198Smariusstatic void 647312245Siansdhci_card_poll(void *arg) 648312245Sian{ 649312245Sian struct sdhci_slot *slot = arg; 650312245Sian 651312245Sian sdhci_handle_card_present(slot, 652312245Sian SDHCI_GET_CARD_PRESENT(slot->bus, slot)); 653312245Sian callout_reset(&slot->card_poll_callout, SDHCI_CARD_PRESENT_TICKS, 654312245Sian sdhci_card_poll, slot); 655312245Sian} 656318198Smarius 657343505Smariusstatic int 658343505Smariussdhci_dma_alloc(struct sdhci_slot *slot) 659184138Smav{ 660241600Sgonzo int err; 661184138Smav 662343505Smarius if (!(slot->quirks & SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY)) { 663343505Smarius if (MAXPHYS <= 1024 * 4) 664343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K; 665343505Smarius else if (MAXPHYS <= 1024 * 8) 666343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_8K; 667343505Smarius else if (MAXPHYS <= 1024 * 16) 668343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_16K; 669343505Smarius else if (MAXPHYS <= 1024 * 32) 670343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_32K; 671343505Smarius else if (MAXPHYS <= 1024 * 64) 672343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_64K; 673343505Smarius else if (MAXPHYS <= 1024 * 128) 674343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_128K; 675343505Smarius else if (MAXPHYS <= 1024 * 256) 676343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_256K; 677343505Smarius else 678343505Smarius slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K; 679343505Smarius } 680343505Smarius slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary); 681343505Smarius /* 682343505Smarius * Allocate the DMA tag for an SDMA bounce buffer. 683343505Smarius * Note that the SDHCI specification doesn't state any alignment 684343505Smarius * constraint for the SDMA system address. However, controllers 685343505Smarius * typically ignore the SDMA boundary bits in SDHCI_DMA_ADDRESS when 686343505Smarius * forming the actual address of data, requiring the SDMA buffer to 687343505Smarius * be aligned to the SDMA boundary. 688343505Smarius */ 689343505Smarius err = bus_dma_tag_create(bus_get_dma_tag(slot->bus), slot->sdma_bbufsz, 690343505Smarius 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 691343505Smarius slot->sdma_bbufsz, 1, slot->sdma_bbufsz, BUS_DMA_ALLOCNOW, 692343505Smarius NULL, NULL, &slot->dmatag); 693241600Sgonzo if (err != 0) { 694343505Smarius slot_printf(slot, "Can't create DMA tag for SDMA\n"); 695241600Sgonzo return (err); 696184138Smav } 697343505Smarius /* Allocate DMA memory for the SDMA bounce buffer. */ 698241600Sgonzo err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem, 699241600Sgonzo BUS_DMA_NOWAIT, &slot->dmamap); 700241600Sgonzo if (err != 0) { 701343505Smarius slot_printf(slot, "Can't alloc DMA memory for SDMA\n"); 702322122Smarius bus_dma_tag_destroy(slot->dmatag); 703241600Sgonzo return (err); 704184138Smav } 705343505Smarius /* Map the memory of the SDMA bounce buffer. */ 706241600Sgonzo err = bus_dmamap_load(slot->dmatag, slot->dmamap, 707343505Smarius (void *)slot->dmamem, slot->sdma_bbufsz, sdhci_getaddr, 708343505Smarius &slot->paddr, 0); 709241600Sgonzo if (err != 0 || slot->paddr == 0) { 710343505Smarius slot_printf(slot, "Can't load DMA memory for SDMA\n"); 711322122Smarius bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); 712322122Smarius bus_dma_tag_destroy(slot->dmatag); 713318198Smarius if (err) 714241600Sgonzo return (err); 715241600Sgonzo else 716241600Sgonzo return (EFAULT); 717184138Smav } 718184138Smav 719343505Smarius return (0); 720343505Smarius} 721343505Smarius 722343505Smariusstatic void 723343505Smariussdhci_dma_free(struct sdhci_slot *slot) 724343505Smarius{ 725343505Smarius 726343505Smarius bus_dmamap_unload(slot->dmatag, slot->dmamap); 727343505Smarius bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); 728343505Smarius bus_dma_tag_destroy(slot->dmatag); 729343505Smarius} 730343505Smarius 731343505Smariusint 732343505Smariussdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) 733343505Smarius{ 734343505Smarius kobjop_desc_t kobj_desc; 735343505Smarius kobj_method_t *kobj_method; 736343505Smarius uint32_t caps, caps2, freq, host_caps; 737343505Smarius int err; 738343505Smarius 739343505Smarius SDHCI_LOCK_INIT(slot); 740343505Smarius 741343505Smarius slot->num = num; 742343505Smarius slot->bus = dev; 743343505Smarius 744318198Smarius slot->version = (RD2(slot, SDHCI_HOST_VERSION) 745241600Sgonzo >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; 746318495Smarius if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) { 747242320Sgonzo caps = slot->caps; 748318495Smarius caps2 = slot->caps2; 749318495Smarius } else { 750242320Sgonzo caps = RD4(slot, SDHCI_CAPABILITIES); 751318495Smarius if (slot->version >= SDHCI_SPEC_300) 752318495Smarius caps2 = RD4(slot, SDHCI_CAPABILITIES2); 753318495Smarius else 754318495Smarius caps2 = 0; 755318495Smarius } 756322122Smarius if (slot->version >= SDHCI_SPEC_300) { 757322122Smarius if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE && 758322122Smarius (caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) { 759343505Smarius slot_printf(slot, 760322122Smarius "Driver doesn't support shared bus slots\n"); 761322122Smarius SDHCI_LOCK_DESTROY(slot); 762322122Smarius return (ENXIO); 763322122Smarius } else if ((caps & SDHCI_SLOTTYPE_MASK) == 764322122Smarius SDHCI_SLOTTYPE_EMBEDDED) { 765322122Smarius slot->opt |= SDHCI_SLOT_EMBEDDED | SDHCI_NON_REMOVABLE; 766322122Smarius } 767322122Smarius } 768241600Sgonzo /* Calculate base clock frequency. */ 769243689Sgonzo if (slot->version >= SDHCI_SPEC_300) 770254507Sian freq = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> 771254507Sian SDHCI_CLOCK_BASE_SHIFT; 772318198Smarius else 773254507Sian freq = (caps & SDHCI_CLOCK_BASE_MASK) >> 774254507Sian SDHCI_CLOCK_BASE_SHIFT; 775254507Sian if (freq != 0) 776254507Sian slot->max_clk = freq * 1000000; 777254507Sian /* 778254507Sian * If the frequency wasn't in the capabilities and the hardware driver 779254507Sian * hasn't already set max_clk we're probably not going to work right 780254507Sian * with an assumption, so complain about it. 781254507Sian */ 782241600Sgonzo if (slot->max_clk == 0) { 783254507Sian slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000; 784343505Smarius slot_printf(slot, "Hardware doesn't specify base clock " 785318198Smarius "frequency, using %dMHz as default.\n", 786318198Smarius SDHCI_DEFAULT_MAX_FREQ); 787241600Sgonzo } 788312400Smarius /* Calculate/set timeout clock frequency. */ 789242320Sgonzo if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) { 790242320Sgonzo slot->timeout_clk = slot->max_clk / 1000; 791312400Smarius } else if (slot->quirks & SDHCI_QUIRK_DATA_TIMEOUT_1MHZ) { 792312400Smarius slot->timeout_clk = 1000; 793242320Sgonzo } else { 794318198Smarius slot->timeout_clk = (caps & SDHCI_TIMEOUT_CLK_MASK) >> 795318198Smarius SDHCI_TIMEOUT_CLK_SHIFT; 796242320Sgonzo if (caps & SDHCI_TIMEOUT_CLK_UNIT) 797242320Sgonzo slot->timeout_clk *= 1000; 798242320Sgonzo } 799254507Sian /* 800254507Sian * If the frequency wasn't in the capabilities and the hardware driver 801254507Sian * hasn't already set timeout_clk we'll probably work okay using the 802254507Sian * max timeout, but still mention it. 803254507Sian */ 804241600Sgonzo if (slot->timeout_clk == 0) { 805343505Smarius slot_printf(slot, "Hardware doesn't specify timeout clock " 806254423Sian "frequency, setting BROKEN_TIMEOUT quirk.\n"); 807254423Sian slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 808241600Sgonzo } 809184138Smav 810246886Sgonzo slot->host.f_min = SDHCI_MIN_FREQ(slot->bus, slot); 811241600Sgonzo slot->host.f_max = slot->max_clk; 812241600Sgonzo slot->host.host_ocr = 0; 813241600Sgonzo if (caps & SDHCI_CAN_VDD_330) 814241600Sgonzo slot->host.host_ocr |= MMC_OCR_320_330 | MMC_OCR_330_340; 815241600Sgonzo if (caps & SDHCI_CAN_VDD_300) 816241600Sgonzo slot->host.host_ocr |= MMC_OCR_290_300 | MMC_OCR_300_310; 817322122Smarius /* 1.8V VDD is not supposed to be used for removable cards. */ 818322122Smarius if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED)) 819241600Sgonzo slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE; 820241600Sgonzo if (slot->host.host_ocr == 0) { 821343505Smarius slot_printf(slot, "Hardware doesn't report any " 822241600Sgonzo "support voltages.\n"); 823184138Smav } 824322120Smarius 825318495Smarius host_caps = MMC_CAP_4_BIT_DATA; 826283318Sian if (caps & SDHCI_CAN_DO_8BITBUS) 827318495Smarius host_caps |= MMC_CAP_8_BIT_DATA; 828241600Sgonzo if (caps & SDHCI_CAN_DO_HISPD) 829318495Smarius host_caps |= MMC_CAP_HSPEED; 830318198Smarius if (slot->quirks & SDHCI_QUIRK_BOOT_NOACC) 831318495Smarius host_caps |= MMC_CAP_BOOT_NOACC; 832318198Smarius if (slot->quirks & SDHCI_QUIRK_WAIT_WHILE_BUSY) 833318495Smarius host_caps |= MMC_CAP_WAIT_WHILE_BUSY; 834322120Smarius 835322120Smarius /* Determine supported UHS-I and eMMC modes. */ 836318495Smarius if (caps2 & (SDHCI_CAN_SDR50 | SDHCI_CAN_SDR104 | SDHCI_CAN_DDR50)) 837318495Smarius host_caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 838318495Smarius if (caps2 & SDHCI_CAN_SDR104) { 839318495Smarius host_caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 840318495Smarius if (!(slot->quirks & SDHCI_QUIRK_BROKEN_MMC_HS200)) 841318495Smarius host_caps |= MMC_CAP_MMC_HS200; 842318495Smarius } else if (caps2 & SDHCI_CAN_SDR50) 843318495Smarius host_caps |= MMC_CAP_UHS_SDR50; 844318495Smarius if (caps2 & SDHCI_CAN_DDR50 && 845318495Smarius !(slot->quirks & SDHCI_QUIRK_BROKEN_UHS_DDR50)) 846318495Smarius host_caps |= MMC_CAP_UHS_DDR50; 847318495Smarius if (slot->quirks & SDHCI_QUIRK_MMC_DDR52) 848318495Smarius host_caps |= MMC_CAP_MMC_DDR52; 849318495Smarius if (slot->quirks & SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 && 850318495Smarius caps2 & SDHCI_CAN_MMC_HS400) 851318495Smarius host_caps |= MMC_CAP_MMC_HS400; 852340764Smarius if (slot->quirks & SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 && 853340764Smarius caps2 & SDHCI_CAN_SDR104) 854340764Smarius host_caps |= MMC_CAP_MMC_HS400; 855322120Smarius 856322120Smarius /* 857322120Smarius * Disable UHS-I and eMMC modes if the set_uhs_timing method is the 858322120Smarius * default NULL implementation. 859322120Smarius */ 860322120Smarius kobj_desc = &sdhci_set_uhs_timing_desc; 861322120Smarius kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL, 862322120Smarius kobj_desc); 863322120Smarius if (kobj_method == &kobj_desc->deflt) 864322120Smarius host_caps &= ~(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 865322120Smarius MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 | MMC_CAP_UHS_SDR104 | 866322120Smarius MMC_CAP_MMC_DDR52 | MMC_CAP_MMC_HS200 | MMC_CAP_MMC_HS400); 867322120Smarius 868322120Smarius#define SDHCI_CAP_MODES_TUNING(caps2) \ 869322120Smarius (((caps2) & SDHCI_TUNE_SDR50 ? MMC_CAP_UHS_SDR50 : 0) | \ 870322120Smarius MMC_CAP_UHS_DDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_MMC_HS200 | \ 871322120Smarius MMC_CAP_MMC_HS400) 872322120Smarius 873322120Smarius /* 874322120Smarius * Disable UHS-I and eMMC modes that require (re-)tuning if either 875322120Smarius * the tune or re-tune method is the default NULL implementation. 876322120Smarius */ 877322120Smarius kobj_desc = &mmcbr_tune_desc; 878322120Smarius kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL, 879322120Smarius kobj_desc); 880322120Smarius if (kobj_method == &kobj_desc->deflt) 881322120Smarius goto no_tuning; 882322120Smarius kobj_desc = &mmcbr_retune_desc; 883322120Smarius kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL, 884322120Smarius kobj_desc); 885322120Smarius if (kobj_method == &kobj_desc->deflt) { 886322120Smariusno_tuning: 887322120Smarius host_caps &= ~(SDHCI_CAP_MODES_TUNING(caps2)); 888322120Smarius } 889322120Smarius 890322120Smarius /* Allocate tuning structures and determine tuning parameters. */ 891322120Smarius if (host_caps & SDHCI_CAP_MODES_TUNING(caps2)) { 892322120Smarius slot->opt |= SDHCI_TUNING_SUPPORTED; 893322120Smarius slot->tune_req = malloc(sizeof(*slot->tune_req), M_DEVBUF, 894322120Smarius M_WAITOK); 895322120Smarius slot->tune_cmd = malloc(sizeof(*slot->tune_cmd), M_DEVBUF, 896322120Smarius M_WAITOK); 897322120Smarius slot->tune_data = malloc(sizeof(*slot->tune_data), M_DEVBUF, 898322120Smarius M_WAITOK); 899322120Smarius if (caps2 & SDHCI_TUNE_SDR50) 900322120Smarius slot->opt |= SDHCI_SDR50_NEEDS_TUNING; 901322120Smarius slot->retune_mode = (caps2 & SDHCI_RETUNE_MODES_MASK) >> 902322120Smarius SDHCI_RETUNE_MODES_SHIFT; 903322120Smarius if (slot->retune_mode == SDHCI_RETUNE_MODE_1) { 904322120Smarius slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >> 905322120Smarius SDHCI_RETUNE_CNT_SHIFT; 906322120Smarius if (slot->retune_count > 0xb) { 907343505Smarius slot_printf(slot, "Unknown re-tuning count " 908322120Smarius "%x, using 1 sec\n", slot->retune_count); 909322120Smarius slot->retune_count = 1; 910322120Smarius } else if (slot->retune_count != 0) 911322120Smarius slot->retune_count = 912322120Smarius 1 << (slot->retune_count - 1); 913322120Smarius } 914322120Smarius } 915322120Smarius 916322120Smarius#undef SDHCI_CAP_MODES_TUNING 917322120Smarius 918322120Smarius /* Determine supported VCCQ signaling levels. */ 919318495Smarius host_caps |= MMC_CAP_SIGNALING_330; 920318495Smarius if (host_caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 921322120Smarius MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 | MMC_CAP_UHS_SDR104 | 922318495Smarius MMC_CAP_MMC_DDR52_180 | MMC_CAP_MMC_HS200_180 | 923318495Smarius MMC_CAP_MMC_HS400_180)) 924322120Smarius host_caps |= MMC_CAP_SIGNALING_120 | MMC_CAP_SIGNALING_180; 925322120Smarius 926322120Smarius /* 927322120Smarius * Disable 1.2 V and 1.8 V signaling if the switch_vccq method is the 928322120Smarius * default NULL implementation. Disable 1.2 V support if it's the 929322120Smarius * generic SDHCI implementation. 930322120Smarius */ 931322120Smarius kobj_desc = &mmcbr_switch_vccq_desc; 932322120Smarius kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL, 933322120Smarius kobj_desc); 934322120Smarius if (kobj_method == &kobj_desc->deflt) 935322120Smarius host_caps &= ~(MMC_CAP_SIGNALING_120 | MMC_CAP_SIGNALING_180); 936322120Smarius else if (kobj_method->func == (kobjop_t)sdhci_generic_switch_vccq) 937322120Smarius host_caps &= ~MMC_CAP_SIGNALING_120; 938322120Smarius 939322120Smarius /* Determine supported driver types (type B is always mandatory). */ 940322120Smarius if (caps2 & SDHCI_CAN_DRIVE_TYPE_A) 941318495Smarius host_caps |= MMC_CAP_DRIVER_TYPE_A; 942322120Smarius if (caps2 & SDHCI_CAN_DRIVE_TYPE_C) 943318495Smarius host_caps |= MMC_CAP_DRIVER_TYPE_C; 944322120Smarius if (caps2 & SDHCI_CAN_DRIVE_TYPE_D) 945318495Smarius host_caps |= MMC_CAP_DRIVER_TYPE_D; 946318495Smarius slot->host.caps = host_caps; 947318495Smarius 948241600Sgonzo /* Decide if we have usable DMA. */ 949241600Sgonzo if (caps & SDHCI_CAN_DO_DMA) 950241600Sgonzo slot->opt |= SDHCI_HAVE_DMA; 951184138Smav 952241600Sgonzo if (slot->quirks & SDHCI_QUIRK_BROKEN_DMA) 953241600Sgonzo slot->opt &= ~SDHCI_HAVE_DMA; 954241600Sgonzo if (slot->quirks & SDHCI_QUIRK_FORCE_DMA) 955241600Sgonzo slot->opt |= SDHCI_HAVE_DMA; 956312400Smarius if (slot->quirks & SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE) 957312400Smarius slot->opt |= SDHCI_NON_REMOVABLE; 958241600Sgonzo 959318198Smarius /* 960247495Sgonzo * Use platform-provided transfer backend 961247495Sgonzo * with PIO as a fallback mechanism 962247495Sgonzo */ 963247495Sgonzo if (slot->opt & SDHCI_PLATFORM_TRANSFER) 964247495Sgonzo slot->opt &= ~SDHCI_HAVE_DMA; 965247495Sgonzo 966343505Smarius if (slot->opt & SDHCI_HAVE_DMA) { 967343505Smarius err = sdhci_dma_alloc(slot); 968343505Smarius if (err != 0) { 969343505Smarius if (slot->opt & SDHCI_TUNING_SUPPORTED) { 970343505Smarius free(slot->tune_req, M_DEVBUF); 971343505Smarius free(slot->tune_cmd, M_DEVBUF); 972343505Smarius free(slot->tune_data, M_DEVBUF); 973343505Smarius } 974343505Smarius SDHCI_LOCK_DESTROY(slot); 975343505Smarius return (err); 976343505Smarius } 977343505Smarius } 978343505Smarius 979241600Sgonzo if (bootverbose || sdhci_debug) { 980318495Smarius slot_printf(slot, 981322122Smarius "%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n", 982241600Sgonzo slot->max_clk / 1000000, 983241600Sgonzo (caps & SDHCI_CAN_DO_HISPD) ? " HS" : "", 984318495Smarius (host_caps & MMC_CAP_8_BIT_DATA) ? "8bits" : 985318495Smarius ((host_caps & MMC_CAP_4_BIT_DATA) ? "4bits" : "1bit"), 986241600Sgonzo (caps & SDHCI_CAN_VDD_330) ? " 3.3V" : "", 987241600Sgonzo (caps & SDHCI_CAN_VDD_300) ? " 3.0V" : "", 988322122Smarius ((caps & SDHCI_CAN_VDD_180) && 989322122Smarius (slot->opt & SDHCI_SLOT_EMBEDDED)) ? " 1.8V" : "", 990318495Smarius (host_caps & MMC_CAP_SIGNALING_180) ? " 1.8V" : "", 991318495Smarius (host_caps & MMC_CAP_SIGNALING_120) ? " 1.2V" : "", 992322120Smarius (host_caps & MMC_CAP_DRIVER_TYPE_A) ? "A" : "", 993322120Smarius (host_caps & MMC_CAP_DRIVER_TYPE_C) ? "C" : "", 994322120Smarius (host_caps & MMC_CAP_DRIVER_TYPE_D) ? "D" : "", 995322122Smarius (slot->opt & SDHCI_HAVE_DMA) ? "DMA" : "PIO", 996322122Smarius (slot->opt & SDHCI_SLOT_EMBEDDED) ? "embedded" : 997322122Smarius (slot->opt & SDHCI_NON_REMOVABLE) ? "non-removable" : 998322122Smarius "removable"); 999318495Smarius if (host_caps & (MMC_CAP_MMC_DDR52 | MMC_CAP_MMC_HS200 | 1000318495Smarius MMC_CAP_MMC_HS400 | MMC_CAP_MMC_ENH_STROBE)) 1001318495Smarius slot_printf(slot, "eMMC:%s%s%s%s\n", 1002318495Smarius (host_caps & MMC_CAP_MMC_DDR52) ? " DDR52" : "", 1003318495Smarius (host_caps & MMC_CAP_MMC_HS200) ? " HS200" : "", 1004318495Smarius (host_caps & MMC_CAP_MMC_HS400) ? " HS400" : "", 1005318495Smarius ((host_caps & 1006318495Smarius (MMC_CAP_MMC_HS400 | MMC_CAP_MMC_ENH_STROBE)) == 1007318495Smarius (MMC_CAP_MMC_HS400 | MMC_CAP_MMC_ENH_STROBE)) ? 1008318495Smarius " HS400ES" : ""); 1009318495Smarius if (host_caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 1010318495Smarius MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104)) 1011318495Smarius slot_printf(slot, "UHS-I:%s%s%s%s%s\n", 1012318495Smarius (host_caps & MMC_CAP_UHS_SDR12) ? " SDR12" : "", 1013318495Smarius (host_caps & MMC_CAP_UHS_SDR25) ? " SDR25" : "", 1014318495Smarius (host_caps & MMC_CAP_UHS_SDR50) ? " SDR50" : "", 1015318495Smarius (host_caps & MMC_CAP_UHS_SDR104) ? " SDR104" : "", 1016318495Smarius (host_caps & MMC_CAP_UHS_DDR50) ? " DDR50" : ""); 1017322120Smarius if (slot->opt & SDHCI_TUNING_SUPPORTED) 1018322120Smarius slot_printf(slot, "Re-tuning count %d secs, mode %d\n", 1019322120Smarius slot->retune_count, slot->retune_mode + 1); 1020241600Sgonzo sdhci_dumpregs(slot); 1021184138Smav } 1022312245Sian 1023312245Sian slot->timeout = 10; 1024312245Sian SYSCTL_ADD_INT(device_get_sysctl_ctx(slot->bus), 1025312245Sian SYSCTL_CHILDREN(device_get_sysctl_tree(slot->bus)), OID_AUTO, 1026312245Sian "timeout", CTLFLAG_RW, &slot->timeout, 0, 1027312245Sian "Maximum timeout for SDHCI transfers (in secs)"); 1028241600Sgonzo TASK_INIT(&slot->card_task, 0, sdhci_card_task, slot); 1029312245Sian TIMEOUT_TASK_INIT(taskqueue_swi_giant, &slot->card_delayed_task, 0, 1030312245Sian sdhci_card_task, slot); 1031312245Sian callout_init(&slot->card_poll_callout, 1); 1032266200Sian callout_init_mtx(&slot->timeout_callout, &slot->mtx, 0); 1033322120Smarius callout_init_mtx(&slot->retune_callout, &slot->mtx, 0); 1034312245Sian 1035312245Sian if ((slot->quirks & SDHCI_QUIRK_POLL_CARD_PRESENT) && 1036312245Sian !(slot->opt & SDHCI_NON_REMOVABLE)) { 1037312245Sian callout_reset(&slot->card_poll_callout, 1038312245Sian SDHCI_CARD_PRESENT_TICKS, sdhci_card_poll, slot); 1039312245Sian } 1040312245Sian 1041322120Smarius sdhci_init(slot); 1042322120Smarius 1043184138Smav return (0); 1044184138Smav} 1045184138Smav 1046241600Sgonzovoid 1047241600Sgonzosdhci_start_slot(struct sdhci_slot *slot) 1048184138Smav{ 1049318198Smarius 1050241600Sgonzo sdhci_card_task(slot, 0); 1051241600Sgonzo} 1052184138Smav 1053241600Sgonzoint 1054241600Sgonzosdhci_cleanup_slot(struct sdhci_slot *slot) 1055241600Sgonzo{ 1056241600Sgonzo device_t d; 1057184138Smav 1058266200Sian callout_drain(&slot->timeout_callout); 1059312245Sian callout_drain(&slot->card_poll_callout); 1060322120Smarius callout_drain(&slot->retune_callout); 1061241600Sgonzo taskqueue_drain(taskqueue_swi_giant, &slot->card_task); 1062312245Sian taskqueue_drain_timeout(taskqueue_swi_giant, &slot->card_delayed_task); 1063184138Smav 1064241600Sgonzo SDHCI_LOCK(slot); 1065241600Sgonzo d = slot->dev; 1066241600Sgonzo slot->dev = NULL; 1067241600Sgonzo SDHCI_UNLOCK(slot); 1068241600Sgonzo if (d != NULL) 1069241600Sgonzo device_delete_child(slot->bus, d); 1070184138Smav 1071241600Sgonzo SDHCI_LOCK(slot); 1072241600Sgonzo sdhci_reset(slot, SDHCI_RESET_ALL); 1073241600Sgonzo SDHCI_UNLOCK(slot); 1074343505Smarius if (slot->opt & SDHCI_HAVE_DMA) 1075343505Smarius sdhci_dma_free(slot); 1076322120Smarius if (slot->opt & SDHCI_TUNING_SUPPORTED) { 1077322120Smarius free(slot->tune_req, M_DEVBUF); 1078322120Smarius free(slot->tune_cmd, M_DEVBUF); 1079322120Smarius free(slot->tune_data, M_DEVBUF); 1080322120Smarius } 1081184138Smav 1082241600Sgonzo SDHCI_LOCK_DESTROY(slot); 1083241600Sgonzo 1084184138Smav return (0); 1085184138Smav} 1086184138Smav 1087241600Sgonzoint 1088241600Sgonzosdhci_generic_suspend(struct sdhci_slot *slot) 1089185527Smav{ 1090318198Smarius 1091322120Smarius /* 1092322120Smarius * We expect the MMC layer to issue initial tuning after resume. 1093322120Smarius * Otherwise, we'd need to indicate re-tuning including circuit reset 1094322120Smarius * being required at least for re-tuning modes 1 and 2 ourselves. 1095322120Smarius */ 1096322120Smarius callout_drain(&slot->retune_callout); 1097322120Smarius SDHCI_LOCK(slot); 1098322120Smarius slot->opt &= ~SDHCI_TUNING_ENABLED; 1099241600Sgonzo sdhci_reset(slot, SDHCI_RESET_ALL); 1100322120Smarius SDHCI_UNLOCK(slot); 1101185527Smav 1102185527Smav return (0); 1103185527Smav} 1104185527Smav 1105241600Sgonzoint 1106241600Sgonzosdhci_generic_resume(struct sdhci_slot *slot) 1107185527Smav{ 1108318198Smarius 1109322120Smarius SDHCI_LOCK(slot); 1110241600Sgonzo sdhci_init(slot); 1111322120Smarius SDHCI_UNLOCK(slot); 1112185527Smav 1113241600Sgonzo return (0); 1114185527Smav} 1115185527Smav 1116246886Sgonzouint32_t 1117318198Smariussdhci_generic_min_freq(device_t brdev __unused, struct sdhci_slot *slot) 1118246886Sgonzo{ 1119318198Smarius 1120246886Sgonzo if (slot->version >= SDHCI_SPEC_300) 1121246886Sgonzo return (slot->max_clk / SDHCI_300_MAX_DIVIDER); 1122246886Sgonzo else 1123246886Sgonzo return (slot->max_clk / SDHCI_200_MAX_DIVIDER); 1124246886Sgonzo} 1125246886Sgonzo 1126312245Sianbool 1127318198Smariussdhci_generic_get_card_present(device_t brdev __unused, struct sdhci_slot *slot) 1128312245Sian{ 1129312245Sian 1130312245Sian if (slot->opt & SDHCI_NON_REMOVABLE) 1131312245Sian return true; 1132312245Sian 1133312245Sian return (RD4(slot, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 1134312245Sian} 1135312245Sian 1136318495Smariusvoid 1137318495Smariussdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot) 1138318495Smarius{ 1139343505Smarius const struct mmc_ios *ios; 1140318495Smarius uint16_t hostctrl2; 1141318495Smarius 1142318495Smarius if (slot->version < SDHCI_SPEC_300) 1143318495Smarius return; 1144318495Smarius 1145322120Smarius SDHCI_ASSERT_LOCKED(slot); 1146318495Smarius ios = &slot->host.ios; 1147318495Smarius sdhci_set_clock(slot, 0); 1148318495Smarius hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); 1149318495Smarius hostctrl2 &= ~SDHCI_CTRL2_UHS_MASK; 1150322120Smarius if (ios->clock > SD_SDR50_MAX) { 1151322120Smarius if (ios->timing == bus_timing_mmc_hs400 || 1152322120Smarius ios->timing == bus_timing_mmc_hs400es) 1153322120Smarius hostctrl2 |= SDHCI_CTRL2_MMC_HS400; 1154322120Smarius else 1155322120Smarius hostctrl2 |= SDHCI_CTRL2_UHS_SDR104; 1156322120Smarius } 1157318495Smarius else if (ios->clock > SD_SDR25_MAX) 1158318495Smarius hostctrl2 |= SDHCI_CTRL2_UHS_SDR50; 1159318495Smarius else if (ios->clock > SD_SDR12_MAX) { 1160318495Smarius if (ios->timing == bus_timing_uhs_ddr50 || 1161318495Smarius ios->timing == bus_timing_mmc_ddr52) 1162318495Smarius hostctrl2 |= SDHCI_CTRL2_UHS_DDR50; 1163318495Smarius else 1164318495Smarius hostctrl2 |= SDHCI_CTRL2_UHS_SDR25; 1165318495Smarius } else if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) 1166318495Smarius hostctrl2 |= SDHCI_CTRL2_UHS_SDR12; 1167318495Smarius WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2); 1168318495Smarius sdhci_set_clock(slot, ios->clock); 1169318495Smarius} 1170318495Smarius 1171241600Sgonzoint 1172241600Sgonzosdhci_generic_update_ios(device_t brdev, device_t reqdev) 1173184138Smav{ 1174184138Smav struct sdhci_slot *slot = device_get_ivars(reqdev); 1175184138Smav struct mmc_ios *ios = &slot->host.ios; 1176184138Smav 1177184138Smav SDHCI_LOCK(slot); 1178184138Smav /* Do full reset on bus power down to clear from any state. */ 1179184138Smav if (ios->power_mode == power_off) { 1180184138Smav WR4(slot, SDHCI_SIGNAL_ENABLE, 0); 1181184138Smav sdhci_init(slot); 1182184138Smav } 1183184138Smav /* Configure the bus. */ 1184184138Smav sdhci_set_clock(slot, ios->clock); 1185283318Sian sdhci_set_power(slot, (ios->power_mode == power_off) ? 0 : ios->vdd); 1186283318Sian if (ios->bus_width == bus_width_8) { 1187283318Sian slot->hostctrl |= SDHCI_CTRL_8BITBUS; 1188283318Sian slot->hostctrl &= ~SDHCI_CTRL_4BITBUS; 1189283318Sian } else if (ios->bus_width == bus_width_4) { 1190283318Sian slot->hostctrl &= ~SDHCI_CTRL_8BITBUS; 1191184138Smav slot->hostctrl |= SDHCI_CTRL_4BITBUS; 1192283318Sian } else if (ios->bus_width == bus_width_1) { 1193283318Sian slot->hostctrl &= ~SDHCI_CTRL_8BITBUS; 1194184138Smav slot->hostctrl &= ~SDHCI_CTRL_4BITBUS; 1195283318Sian } else { 1196283318Sian panic("Invalid bus width: %d", ios->bus_width); 1197283318Sian } 1198318495Smarius if (ios->clock > SD_SDR12_MAX && 1199278703Sian !(slot->quirks & SDHCI_QUIRK_DONT_SET_HISPD_BIT)) 1200184138Smav slot->hostctrl |= SDHCI_CTRL_HISPD; 1201184138Smav else 1202184138Smav slot->hostctrl &= ~SDHCI_CTRL_HISPD; 1203184138Smav WR1(slot, SDHCI_HOST_CONTROL, slot->hostctrl); 1204318495Smarius SDHCI_SET_UHS_TIMING(brdev, slot); 1205184138Smav /* Some controllers like reset after bus changes. */ 1206318198Smarius if (slot->quirks & SDHCI_QUIRK_RESET_ON_IOS) 1207184138Smav sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1208184138Smav 1209184138Smav SDHCI_UNLOCK(slot); 1210184138Smav return (0); 1211184138Smav} 1212184138Smav 1213318495Smariusint 1214318495Smariussdhci_generic_switch_vccq(device_t brdev __unused, device_t reqdev) 1215318495Smarius{ 1216318495Smarius struct sdhci_slot *slot = device_get_ivars(reqdev); 1217318495Smarius enum mmc_vccq vccq; 1218318495Smarius int err; 1219318495Smarius uint16_t hostctrl2; 1220318495Smarius 1221318495Smarius if (slot->version < SDHCI_SPEC_300) 1222318495Smarius return (0); 1223318495Smarius 1224318495Smarius err = 0; 1225318495Smarius vccq = slot->host.ios.vccq; 1226318495Smarius SDHCI_LOCK(slot); 1227318495Smarius sdhci_set_clock(slot, 0); 1228318495Smarius hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); 1229318495Smarius switch (vccq) { 1230318495Smarius case vccq_330: 1231318495Smarius if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) 1232318495Smarius goto done; 1233318495Smarius hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE; 1234318495Smarius WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2); 1235318495Smarius DELAY(5000); 1236318495Smarius hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); 1237318495Smarius if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) 1238318495Smarius goto done; 1239318495Smarius err = EAGAIN; 1240318495Smarius break; 1241318495Smarius case vccq_180: 1242318495Smarius if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) { 1243318495Smarius err = EINVAL; 1244318495Smarius goto done; 1245318495Smarius } 1246318495Smarius if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) 1247318495Smarius goto done; 1248318495Smarius hostctrl2 |= SDHCI_CTRL2_S18_ENABLE; 1249318495Smarius WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2); 1250318495Smarius DELAY(5000); 1251318495Smarius hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); 1252318495Smarius if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) 1253318495Smarius goto done; 1254318495Smarius err = EAGAIN; 1255318495Smarius break; 1256318495Smarius default: 1257318495Smarius slot_printf(slot, 1258318495Smarius "Attempt to set unsupported signaling voltage\n"); 1259318495Smarius err = EINVAL; 1260318495Smarius break; 1261318495Smarius } 1262318495Smariusdone: 1263318495Smarius sdhci_set_clock(slot, slot->host.ios.clock); 1264318495Smarius SDHCI_UNLOCK(slot); 1265318495Smarius return (err); 1266318495Smarius} 1267318495Smarius 1268322120Smariusint 1269322120Smariussdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400) 1270322120Smarius{ 1271322120Smarius struct sdhci_slot *slot = device_get_ivars(reqdev); 1272343505Smarius const struct mmc_ios *ios = &slot->host.ios; 1273322120Smarius struct mmc_command *tune_cmd; 1274322120Smarius struct mmc_data *tune_data; 1275322120Smarius uint32_t opcode; 1276322120Smarius int err; 1277322120Smarius 1278322120Smarius if (!(slot->opt & SDHCI_TUNING_SUPPORTED)) 1279322120Smarius return (0); 1280322120Smarius 1281322120Smarius slot->retune_ticks = slot->retune_count * hz; 1282322120Smarius opcode = MMC_SEND_TUNING_BLOCK; 1283322120Smarius SDHCI_LOCK(slot); 1284322120Smarius switch (ios->timing) { 1285322120Smarius case bus_timing_mmc_hs400: 1286322120Smarius slot_printf(slot, "HS400 must be tuned in HS200 mode\n"); 1287322120Smarius SDHCI_UNLOCK(slot); 1288322120Smarius return (EINVAL); 1289322120Smarius case bus_timing_mmc_hs200: 1290322120Smarius /* 1291322120Smarius * In HS400 mode, controllers use the data strobe line to 1292322120Smarius * latch data from the devices so periodic re-tuning isn't 1293322120Smarius * expected to be required. 1294322120Smarius */ 1295322120Smarius if (hs400) 1296322120Smarius slot->retune_ticks = 0; 1297322120Smarius opcode = MMC_SEND_TUNING_BLOCK_HS200; 1298322120Smarius break; 1299322120Smarius case bus_timing_uhs_ddr50: 1300322120Smarius case bus_timing_uhs_sdr104: 1301322120Smarius break; 1302322120Smarius case bus_timing_uhs_sdr50: 1303322120Smarius if (slot->opt & SDHCI_SDR50_NEEDS_TUNING) 1304322120Smarius break; 1305322120Smarius /* FALLTHROUGH */ 1306322120Smarius default: 1307322120Smarius SDHCI_UNLOCK(slot); 1308322120Smarius return (0); 1309322120Smarius } 1310322120Smarius 1311322120Smarius tune_cmd = slot->tune_cmd; 1312322120Smarius memset(tune_cmd, 0, sizeof(*tune_cmd)); 1313322120Smarius tune_cmd->opcode = opcode; 1314322120Smarius tune_cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; 1315322120Smarius tune_data = tune_cmd->data = slot->tune_data; 1316322120Smarius memset(tune_data, 0, sizeof(*tune_data)); 1317322120Smarius tune_data->len = (opcode == MMC_SEND_TUNING_BLOCK_HS200 && 1318322120Smarius ios->bus_width == bus_width_8) ? MMC_TUNING_LEN_HS200 : 1319322120Smarius MMC_TUNING_LEN; 1320322120Smarius tune_data->flags = MMC_DATA_READ; 1321322120Smarius tune_data->mrq = tune_cmd->mrq = slot->tune_req; 1322322120Smarius 1323322120Smarius slot->opt &= ~SDHCI_TUNING_ENABLED; 1324322120Smarius err = sdhci_exec_tuning(slot, true); 1325322120Smarius if (err == 0) { 1326322120Smarius slot->opt |= SDHCI_TUNING_ENABLED; 1327322120Smarius slot->intmask |= sdhci_tuning_intmask(slot); 1328331035Smarius WR4(slot, SDHCI_INT_ENABLE, slot->intmask); 1329322120Smarius WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 1330322120Smarius if (slot->retune_ticks) { 1331322120Smarius callout_reset(&slot->retune_callout, slot->retune_ticks, 1332322120Smarius sdhci_retune, slot); 1333322120Smarius } 1334322120Smarius } 1335322120Smarius SDHCI_UNLOCK(slot); 1336322120Smarius return (err); 1337322120Smarius} 1338322120Smarius 1339322120Smariusint 1340322120Smariussdhci_generic_retune(device_t brdev __unused, device_t reqdev, bool reset) 1341322120Smarius{ 1342322120Smarius struct sdhci_slot *slot = device_get_ivars(reqdev); 1343322120Smarius int err; 1344322120Smarius 1345322120Smarius if (!(slot->opt & SDHCI_TUNING_ENABLED)) 1346322120Smarius return (0); 1347322120Smarius 1348322120Smarius /* HS400 must be tuned in HS200 mode. */ 1349322120Smarius if (slot->host.ios.timing == bus_timing_mmc_hs400) 1350322120Smarius return (EINVAL); 1351322120Smarius 1352322120Smarius SDHCI_LOCK(slot); 1353322120Smarius err = sdhci_exec_tuning(slot, reset); 1354322120Smarius /* 1355322120Smarius * There are two ways sdhci_exec_tuning() can fail: 1356322120Smarius * EBUSY should not actually happen when requests are only issued 1357322120Smarius * with the host properly acquired, and 1358322120Smarius * EIO re-tuning failed (but it did work initially). 1359322120Smarius * 1360322120Smarius * In both cases, we should retry at later point if periodic re-tuning 1361322120Smarius * is enabled. Note that due to slot->retune_req not being cleared in 1362322120Smarius * these failure cases, the MMC layer should trigger another attempt at 1363322120Smarius * re-tuning with the next request anyway, though. 1364322120Smarius */ 1365322120Smarius if (slot->retune_ticks) { 1366322120Smarius callout_reset(&slot->retune_callout, slot->retune_ticks, 1367322120Smarius sdhci_retune, slot); 1368322120Smarius } 1369322120Smarius SDHCI_UNLOCK(slot); 1370322120Smarius return (err); 1371322120Smarius} 1372322120Smarius 1373322120Smariusstatic int 1374322120Smariussdhci_exec_tuning(struct sdhci_slot *slot, bool reset) 1375322120Smarius{ 1376322120Smarius struct mmc_request *tune_req; 1377322120Smarius struct mmc_command *tune_cmd; 1378322120Smarius int i; 1379322120Smarius uint32_t intmask; 1380322120Smarius uint16_t hostctrl2; 1381322120Smarius u_char opt; 1382322120Smarius 1383322120Smarius SDHCI_ASSERT_LOCKED(slot); 1384322120Smarius if (slot->req != NULL) 1385322120Smarius return (EBUSY); 1386322120Smarius 1387322120Smarius /* Tuning doesn't work with DMA enabled. */ 1388322120Smarius opt = slot->opt; 1389322120Smarius slot->opt = opt & ~SDHCI_HAVE_DMA; 1390322120Smarius 1391322120Smarius /* 1392322120Smarius * Ensure that as documented, SDHCI_INT_DATA_AVAIL is the only 1393322120Smarius * kind of interrupt we receive in response to a tuning request. 1394322120Smarius */ 1395322120Smarius intmask = slot->intmask; 1396322120Smarius slot->intmask = SDHCI_INT_DATA_AVAIL; 1397331035Smarius WR4(slot, SDHCI_INT_ENABLE, SDHCI_INT_DATA_AVAIL); 1398322120Smarius WR4(slot, SDHCI_SIGNAL_ENABLE, SDHCI_INT_DATA_AVAIL); 1399322120Smarius 1400322120Smarius hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); 1401322120Smarius if (reset) 1402322120Smarius hostctrl2 &= ~SDHCI_CTRL2_SAMPLING_CLOCK; 1403322120Smarius else 1404322120Smarius hostctrl2 |= SDHCI_CTRL2_SAMPLING_CLOCK; 1405322120Smarius WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2 | SDHCI_CTRL2_EXEC_TUNING); 1406322120Smarius 1407322120Smarius tune_req = slot->tune_req; 1408322120Smarius tune_cmd = slot->tune_cmd; 1409322120Smarius for (i = 0; i < MMC_TUNING_MAX; i++) { 1410322120Smarius memset(tune_req, 0, sizeof(*tune_req)); 1411322120Smarius tune_req->cmd = tune_cmd; 1412322120Smarius tune_req->done = sdhci_req_wakeup; 1413322120Smarius tune_req->done_data = slot; 1414322120Smarius slot->req = tune_req; 1415322120Smarius slot->flags = 0; 1416322120Smarius sdhci_start(slot); 1417322120Smarius while (!(tune_req->flags & MMC_REQ_DONE)) 1418322120Smarius msleep(tune_req, &slot->mtx, 0, "sdhciet", 0); 1419322120Smarius if (!(tune_req->flags & MMC_TUNE_DONE)) 1420322120Smarius break; 1421322120Smarius hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); 1422322120Smarius if (!(hostctrl2 & SDHCI_CTRL2_EXEC_TUNING)) 1423322120Smarius break; 1424322120Smarius if (tune_cmd->opcode == MMC_SEND_TUNING_BLOCK) 1425322120Smarius DELAY(1000); 1426322120Smarius } 1427322120Smarius 1428331035Smarius /* 1429331035Smarius * Restore DMA usage and interrupts. 1430331035Smarius * Note that the interrupt aggregation code might have cleared 1431331035Smarius * SDHCI_INT_DMA_END and/or SDHCI_INT_RESPONSE in slot->intmask 1432331035Smarius * and SDHCI_SIGNAL_ENABLE respectively so ensure SDHCI_INT_ENABLE 1433331035Smarius * doesn't lose these. 1434331035Smarius */ 1435322120Smarius slot->opt = opt; 1436322120Smarius slot->intmask = intmask; 1437331035Smarius WR4(slot, SDHCI_INT_ENABLE, intmask | SDHCI_INT_DMA_END | 1438331035Smarius SDHCI_INT_RESPONSE); 1439322120Smarius WR4(slot, SDHCI_SIGNAL_ENABLE, intmask); 1440322120Smarius 1441322120Smarius if ((hostctrl2 & (SDHCI_CTRL2_EXEC_TUNING | 1442322120Smarius SDHCI_CTRL2_SAMPLING_CLOCK)) == SDHCI_CTRL2_SAMPLING_CLOCK) { 1443322120Smarius slot->retune_req = 0; 1444322120Smarius return (0); 1445322120Smarius } 1446322120Smarius 1447322120Smarius slot_printf(slot, "Tuning failed, using fixed sampling clock\n"); 1448322120Smarius WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2 & ~(SDHCI_CTRL2_EXEC_TUNING | 1449322120Smarius SDHCI_CTRL2_SAMPLING_CLOCK)); 1450322120Smarius sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1451322120Smarius return (EIO); 1452322120Smarius} 1453322120Smarius 1454318198Smariusstatic void 1455322120Smariussdhci_retune(void *arg) 1456322120Smarius{ 1457322120Smarius struct sdhci_slot *slot = arg; 1458322120Smarius 1459322120Smarius slot->retune_req |= SDHCI_RETUNE_REQ_NEEDED; 1460322120Smarius} 1461322120Smarius 1462322120Smariusstatic void 1463266200Siansdhci_req_done(struct sdhci_slot *slot) 1464266200Sian{ 1465266200Sian struct mmc_request *req; 1466266200Sian 1467266200Sian if (slot->req != NULL && slot->curcmd != NULL) { 1468266200Sian callout_stop(&slot->timeout_callout); 1469266200Sian req = slot->req; 1470266200Sian slot->req = NULL; 1471266200Sian slot->curcmd = NULL; 1472266200Sian req->done(req); 1473266200Sian } 1474266200Sian} 1475318198Smarius 1476318198Smariusstatic void 1477322120Smariussdhci_req_wakeup(struct mmc_request *req) 1478322120Smarius{ 1479322120Smarius struct sdhci_slot *slot; 1480322120Smarius 1481322120Smarius slot = req->done_data; 1482322120Smarius req->flags |= MMC_REQ_DONE; 1483322120Smarius wakeup(req); 1484322120Smarius} 1485322120Smarius 1486322120Smariusstatic void 1487266200Siansdhci_timeout(void *arg) 1488266200Sian{ 1489266200Sian struct sdhci_slot *slot = arg; 1490266200Sian 1491266200Sian if (slot->curcmd != NULL) { 1492322120Smarius slot_printf(slot, "Controller timeout\n"); 1493276287Sian sdhci_dumpregs(slot); 1494318198Smarius sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 1495266200Sian slot->curcmd->error = MMC_ERR_TIMEOUT; 1496266200Sian sdhci_req_done(slot); 1497276287Sian } else { 1498322120Smarius slot_printf(slot, "Spurious timeout - no active command\n"); 1499266200Sian } 1500266200Sian} 1501318198Smarius 1502184138Smavstatic void 1503343505Smariussdhci_set_transfer_mode(struct sdhci_slot *slot, const struct mmc_data *data) 1504184138Smav{ 1505184138Smav uint16_t mode; 1506184138Smav 1507184138Smav if (data == NULL) 1508184138Smav return; 1509184138Smav 1510184138Smav mode = SDHCI_TRNS_BLK_CNT_EN; 1511338634Smarius if (data->len > 512) { 1512184138Smav mode |= SDHCI_TRNS_MULTI; 1513338634Smarius if (__predict_true(slot->req->stop != NULL)) 1514338634Smarius mode |= SDHCI_TRNS_ACMD12; 1515338634Smarius } 1516184138Smav if (data->flags & MMC_DATA_READ) 1517184138Smav mode |= SDHCI_TRNS_READ; 1518184138Smav if (slot->flags & SDHCI_USE_DMA) 1519184138Smav mode |= SDHCI_TRNS_DMA; 1520184138Smav 1521184138Smav WR2(slot, SDHCI_TRANSFER_MODE, mode); 1522184138Smav} 1523184138Smav 1524184138Smavstatic void 1525184138Smavsdhci_start_command(struct sdhci_slot *slot, struct mmc_command *cmd) 1526184138Smav{ 1527184138Smav int flags, timeout; 1528312245Sian uint32_t mask; 1529184138Smav 1530184138Smav slot->curcmd = cmd; 1531184138Smav slot->cmd_done = 0; 1532184138Smav 1533184138Smav cmd->error = MMC_ERR_NONE; 1534184138Smav 1535184138Smav /* This flags combination is not supported by controller. */ 1536184138Smav if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 1537184138Smav slot_printf(slot, "Unsupported response type!\n"); 1538184138Smav cmd->error = MMC_ERR_FAILED; 1539266200Sian sdhci_req_done(slot); 1540184138Smav return; 1541184138Smav } 1542184138Smav 1543318198Smarius /* 1544318198Smarius * Do not issue command if there is no card, clock or power. 1545318198Smarius * Controller will not detect timeout without clock active. 1546318198Smarius */ 1547312245Sian if (!SDHCI_GET_CARD_PRESENT(slot->bus, slot) || 1548185661Smav slot->power == 0 || 1549185661Smav slot->clock == 0) { 1550184138Smav cmd->error = MMC_ERR_FAILED; 1551266200Sian sdhci_req_done(slot); 1552184138Smav return; 1553184138Smav } 1554184138Smav /* Always wait for free CMD bus. */ 1555184138Smav mask = SDHCI_CMD_INHIBIT; 1556184138Smav /* Wait for free DAT if we have data or busy signal. */ 1557184138Smav if (cmd->data || (cmd->flags & MMC_RSP_BUSY)) 1558184138Smav mask |= SDHCI_DAT_INHIBIT; 1559322120Smarius /* 1560322120Smarius * We shouldn't wait for DAT for stop commands or CMD19/CMD21. Note 1561322120Smarius * that these latter are also special in that SDHCI_CMD_DATA should 1562322120Smarius * be set below but no actual data is ever read from the controller. 1563322120Smarius */ 1564322120Smarius if (cmd == slot->req->stop || 1565322120Smarius __predict_false(cmd->opcode == MMC_SEND_TUNING_BLOCK || 1566322120Smarius cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)) 1567184138Smav mask &= ~SDHCI_DAT_INHIBIT; 1568266200Sian /* 1569266200Sian * Wait for bus no more then 250 ms. Typically there will be no wait 1570266200Sian * here at all, but when writing a crash dump we may be bypassing the 1571266200Sian * host platform's interrupt handler, and in some cases that handler 1572266200Sian * may be working around hardware quirks such as not respecting r1b 1573266200Sian * busy indications. In those cases, this wait-loop serves the purpose 1574266200Sian * of waiting for the prior command and data transfers to be done, and 1575266200Sian * SD cards are allowed to take up to 250ms for write and erase ops. 1576266200Sian * (It's usually more like 20-30ms in the real world.) 1577266200Sian */ 1578266200Sian timeout = 250; 1579312245Sian while (mask & RD4(slot, SDHCI_PRESENT_STATE)) { 1580184138Smav if (timeout == 0) { 1581184138Smav slot_printf(slot, "Controller never released " 1582184138Smav "inhibit bit(s).\n"); 1583184138Smav sdhci_dumpregs(slot); 1584184138Smav cmd->error = MMC_ERR_FAILED; 1585266200Sian sdhci_req_done(slot); 1586184138Smav return; 1587184138Smav } 1588184138Smav timeout--; 1589184138Smav DELAY(1000); 1590184138Smav } 1591184138Smav 1592184138Smav /* Prepare command flags. */ 1593184138Smav if (!(cmd->flags & MMC_RSP_PRESENT)) 1594184138Smav flags = SDHCI_CMD_RESP_NONE; 1595184138Smav else if (cmd->flags & MMC_RSP_136) 1596184138Smav flags = SDHCI_CMD_RESP_LONG; 1597184138Smav else if (cmd->flags & MMC_RSP_BUSY) 1598184138Smav flags = SDHCI_CMD_RESP_SHORT_BUSY; 1599184138Smav else 1600184138Smav flags = SDHCI_CMD_RESP_SHORT; 1601184138Smav if (cmd->flags & MMC_RSP_CRC) 1602184138Smav flags |= SDHCI_CMD_CRC; 1603184138Smav if (cmd->flags & MMC_RSP_OPCODE) 1604184138Smav flags |= SDHCI_CMD_INDEX; 1605184138Smav if (cmd->data) 1606184138Smav flags |= SDHCI_CMD_DATA; 1607184138Smav if (cmd->opcode == MMC_STOP_TRANSMISSION) 1608184138Smav flags |= SDHCI_CMD_TYPE_ABORT; 1609184138Smav /* Prepare data. */ 1610184138Smav sdhci_start_data(slot, cmd->data); 1611318198Smarius /* 1612184138Smav * Interrupt aggregation: To reduce total number of interrupts 1613184138Smav * group response interrupt with data interrupt when possible. 1614184138Smav * If there going to be data interrupt, mask response one. 1615184138Smav */ 1616184138Smav if (slot->data_done == 0) { 1617184138Smav WR4(slot, SDHCI_SIGNAL_ENABLE, 1618184138Smav slot->intmask &= ~SDHCI_INT_RESPONSE); 1619184138Smav } 1620184138Smav /* Set command argument. */ 1621184138Smav WR4(slot, SDHCI_ARGUMENT, cmd->arg); 1622184138Smav /* Set data transfer mode. */ 1623184138Smav sdhci_set_transfer_mode(slot, cmd->data); 1624184138Smav /* Start command. */ 1625241600Sgonzo WR2(slot, SDHCI_COMMAND_FLAGS, (cmd->opcode << 8) | (flags & 0xff)); 1626266200Sian /* Start timeout callout. */ 1627312245Sian callout_reset(&slot->timeout_callout, slot->timeout * hz, 1628312245Sian sdhci_timeout, slot); 1629184138Smav} 1630184138Smav 1631184138Smavstatic void 1632184138Smavsdhci_finish_command(struct sdhci_slot *slot) 1633184138Smav{ 1634184138Smav int i; 1635318198Smarius uint32_t val; 1636318198Smarius uint8_t extra; 1637184138Smav 1638184138Smav slot->cmd_done = 1; 1639318198Smarius /* 1640318198Smarius * Interrupt aggregation: Restore command interrupt. 1641184138Smav * Main restore point for the case when command interrupt 1642318198Smarius * happened first. 1643318198Smarius */ 1644322120Smarius if (__predict_true(slot->curcmd->opcode != MMC_SEND_TUNING_BLOCK && 1645322120Smarius slot->curcmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)) 1646322120Smarius WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask |= 1647322120Smarius SDHCI_INT_RESPONSE); 1648184138Smav /* In case of error - reset host and return. */ 1649184138Smav if (slot->curcmd->error) { 1650322120Smarius if (slot->curcmd->error == MMC_ERR_BADCRC) 1651322120Smarius slot->retune_req |= SDHCI_RETUNE_REQ_RESET; 1652184138Smav sdhci_reset(slot, SDHCI_RESET_CMD); 1653184138Smav sdhci_reset(slot, SDHCI_RESET_DATA); 1654184138Smav sdhci_start(slot); 1655184138Smav return; 1656184138Smav } 1657184138Smav /* If command has response - fetch it. */ 1658184138Smav if (slot->curcmd->flags & MMC_RSP_PRESENT) { 1659184138Smav if (slot->curcmd->flags & MMC_RSP_136) { 1660184138Smav /* CRC is stripped so we need one byte shift. */ 1661318198Smarius extra = 0; 1662184138Smav for (i = 0; i < 4; i++) { 1663318198Smarius val = RD4(slot, SDHCI_RESPONSE + i * 4); 1664318198Smarius if (slot->quirks & 1665318198Smarius SDHCI_QUIRK_DONT_SHIFT_RESPONSE) 1666254496Sian slot->curcmd->resp[3 - i] = val; 1667254496Sian else { 1668318198Smarius slot->curcmd->resp[3 - i] = 1669254496Sian (val << 8) | extra; 1670254496Sian extra = val >> 24; 1671254496Sian } 1672184138Smav } 1673184138Smav } else 1674184138Smav slot->curcmd->resp[0] = RD4(slot, SDHCI_RESPONSE); 1675184138Smav } 1676184138Smav /* If data ready - finish. */ 1677184138Smav if (slot->data_done) 1678184138Smav sdhci_start(slot); 1679184138Smav} 1680184138Smav 1681184138Smavstatic void 1682343505Smariussdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data) 1683184138Smav{ 1684343505Smarius uint32_t blkcnt, blksz, current_timeout, sdma_bbufsz, target_timeout; 1685184138Smav uint8_t div; 1686184138Smav 1687184138Smav if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) { 1688184138Smav slot->data_done = 1; 1689184138Smav return; 1690184138Smav } 1691184138Smav 1692184138Smav slot->data_done = 0; 1693184138Smav 1694184138Smav /* Calculate and set data timeout.*/ 1695184138Smav /* XXX: We should have this from mmc layer, now assume 1 sec. */ 1696254423Sian if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) { 1697184138Smav div = 0xE; 1698254423Sian } else { 1699254423Sian target_timeout = 1000000; 1700254423Sian div = 0; 1701254423Sian current_timeout = (1 << 13) * 1000 / slot->timeout_clk; 1702254423Sian while (current_timeout < target_timeout && div < 0xE) { 1703254423Sian ++div; 1704254423Sian current_timeout <<= 1; 1705254423Sian } 1706254423Sian /* Compensate for an off-by-one error in the CaFe chip.*/ 1707318198Smarius if (div < 0xE && 1708254423Sian (slot->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)) { 1709254423Sian ++div; 1710254423Sian } 1711184138Smav } 1712184138Smav WR1(slot, SDHCI_TIMEOUT_CONTROL, div); 1713184138Smav 1714184138Smav if (data == NULL) 1715184138Smav return; 1716184138Smav 1717184138Smav /* Use DMA if possible. */ 1718184138Smav if ((slot->opt & SDHCI_HAVE_DMA)) 1719184138Smav slot->flags |= SDHCI_USE_DMA; 1720343505Smarius /* If data is small, broken DMA may return zeroes instead of data. */ 1721241600Sgonzo if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) && 1722184138Smav (data->len <= 512)) 1723184138Smav slot->flags &= ~SDHCI_USE_DMA; 1724184138Smav /* Some controllers require even block sizes. */ 1725241600Sgonzo if ((slot->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) && 1726184138Smav ((data->len) & 0x3)) 1727184138Smav slot->flags &= ~SDHCI_USE_DMA; 1728184138Smav /* Load DMA buffer. */ 1729184138Smav if (slot->flags & SDHCI_USE_DMA) { 1730343505Smarius sdma_bbufsz = slot->sdma_bbufsz; 1731184138Smav if (data->flags & MMC_DATA_READ) 1732318198Smarius bus_dmamap_sync(slot->dmatag, slot->dmamap, 1733254512Srpaulo BUS_DMASYNC_PREREAD); 1734184138Smav else { 1735343505Smarius memcpy(slot->dmamem, data->data, ulmin(data->len, 1736343505Smarius sdma_bbufsz)); 1737318198Smarius bus_dmamap_sync(slot->dmatag, slot->dmamap, 1738254512Srpaulo BUS_DMASYNC_PREWRITE); 1739184138Smav } 1740184138Smav WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr); 1741343505Smarius /* 1742343505Smarius * Interrupt aggregation: Mask border interrupt for the last 1743343505Smarius * bounce buffer and unmask otherwise. 1744343505Smarius */ 1745343505Smarius if (data->len == sdma_bbufsz) 1746184138Smav slot->intmask &= ~SDHCI_INT_DMA_END; 1747184138Smav else 1748184138Smav slot->intmask |= SDHCI_INT_DMA_END; 1749184138Smav WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 1750184138Smav } 1751184138Smav /* Current data offset for both PIO and DMA. */ 1752184138Smav slot->offset = 0; 1753343505Smarius /* Set block size and request border interrupts on the SDMA boundary. */ 1754343505Smarius blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512)); 1755343505Smarius WR2(slot, SDHCI_BLOCK_SIZE, blksz); 1756184138Smav /* Set block count. */ 1757343505Smarius blkcnt = howmany(data->len, 512); 1758343505Smarius WR2(slot, SDHCI_BLOCK_COUNT, blkcnt); 1759184138Smav} 1760184138Smav 1761247495Sgonzovoid 1762184138Smavsdhci_finish_data(struct sdhci_slot *slot) 1763184138Smav{ 1764184138Smav struct mmc_data *data = slot->curcmd->data; 1765318198Smarius size_t left; 1766184138Smav 1767184138Smav /* Interrupt aggregation: Restore command interrupt. 1768254512Srpaulo * Auxiliary restore point for the case when data interrupt 1769184138Smav * happened first. */ 1770184138Smav if (!slot->cmd_done) { 1771184138Smav WR4(slot, SDHCI_SIGNAL_ENABLE, 1772184138Smav slot->intmask |= SDHCI_INT_RESPONSE); 1773184138Smav } 1774184138Smav /* Unload rest of data from DMA buffer. */ 1775278688Sian if (!slot->data_done && (slot->flags & SDHCI_USE_DMA)) { 1776184138Smav if (data->flags & MMC_DATA_READ) { 1777318198Smarius left = data->len - slot->offset; 1778318198Smarius bus_dmamap_sync(slot->dmatag, slot->dmamap, 1779254512Srpaulo BUS_DMASYNC_POSTREAD); 1780184138Smav memcpy((u_char*)data->data + slot->offset, slot->dmamem, 1781343505Smarius ulmin(left, slot->sdma_bbufsz)); 1782184138Smav } else 1783318198Smarius bus_dmamap_sync(slot->dmatag, slot->dmamap, 1784254512Srpaulo BUS_DMASYNC_POSTWRITE); 1785184138Smav } 1786278688Sian slot->data_done = 1; 1787184138Smav /* If there was error - reset the host. */ 1788184138Smav if (slot->curcmd->error) { 1789322120Smarius if (slot->curcmd->error == MMC_ERR_BADCRC) 1790322120Smarius slot->retune_req |= SDHCI_RETUNE_REQ_RESET; 1791184138Smav sdhci_reset(slot, SDHCI_RESET_CMD); 1792184138Smav sdhci_reset(slot, SDHCI_RESET_DATA); 1793184138Smav sdhci_start(slot); 1794184138Smav return; 1795184138Smav } 1796184138Smav /* If we already have command response - finish. */ 1797184138Smav if (slot->cmd_done) 1798184138Smav sdhci_start(slot); 1799184138Smav} 1800184138Smav 1801184138Smavstatic void 1802184138Smavsdhci_start(struct sdhci_slot *slot) 1803184138Smav{ 1804343505Smarius const struct mmc_request *req; 1805184138Smav 1806184138Smav req = slot->req; 1807184138Smav if (req == NULL) 1808184138Smav return; 1809184138Smav 1810184138Smav if (!(slot->flags & CMD_STARTED)) { 1811184138Smav slot->flags |= CMD_STARTED; 1812184138Smav sdhci_start_command(slot, req->cmd); 1813184138Smav return; 1814184138Smav } 1815184138Smav/* We don't need this until using Auto-CMD12 feature 1816184138Smav if (!(slot->flags & STOP_STARTED) && req->stop) { 1817184138Smav slot->flags |= STOP_STARTED; 1818184138Smav sdhci_start_command(slot, req->stop); 1819184138Smav return; 1820184138Smav } 1821184138Smav*/ 1822322120Smarius if (__predict_false(sdhci_debug > 1)) 1823187876Smav slot_printf(slot, "result: %d\n", req->cmd->error); 1824187876Smav if (!req->cmd->error && 1825241600Sgonzo (slot->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { 1826184138Smav sdhci_reset(slot, SDHCI_RESET_CMD); 1827184138Smav sdhci_reset(slot, SDHCI_RESET_DATA); 1828184138Smav } 1829184138Smav 1830266200Sian sdhci_req_done(slot); 1831184138Smav} 1832184138Smav 1833241600Sgonzoint 1834318198Smariussdhci_generic_request(device_t brdev __unused, device_t reqdev, 1835318198Smarius struct mmc_request *req) 1836184138Smav{ 1837184138Smav struct sdhci_slot *slot = device_get_ivars(reqdev); 1838184138Smav 1839184138Smav SDHCI_LOCK(slot); 1840184138Smav if (slot->req != NULL) { 1841184138Smav SDHCI_UNLOCK(slot); 1842184138Smav return (EBUSY); 1843184138Smav } 1844322120Smarius if (__predict_false(sdhci_debug > 1)) { 1845318198Smarius slot_printf(slot, 1846318198Smarius "CMD%u arg %#x flags %#x dlen %u dflags %#x\n", 1847318198Smarius req->cmd->opcode, req->cmd->arg, req->cmd->flags, 1848318198Smarius (req->cmd->data)?(u_int)req->cmd->data->len:0, 1849187876Smav (req->cmd->data)?req->cmd->data->flags:0); 1850187876Smav } 1851184138Smav slot->req = req; 1852184138Smav slot->flags = 0; 1853184138Smav sdhci_start(slot); 1854184138Smav SDHCI_UNLOCK(slot); 1855188724Smav if (dumping) { 1856188724Smav while (slot->req != NULL) { 1857241600Sgonzo sdhci_generic_intr(slot); 1858188724Smav DELAY(10); 1859188724Smav } 1860188724Smav } 1861184138Smav return (0); 1862184138Smav} 1863184138Smav 1864241600Sgonzoint 1865318198Smariussdhci_generic_get_ro(device_t brdev __unused, device_t reqdev) 1866184138Smav{ 1867184138Smav struct sdhci_slot *slot = device_get_ivars(reqdev); 1868184138Smav uint32_t val; 1869184138Smav 1870184138Smav SDHCI_LOCK(slot); 1871184138Smav val = RD4(slot, SDHCI_PRESENT_STATE); 1872184138Smav SDHCI_UNLOCK(slot); 1873184138Smav return (!(val & SDHCI_WRITE_PROTECT)); 1874184138Smav} 1875184138Smav 1876241600Sgonzoint 1877318198Smariussdhci_generic_acquire_host(device_t brdev __unused, device_t reqdev) 1878184138Smav{ 1879184138Smav struct sdhci_slot *slot = device_get_ivars(reqdev); 1880184138Smav int err = 0; 1881184138Smav 1882184138Smav SDHCI_LOCK(slot); 1883184138Smav while (slot->bus_busy) 1884185722Smav msleep(slot, &slot->mtx, 0, "sdhciah", 0); 1885184138Smav slot->bus_busy++; 1886184138Smav /* Activate led. */ 1887184138Smav WR1(slot, SDHCI_HOST_CONTROL, slot->hostctrl |= SDHCI_CTRL_LED); 1888184138Smav SDHCI_UNLOCK(slot); 1889184138Smav return (err); 1890184138Smav} 1891184138Smav 1892241600Sgonzoint 1893318198Smariussdhci_generic_release_host(device_t brdev __unused, device_t reqdev) 1894184138Smav{ 1895184138Smav struct sdhci_slot *slot = device_get_ivars(reqdev); 1896184138Smav 1897184138Smav SDHCI_LOCK(slot); 1898184138Smav /* Deactivate led. */ 1899184138Smav WR1(slot, SDHCI_HOST_CONTROL, slot->hostctrl &= ~SDHCI_CTRL_LED); 1900184138Smav slot->bus_busy--; 1901185722Smav SDHCI_UNLOCK(slot); 1902184138Smav wakeup(slot); 1903184138Smav return (0); 1904184138Smav} 1905184138Smav 1906184138Smavstatic void 1907184138Smavsdhci_cmd_irq(struct sdhci_slot *slot, uint32_t intmask) 1908184138Smav{ 1909184138Smav 1910184138Smav if (!slot->curcmd) { 1911184138Smav slot_printf(slot, "Got command interrupt 0x%08x, but " 1912184138Smav "there is no active command.\n", intmask); 1913184138Smav sdhci_dumpregs(slot); 1914184138Smav return; 1915184138Smav } 1916184138Smav if (intmask & SDHCI_INT_TIMEOUT) 1917184138Smav slot->curcmd->error = MMC_ERR_TIMEOUT; 1918184138Smav else if (intmask & SDHCI_INT_CRC) 1919184138Smav slot->curcmd->error = MMC_ERR_BADCRC; 1920184138Smav else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) 1921184138Smav slot->curcmd->error = MMC_ERR_FIFO; 1922184138Smav 1923184138Smav sdhci_finish_command(slot); 1924184138Smav} 1925184138Smav 1926184138Smavstatic void 1927184138Smavsdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask) 1928184138Smav{ 1929318198Smarius struct mmc_data *data; 1930318198Smarius size_t left; 1931343505Smarius uint32_t sdma_bbufsz; 1932184138Smav 1933184138Smav if (!slot->curcmd) { 1934184138Smav slot_printf(slot, "Got data interrupt 0x%08x, but " 1935184138Smav "there is no active command.\n", intmask); 1936184138Smav sdhci_dumpregs(slot); 1937184138Smav return; 1938184138Smav } 1939184138Smav if (slot->curcmd->data == NULL && 1940184138Smav (slot->curcmd->flags & MMC_RSP_BUSY) == 0) { 1941184138Smav slot_printf(slot, "Got data interrupt 0x%08x, but " 1942184138Smav "there is no active data operation.\n", 1943184138Smav intmask); 1944184138Smav sdhci_dumpregs(slot); 1945184138Smav return; 1946184138Smav } 1947184138Smav if (intmask & SDHCI_INT_DATA_TIMEOUT) 1948184138Smav slot->curcmd->error = MMC_ERR_TIMEOUT; 1949246891Sgonzo else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) 1950184138Smav slot->curcmd->error = MMC_ERR_BADCRC; 1951184138Smav if (slot->curcmd->data == NULL && 1952184138Smav (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | 1953184138Smav SDHCI_INT_DMA_END))) { 1954184138Smav slot_printf(slot, "Got data interrupt 0x%08x, but " 1955184138Smav "there is busy-only command.\n", intmask); 1956184138Smav sdhci_dumpregs(slot); 1957184138Smav slot->curcmd->error = MMC_ERR_INVALID; 1958184138Smav } 1959184138Smav if (slot->curcmd->error) { 1960184138Smav /* No need to continue after any error. */ 1961278688Sian goto done; 1962184138Smav } 1963184138Smav 1964322120Smarius /* Handle tuning completion interrupt. */ 1965322120Smarius if (__predict_false((intmask & SDHCI_INT_DATA_AVAIL) && 1966322120Smarius (slot->curcmd->opcode == MMC_SEND_TUNING_BLOCK || 1967322120Smarius slot->curcmd->opcode == MMC_SEND_TUNING_BLOCK_HS200))) { 1968322120Smarius slot->req->flags |= MMC_TUNE_DONE; 1969322120Smarius sdhci_finish_command(slot); 1970322120Smarius sdhci_finish_data(slot); 1971322120Smarius return; 1972322120Smarius } 1973184138Smav /* Handle PIO interrupt. */ 1974247495Sgonzo if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) { 1975318198Smarius if ((slot->opt & SDHCI_PLATFORM_TRANSFER) && 1976247495Sgonzo SDHCI_PLATFORM_WILL_HANDLE(slot->bus, slot)) { 1977318198Smarius SDHCI_PLATFORM_START_TRANSFER(slot->bus, slot, 1978318198Smarius &intmask); 1979247495Sgonzo slot->flags |= PLATFORM_DATA_STARTED; 1980247495Sgonzo } else 1981247495Sgonzo sdhci_transfer_pio(slot); 1982247495Sgonzo } 1983184138Smav /* Handle DMA border. */ 1984184138Smav if (intmask & SDHCI_INT_DMA_END) { 1985318198Smarius data = slot->curcmd->data; 1986343505Smarius sdma_bbufsz = slot->sdma_bbufsz; 1987184138Smav 1988318198Smarius /* Unload DMA buffer ... */ 1989184138Smav left = data->len - slot->offset; 1990184138Smav if (data->flags & MMC_DATA_READ) { 1991184138Smav bus_dmamap_sync(slot->dmatag, slot->dmamap, 1992184138Smav BUS_DMASYNC_POSTREAD); 1993184138Smav memcpy((u_char*)data->data + slot->offset, slot->dmamem, 1994343505Smarius ulmin(left, sdma_bbufsz)); 1995184138Smav } else { 1996184138Smav bus_dmamap_sync(slot->dmatag, slot->dmamap, 1997184138Smav BUS_DMASYNC_POSTWRITE); 1998184138Smav } 1999184138Smav /* ... and reload it again. */ 2000343505Smarius slot->offset += sdma_bbufsz; 2001184138Smav left = data->len - slot->offset; 2002184138Smav if (data->flags & MMC_DATA_READ) { 2003184138Smav bus_dmamap_sync(slot->dmatag, slot->dmamap, 2004184138Smav BUS_DMASYNC_PREREAD); 2005184138Smav } else { 2006184138Smav memcpy(slot->dmamem, (u_char*)data->data + slot->offset, 2007343505Smarius ulmin(left, sdma_bbufsz)); 2008184138Smav bus_dmamap_sync(slot->dmatag, slot->dmamap, 2009184138Smav BUS_DMASYNC_PREWRITE); 2010184138Smav } 2011343505Smarius /* 2012343505Smarius * Interrupt aggregation: Mask border interrupt for the last 2013343505Smarius * bounce buffer. 2014343505Smarius */ 2015343505Smarius if (left == sdma_bbufsz) { 2016184138Smav slot->intmask &= ~SDHCI_INT_DMA_END; 2017184138Smav WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 2018184138Smav } 2019184138Smav /* Restart DMA. */ 2020184138Smav WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr); 2021184138Smav } 2022184138Smav /* We have got all data. */ 2023247495Sgonzo if (intmask & SDHCI_INT_DATA_END) { 2024247495Sgonzo if (slot->flags & PLATFORM_DATA_STARTED) { 2025247495Sgonzo slot->flags &= ~PLATFORM_DATA_STARTED; 2026247495Sgonzo SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot); 2027247495Sgonzo } else 2028247495Sgonzo sdhci_finish_data(slot); 2029247495Sgonzo } 2030278688Siandone: 2031278688Sian if (slot->curcmd != NULL && slot->curcmd->error != 0) { 2032278688Sian if (slot->flags & PLATFORM_DATA_STARTED) { 2033278688Sian slot->flags &= ~PLATFORM_DATA_STARTED; 2034278688Sian SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot); 2035278688Sian } else 2036278688Sian sdhci_finish_data(slot); 2037278688Sian } 2038184138Smav} 2039184138Smav 2040184138Smavstatic void 2041338634Smariussdhci_acmd_irq(struct sdhci_slot *slot, uint16_t acmd_err) 2042184138Smav{ 2043318198Smarius 2044184138Smav if (!slot->curcmd) { 2045184138Smav slot_printf(slot, "Got AutoCMD12 error 0x%04x, but " 2046338634Smarius "there is no active command.\n", acmd_err); 2047184138Smav sdhci_dumpregs(slot); 2048184138Smav return; 2049184138Smav } 2050338634Smarius slot_printf(slot, "Got AutoCMD12 error 0x%04x\n", acmd_err); 2051184138Smav sdhci_reset(slot, SDHCI_RESET_CMD); 2052184138Smav} 2053184138Smav 2054241600Sgonzovoid 2055241600Sgonzosdhci_generic_intr(struct sdhci_slot *slot) 2056184138Smav{ 2057312245Sian uint32_t intmask, present; 2058338634Smarius uint16_t val16; 2059318198Smarius 2060241600Sgonzo SDHCI_LOCK(slot); 2061241600Sgonzo /* Read slot interrupt status. */ 2062241600Sgonzo intmask = RD4(slot, SDHCI_INT_STATUS); 2063241600Sgonzo if (intmask == 0 || intmask == 0xffffffff) { 2064241600Sgonzo SDHCI_UNLOCK(slot); 2065241600Sgonzo return; 2066241600Sgonzo } 2067322120Smarius if (__predict_false(sdhci_debug > 2)) 2068241600Sgonzo slot_printf(slot, "Interrupt %#x\n", intmask); 2069184138Smav 2070322120Smarius /* Handle tuning error interrupt. */ 2071322120Smarius if (__predict_false(intmask & SDHCI_INT_TUNEERR)) { 2072338634Smarius WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_TUNEERR); 2073322120Smarius slot_printf(slot, "Tuning error indicated\n"); 2074322120Smarius slot->retune_req |= SDHCI_RETUNE_REQ_RESET; 2075322120Smarius if (slot->curcmd) { 2076322120Smarius slot->curcmd->error = MMC_ERR_BADCRC; 2077322120Smarius sdhci_finish_command(slot); 2078322120Smarius } 2079322120Smarius } 2080322120Smarius /* Handle re-tuning interrupt. */ 2081322120Smarius if (__predict_false(intmask & SDHCI_INT_RETUNE)) 2082322120Smarius slot->retune_req |= SDHCI_RETUNE_REQ_NEEDED; 2083241600Sgonzo /* Handle card presence interrupts. */ 2084241600Sgonzo if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 2085312245Sian present = (intmask & SDHCI_INT_CARD_INSERT) != 0; 2086312245Sian slot->intmask &= 2087312245Sian ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); 2088312245Sian slot->intmask |= present ? SDHCI_INT_CARD_REMOVE : 2089312245Sian SDHCI_INT_CARD_INSERT; 2090312245Sian WR4(slot, SDHCI_INT_ENABLE, slot->intmask); 2091312245Sian WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); 2092318198Smarius WR4(slot, SDHCI_INT_STATUS, intmask & 2093241600Sgonzo (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)); 2094312245Sian sdhci_handle_card_present_locked(slot, present); 2095184138Smav } 2096241600Sgonzo /* Handle command interrupts. */ 2097241600Sgonzo if (intmask & SDHCI_INT_CMD_MASK) { 2098241600Sgonzo WR4(slot, SDHCI_INT_STATUS, intmask & SDHCI_INT_CMD_MASK); 2099241600Sgonzo sdhci_cmd_irq(slot, intmask & SDHCI_INT_CMD_MASK); 2100241600Sgonzo } 2101241600Sgonzo /* Handle data interrupts. */ 2102241600Sgonzo if (intmask & SDHCI_INT_DATA_MASK) { 2103241600Sgonzo WR4(slot, SDHCI_INT_STATUS, intmask & SDHCI_INT_DATA_MASK); 2104318198Smarius /* Don't call data_irq in case of errored command. */ 2105276287Sian if ((intmask & SDHCI_INT_CMD_ERROR_MASK) == 0) 2106276287Sian sdhci_data_irq(slot, intmask & SDHCI_INT_DATA_MASK); 2107241600Sgonzo } 2108241600Sgonzo /* Handle AutoCMD12 error interrupt. */ 2109241600Sgonzo if (intmask & SDHCI_INT_ACMD12ERR) { 2110338634Smarius /* Clearing SDHCI_INT_ACMD12ERR may clear SDHCI_ACMD12_ERR. */ 2111338634Smarius val16 = RD2(slot, SDHCI_ACMD12_ERR); 2112241600Sgonzo WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_ACMD12ERR); 2113338634Smarius sdhci_acmd_irq(slot, val16); 2114241600Sgonzo } 2115241600Sgonzo /* Handle bus power interrupt. */ 2116241600Sgonzo if (intmask & SDHCI_INT_BUS_POWER) { 2117241600Sgonzo WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_BUS_POWER); 2118322120Smarius slot_printf(slot, "Card is consuming too much power!\n"); 2119241600Sgonzo } 2120322120Smarius intmask &= ~(SDHCI_INT_ERROR | SDHCI_INT_TUNEERR | SDHCI_INT_RETUNE | 2121322120Smarius SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | 2122322120Smarius SDHCI_INT_DATA_MASK | SDHCI_INT_ACMD12ERR | SDHCI_INT_BUS_POWER); 2123241600Sgonzo /* The rest is unknown. */ 2124241600Sgonzo if (intmask) { 2125241600Sgonzo WR4(slot, SDHCI_INT_STATUS, intmask); 2126241600Sgonzo slot_printf(slot, "Unexpected interrupt 0x%08x.\n", 2127241600Sgonzo intmask); 2128241600Sgonzo sdhci_dumpregs(slot); 2129241600Sgonzo } 2130318198Smarius 2131241600Sgonzo SDHCI_UNLOCK(slot); 2132184138Smav} 2133184138Smav 2134241600Sgonzoint 2135318198Smariussdhci_generic_read_ivar(device_t bus, device_t child, int which, 2136318198Smarius uintptr_t *result) 2137184138Smav{ 2138343505Smarius const struct sdhci_slot *slot = device_get_ivars(child); 2139184138Smav 2140184138Smav switch (which) { 2141184138Smav default: 2142184138Smav return (EINVAL); 2143184138Smav case MMCBR_IVAR_BUS_MODE: 2144222475Sjchandra *result = slot->host.ios.bus_mode; 2145184138Smav break; 2146184138Smav case MMCBR_IVAR_BUS_WIDTH: 2147222475Sjchandra *result = slot->host.ios.bus_width; 2148184138Smav break; 2149184138Smav case MMCBR_IVAR_CHIP_SELECT: 2150222475Sjchandra *result = slot->host.ios.chip_select; 2151184138Smav break; 2152184138Smav case MMCBR_IVAR_CLOCK: 2153222475Sjchandra *result = slot->host.ios.clock; 2154184138Smav break; 2155184138Smav case MMCBR_IVAR_F_MIN: 2156222475Sjchandra *result = slot->host.f_min; 2157184138Smav break; 2158184138Smav case MMCBR_IVAR_F_MAX: 2159222475Sjchandra *result = slot->host.f_max; 2160184138Smav break; 2161184138Smav case MMCBR_IVAR_HOST_OCR: 2162222475Sjchandra *result = slot->host.host_ocr; 2163184138Smav break; 2164184138Smav case MMCBR_IVAR_MODE: 2165222475Sjchandra *result = slot->host.mode; 2166184138Smav break; 2167184138Smav case MMCBR_IVAR_OCR: 2168222475Sjchandra *result = slot->host.ocr; 2169184138Smav break; 2170184138Smav case MMCBR_IVAR_POWER_MODE: 2171222475Sjchandra *result = slot->host.ios.power_mode; 2172184138Smav break; 2173184138Smav case MMCBR_IVAR_VDD: 2174222475Sjchandra *result = slot->host.ios.vdd; 2175184138Smav break; 2176322120Smarius case MMCBR_IVAR_RETUNE_REQ: 2177322120Smarius if (slot->opt & SDHCI_TUNING_ENABLED) { 2178322120Smarius if (slot->retune_req & SDHCI_RETUNE_REQ_RESET) { 2179322120Smarius *result = retune_req_reset; 2180322120Smarius break; 2181322120Smarius } 2182322120Smarius if (slot->retune_req & SDHCI_RETUNE_REQ_NEEDED) { 2183322120Smarius *result = retune_req_normal; 2184322120Smarius break; 2185322120Smarius } 2186322120Smarius } 2187322120Smarius *result = retune_req_none; 2188322120Smarius break; 2189318495Smarius case MMCBR_IVAR_VCCQ: 2190318495Smarius *result = slot->host.ios.vccq; 2191318495Smarius break; 2192184138Smav case MMCBR_IVAR_CAPS: 2193222475Sjchandra *result = slot->host.caps; 2194184138Smav break; 2195184138Smav case MMCBR_IVAR_TIMING: 2196222475Sjchandra *result = slot->host.ios.timing; 2197184138Smav break; 2198184452Smav case MMCBR_IVAR_MAX_DATA: 2199322120Smarius /* 2200322120Smarius * Re-tuning modes 1 and 2 restrict the maximum data length 2201322120Smarius * per read/write command to 4 MiB. 2202322120Smarius */ 2203322120Smarius if (slot->opt & SDHCI_TUNING_ENABLED && 2204322120Smarius (slot->retune_mode == SDHCI_RETUNE_MODE_1 || 2205322120Smarius slot->retune_mode == SDHCI_RETUNE_MODE_2)) { 2206322120Smarius *result = 4 * 1024 * 1024 / MMC_SECTOR_SIZE; 2207322120Smarius break; 2208322120Smarius } 2209222475Sjchandra *result = 65535; 2210184452Smav break; 2211318198Smarius case MMCBR_IVAR_MAX_BUSY_TIMEOUT: 2212318198Smarius /* 2213318198Smarius * Currently, sdhci_start_data() hardcodes 1 s for all CMDs. 2214318198Smarius */ 2215318198Smarius *result = 1000000; 2216318198Smarius break; 2217184138Smav } 2218184138Smav return (0); 2219184138Smav} 2220184138Smav 2221241600Sgonzoint 2222318198Smariussdhci_generic_write_ivar(device_t bus, device_t child, int which, 2223318198Smarius uintptr_t value) 2224184138Smav{ 2225184138Smav struct sdhci_slot *slot = device_get_ivars(child); 2226318198Smarius uint32_t clock, max_clock; 2227318198Smarius int i; 2228184138Smav 2229184138Smav switch (which) { 2230184138Smav default: 2231184138Smav return (EINVAL); 2232184138Smav case MMCBR_IVAR_BUS_MODE: 2233184138Smav slot->host.ios.bus_mode = value; 2234184138Smav break; 2235184138Smav case MMCBR_IVAR_BUS_WIDTH: 2236184138Smav slot->host.ios.bus_width = value; 2237184138Smav break; 2238184138Smav case MMCBR_IVAR_CHIP_SELECT: 2239184138Smav slot->host.ios.chip_select = value; 2240184138Smav break; 2241184138Smav case MMCBR_IVAR_CLOCK: 2242184138Smav if (value > 0) { 2243246886Sgonzo max_clock = slot->max_clk; 2244246886Sgonzo clock = max_clock; 2245246886Sgonzo 2246246886Sgonzo if (slot->version < SDHCI_SPEC_300) { 2247246886Sgonzo for (i = 0; i < SDHCI_200_MAX_DIVIDER; 2248246886Sgonzo i <<= 1) { 2249246886Sgonzo if (clock <= value) 2250246886Sgonzo break; 2251246886Sgonzo clock >>= 1; 2252246886Sgonzo } 2253318198Smarius } else { 2254246886Sgonzo for (i = 0; i < SDHCI_300_MAX_DIVIDER; 2255246886Sgonzo i += 2) { 2256246886Sgonzo if (clock <= value) 2257246886Sgonzo break; 2258246886Sgonzo clock = max_clock / (i + 2); 2259246886Sgonzo } 2260246886Sgonzo } 2261246886Sgonzo 2262184138Smav slot->host.ios.clock = clock; 2263184138Smav } else 2264184138Smav slot->host.ios.clock = 0; 2265184138Smav break; 2266184138Smav case MMCBR_IVAR_MODE: 2267184138Smav slot->host.mode = value; 2268184138Smav break; 2269184138Smav case MMCBR_IVAR_OCR: 2270184138Smav slot->host.ocr = value; 2271184138Smav break; 2272184138Smav case MMCBR_IVAR_POWER_MODE: 2273184138Smav slot->host.ios.power_mode = value; 2274184138Smav break; 2275184138Smav case MMCBR_IVAR_VDD: 2276184138Smav slot->host.ios.vdd = value; 2277184138Smav break; 2278318495Smarius case MMCBR_IVAR_VCCQ: 2279318495Smarius slot->host.ios.vccq = value; 2280318495Smarius break; 2281184138Smav case MMCBR_IVAR_TIMING: 2282184138Smav slot->host.ios.timing = value; 2283184138Smav break; 2284184138Smav case MMCBR_IVAR_CAPS: 2285184138Smav case MMCBR_IVAR_HOST_OCR: 2286184138Smav case MMCBR_IVAR_F_MIN: 2287184138Smav case MMCBR_IVAR_F_MAX: 2288184452Smav case MMCBR_IVAR_MAX_DATA: 2289322120Smarius case MMCBR_IVAR_RETUNE_REQ: 2290184138Smav return (EINVAL); 2291184138Smav } 2292184138Smav return (0); 2293184138Smav} 2294184138Smav 2295343505SmariusMODULE_VERSION(sdhci, SDHCI_VERSION); 2296