1 /* $NetBSD: ti_sdhc.c,v 1.12 2022/02/06 15:52:20 jmcneill Exp $ */ 2 /*- 3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Matt Thomas of 3am Software Foundry. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: ti_sdhc.c,v 1.12 2022/02/06 15:52:20 jmcneill Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 #include <sys/errno.h> 38 #include <sys/kernel.h> 39 #include <sys/proc.h> 40 #include <sys/queue.h> 41 #include <sys/mutex.h> 42 #include <sys/condvar.h> 43 #include <sys/bus.h> 44 45 #include <arm/ti/ti_prcm.h> 46 #include <arm/ti/ti_edma.h> 47 #include <arm/ti/ti_sdhcreg.h> 48 49 #include <dev/sdmmc/sdhcreg.h> 50 #include <dev/sdmmc/sdhcvar.h> 51 #include <dev/sdmmc/sdmmcvar.h> 52 53 #include <dev/fdt/fdtvar.h> 54 55 #define EDMA_MAX_PARAMS 32 56 57 #ifdef TISDHC_DEBUG 58 int tisdhcdebug = 1; 59 #define DPRINTF(n,s) do { if ((n) <= tisdhcdebug) device_printf s; } while (0) 60 #else 61 #define DPRINTF(n,s) do {} while (0) 62 #endif 63 64 65 #define CLKD(kz) (sc->sc.sc_clkbase / (kz)) 66 67 #define SDHC_READ(sc, reg) \ 68 bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg)) 69 #define SDHC_WRITE(sc, reg, val) \ 70 bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val)) 71 72 struct ti_sdhc_config { 73 bus_size_t regoff; 74 uint32_t flags; 75 }; 76 77 static const struct ti_sdhc_config omap2_hsmmc_config = { 78 }; 79 80 static const struct ti_sdhc_config omap3_pre_es3_hsmmc_config = { 81 .flags = SDHC_FLAG_SINGLE_ONLY 82 }; 83 84 static const struct ti_sdhc_config omap4_hsmmc_config = { 85 .regoff = 0x100 86 }; 87 88 static const struct ti_sdhc_config am335_sdhci_config = { 89 .regoff = 0x100 90 }; 91 92 static const struct device_compatible_entry compat_data[] = { 93 { .compat = "ti,omap2-hsmmc", 94 .data = &omap2_hsmmc_config }, 95 { .compat = "ti,omap3-hsmmc", 96 .data = &omap2_hsmmc_config }, 97 { .compat = "ti,omap3-pre-es3-hsmmc", 98 .data = &omap3_pre_es3_hsmmc_config }, 99 { .compat = "ti,omap4-hsmmc", 100 .data = &omap4_hsmmc_config }, 101 { .compat = "ti,am335-sdhci", 102 .data = &am335_sdhci_config }, 103 104 DEVICE_COMPAT_EOL 105 }; 106 107 enum { 108 EDMA_CHAN_TX, 109 EDMA_CHAN_RX, 110 EDMA_NCHAN 111 }; 112 113 struct ti_sdhc_softc { 114 struct sdhc_softc sc; 115 int sc_phandle; 116 bus_addr_t sc_addr; 117 bus_space_tag_t sc_bst; 118 bus_space_handle_t sc_bsh; 119 bus_space_handle_t sc_hl_bsh; 120 bus_space_handle_t sc_sdhc_bsh; 121 struct sdhc_host *sc_hosts[1]; 122 void *sc_ih; /* interrupt vectoring */ 123 124 int sc_edma_chan[EDMA_NCHAN]; 125 struct edma_channel *sc_edma_tx; 126 struct edma_channel *sc_edma_rx; 127 uint16_t sc_edma_param_tx[EDMA_MAX_PARAMS]; 128 uint16_t sc_edma_param_rx[EDMA_MAX_PARAMS]; 129 kcondvar_t sc_edma_cv; 130 bus_addr_t sc_edma_fifo; 131 bool sc_edma_pending; 132 bus_dmamap_t sc_edma_dmamap; 133 bus_dma_segment_t sc_edma_segs[1]; 134 void *sc_edma_bbuf; 135 }; 136 137 static int ti_sdhc_match(device_t, cfdata_t, void *); 138 static void ti_sdhc_attach(device_t, device_t, void *); 139 140 static void ti_sdhc_init(struct ti_sdhc_softc *, const struct ti_sdhc_config *); 141 142 static int ti_sdhc_bus_width(struct sdhc_softc *, int); 143 static int ti_sdhc_rod(struct sdhc_softc *, int); 144 static int ti_sdhc_write_protect(struct sdhc_softc *); 145 static int ti_sdhc_card_detect(struct sdhc_softc *); 146 147 static int ti_sdhc_edma_init(struct ti_sdhc_softc *, u_int, u_int); 148 static int ti_sdhc_edma_xfer_data(struct sdhc_softc *, struct sdmmc_command *); 149 static void ti_sdhc_edma_done(void *); 150 static int ti_sdhc_edma_transfer(struct sdhc_softc *, struct sdmmc_command *); 151 152 CFATTACH_DECL_NEW(ti_sdhc, sizeof(struct ti_sdhc_softc), 153 ti_sdhc_match, ti_sdhc_attach, NULL, NULL); 154 155 static int 156 ti_sdhc_match(device_t parent, cfdata_t cf, void *aux) 157 { 158 struct fdt_attach_args * const faa = aux; 159 160 return of_compatible_match(faa->faa_phandle, compat_data); 161 } 162 163 static void 164 ti_sdhc_attach(device_t parent, device_t self, void *aux) 165 { 166 struct ti_sdhc_softc * const sc = device_private(self); 167 struct fdt_attach_args * const faa = aux; 168 const int phandle = faa->faa_phandle; 169 const struct ti_sdhc_config *conf; 170 bus_addr_t addr; 171 bus_size_t size; 172 u_int bus_width; 173 174 conf = of_compatible_lookup(phandle, compat_data)->data; 175 176 if (ti_prcm_enable_hwmod(phandle, 0) != 0) { 177 aprint_error(": couldn't enable module\n"); 178 return; 179 } 180 181 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0 || size <= conf->regoff) { 182 aprint_error(": couldn't get registers\n"); 183 return; 184 } 185 addr += conf->regoff; 186 size -= conf->regoff; 187 188 sc->sc.sc_dmat = faa->faa_dmat; 189 sc->sc.sc_dev = self; 190 sc->sc_phandle = phandle; 191 sc->sc_addr = addr; 192 sc->sc_bst = faa->faa_bst; 193 194 /* XXX use fdtbus_dma API */ 195 int len; 196 const u_int *dmas = fdtbus_get_prop(phandle, "dmas", &len); 197 switch (len) { 198 case 24: 199 sc->sc_edma_chan[EDMA_CHAN_TX] = be32toh(dmas[1]); 200 sc->sc_edma_chan[EDMA_CHAN_RX] = be32toh(dmas[4]); 201 break; 202 case 32: 203 sc->sc_edma_chan[EDMA_CHAN_TX] = be32toh(dmas[1]); 204 sc->sc_edma_chan[EDMA_CHAN_RX] = be32toh(dmas[5]); 205 break; 206 default: 207 sc->sc_edma_chan[EDMA_CHAN_TX] = -1; 208 sc->sc_edma_chan[EDMA_CHAN_RX] = -1; 209 break; 210 } 211 212 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 213 aprint_error(": couldn't map registers\n"); 214 return; 215 } 216 217 if (of_getprop_uint32(phandle, "bus-width", &bus_width) != 0) 218 bus_width = 4; 219 220 sc->sc.sc_flags |= conf->flags; 221 sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS; 222 sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON; 223 sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC; 224 if (bus_width == 8) 225 sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE; 226 if (of_hasprop(phandle, "ti,needs-special-reset")) 227 sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET; 228 if (!of_hasprop(phandle, "ti,needs-special-hs-handling")) 229 sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT; 230 if (of_hasprop(phandle, "ti,dual-volt")) 231 sc->sc.sc_caps = SDHC_VOLTAGE_SUPP_3_0V; 232 233 sc->sc.sc_host = sc->sc_hosts; 234 sc->sc.sc_clkbase = 96000; /* 96MHZ */ 235 sc->sc.sc_clkmsk = 0x0000ffc0; 236 sc->sc.sc_vendor_rod = ti_sdhc_rod; 237 sc->sc.sc_vendor_write_protect = ti_sdhc_write_protect; 238 sc->sc.sc_vendor_card_detect = ti_sdhc_card_detect; 239 sc->sc.sc_vendor_bus_width = ti_sdhc_bus_width; 240 241 if (bus_space_subregion(sc->sc_bst, sc->sc_bsh, 0x100, 0x100, 242 &sc->sc_sdhc_bsh) != 0) { 243 aprint_error(": couldn't map subregion\n"); 244 return; 245 } 246 247 aprint_naive("\n"); 248 aprint_normal(": MMCHS\n"); 249 250 ti_sdhc_init(sc, conf); 251 } 252 253 static void 254 ti_sdhc_init(struct ti_sdhc_softc *sc, const struct ti_sdhc_config *conf) 255 { 256 device_t dev = sc->sc.sc_dev; 257 uint32_t clkd, stat; 258 int error, timo, clksft, n; 259 char intrstr[128]; 260 261 const int tx_chan = sc->sc_edma_chan[EDMA_CHAN_TX]; 262 const int rx_chan = sc->sc_edma_chan[EDMA_CHAN_RX]; 263 264 if (tx_chan != -1 && rx_chan != -1) { 265 aprint_normal_dev(dev, 266 "EDMA tx channel %d, rx channel %d\n", 267 tx_chan, rx_chan); 268 269 if (ti_sdhc_edma_init(sc, tx_chan, rx_chan) != 0) { 270 aprint_error_dev(dev, "EDMA disabled\n"); 271 goto no_dma; 272 } 273 274 cv_init(&sc->sc_edma_cv, "sdhcedma"); 275 sc->sc_edma_fifo = sc->sc_addr + 0x100 + SDHC_DATA; 276 sc->sc.sc_flags |= SDHC_FLAG_USE_DMA; 277 sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA; 278 sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN; 279 sc->sc.sc_vendor_transfer_data_dma = ti_sdhc_edma_xfer_data; 280 } 281 no_dma: 282 283 /* XXXXXX: Turn-on regulator via I2C. */ 284 /* XXXXXX: And enable ICLOCK/FCLOCK. */ 285 286 SDHC_WRITE(sc, SDHC_CAPABILITIES, 287 SDHC_READ(sc, SDHC_CAPABILITIES) | SDHC_VOLTAGE_SUPP_1_8V); 288 if (sc->sc.sc_caps & SDHC_VOLTAGE_SUPP_3_0V) 289 SDHC_WRITE(sc, SDHC_CAPABILITIES, 290 SDHC_READ(sc, SDHC_CAPABILITIES) | SDHC_VOLTAGE_SUPP_3_0V); 291 292 /* MMCHS Soft reset */ 293 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG, 294 SYSCONFIG_SOFTRESET); 295 timo = 3000000; /* XXXX 3 sec. */ 296 while (timo--) { 297 if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) & 298 SYSSTATUS_RESETDONE) 299 break; 300 delay(1); 301 } 302 if (timo == 0) 303 aprint_error_dev(dev, "Soft reset timeout\n"); 304 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG, 305 SYSCONFIG_ENAWAKEUP | 306 #if notyet 307 SYSCONFIG_AUTOIDLE | 308 SYSCONFIG_SIDLEMODE_AUTO | 309 #else 310 SYSCONFIG_SIDLEMODE_IGNORE | 311 #endif 312 SYSCONFIG_CLOCKACTIVITY_FCLK | 313 SYSCONFIG_CLOCKACTIVITY_ICLK); 314 315 if (!fdtbus_intr_str(sc->sc_phandle, 0, intrstr, sizeof(intrstr))) { 316 aprint_error_dev(dev, "couldn't decode interrupt\n"); 317 return; 318 } 319 sc->sc_ih = fdtbus_intr_establish_xname(sc->sc_phandle, 0, IPL_VM, 320 0, sdhc_intr, &sc->sc, device_xname(dev)); 321 if (sc->sc_ih == NULL) { 322 aprint_error_dev(dev, "couldn't establish interrupt\n"); 323 return; 324 } 325 aprint_normal_dev(dev, "interrupting on %s\n", intrstr); 326 327 error = sdhc_host_found(&sc->sc, sc->sc_bst, sc->sc_sdhc_bsh, 0x100); 328 if (error != 0) { 329 aprint_error_dev(dev, "couldn't initialize host, error=%d\n", 330 error); 331 fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih); 332 return; 333 } 334 335 clksft = ffs(sc->sc.sc_clkmsk) - 1; 336 337 /* Set SDVS 1.8v and DTW 1bit mode */ 338 SDHC_WRITE(sc, SDHC_HOST_CTL, 339 SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8)); 340 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 341 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE | 342 SDHC_SDCLK_ENABLE); 343 SDHC_WRITE(sc, SDHC_HOST_CTL, 344 SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8); 345 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 346 SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft); 347 348 /* 349 * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start 350 * from 'OMAP35x Applications Processor Technical Reference Manual'. 351 * 352 * During the INIT procedure, the MMCHS controller generates 80 clock 353 * periods. In order to keep the 1ms gap, the MMCHS controller should 354 * be configured to generate a clock whose frequency is smaller or 355 * equal to 80 KHz. 356 */ 357 358 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 359 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE); 360 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 361 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk); 362 clkd = CLKD(80); 363 n = 1; 364 while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) { 365 clkd >>= 1; 366 n <<= 1; 367 } 368 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 369 SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft)); 370 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 371 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE); 372 373 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 374 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT); 375 SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000); 376 delay(1000); 377 stat = SDHC_READ(sc, SDHC_NINTR_STATUS); 378 SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat | SDHC_COMMAND_COMPLETE); 379 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 380 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT); 381 SDHC_WRITE(sc, SDHC_NINTR_STATUS, 0xffffffff); 382 383 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 384 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE); 385 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 386 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk); 387 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 388 SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft); 389 timo = 3000000; /* XXXX 3 sec. */ 390 while (--timo) { 391 if (SDHC_READ(sc, SDHC_CLOCK_CTL) & SDHC_INTCLK_STABLE) 392 break; 393 delay(1); 394 } 395 if (timo == 0) 396 aprint_error_dev(dev, "ICS timeout\n"); 397 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 398 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE); 399 400 #if notyet 401 if (sc->sc_use_adma2) { 402 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 403 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | 404 CON_MNS); 405 } 406 #endif 407 } 408 409 static int 410 ti_sdhc_rod(struct sdhc_softc *sc, int on) 411 { 412 struct ti_sdhc_softc *hmsc = (struct ti_sdhc_softc *)sc; 413 uint32_t con; 414 415 con = bus_space_read_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON); 416 if (on) 417 con |= CON_OD; 418 else 419 con &= ~CON_OD; 420 bus_space_write_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON, con); 421 422 return 0; 423 } 424 425 static int 426 ti_sdhc_write_protect(struct sdhc_softc *sc) 427 { 428 429 /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */ 430 return 0; /* XXXXXXX */ 431 } 432 433 static int 434 ti_sdhc_card_detect(struct sdhc_softc *sc) 435 { 436 437 /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */ 438 return 1; /* XXXXXXXX */ 439 } 440 441 static int 442 ti_sdhc_bus_width(struct sdhc_softc *sc, int width) 443 { 444 struct ti_sdhc_softc *hmsc = (struct ti_sdhc_softc *)sc; 445 uint32_t con, hctl; 446 447 con = bus_space_read_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON); 448 hctl = SDHC_READ(hmsc, SDHC_HOST_CTL); 449 if (width == 8) { 450 con |= CON_DW8; 451 } else if (width == 4) { 452 con &= ~CON_DW8; 453 hctl |= SDHC_4BIT_MODE; 454 } else { 455 con &= ~CON_DW8; 456 hctl &= ~SDHC_4BIT_MODE; 457 } 458 bus_space_write_4(hmsc->sc_bst, hmsc->sc_bsh, MMCHS_CON, con); 459 SDHC_WRITE(hmsc, SDHC_HOST_CTL, hctl); 460 461 return 0; 462 } 463 464 static int 465 ti_sdhc_edma_init(struct ti_sdhc_softc *sc, u_int tx_chan, u_int rx_chan) 466 { 467 int i, error, rseg; 468 469 /* Request tx and rx DMA channels */ 470 sc->sc_edma_tx = edma_channel_alloc(EDMA_TYPE_DMA, tx_chan, 471 ti_sdhc_edma_done, sc); 472 KASSERT(sc->sc_edma_tx != NULL); 473 sc->sc_edma_rx = edma_channel_alloc(EDMA_TYPE_DMA, rx_chan, 474 ti_sdhc_edma_done, sc); 475 KASSERT(sc->sc_edma_rx != NULL); 476 477 /* Allocate some PaRAM pages */ 478 for (i = 0; i < __arraycount(sc->sc_edma_param_tx); i++) { 479 sc->sc_edma_param_tx[i] = edma_param_alloc(sc->sc_edma_tx); 480 KASSERT(sc->sc_edma_param_tx[i] != 0xffff); 481 } 482 for (i = 0; i < __arraycount(sc->sc_edma_param_rx); i++) { 483 sc->sc_edma_param_rx[i] = edma_param_alloc(sc->sc_edma_rx); 484 KASSERT(sc->sc_edma_param_rx[i] != 0xffff); 485 } 486 487 /* Setup bounce buffer */ 488 error = bus_dmamem_alloc(sc->sc.sc_dmat, MAXPHYS, 32, MAXPHYS, 489 sc->sc_edma_segs, 1, &rseg, BUS_DMA_WAITOK); 490 if (error) { 491 aprint_error_dev(sc->sc.sc_dev, 492 "couldn't allocate dmamem: %d\n", error); 493 return error; 494 } 495 KASSERT(rseg == 1); 496 error = bus_dmamem_map(sc->sc.sc_dmat, sc->sc_edma_segs, rseg, MAXPHYS, 497 &sc->sc_edma_bbuf, BUS_DMA_WAITOK); 498 if (error) { 499 aprint_error_dev(sc->sc.sc_dev, "couldn't map dmamem: %d\n", 500 error); 501 return error; 502 } 503 error = bus_dmamap_create(sc->sc.sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 504 BUS_DMA_WAITOK, &sc->sc_edma_dmamap); 505 if (error) { 506 aprint_error_dev(sc->sc.sc_dev, "couldn't create dmamap: %d\n", 507 error); 508 return error; 509 } 510 error = bus_dmamap_load(sc->sc.sc_dmat, sc->sc_edma_dmamap, 511 sc->sc_edma_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK); 512 if (error) { 513 device_printf(sc->sc.sc_dev, "couldn't load dmamap: %d\n", 514 error); 515 return error; 516 } 517 518 return error; 519 } 520 521 static int 522 ti_sdhc_edma_xfer_data(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd) 523 { 524 struct ti_sdhc_softc *sc = device_private(sdhc_sc->sc_dev); 525 const bus_dmamap_t map = cmd->c_dmamap; 526 bool bounce; 527 int error; 528 529 #if notyet 530 bounce = false; 531 for (int seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { 532 if ((cmd->c_dmamap->dm_segs[seg].ds_addr & 0x1f) != 0 || 533 (cmd->c_dmamap->dm_segs[seg].ds_len & 3) != 0) { 534 bounce = true; 535 break; 536 } 537 } 538 #else 539 bounce = true; 540 #endif 541 542 if (bounce) { 543 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 544 bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 545 MAXPHYS, BUS_DMASYNC_PREREAD); 546 } else { 547 memcpy(sc->sc_edma_bbuf, cmd->c_data, cmd->c_datalen); 548 bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 549 MAXPHYS, BUS_DMASYNC_PREWRITE); 550 } 551 552 cmd->c_dmamap = sc->sc_edma_dmamap; 553 } 554 555 error = ti_sdhc_edma_transfer(sdhc_sc, cmd); 556 557 if (bounce) { 558 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 559 bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 560 MAXPHYS, BUS_DMASYNC_POSTREAD); 561 } else { 562 bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0, 563 MAXPHYS, BUS_DMASYNC_POSTWRITE); 564 } 565 if (ISSET(cmd->c_flags, SCF_CMD_READ) && error == 0) { 566 memcpy(cmd->c_data, sc->sc_edma_bbuf, cmd->c_datalen); 567 } 568 569 cmd->c_dmamap = map; 570 } 571 572 return error; 573 } 574 575 static int 576 ti_sdhc_edma_transfer(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd) 577 { 578 struct ti_sdhc_softc *sc = device_private(sdhc_sc->sc_dev); 579 kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]); 580 struct edma_channel *edma; 581 uint16_t *edma_param; 582 struct edma_param ep; 583 size_t seg; 584 int error, resid = cmd->c_datalen; 585 int blksize = MIN(cmd->c_datalen, cmd->c_blklen); 586 587 KASSERT(mutex_owned(plock)); 588 589 edma = ISSET(cmd->c_flags, SCF_CMD_READ) ? 590 sc->sc_edma_rx : sc->sc_edma_tx; 591 edma_param = ISSET(cmd->c_flags, SCF_CMD_READ) ? 592 sc->sc_edma_param_rx : sc->sc_edma_param_tx; 593 594 DPRINTF(1, (sc->sc.sc_dev, "edma xfer: nsegs=%d ch# %d\n", 595 cmd->c_dmamap->dm_nsegs, edma_channel_index(edma))); 596 597 if (cmd->c_dmamap->dm_nsegs > EDMA_MAX_PARAMS) { 598 return ENOMEM; 599 } 600 601 for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { 602 KASSERT(resid > 0); 603 const int xferlen = uimin(resid, 604 cmd->c_dmamap->dm_segs[seg].ds_len); 605 KASSERT(xferlen == cmd->c_dmamap->dm_segs[seg].ds_len || 606 seg == cmd->c_dmamap->dm_nsegs - 1); 607 resid -= xferlen; 608 KASSERT((xferlen & 0x3) == 0); 609 ep.ep_opt = __SHIFTIN(2, EDMA_PARAM_OPT_FWID) /* 32-bit */; 610 ep.ep_opt |= __SHIFTIN(edma_channel_index(edma), 611 EDMA_PARAM_OPT_TCC); 612 if (seg == cmd->c_dmamap->dm_nsegs - 1) { 613 ep.ep_opt |= EDMA_PARAM_OPT_TCINTEN; 614 ep.ep_link = 0xffff; 615 } else { 616 ep.ep_link = EDMA_PARAM_BASE(edma_param[seg+1]); 617 } 618 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 619 ep.ep_opt |= EDMA_PARAM_OPT_SAM; 620 ep.ep_src = sc->sc_edma_fifo; 621 ep.ep_dst = cmd->c_dmamap->dm_segs[seg].ds_addr; 622 } else { 623 ep.ep_opt |= EDMA_PARAM_OPT_DAM; 624 ep.ep_src = cmd->c_dmamap->dm_segs[seg].ds_addr; 625 ep.ep_dst = sc->sc_edma_fifo; 626 } 627 628 KASSERT(xferlen <= 65536 * 4); 629 630 /* 631 * In constant addressing mode, the address must be aligned 632 * to 256-bits. 633 */ 634 KASSERT((cmd->c_dmamap->dm_segs[seg].ds_addr & 0x1f) == 0); 635 636 /* 637 * For unknown reason, the A-DMA transfers never completes for 638 * transfers larger than 64 butes. So use a AB transfer, 639 * with a 64 bytes A len 640 */ 641 ep.ep_bcntrld = 0; /* not used for AB-synchronous mode */ 642 ep.ep_opt |= EDMA_PARAM_OPT_SYNCDIM; 643 ep.ep_acnt = uimin(xferlen, 64); 644 ep.ep_bcnt = uimin(xferlen, blksize) / ep.ep_acnt; 645 ep.ep_ccnt = xferlen / (ep.ep_acnt * ep.ep_bcnt); 646 ep.ep_srcbidx = ep.ep_dstbidx = 0; 647 ep.ep_srccidx = ep.ep_dstcidx = 0; 648 if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 649 ep.ep_dstbidx = ep.ep_acnt; 650 ep.ep_dstcidx = ep.ep_acnt * ep.ep_bcnt; 651 } else { 652 ep.ep_srcbidx = ep.ep_acnt; 653 ep.ep_srccidx = ep.ep_acnt * ep.ep_bcnt; 654 } 655 656 edma_set_param(edma, edma_param[seg], &ep); 657 #ifdef TISDHC_DEBUG 658 if (tisdhcdebug >= 1) { 659 printf("target OPT: %08x\n", ep.ep_opt); 660 edma_dump_param(edma, edma_param[seg]); 661 } 662 #endif 663 } 664 665 error = 0; 666 sc->sc_edma_pending = true; 667 edma_transfer_enable(edma, edma_param[0]); 668 while (sc->sc_edma_pending) { 669 error = cv_timedwait(&sc->sc_edma_cv, plock, hz*10); 670 if (error == EWOULDBLOCK) { 671 device_printf(sc->sc.sc_dev, "transfer timeout!\n"); 672 edma_dump(edma); 673 edma_dump_param(edma, edma_param[0]); 674 edma_halt(edma); 675 sc->sc_edma_pending = false; 676 error = ETIMEDOUT; 677 break; 678 } 679 } 680 edma_halt(edma); 681 682 return error; 683 } 684 685 static void 686 ti_sdhc_edma_done(void *priv) 687 { 688 struct ti_sdhc_softc *sc = priv; 689 kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]); 690 691 mutex_enter(plock); 692 KASSERT(sc->sc_edma_pending == true); 693 sc->sc_edma_pending = false; 694 cv_broadcast(&sc->sc_edma_cv); 695 mutex_exit(plock); 696 } 697