1/* $NetBSD: meson_sdio.c,v 1.5 2021/08/07 16:18:43 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2015-2019 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: meson_sdio.c,v 1.5 2021/08/07 16:18:43 thorpej Exp $"); 31 32#include <sys/param.h> 33#include <sys/bus.h> 34#include <sys/device.h> 35#include <sys/intr.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/gpio.h> 39 40#include <dev/sdmmc/sdmmcvar.h> 41#include <dev/sdmmc/sdmmcchip.h> 42#include <dev/sdmmc/sdmmc_ioreg.h> 43 44#include <dev/fdt/fdtvar.h> 45 46#include <arm/amlogic/meson_sdioreg.h> 47 48static int meson_sdio_match(device_t, cfdata_t, void *); 49static void meson_sdio_attach(device_t, device_t, void *); 50static void meson_sdio_attach_i(device_t); 51 52static int meson_sdio_intr(void *); 53 54struct meson_sdio_softc { 55 device_t sc_dev; 56 bus_space_tag_t sc_bst; 57 bus_space_handle_t sc_bsh; 58 bus_dma_tag_t sc_dmat; 59 void *sc_ih; 60 61 int sc_slot_phandle; 62 63 uint32_t sc_bus_freq; 64 u_int sc_cur_width; 65 int sc_cur_port; 66 67 struct fdtbus_gpio_pin *sc_gpio_cd; 68 int sc_gpio_cd_inverted; 69 struct fdtbus_gpio_pin *sc_gpio_wp; 70 int sc_gpio_wp_inverted; 71 72 struct fdtbus_regulator *sc_reg_vmmc; 73 struct fdtbus_regulator *sc_reg_vqmmc; 74 75 bool sc_non_removable; 76 bool sc_broken_cd; 77 78 device_t sc_sdmmc_dev; 79 kmutex_t sc_intr_lock; 80 kcondvar_t sc_intr_cv; 81 82 uint32_t sc_intr_irqs; 83 84 bus_dmamap_t sc_dmamap; 85 bus_dma_segment_t sc_segs[1]; 86 void *sc_bbuf; 87}; 88 89CFATTACH_DECL_NEW(meson_sdio, sizeof(struct meson_sdio_softc), 90 meson_sdio_match, meson_sdio_attach, NULL, NULL); 91 92static int meson_sdio_host_reset(sdmmc_chipset_handle_t); 93static uint32_t meson_sdio_host_ocr(sdmmc_chipset_handle_t); 94static int meson_sdio_host_maxblklen(sdmmc_chipset_handle_t); 95static int meson_sdio_card_detect(sdmmc_chipset_handle_t); 96static int meson_sdio_write_protect(sdmmc_chipset_handle_t); 97static int meson_sdio_bus_power(sdmmc_chipset_handle_t, uint32_t); 98static int meson_sdio_bus_clock(sdmmc_chipset_handle_t, int); 99static int meson_sdio_bus_width(sdmmc_chipset_handle_t, int); 100static int meson_sdio_bus_rod(sdmmc_chipset_handle_t, int); 101static int meson_sdio_signal_voltage(sdmmc_chipset_handle_t, int); 102static void meson_sdio_exec_command(sdmmc_chipset_handle_t, 103 struct sdmmc_command *); 104static void meson_sdio_card_enable_intr(sdmmc_chipset_handle_t, int); 105static void meson_sdio_card_intr_ack(sdmmc_chipset_handle_t); 106 107static int meson_sdio_set_clock(struct meson_sdio_softc *, u_int); 108static int meson_sdio_wait_irqs(struct meson_sdio_softc *, uint32_t, int); 109 110static void meson_sdio_dmainit(struct meson_sdio_softc *); 111 112static struct sdmmc_chip_functions meson_sdio_chip_functions = { 113 .host_reset = meson_sdio_host_reset, 114 .host_ocr = meson_sdio_host_ocr, 115 .host_maxblklen = meson_sdio_host_maxblklen, 116 .card_detect = meson_sdio_card_detect, 117 .write_protect = meson_sdio_write_protect, 118 .bus_power = meson_sdio_bus_power, 119 .bus_clock = meson_sdio_bus_clock, 120 .bus_width = meson_sdio_bus_width, 121 .bus_rod = meson_sdio_bus_rod, 122 .signal_voltage = meson_sdio_signal_voltage, 123 .exec_command = meson_sdio_exec_command, 124 .card_enable_intr = meson_sdio_card_enable_intr, 125 .card_intr_ack = meson_sdio_card_intr_ack, 126}; 127 128#define SDIO_WRITE(sc, reg, val) \ 129 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 130#define SDIO_READ(sc, reg) \ 131 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 132 133static const struct device_compatible_entry compat_data[] = { 134 { .compat = "amlogic,meson8b-sdio" }, 135 DEVICE_COMPAT_EOL 136}; 137 138static const struct device_compatible_entry slot_compat_data[] = { 139 { .compat = "mmc-slot" }, 140 DEVICE_COMPAT_EOL 141}; 142 143static int 144meson_sdio_match(device_t parent, cfdata_t cf, void *aux) 145{ 146 struct fdt_attach_args * const faa = aux; 147 148 return of_compatible_match(faa->faa_phandle, compat_data); 149} 150 151static void 152meson_sdio_attach(device_t parent, device_t self, void *aux) 153{ 154 struct meson_sdio_softc * const sc = device_private(self); 155 struct fdt_attach_args * const faa = aux; 156 const int phandle = faa->faa_phandle; 157 char intrstr[128]; 158 struct clk *clk_clkin, *clk_core; 159 bus_addr_t addr, port; 160 bus_size_t size; 161 int child; 162 163 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 164 aprint_error(": couldn't get registers\n"); 165 return; 166 } 167 168 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 169 aprint_error(": failed to decode interrupt\n"); 170 return; 171 } 172 173 clk_core = fdtbus_clock_get(phandle, "core"); 174 if (clk_core == NULL || clk_enable(clk_core) != 0) { 175 aprint_error(": failed to enable core clock\n"); 176 return; 177 } 178 179 clk_clkin = fdtbus_clock_get(phandle, "clkin"); 180 if (clk_clkin == NULL) { 181 aprint_error(": failed to get clkin clock\n"); 182 return; 183 } 184 185 sc->sc_dev = self; 186 sc->sc_bst = faa->faa_bst; 187 sc->sc_dmat = faa->faa_dmat; 188 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 189 aprint_error(": failed to map registers\n"); 190 return; 191 } 192 193 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO); 194 cv_init(&sc->sc_intr_cv, "sdiointr"); 195 196 sc->sc_cur_port = -1; 197 for (child = OF_child(phandle); child; child = OF_peer(child)) 198 if (of_compatible_match(child, slot_compat_data)) { 199 if (fdtbus_get_reg(child, 0, &port, NULL) == 0) { 200 sc->sc_slot_phandle = child; 201 sc->sc_cur_port = port; 202 } 203 break; 204 } 205 if (sc->sc_cur_port == -1) { 206 aprint_error(": couldn't get mmc slot\n"); 207 return; 208 } 209 210 aprint_naive("\n"); 211 aprint_normal(": SDIO controller (port %c)\n", sc->sc_cur_port + 'A'); 212 213 sc->sc_reg_vmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vmmc-supply"); 214 sc->sc_reg_vqmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vqmmc-supply"); 215 216 sc->sc_gpio_cd = fdtbus_gpio_acquire(sc->sc_slot_phandle, "cd-gpios", 217 GPIO_PIN_INPUT); 218 sc->sc_gpio_wp = fdtbus_gpio_acquire(sc->sc_slot_phandle, "wp-gpios", 219 GPIO_PIN_INPUT); 220 221 sc->sc_gpio_cd_inverted = of_hasprop(sc->sc_slot_phandle, "cd-inverted"); 222 sc->sc_gpio_wp_inverted = of_hasprop(sc->sc_slot_phandle, "wp-inverted"); 223 224 sc->sc_non_removable = of_hasprop(sc->sc_slot_phandle, "non-removable"); 225 sc->sc_broken_cd = of_hasprop(sc->sc_slot_phandle, "broken-cd"); 226 227 sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0, 228 meson_sdio_intr, sc, device_xname(self)); 229 if (sc->sc_ih == NULL) { 230 aprint_error_dev(self, "couldn't establish interrupt on %s\n", 231 intrstr); 232 return; 233 } 234 aprint_normal_dev(self, "interrupting on %s\n", intrstr); 235 236 sc->sc_bus_freq = clk_get_rate(clk_clkin); 237 238 aprint_normal_dev(self, "core %u Hz, clkin %u Hz\n", clk_get_rate(clk_core), clk_get_rate(clk_clkin)); 239 240 meson_sdio_dmainit(sc); 241 242 config_interrupts(self, meson_sdio_attach_i); 243} 244 245static void 246meson_sdio_attach_i(device_t self) 247{ 248 struct meson_sdio_softc *sc = device_private(self); 249 struct sdmmcbus_attach_args saa; 250 251 meson_sdio_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_330); 252 meson_sdio_host_reset(sc); 253 meson_sdio_bus_clock(sc, 400); 254 meson_sdio_bus_width(sc, 1); 255 256 memset(&saa, 0, sizeof(saa)); 257 saa.saa_busname = "sdmmc"; 258 saa.saa_sct = &meson_sdio_chip_functions; 259 saa.saa_dmat = sc->sc_dmat; 260 saa.saa_sch = sc; 261 saa.saa_clkmin = 400; 262 saa.saa_clkmax = sc->sc_bus_freq; 263 /* Do not advertise DMA capabilities, we handle DMA ourselves */ 264 saa.saa_caps = SMC_CAPS_4BIT_MODE| 265 SMC_CAPS_SD_HIGHSPEED| 266 SMC_CAPS_MMC_HIGHSPEED; 267 268 sc->sc_sdmmc_dev = config_found(self, &saa, NULL, CFARGS_NONE); 269} 270 271static int 272meson_sdio_intr(void *priv) 273{ 274 struct meson_sdio_softc *sc = priv; 275 276 mutex_enter(&sc->sc_intr_lock); 277 const u_int irqs = SDIO_READ(sc, SDIO_IRQS_REG); 278 if (irqs & SDIO_IRQS_CLEAR) { 279 SDIO_WRITE(sc, SDIO_IRQS_REG, irqs); 280 sc->sc_intr_irqs |= irqs; 281 cv_broadcast(&sc->sc_intr_cv); 282 } 283 mutex_exit(&sc->sc_intr_lock); 284 285 return 1; 286} 287 288static void 289meson_sdio_dmainit(struct meson_sdio_softc *sc) 290{ 291 int error, rseg; 292 293 error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS, PAGE_SIZE, MAXPHYS, 294 sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK); 295 if (error) { 296 device_printf(sc->sc_dev, "bus_dmamem_alloc failed\n"); 297 return; 298 } 299 KASSERT(rseg == 1); 300 301 error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, MAXPHYS, 302 &sc->sc_bbuf, BUS_DMA_WAITOK); 303 if (error) { 304 device_printf(sc->sc_dev, "bus_dmamem_map failed\n"); 305 return; 306 } 307 308 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 309 BUS_DMA_WAITOK, &sc->sc_dmamap); 310 if (error) { 311 device_printf(sc->sc_dev, "bus_dmamap_create failed\n"); 312 return; 313 } 314} 315 316static int 317meson_sdio_set_clock(struct meson_sdio_softc *sc, u_int freq) 318{ 319 const u_int pll_freq = sc->sc_bus_freq / 2000; 320 uint32_t conf; 321 int clk_div; 322 323 if (freq == 0) 324 return 0; 325 326 clk_div = howmany(pll_freq, freq); 327 328 conf = SDIO_READ(sc, SDIO_CONF_REG); 329 conf &= ~SDIO_CONF_COMMAND_CLK_DIV; 330 conf |= __SHIFTIN(clk_div - 1, SDIO_CONF_COMMAND_CLK_DIV); 331 SDIO_WRITE(sc, SDIO_CONF_REG, conf); 332 333 return 0; 334} 335 336static int 337meson_sdio_wait_irqs(struct meson_sdio_softc *sc, uint32_t mask, int timeout) 338{ 339 int retry, error; 340 341 KASSERT(mutex_owned(&sc->sc_intr_lock)); 342 343 if (sc->sc_intr_irqs & mask) 344 return 0; 345 346 retry = timeout / hz; 347 348 while (retry > 0) { 349 error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz); 350 if (error && error != EWOULDBLOCK) 351 return error; 352 if (sc->sc_intr_irqs & mask) 353 return 0; 354 --retry; 355 } 356 357 return ETIMEDOUT; 358} 359 360static int 361meson_sdio_host_reset(sdmmc_chipset_handle_t sch) 362{ 363 struct meson_sdio_softc *sc = sch; 364 365 SDIO_WRITE(sc, SDIO_IRQC_REG, SDIO_IRQC_SOFT_RESET); 366 367 delay(2); 368 369 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_CLEAR); 370 SDIO_WRITE(sc, SDIO_CONF_REG, 371 __SHIFTIN(2, SDIO_CONF_WRITE_CRC_OK_STATUS) | 372 __SHIFTIN(2, SDIO_CONF_WRITE_NWR) | 373 __SHIFTIN(3, SDIO_CONF_M_ENDIAN) | 374 __SHIFTIN(39, SDIO_CONF_COMMAND_ARG_BITS) | 375 __SHIFTIN(0x1f4, SDIO_CONF_COMMAND_CLK_DIV)); 376 377 SDIO_WRITE(sc, SDIO_MULT_REG, 378 __SHIFTIN(sc->sc_cur_port, SDIO_MULT_PORT_SEL)); 379 380 return 0; 381} 382 383static uint32_t 384meson_sdio_host_ocr(sdmmc_chipset_handle_t sch) 385{ 386 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V; 387} 388 389static int 390meson_sdio_host_maxblklen(sdmmc_chipset_handle_t sch) 391{ 392 return 512; 393} 394 395static int 396meson_sdio_card_detect(sdmmc_chipset_handle_t sch) 397{ 398 struct meson_sdio_softc *sc = sch; 399 int val; 400 401 if (sc->sc_non_removable || sc->sc_broken_cd) { 402 return 1; 403 } else if (sc->sc_gpio_cd != NULL) { 404 val = fdtbus_gpio_read(sc->sc_gpio_cd); 405 if (sc->sc_gpio_cd_inverted) 406 val = !val; 407 return val; 408 } else { 409 return 1; 410 } 411} 412 413static int 414meson_sdio_write_protect(sdmmc_chipset_handle_t sch) 415{ 416 struct meson_sdio_softc *sc = sch; 417 int val; 418 419 if (sc->sc_gpio_wp != NULL) { 420 val = fdtbus_gpio_read(sc->sc_gpio_wp); 421 if (sc->sc_gpio_wp_inverted) 422 val = !val; 423 return val; 424 } 425 426 return 0; 427} 428 429static int 430meson_sdio_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 431{ 432 return 0; 433} 434 435static int 436meson_sdio_bus_clock(sdmmc_chipset_handle_t sch, int freq) 437{ 438 struct meson_sdio_softc *sc = sch; 439 440 return meson_sdio_set_clock(sc, freq); 441} 442 443static int 444meson_sdio_bus_width(sdmmc_chipset_handle_t sch, int width) 445{ 446 struct meson_sdio_softc *sc = sch; 447 uint32_t conf; 448 449 conf = SDIO_READ(sc, SDIO_CONF_REG); 450 if (width == 1) { 451 conf &= ~SDIO_CONF_BUS_WIDTH; 452 } else if (width == 4) { 453 conf |= SDIO_CONF_BUS_WIDTH; 454 } else { 455 return EINVAL; 456 } 457 SDIO_WRITE(sc, SDIO_CONF_REG, conf); 458 459 sc->sc_cur_width = width; 460 461 return 0; 462} 463 464static int 465meson_sdio_bus_rod(sdmmc_chipset_handle_t sch, int on) 466{ 467 return ENOTSUP; 468} 469 470static int 471meson_sdio_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage) 472{ 473 struct meson_sdio_softc *sc = sch; 474 u_int uvol; 475 int error; 476 477 if (sc->sc_reg_vqmmc == NULL) 478 return 0; 479 480 switch (signal_voltage) { 481 case SDMMC_SIGNAL_VOLTAGE_330: 482 uvol = 3300000; 483 break; 484 case SDMMC_SIGNAL_VOLTAGE_180: 485 uvol = 1800000; 486 break; 487 default: 488 return EINVAL; 489 } 490 491 error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol); 492 if (error != 0) 493 return 0; 494 495 error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol); 496 if (error != 0) 497 return error; 498 499 return fdtbus_regulator_enable(sc->sc_reg_vqmmc); 500} 501 502static void 503meson_sdio_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 504{ 505 struct meson_sdio_softc *sc = sch; 506 uint32_t send, ext, mult, addr; 507 bool use_bbuf = false; 508 int i; 509 510 KASSERT(cmd->c_blklen <= 512); 511 512 send = ext = mult = addr = 0; 513 514 mutex_enter(&sc->sc_intr_lock); 515 516 if (cmd->c_opcode == SD_IO_SEND_OP_COND || 517 cmd->c_opcode == SD_IO_RW_DIRECT || 518 cmd->c_opcode == SD_IO_RW_EXTENDED) { 519 cmd->c_error = EINVAL; 520 goto done; 521 } 522 523 sc->sc_intr_irqs = 0; 524 525 if (cmd->c_flags & SCF_RSP_PRESENT) { 526 if (cmd->c_flags & SCF_RSP_136) { 527 send |= __SHIFTIN(133, SDIO_SEND_RESPONSE_BITS); 528 send |= SDIO_SEND_RESPONSE_CRC7_FROM_8; 529 } else { 530 send |= __SHIFTIN(45, SDIO_SEND_RESPONSE_BITS); 531 } 532 } 533 if ((cmd->c_flags & SCF_RSP_CRC) == 0) { 534 send |= SDIO_SEND_RESPONSE_NO_CRC; 535 } 536 if (cmd->c_flags & SCF_RSP_BSY) { 537 send |= SDIO_SEND_CHECK_BUSY_DAT0; 538 } 539 540 if (cmd->c_datalen > 0) { 541 unsigned int nblks, packlen; 542 543 nblks = cmd->c_datalen / cmd->c_blklen; 544 if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0) 545 ++nblks; 546 packlen = (cmd->c_blklen * 8) + (0xf * sc->sc_cur_width); 547 548 send |= __SHIFTIN(nblks - 1, SDIO_SEND_REPEAT_PACKAGE); 549 ext |= __SHIFTIN(packlen, SDIO_EXT_DATA_RW_NUMBER); 550 551 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 552 send |= SDIO_SEND_RESPONSE_DATA; 553 } else { 554 send |= SDIO_SEND_COMMAND_HAS_DATA; 555 } 556 557 cmd->c_error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, 558 sc->sc_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK); 559 if (cmd->c_error) { 560 device_printf(sc->sc_dev, "bus_dmamap_load failed\n"); 561 goto done; 562 } 563 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 564 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 565 MAXPHYS, BUS_DMASYNC_PREREAD); 566 } else { 567 memcpy(sc->sc_bbuf, cmd->c_data, cmd->c_datalen); 568 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 569 MAXPHYS, BUS_DMASYNC_PREWRITE); 570 } 571 addr = sc->sc_dmamap->dm_segs[0].ds_addr; 572 use_bbuf = true; 573 } 574 send |= __SHIFTIN(cmd->c_opcode | 0x40, SDIO_SEND_COMMAND_INDEX); 575 576 mult |= __SHIFTIN(sc->sc_cur_port, SDIO_MULT_PORT_SEL); 577 578 SDIO_WRITE(sc, SDIO_IRQC_REG, SDIO_IRQC_SOFT_RESET); 579 delay(2); 580 581 SDIO_WRITE(sc, SDIO_IRQC_REG, SDIO_IRQC_ARC_CMD_INTEN); 582 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_CLEAR); 583 584 SDIO_WRITE(sc, SDIO_ARGU_REG, cmd->c_arg); 585 SDIO_WRITE(sc, SDIO_MULT_REG, mult); 586 SDIO_WRITE(sc, SDIO_EXT_REG, ext); 587 SDIO_WRITE(sc, SDIO_ADDR_REG, addr); 588 SDIO_WRITE(sc, SDIO_SEND_REG, send); 589 590 cmd->c_error = meson_sdio_wait_irqs(sc, SDIO_IRQS_CMD_INT, hz * 3); 591 if (cmd->c_error) { 592 goto done; 593 } 594 595 if (SDIO_READ(sc, SDIO_IRQS_REG) & SDIO_IRQS_CMD_BUSY) { 596 int retry; 597 for (retry = 10000; retry > 0; retry--) { 598 const uint32_t irqs = SDIO_READ(sc, SDIO_IRQS_REG); 599 if ((irqs & SDIO_IRQS_CMD_BUSY) == 0) 600 break; 601 delay(100); 602 } 603 if (retry == 0) { 604 aprint_debug_dev(sc->sc_dev, 605 "busy timeout, opcode %d flags %#x datalen %d\n", 606 cmd->c_opcode, cmd->c_flags, cmd->c_datalen); 607 cmd->c_error = ETIMEDOUT; 608 goto done; 609 } 610 } 611 612 const uint32_t irqs = SDIO_READ(sc, SDIO_IRQS_REG); 613 if (cmd->c_flags & SCF_RSP_CRC) { 614 if ((irqs & SDIO_IRQS_RESPONSE_CRC7_OK) == 0) { 615 device_printf(sc->sc_dev, "response crc error\n"); 616 cmd->c_error = EIO; 617 goto done; 618 } 619 } 620 if (cmd->c_datalen > 0) { 621 uint32_t crcmask = SDIO_IRQS_DATA_READ_CRC16_OK| 622 SDIO_IRQS_DATA_WRITE_CRC16_OK; 623 if ((irqs & crcmask) == 0) { 624 device_printf(sc->sc_dev, "data crc error\n"); 625 cmd->c_error = EIO; 626 goto done; 627 } 628 } 629 630 if (cmd->c_flags & SCF_RSP_PRESENT) { 631 mult |= SDIO_MULT_WRITE_READ_OUT_INDEX; 632 mult &= ~SDIO_MULT_RESPONSE_READ_INDEX; 633 SDIO_WRITE(sc, SDIO_MULT_REG, mult); 634 635 if (cmd->c_flags & SCF_RSP_136) { 636 for (i = 0; i < 4; i++) { 637 cmd->c_resp[i] = SDIO_READ(sc, SDIO_ARGU_REG); 638 } 639 } else { 640 cmd->c_resp[0] = SDIO_READ(sc, SDIO_ARGU_REG); 641 } 642 } 643 644done: 645 if (use_bbuf) { 646 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 647 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 648 MAXPHYS, BUS_DMASYNC_POSTREAD); 649 } else { 650 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 651 MAXPHYS, BUS_DMASYNC_POSTWRITE); 652 } 653 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap); 654 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 655 memcpy(cmd->c_data, sc->sc_bbuf, cmd->c_datalen); 656 } 657 } 658 cmd->c_flags |= SCF_ITSDONE; 659 660 SDIO_WRITE(sc, SDIO_IRQC_REG, 0); 661 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_CLEAR); 662 663 mutex_exit(&sc->sc_intr_lock); 664} 665 666static void 667meson_sdio_card_enable_intr(sdmmc_chipset_handle_t sch, int enable) 668{ 669 struct meson_sdio_softc *sc = sch; 670 uint32_t irqc; 671 672 mutex_enter(&sc->sc_intr_lock); 673 irqc = SDIO_READ(sc, SDIO_IRQC_REG); 674 if (enable) { 675 irqc |= SDIO_IRQC_ARC_IF_INTEN; 676 } else { 677 irqc &= ~SDIO_IRQC_ARC_IF_INTEN; 678 } 679 SDIO_WRITE(sc, SDIO_IRQC_REG, irqc); 680 mutex_exit(&sc->sc_intr_lock); 681} 682 683static void 684meson_sdio_card_intr_ack(sdmmc_chipset_handle_t sch) 685{ 686 struct meson_sdio_softc *sc = sch; 687 688 mutex_enter(&sc->sc_intr_lock); 689 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_IF_INT); 690 mutex_exit(&sc->sc_intr_lock); 691} 692