1/* $NetBSD: mvsdio.c,v 1.8 2021/08/07 16:19:13 thorpej Exp $ */ 2/* 3 * Copyright (c) 2010 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27#include <sys/cdefs.h> 28__KERNEL_RCSID(0, "$NetBSD: mvsdio.c,v 1.8 2021/08/07 16:19:13 thorpej Exp $"); 29 30#include "opt_mvsdio.h" 31 32#include <sys/param.h> 33#include <sys/bus.h> 34#include <sys/condvar.h> 35#include <sys/device.h> 36#include <sys/errno.h> 37#include <sys/mutex.h> 38 39#include <dev/marvell/marvellreg.h> 40#include <dev/marvell/marvellvar.h> 41#include <dev/marvell/mvsdioreg.h> 42 43#include <dev/sdmmc/sdmmcvar.h> 44#include <dev/sdmmc/sdmmcchip.h> 45 46//#define MVSDIO_DEBUG 1 47#ifdef MVSDIO_DEBUG 48#define DPRINTF(n, x) if (mvsdio_debug >= (n)) printf x 49int mvsdio_debug = MVSDIO_DEBUG; 50#else 51#define DPRINTF(n, x) 52#endif 53 54struct mvsdio_softc { 55 device_t sc_dev; 56 device_t sc_sdmmc; 57 58 bus_space_tag_t sc_iot; 59 bus_space_handle_t sc_ioh; 60 bus_dma_tag_t sc_dmat; 61 62 struct kmutex sc_mtx; 63 kcondvar_t sc_cv; 64 65 struct sdmmc_command *sc_exec_cmd; 66 uint32_t sc_waitintr; 67}; 68 69static int mvsdio_match(device_t, struct cfdata *, void *); 70static void mvsdio_attach(device_t, device_t, void *); 71 72static int mvsdio_intr(void *); 73 74static int mvsdio_host_reset(sdmmc_chipset_handle_t); 75static uint32_t mvsdio_host_ocr(sdmmc_chipset_handle_t); 76static int mvsdio_host_maxblklen(sdmmc_chipset_handle_t); 77#ifdef MVSDIO_CARD_DETECT 78int MVSDIO_CARD_DETECT(sdmmc_chipset_handle_t); 79#else 80static int mvsdio_card_detect(sdmmc_chipset_handle_t); 81#endif 82#ifdef MVSDIO_WRITE_PROTECT 83int MVSDIO_WRITE_PROTECT(sdmmc_chipset_handle_t); 84#else 85static int mvsdio_write_protect(sdmmc_chipset_handle_t); 86#endif 87static int mvsdio_bus_power(sdmmc_chipset_handle_t, uint32_t); 88static int mvsdio_bus_clock(sdmmc_chipset_handle_t, int); 89static int mvsdio_bus_width(sdmmc_chipset_handle_t, int); 90static int mvsdio_bus_rod(sdmmc_chipset_handle_t, int); 91static void mvsdio_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *); 92static void mvsdio_card_enable_intr(sdmmc_chipset_handle_t, int); 93static void mvsdio_card_intr_ack(sdmmc_chipset_handle_t); 94 95static void mvsdio_wininit(struct mvsdio_softc *, enum marvell_tags *); 96 97static struct sdmmc_chip_functions mvsdio_chip_functions = { 98 /* host controller reset */ 99 .host_reset = mvsdio_host_reset, 100 101 /* host controller capabilities */ 102 .host_ocr = mvsdio_host_ocr, 103 .host_maxblklen = mvsdio_host_maxblklen, 104 105 /* card detection */ 106#ifdef MVSDIO_CARD_DETECT 107 .card_detect = MVSDIO_CARD_DETECT, 108#else 109 .card_detect = mvsdio_card_detect, 110#endif 111 112 /* write protect */ 113#ifdef MVSDIO_WRITE_PROTECT 114 .write_protect = MVSDIO_WRITE_PROTECT, 115#else 116 .write_protect = mvsdio_write_protect, 117#endif 118 119 /* bus power, clock frequency, width, rod */ 120 .bus_power = mvsdio_bus_power, 121 .bus_clock = mvsdio_bus_clock, 122 .bus_width = mvsdio_bus_width, 123 .bus_rod = mvsdio_bus_rod, 124 125 /* command execution */ 126 .exec_command = mvsdio_exec_command, 127 128 /* card interrupt */ 129 .card_enable_intr = mvsdio_card_enable_intr, 130 .card_intr_ack = mvsdio_card_intr_ack, 131}; 132 133CFATTACH_DECL_NEW(mvsdio_mbus, sizeof(struct mvsdio_softc), 134 mvsdio_match, mvsdio_attach, NULL, NULL); 135 136 137/* ARGSUSED */ 138static int 139mvsdio_match(device_t parent, struct cfdata *match, void *aux) 140{ 141 struct marvell_attach_args *mva = aux; 142 143 if (strcmp(mva->mva_name, match->cf_name) != 0) 144 return 0; 145 if (mva->mva_offset == MVA_OFFSET_DEFAULT) 146 return 0; 147 148 mva->mva_size = MVSDIO_SIZE; 149 return 1; 150} 151 152/* ARGSUSED */ 153static void 154mvsdio_attach(device_t parent, device_t self, void *aux) 155{ 156 struct mvsdio_softc *sc = device_private(self); 157 struct marvell_attach_args *mva = aux; 158 struct sdmmcbus_attach_args saa; 159 uint32_t nis, eis; 160 uint32_t hps; 161 162 aprint_naive("\n"); 163 aprint_normal(": Marvell Secure Digital Input/Output Interface\n"); 164 165 sc->sc_dev = self; 166 sc->sc_iot = mva->mva_iot; 167 if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset, 168 mva->mva_size, &sc->sc_ioh)) { 169 aprint_error_dev(self, "Cannot map registers\n"); 170 return; 171 } 172 sc->sc_dmat = mva->mva_dmat; 173 174 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_SDMMC); 175 cv_init(&sc->sc_cv, "mvsdio_intr"); 176 177 sc->sc_exec_cmd = NULL; 178 sc->sc_waitintr = 0; 179 180 marvell_intr_establish(mva->mva_irq, IPL_SDMMC, mvsdio_intr, sc); 181 182 mvsdio_wininit(sc, mva->mva_tags); 183 184#if BYTE_ORDER == LITTLE_ENDIAN 185 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, HC_BIGENDIAN); 186#else 187 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, HC_LSBFIRST); 188#endif 189 nis = 190 NIS_CMDCOMPLETE /* Command Complete */ | 191 NIS_XFERCOMPLETE /* Transfer Complete */ | 192 NIS_BLOCKGAPEV /* Block gap event */ | 193 NIS_DMAINT /* DMA interrupt */ | 194 NIS_CARDINT /* Card interrupt */ | 195 NIS_READWAITON /* Read Wait state is on */ | 196 NIS_SUSPENSEON | 197 NIS_AUTOCMD12COMPLETE /* Auto_cmd12 is comp */| 198 NIS_UNEXPECTEDRESPDET | 199 NIS_ERRINT; /* Error interrupt */ 200 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NIS, nis); 201 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISE, nis); 202 203#define NIC_DYNAMIC_CONFIG_INTRS (NIS_CMDCOMPLETE | \ 204 NIS_XFERCOMPLETE | \ 205 NIS_DMAINT | \ 206 NIS_CARDINT | \ 207 NIS_AUTOCMD12COMPLETE) 208 209 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE, 210 nis & ~NIC_DYNAMIC_CONFIG_INTRS); 211 212 eis = 213 EIS_CMDTIMEOUTERR /*Command timeout err*/ | 214 EIS_CMDCRCERR /* Command CRC Error */ | 215 EIS_CMDENDBITERR /*Command end bit err*/ | 216 EIS_CMDINDEXERR /*Command Index Error*/ | 217 EIS_DATATIMEOUTERR /* Data timeout error */ | 218 EIS_RDDATACRCERR /* Read data CRC err */ | 219 EIS_RDDATAENDBITERR /*Rd data end bit err*/ | 220 EIS_AUTOCMD12ERR /* Auto CMD12 error */ | 221 EIS_CMDSTARTBITERR /*Cmd start bit error*/ | 222 EIS_XFERSIZEERR /*Tx size mismatched err*/ | 223 EIS_RESPTBITERR /* Response T bit err */ | 224 EIS_CRCENDBITERR /* CRC end bit error */ | 225 EIS_CRCSTARTBITERR /* CRC start bit err */ | 226 EIS_CRCSTATERR; /* CRC status error */ 227 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EIS, eis); 228 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISE, eis); 229 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISIE, eis); 230 231 hps = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HPS16LSB); 232 if ((hps & HPS16LSB_CMDLEVEL) == 0) { 233 aprint_error_dev(sc->sc_dev, 234 "CMD line not idle, HPS 0x%x (bad MPP config?)\n", hps); 235 return; 236 } 237 238 /* 239 * Attach the generic SD/MMC bus driver. (The bus driver must 240 * not invoke any chipset functions before it is attached.) 241 */ 242 memset(&saa, 0, sizeof(saa)); 243 saa.saa_busname = "sdmmc"; 244 saa.saa_sct = &mvsdio_chip_functions; 245 saa.saa_sch = sc; 246 saa.saa_dmat = sc->sc_dmat; 247 saa.saa_clkmin = 100; /* XXXX: 100 kHz from SheevaPlug LSP */ 248 saa.saa_clkmax = MVSDIO_MAX_CLOCK; 249 saa.saa_caps = SMC_CAPS_AUTO_STOP | SMC_CAPS_4BIT_MODE | SMC_CAPS_DMA | 250 SMC_CAPS_SD_HIGHSPEED | SMC_CAPS_MMC_HIGHSPEED; 251#ifndef MVSDIO_CARD_DETECT 252 saa.saa_caps |= SMC_CAPS_POLL_CARD_DET; 253#endif 254 sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL, CFARGS_NONE); 255} 256 257static int 258mvsdio_intr(void *arg) 259{ 260 struct mvsdio_softc *sc = (struct mvsdio_softc *)arg; 261 struct sdmmc_command *cmd = sc->sc_exec_cmd; 262 uint32_t nis, eis; 263 int handled = 0, error; 264 265 nis = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NIS); 266 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NIS, nis); 267 268 DPRINTF(3, ("%s: intr: NIS=0x%x, NISE=0x%x, NISIE=0x%x\n", 269 __func__, nis, 270 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISE), 271 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE))); 272 273 if (__predict_false(nis & NIS_ERRINT)) { 274 sc->sc_exec_cmd = NULL; 275 eis = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EIS); 276 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EIS, eis); 277 278 DPRINTF(3, (" EIS=0x%x, EISE=0x%x, EISIE=0x%x\n", 279 eis, 280 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISE), 281 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISIE))); 282 283 if (eis & (EIS_CMDTIMEOUTERR | EIS_DATATIMEOUTERR)) { 284 error = ETIMEDOUT; /* Timeouts */ 285 DPRINTF(2, (" Command/Data Timeout (0x%x)\n", 286 eis & (EIS_CMDTIMEOUTERR | EIS_DATATIMEOUTERR))); 287 } else { 288 289#define CRC_ERROR (EIS_CMDCRCERR | \ 290 EIS_RDDATACRCERR | \ 291 EIS_CRCENDBITERR | \ 292 EIS_CRCSTARTBITERR | \ 293 EIS_CRCSTATERR) 294 if (eis & CRC_ERROR) { 295 error = EIO; /* CRC errors */ 296 aprint_error_dev(sc->sc_dev, 297 "CRC Error (0x%x)\n", eis & CRC_ERROR); 298 } 299 300#define COMMAND_ERROR (EIS_CMDENDBITERR | \ 301 EIS_CMDINDEXERR | \ 302 EIS_CMDSTARTBITERR) 303 if (eis & COMMAND_ERROR) { 304 error = EIO; /*Other command errors*/ 305 aprint_error_dev(sc->sc_dev, 306 "Command Error (0x%x)\n", 307 eis & COMMAND_ERROR); 308 } 309 310#define MISC_ERROR (EIS_RDDATAENDBITERR | \ 311 EIS_AUTOCMD12ERR | \ 312 EIS_XFERSIZEERR | \ 313 EIS_RESPTBITERR) 314 if (eis & MISC_ERROR) { 315 error = EIO; /* Misc error */ 316 aprint_error_dev(sc->sc_dev, 317 "Misc Error (0x%x)\n", eis & MISC_ERROR); 318 } 319 } 320 321 if (cmd != NULL) { 322 cmd->c_error = error; 323 cv_signal(&sc->sc_cv); 324 } 325 handled = 1; 326 } else if (cmd != NULL && 327 ((nis & sc->sc_waitintr) || (nis & NIS_UNEXPECTEDRESPDET))) { 328 sc->sc_exec_cmd = NULL; 329 sc->sc_waitintr = 0; 330 if (cmd->c_flags & SCF_RSP_PRESENT) { 331 uint16_t rh[MVSDIO_NRH + 1]; 332 int i, j; 333 334 if (cmd->c_flags & SCF_RSP_136) { 335 for (i = 0; i < MVSDIO_NRH; i++) 336 rh[i + 1] = bus_space_read_4(sc->sc_iot, 337 sc->sc_ioh, MVSDIO_RH(i)); 338 rh[0] = 0; 339 for (j = 3, i = 1; j >= 0; j--, i += 2) { 340 cmd->c_resp[j] = 341 rh[i - 1] << 30 | 342 rh[i + 0] << 14 | 343 rh[i + 1] >> 2; 344 } 345 cmd->c_resp[3] &= 0x00ffffff; 346 } else { 347 for (i = 0; i < 3; i++) 348 rh[i] = bus_space_read_4(sc->sc_iot, 349 sc->sc_ioh, MVSDIO_RH(i)); 350 cmd->c_resp[0] = 351 ((rh[0] & 0x03ff) << 22) | 352 ((rh[1] ) << 6) | 353 ((rh[2] & 0x003f) << 0); 354 cmd->c_resp[1] = (rh[0] & 0xfc00) >> 10; 355 cmd->c_resp[2] = 0; 356 cmd->c_resp[3] = 0; 357 } 358 } 359 if (nis & NIS_UNEXPECTEDRESPDET) 360 cmd->c_error = EIO; 361 cv_signal(&sc->sc_cv); 362 } 363 364 if (nis & NIS_CARDINT) 365 if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE) & 366 NIS_CARDINT) { 367 sdmmc_card_intr(sc->sc_sdmmc); 368 handled = 1; 369 } 370 371 return handled; 372} 373 374static int 375mvsdio_host_reset(sdmmc_chipset_handle_t sch) 376{ 377 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 378 379 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_SR, SR_SWRESET); 380 return 0; 381} 382 383static uint32_t 384mvsdio_host_ocr(sdmmc_chipset_handle_t sch) 385{ 386 387 return MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V; 388} 389 390static int 391mvsdio_host_maxblklen(sdmmc_chipset_handle_t sch) 392{ 393 394 return DBS_BLOCKSIZE_MAX; 395} 396 397#ifndef MVSDIO_CARD_DETECT 398static int 399mvsdio_card_detect(sdmmc_chipset_handle_t sch) 400{ 401 struct mvsdio_softc *sc __unused = (struct mvsdio_softc *)sch; 402 403 DPRINTF(2, ("%s: driver lacks card_detect() function.\n", 404 device_xname(sc->sc_dev))); 405 return 1; /* always detect */ 406} 407#endif 408 409#ifndef MVSDIO_WRITE_PROTECT 410static int 411mvsdio_write_protect(sdmmc_chipset_handle_t sch) 412{ 413 414 /* Nothing */ 415 416 return 0; 417} 418#endif 419 420static int 421mvsdio_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 422{ 423 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 424 uint32_t reg; 425 426 /* Initial state is Open Drain on CMD line. */ 427 mutex_enter(&sc->sc_mtx); 428 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC); 429 reg &= ~HC_PUSHPULLEN; 430 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, reg); 431 mutex_exit(&sc->sc_mtx); 432 433 return 0; 434} 435 436static int 437mvsdio_bus_clock(sdmmc_chipset_handle_t sch, int freq) 438{ 439 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 440 uint32_t reg; 441 int m; 442 443 mutex_enter(&sc->sc_mtx); 444 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_TM); 445 446 /* Just stop the clock. */ 447 if (freq == 0) { 448 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_TM, 449 reg | TM_STOPCLKEN); 450 goto out; 451 } 452 453#define FREQ_TO_M(f) (100000 / (f) - 1) 454 455 m = FREQ_TO_M(freq); 456 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_CDV, 457 m & CDV_CLKDVDRMVALUE_MASK); 458 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_TM, 459 reg & ~TM_STOPCLKEN); 460 461 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC); 462 if (freq > 25000) 463 reg |= HC_HISPEEDEN; 464 else 465 reg &= ~HC_HISPEEDEN; /* up to 25 MHz */ 466 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, reg); 467 468out: 469 mutex_exit(&sc->sc_mtx); 470 471 return 0; 472} 473 474static int 475mvsdio_bus_width(sdmmc_chipset_handle_t sch, int width) 476{ 477 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 478 uint32_t reg, v; 479 480 switch (width) { 481 case 1: 482 v = 0; 483 break; 484 485 case 4: 486 v = HC_DATAWIDTH; 487 break; 488 489 default: 490 DPRINTF(0, ("%s: unsupported bus width (%d)\n", 491 device_xname(sc->sc_dev), width)); 492 return EINVAL; 493 } 494 495 mutex_enter(&sc->sc_mtx); 496 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC); 497 reg &= ~HC_DATAWIDTH; 498 reg |= v; 499 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, reg); 500 mutex_exit(&sc->sc_mtx); 501 502 return 0; 503} 504 505static int 506mvsdio_bus_rod(sdmmc_chipset_handle_t sch, int on) 507{ 508 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 509 uint32_t reg; 510 511 /* Change Open-drain/Push-pull. */ 512 mutex_enter(&sc->sc_mtx); 513 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC); 514 if (on) 515 reg &= ~HC_PUSHPULLEN; 516 else 517 reg |= HC_PUSHPULLEN; 518 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, reg); 519 mutex_exit(&sc->sc_mtx); 520 521 return 0; 522} 523 524static void 525mvsdio_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 526{ 527 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 528 uint32_t tm, c, hc, aacc, nisie, wait; 529 int blklen; 530 531 DPRINTF(1, ("%s: start cmd %d arg=%#x data=%p dlen=%d flags=%#x\n", 532 device_xname(sc->sc_dev), cmd->c_opcode, cmd->c_arg, cmd->c_data, 533 cmd->c_datalen, cmd->c_flags)); 534 535 mutex_enter(&sc->sc_mtx); 536 537 tm = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_TM); 538 539 if (cmd->c_datalen > 0) { 540 bus_dma_segment_t *dm_seg = 541 &cmd->c_dmamap->dm_segs[cmd->c_dmaseg]; 542 bus_addr_t ds_addr = dm_seg->ds_addr + cmd->c_dmaoff; 543 544 blklen = MIN(cmd->c_datalen, cmd->c_blklen); 545 546 if (cmd->c_datalen % blklen > 0) { 547 aprint_error_dev(sc->sc_dev, 548 "data not a multiple of %u bytes\n", blklen); 549 cmd->c_error = EINVAL; 550 goto out; 551 } 552 if ((uint32_t)cmd->c_data & 0x3) { 553 aprint_error_dev(sc->sc_dev, 554 "data not 4byte aligned\n"); 555 cmd->c_error = EINVAL; 556 goto out; 557 } 558 559 /* Set DMA Buffer Address */ 560 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_DMABA16LSB, 561 ds_addr & 0xffff); 562 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_DMABA16MSB, 563 (ds_addr >> 16) & 0xffff); 564 565 /* Set Data Block Size and Count */ 566 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_DBS, 567 DBS_BLOCKSIZE(blklen)); 568 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_DBC, 569 DBC_BLOCKCOUNT(cmd->c_datalen / blklen)); 570 571 tm &= ~TM_HOSTXFERMODE; /* Always DMA */ 572 if (cmd->c_flags & SCF_CMD_READ) 573 tm |= TM_DATAXFERTOWARDHOST; 574 else 575 tm &= ~TM_DATAXFERTOWARDHOST; 576 tm |= TM_HWWRDATAEN; 577 wait = NIS_XFERCOMPLETE; 578 } else { 579 tm &= ~TM_HWWRDATAEN; 580 wait = NIS_CMDCOMPLETE; 581 } 582 583 /* Set Argument in Command */ 584 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_AC16LSB, 585 cmd->c_arg & 0xffff); 586 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_AC16MSB, 587 (cmd->c_arg >> 16) & 0xffff); 588 589 /* Set Host Control, exclude PushPullEn, DataWidth, HiSpeedEn. */ 590 hc = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC); 591 hc |= (HC_TIMEOUTVALUE_MAX | HC_TIMEOUTEN); 592 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, hc); 593 594 /* Data Block Gap Control: Resume */ 595 596 /* Clock Control: SclkMasterEn */ 597 598 if (cmd->c_opcode == MMC_READ_BLOCK_MULTIPLE || 599 cmd->c_opcode == MMC_WRITE_BLOCK_MULTIPLE) { 600 aacc = 0; 601#if 1 /* XXXX: need? */ 602 if (cmd->c_opcode == MMC_READ_BLOCK_MULTIPLE) { 603 struct sdmmc_softc *sdmmc = 604 device_private(sc->sc_sdmmc); 605 struct sdmmc_function *sf = sdmmc->sc_card; 606 607 aacc = MMC_ARG_RCA(sf->rca); 608 } 609#endif 610 611 /* Set Argument in Auto Cmd12 Command */ 612 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_AACC16LSBT, 613 aacc & 0xffff); 614 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_AACC16MSBT, 615 (aacc >> 16) & 0xffff); 616 617 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_IACCT, 618 IACCT_AUTOCMD12BUSYCHKEN | 619 IACCT_AUTOCMD12INDEXCHKEN | 620 IACCT_AUTOCMD12INDEX); 621 622 tm |= TM_AUTOCMD12EN; 623 wait = NIS_AUTOCMD12COMPLETE; 624 } else 625 tm &= ~TM_AUTOCMD12EN; 626 627 tm |= TM_INTCHKEN; 628 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_TM, tm); 629 630 c = C_CMDINDEX(cmd->c_opcode); 631 if (cmd->c_flags & SCF_RSP_PRESENT) { 632 if (cmd->c_flags & SCF_RSP_136) 633 c |= C_RESPTYPE_136BR; 634 else if (!(cmd->c_flags & SCF_RSP_BSY)) 635 c |= C_RESPTYPE_48BR; 636 else 637 c |= C_RESPTYPE_48BRCB; 638 c |= C_UNEXPECTEDRESPEN; 639 } else 640 c |= C_RESPTYPE_NR; 641 if (cmd->c_flags & SCF_RSP_CRC) 642 c |= C_CMDCRCCHKEN; 643 if (cmd->c_flags & SCF_RSP_IDX) 644 c |= C_CMDINDEXCHKEN; 645 if (cmd->c_datalen > 0) 646 c |= (C_DATAPRESENT | C_DATACRC16CHKEN); 647 648 DPRINTF(2, ("%s: TM=0x%x, C=0x%x, HC=0x%x\n", __func__, tm, c, hc)); 649 650 nisie = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE); 651 nisie &= ~(NIS_CMDCOMPLETE | NIS_XFERCOMPLETE | NIS_AUTOCMD12COMPLETE); 652 nisie |= wait; 653 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE, nisie); 654 655 /* Execute command */ 656 sc->sc_exec_cmd = cmd; 657 sc->sc_waitintr = wait; 658 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_C, c); 659 660 /* Wait interrupt for complete or error or timeout */ 661 while (sc->sc_exec_cmd == cmd) 662 cv_wait(&sc->sc_cv, &sc->sc_mtx); 663 664out: 665 mutex_exit(&sc->sc_mtx); 666 667 DPRINTF(1, ("%s: cmd %d done (flags=%08x error=%d)\n", 668 device_xname(sc->sc_dev), 669 cmd->c_opcode, cmd->c_flags, cmd->c_error)); 670} 671 672static void 673mvsdio_card_enable_intr(sdmmc_chipset_handle_t sch, int enable) 674{ 675 struct mvsdio_softc *sc = (struct mvsdio_softc *)sch; 676 uint32_t reg; 677 678 mutex_enter(&sc->sc_mtx); 679 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE); 680 reg |= NIS_CARDINT; 681 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE, reg); 682 mutex_exit(&sc->sc_mtx); 683} 684 685static void 686mvsdio_card_intr_ack(sdmmc_chipset_handle_t sch) 687{ 688 689 /* Nothing */ 690} 691 692 693static void 694mvsdio_wininit(struct mvsdio_softc *sc, enum marvell_tags *tags) 695{ 696 uint64_t base; 697 uint32_t size; 698 int window, target, attr, rv, i; 699 700 for (window = 0, i = 0; 701 tags[i] != MARVELL_TAG_UNDEFINED && window < MVSDIO_NWINDOW; i++) { 702 rv = marvell_winparams_by_tag(sc->sc_dev, tags[i], 703 &target, &attr, &base, &size); 704 if (rv != 0 || size == 0) 705 continue; 706 707 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_WC(window), 708 WC_WINEN | 709 WC_TARGET(target) | 710 WC_ATTR(attr) | 711 WC_SIZE(size)); 712 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_WB(window), 713 WB_BASE(base)); 714 window++; 715 } 716 for (; window < MVSDIO_NWINDOW; window++) 717 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_WC(window), 0); 718} 719