1 /* $NetBSD: meson_sdio.c,v 1.1 2019/01/19 20:56:03 jmcneill 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.1 2019/01/19 20:56:03 jmcneill 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 48 static int meson_sdio_match(device_t, cfdata_t, void *); 49 static void meson_sdio_attach(device_t, device_t, void *); 50 static void meson_sdio_attach_i(device_t); 51 52 static int meson_sdio_intr(void *); 53 54 struct 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 89 CFATTACH_DECL_NEW(meson_sdio, sizeof(struct meson_sdio_softc), 90 meson_sdio_match, meson_sdio_attach, NULL, NULL); 91 92 static int meson_sdio_host_reset(sdmmc_chipset_handle_t); 93 static uint32_t meson_sdio_host_ocr(sdmmc_chipset_handle_t); 94 static int meson_sdio_host_maxblklen(sdmmc_chipset_handle_t); 95 static int meson_sdio_card_detect(sdmmc_chipset_handle_t); 96 static int meson_sdio_write_protect(sdmmc_chipset_handle_t); 97 static int meson_sdio_bus_power(sdmmc_chipset_handle_t, uint32_t); 98 static int meson_sdio_bus_clock(sdmmc_chipset_handle_t, int); 99 static int meson_sdio_bus_width(sdmmc_chipset_handle_t, int); 100 static int meson_sdio_bus_rod(sdmmc_chipset_handle_t, int); 101 static int meson_sdio_signal_voltage(sdmmc_chipset_handle_t, int); 102 static void meson_sdio_exec_command(sdmmc_chipset_handle_t, 103 struct sdmmc_command *); 104 static void meson_sdio_card_enable_intr(sdmmc_chipset_handle_t, int); 105 static void meson_sdio_card_intr_ack(sdmmc_chipset_handle_t); 106 107 static int meson_sdio_set_clock(struct meson_sdio_softc *, u_int); 108 static int meson_sdio_wait_irqs(struct meson_sdio_softc *, uint32_t, int); 109 110 static void meson_sdio_dmainit(struct meson_sdio_softc *); 111 112 static 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 133 static const char * const compatible[] = { 134 "amlogic,meson8b-sdio", 135 NULL 136 }; 137 138 static const char * const slot_compatible[] = { 139 "mmc-slot", 140 NULL 141 }; 142 143 static int 144 meson_sdio_match(device_t parent, cfdata_t cf, void *aux) 145 { 146 struct fdt_attach_args * const faa = aux; 147 148 return of_match_compatible(faa->faa_phandle, compatible); 149 } 150 151 static void 152 meson_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_match_compatible(child, slot_compatible) > 0) { 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(phandle, 0, IPL_BIO, 0, meson_sdio_intr, sc); 228 if (sc->sc_ih == NULL) { 229 aprint_error_dev(self, "couldn't establish interrupt on %s\n", 230 intrstr); 231 return; 232 } 233 aprint_normal_dev(self, "interrupting on %s\n", intrstr); 234 235 sc->sc_bus_freq = clk_get_rate(clk_clkin); 236 237 aprint_normal_dev(self, "core %u Hz, clkin %u Hz\n", clk_get_rate(clk_core), clk_get_rate(clk_clkin)); 238 239 meson_sdio_dmainit(sc); 240 241 config_interrupts(self, meson_sdio_attach_i); 242 } 243 244 static void 245 meson_sdio_attach_i(device_t self) 246 { 247 struct meson_sdio_softc *sc = device_private(self); 248 struct sdmmcbus_attach_args saa; 249 250 meson_sdio_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_330); 251 meson_sdio_host_reset(sc); 252 meson_sdio_bus_clock(sc, 400); 253 meson_sdio_bus_width(sc, 1); 254 255 memset(&saa, 0, sizeof(saa)); 256 saa.saa_busname = "sdmmc"; 257 saa.saa_sct = &meson_sdio_chip_functions; 258 saa.saa_dmat = sc->sc_dmat; 259 saa.saa_sch = sc; 260 saa.saa_clkmin = 400; 261 saa.saa_clkmax = sc->sc_bus_freq; 262 /* Do not advertise DMA capabilities, we handle DMA ourselves */ 263 saa.saa_caps = SMC_CAPS_4BIT_MODE| 264 SMC_CAPS_SD_HIGHSPEED| 265 SMC_CAPS_MMC_HIGHSPEED; 266 267 sc->sc_sdmmc_dev = config_found(self, &saa, NULL); 268 } 269 270 static int 271 meson_sdio_intr(void *priv) 272 { 273 struct meson_sdio_softc *sc = priv; 274 275 mutex_enter(&sc->sc_intr_lock); 276 const u_int irqs = SDIO_READ(sc, SDIO_IRQS_REG); 277 if (irqs & SDIO_IRQS_CLEAR) { 278 SDIO_WRITE(sc, SDIO_IRQS_REG, irqs); 279 sc->sc_intr_irqs |= irqs; 280 cv_broadcast(&sc->sc_intr_cv); 281 } 282 mutex_exit(&sc->sc_intr_lock); 283 284 return 1; 285 } 286 287 static void 288 meson_sdio_dmainit(struct meson_sdio_softc *sc) 289 { 290 int error, rseg; 291 292 error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS, PAGE_SIZE, MAXPHYS, 293 sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK); 294 if (error) { 295 device_printf(sc->sc_dev, "bus_dmamem_alloc failed\n"); 296 return; 297 } 298 KASSERT(rseg == 1); 299 300 error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, MAXPHYS, 301 &sc->sc_bbuf, BUS_DMA_WAITOK); 302 if (error) { 303 device_printf(sc->sc_dev, "bus_dmamem_map failed\n"); 304 return; 305 } 306 307 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 308 BUS_DMA_WAITOK, &sc->sc_dmamap); 309 if (error) { 310 device_printf(sc->sc_dev, "bus_dmamap_create failed\n"); 311 return; 312 } 313 } 314 315 static int 316 meson_sdio_set_clock(struct meson_sdio_softc *sc, u_int freq) 317 { 318 const u_int pll_freq = sc->sc_bus_freq / 2000; 319 uint32_t conf; 320 int clk_div; 321 322 if (freq == 0) 323 return 0; 324 325 clk_div = howmany(pll_freq, freq); 326 327 conf = SDIO_READ(sc, SDIO_CONF_REG); 328 conf &= ~SDIO_CONF_COMMAND_CLK_DIV; 329 conf |= __SHIFTIN(clk_div - 1, SDIO_CONF_COMMAND_CLK_DIV); 330 SDIO_WRITE(sc, SDIO_CONF_REG, conf); 331 332 return 0; 333 } 334 335 static int 336 meson_sdio_wait_irqs(struct meson_sdio_softc *sc, uint32_t mask, int timeout) 337 { 338 int retry, error; 339 340 KASSERT(mutex_owned(&sc->sc_intr_lock)); 341 342 if (sc->sc_intr_irqs & mask) 343 return 0; 344 345 retry = timeout / hz; 346 347 while (retry > 0) { 348 error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz); 349 if (error && error != EWOULDBLOCK) 350 return error; 351 if (sc->sc_intr_irqs & mask) 352 return 0; 353 --retry; 354 } 355 356 return ETIMEDOUT; 357 } 358 359 static int 360 meson_sdio_host_reset(sdmmc_chipset_handle_t sch) 361 { 362 struct meson_sdio_softc *sc = sch; 363 364 SDIO_WRITE(sc, SDIO_IRQC_REG, SDIO_IRQC_SOFT_RESET); 365 366 delay(2); 367 368 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_CLEAR); 369 SDIO_WRITE(sc, SDIO_CONF_REG, 370 __SHIFTIN(2, SDIO_CONF_WRITE_CRC_OK_STATUS) | 371 __SHIFTIN(2, SDIO_CONF_WRITE_NWR) | 372 __SHIFTIN(3, SDIO_CONF_M_ENDIAN) | 373 __SHIFTIN(39, SDIO_CONF_COMMAND_ARG_BITS) | 374 __SHIFTIN(0x1f4, SDIO_CONF_COMMAND_CLK_DIV)); 375 376 SDIO_WRITE(sc, SDIO_MULT_REG, 377 __SHIFTIN(sc->sc_cur_port, SDIO_MULT_PORT_SEL)); 378 379 return 0; 380 } 381 382 static uint32_t 383 meson_sdio_host_ocr(sdmmc_chipset_handle_t sch) 384 { 385 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V; 386 } 387 388 static int 389 meson_sdio_host_maxblklen(sdmmc_chipset_handle_t sch) 390 { 391 return 512; 392 } 393 394 static int 395 meson_sdio_card_detect(sdmmc_chipset_handle_t sch) 396 { 397 struct meson_sdio_softc *sc = sch; 398 int val; 399 400 if (sc->sc_non_removable || sc->sc_broken_cd) { 401 return 1; 402 } else if (sc->sc_gpio_cd != NULL) { 403 val = fdtbus_gpio_read(sc->sc_gpio_cd); 404 if (sc->sc_gpio_cd_inverted) 405 val = !val; 406 return val; 407 } else { 408 return 1; 409 } 410 } 411 412 static int 413 meson_sdio_write_protect(sdmmc_chipset_handle_t sch) 414 { 415 struct meson_sdio_softc *sc = sch; 416 int val; 417 418 if (sc->sc_gpio_wp != NULL) { 419 val = fdtbus_gpio_read(sc->sc_gpio_wp); 420 if (sc->sc_gpio_wp_inverted) 421 val = !val; 422 return val; 423 } 424 425 return 0; 426 } 427 428 static int 429 meson_sdio_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 430 { 431 return 0; 432 } 433 434 static int 435 meson_sdio_bus_clock(sdmmc_chipset_handle_t sch, int freq) 436 { 437 struct meson_sdio_softc *sc = sch; 438 439 return meson_sdio_set_clock(sc, freq); 440 } 441 442 static int 443 meson_sdio_bus_width(sdmmc_chipset_handle_t sch, int width) 444 { 445 struct meson_sdio_softc *sc = sch; 446 uint32_t conf; 447 448 conf = SDIO_READ(sc, SDIO_CONF_REG); 449 if (width == 1) { 450 conf &= ~SDIO_CONF_BUS_WIDTH; 451 } else if (width == 4) { 452 conf |= SDIO_CONF_BUS_WIDTH; 453 } else { 454 return EINVAL; 455 } 456 SDIO_WRITE(sc, SDIO_CONF_REG, conf); 457 458 sc->sc_cur_width = width; 459 460 return 0; 461 } 462 463 static int 464 meson_sdio_bus_rod(sdmmc_chipset_handle_t sch, int on) 465 { 466 return ENOTSUP; 467 } 468 469 static int 470 meson_sdio_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage) 471 { 472 struct meson_sdio_softc *sc = sch; 473 u_int uvol; 474 int error; 475 476 if (sc->sc_reg_vqmmc == NULL) 477 return 0; 478 479 switch (signal_voltage) { 480 case SDMMC_SIGNAL_VOLTAGE_330: 481 uvol = 3300000; 482 break; 483 case SDMMC_SIGNAL_VOLTAGE_180: 484 uvol = 1800000; 485 break; 486 default: 487 return EINVAL; 488 } 489 490 error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol); 491 if (error != 0) 492 return 0; 493 494 error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol); 495 if (error != 0) 496 return error; 497 498 return fdtbus_regulator_enable(sc->sc_reg_vqmmc); 499 } 500 501 static void 502 meson_sdio_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 503 { 504 struct meson_sdio_softc *sc = sch; 505 uint32_t send, ext, mult, addr; 506 bool use_bbuf = false; 507 int i; 508 509 KASSERT(cmd->c_blklen <= 512); 510 511 send = ext = mult = addr = 0; 512 513 mutex_enter(&sc->sc_intr_lock); 514 515 if (cmd->c_opcode == SD_IO_SEND_OP_COND || 516 cmd->c_opcode == SD_IO_RW_DIRECT || 517 cmd->c_opcode == SD_IO_RW_EXTENDED) { 518 cmd->c_error = EINVAL; 519 goto done; 520 } 521 522 sc->sc_intr_irqs = 0; 523 524 if (cmd->c_flags & SCF_RSP_PRESENT) { 525 if (cmd->c_flags & SCF_RSP_136) { 526 send |= __SHIFTIN(133, SDIO_SEND_RESPONSE_BITS); 527 send |= SDIO_SEND_RESPONSE_CRC7_FROM_8; 528 } else { 529 send |= __SHIFTIN(45, SDIO_SEND_RESPONSE_BITS); 530 } 531 } 532 if ((cmd->c_flags & SCF_RSP_CRC) == 0) { 533 send |= SDIO_SEND_RESPONSE_NO_CRC; 534 } 535 if (cmd->c_flags & SCF_RSP_BSY) { 536 send |= SDIO_SEND_CHECK_BUSY_DAT0; 537 } 538 539 if (cmd->c_datalen > 0) { 540 unsigned int nblks, packlen; 541 542 nblks = cmd->c_datalen / cmd->c_blklen; 543 if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0) 544 ++nblks; 545 packlen = (cmd->c_blklen * 8) + (0xf * sc->sc_cur_width); 546 547 send |= __SHIFTIN(nblks - 1, SDIO_SEND_REPEAT_PACKAGE); 548 ext |= __SHIFTIN(packlen, SDIO_EXT_DATA_RW_NUMBER); 549 550 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 551 send |= SDIO_SEND_RESPONSE_DATA; 552 } else { 553 send |= SDIO_SEND_COMMAND_HAS_DATA; 554 } 555 556 cmd->c_error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, 557 sc->sc_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK); 558 if (cmd->c_error) { 559 device_printf(sc->sc_dev, "bus_dmamap_load failed\n"); 560 goto done; 561 } 562 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 563 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 564 MAXPHYS, BUS_DMASYNC_PREREAD); 565 } else { 566 memcpy(sc->sc_bbuf, cmd->c_data, cmd->c_datalen); 567 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 568 MAXPHYS, BUS_DMASYNC_PREWRITE); 569 } 570 addr = sc->sc_dmamap->dm_segs[0].ds_addr; 571 use_bbuf = true; 572 } 573 send |= __SHIFTIN(cmd->c_opcode | 0x40, SDIO_SEND_COMMAND_INDEX); 574 575 mult |= __SHIFTIN(sc->sc_cur_port, SDIO_MULT_PORT_SEL); 576 577 SDIO_WRITE(sc, SDIO_IRQC_REG, SDIO_IRQC_SOFT_RESET); 578 delay(2); 579 580 SDIO_WRITE(sc, SDIO_IRQC_REG, SDIO_IRQC_ARC_CMD_INTEN); 581 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_CLEAR); 582 583 SDIO_WRITE(sc, SDIO_ARGU_REG, cmd->c_arg); 584 SDIO_WRITE(sc, SDIO_MULT_REG, mult); 585 SDIO_WRITE(sc, SDIO_EXT_REG, ext); 586 SDIO_WRITE(sc, SDIO_ADDR_REG, addr); 587 SDIO_WRITE(sc, SDIO_SEND_REG, send); 588 589 cmd->c_error = meson_sdio_wait_irqs(sc, SDIO_IRQS_CMD_INT, hz * 3); 590 if (cmd->c_error) { 591 goto done; 592 } 593 594 if (SDIO_READ(sc, SDIO_IRQS_REG) & SDIO_IRQS_CMD_BUSY) { 595 int retry; 596 for (retry = 10000; retry > 0; retry--) { 597 const uint32_t irqs = SDIO_READ(sc, SDIO_IRQS_REG); 598 if ((irqs & SDIO_IRQS_CMD_BUSY) == 0) 599 break; 600 delay(100); 601 } 602 if (retry == 0) { 603 aprint_debug_dev(sc->sc_dev, 604 "busy timeout, opcode %d flags %#x datalen %d\n", 605 cmd->c_opcode, cmd->c_flags, cmd->c_datalen); 606 cmd->c_error = ETIMEDOUT; 607 goto done; 608 } 609 } 610 611 const uint32_t irqs = SDIO_READ(sc, SDIO_IRQS_REG); 612 if (cmd->c_flags & SCF_RSP_CRC) { 613 if ((irqs & SDIO_IRQS_RESPONSE_CRC7_OK) == 0) { 614 device_printf(sc->sc_dev, "response crc error\n"); 615 cmd->c_error = EIO; 616 goto done; 617 } 618 } 619 if (cmd->c_datalen > 0) { 620 uint32_t crcmask = SDIO_IRQS_DATA_READ_CRC16_OK| 621 SDIO_IRQS_DATA_WRITE_CRC16_OK; 622 if ((irqs & crcmask) == 0) { 623 device_printf(sc->sc_dev, "data crc error\n"); 624 cmd->c_error = EIO; 625 goto done; 626 } 627 } 628 629 if (cmd->c_flags & SCF_RSP_PRESENT) { 630 mult |= SDIO_MULT_WRITE_READ_OUT_INDEX; 631 mult &= ~SDIO_MULT_RESPONSE_READ_INDEX; 632 SDIO_WRITE(sc, SDIO_MULT_REG, mult); 633 634 if (cmd->c_flags & SCF_RSP_136) { 635 for (i = 0; i < 4; i++) { 636 cmd->c_resp[i] = SDIO_READ(sc, SDIO_ARGU_REG); 637 } 638 } else { 639 cmd->c_resp[0] = SDIO_READ(sc, SDIO_ARGU_REG); 640 } 641 } 642 643 done: 644 if (use_bbuf) { 645 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 646 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 647 MAXPHYS, BUS_DMASYNC_POSTREAD); 648 } else { 649 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 650 MAXPHYS, BUS_DMASYNC_POSTWRITE); 651 } 652 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap); 653 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 654 memcpy(cmd->c_data, sc->sc_bbuf, cmd->c_datalen); 655 } 656 } 657 cmd->c_flags |= SCF_ITSDONE; 658 659 SDIO_WRITE(sc, SDIO_IRQC_REG, 0); 660 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_CLEAR); 661 662 mutex_exit(&sc->sc_intr_lock); 663 } 664 665 static void 666 meson_sdio_card_enable_intr(sdmmc_chipset_handle_t sch, int enable) 667 { 668 struct meson_sdio_softc *sc = sch; 669 uint32_t irqc; 670 671 mutex_enter(&sc->sc_intr_lock); 672 irqc = SDIO_READ(sc, SDIO_IRQC_REG); 673 if (enable) { 674 irqc |= SDIO_IRQC_ARC_IF_INTEN; 675 } else { 676 irqc &= ~SDIO_IRQC_ARC_IF_INTEN; 677 } 678 SDIO_WRITE(sc, SDIO_IRQC_REG, irqc); 679 mutex_exit(&sc->sc_intr_lock); 680 } 681 682 static void 683 meson_sdio_card_intr_ack(sdmmc_chipset_handle_t sch) 684 { 685 struct meson_sdio_softc *sc = sch; 686 687 mutex_enter(&sc->sc_intr_lock); 688 SDIO_WRITE(sc, SDIO_IRQS_REG, SDIO_IRQS_IF_INT); 689 mutex_exit(&sc->sc_intr_lock); 690 } 691