1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <linux/mmc/card.h> 21 #include <linux/mmc/mmc.h> 22 #include <linux/mmc/host.h> 23 #include <linux/mmc/sdio_func.h> 24 #include <linux/mmc/sdio_ids.h> 25 #include <linux/mmc/sdio.h> 26 #include <linux/mmc/sd.h> 27 #include <linux/kthread.h> 28 #include <linux/version.h> 29 #include <linux/module.h> 30 #include <qdf_atomic.h> 31 #include <cds_utils.h> 32 #include <qdf_timer.h> 33 #include <cds_api.h> 34 #include <qdf_time.h> 35 #include "hif_sdio_dev.h" 36 #include "if_sdio.h" 37 #include "regtable_sdio.h" 38 #include "wma_api.h" 39 #include "hif_internal.h" 40 #include <transfer/transfer.h> 41 42 /* QUIRK PARAMETERS */ 43 unsigned int writecccr1; 44 module_param(writecccr1, uint, 0644); 45 unsigned int writecccr1value; 46 module_param(writecccr1value, uint, 0644); 47 48 unsigned int writecccr2; 49 module_param(writecccr2, uint, 0644); 50 unsigned int writecccr2value; 51 module_param(writecccr2value, uint, 0644); 52 53 unsigned int writecccr3; 54 module_param(writecccr3, uint, 0644); 55 unsigned int writecccr3value; 56 module_param(writecccr3value, uint, 0644); 57 58 unsigned int writecccr4; 59 module_param(writecccr4, uint, 0644); 60 unsigned int writecccr4value; 61 module_param(writecccr4value, uint, 0644); 62 63 unsigned int modstrength; 64 module_param(modstrength, uint, 0644); 65 MODULE_PARM_DESC(modstrength, "Adjust internal driver strength"); 66 67 unsigned int mmcbuswidth; 68 /* PERM:S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH */ 69 module_param(mmcbuswidth, uint, 0644); 70 MODULE_PARM_DESC(mmcbuswidth, 71 "Set MMC driver Bus Width: 1-1Bit, 4-4Bit, 8-8Bit"); 72 73 unsigned int mmcclock; 74 module_param(mmcclock, uint, 0644); 75 MODULE_PARM_DESC(mmcclock, "Set MMC driver Clock value"); 76 77 #ifdef CONFIG_X86 78 unsigned int asyncintdelay = 2; 79 module_param(asyncintdelay, uint, 0644); 80 MODULE_PARM_DESC(asyncintdelay, "Delay clock count for async interrupt, 2 is default, valid values are 1 and 2"); 81 #else 82 unsigned int asyncintdelay; 83 module_param(asyncintdelay, uint, 0644); 84 MODULE_PARM_DESC(asyncintdelay, "Delay clock count for async interrupt, 0 is default, valid values are 1 and 2"); 85 #endif 86 87 unsigned int brokenirq; 88 module_param(brokenirq, uint, 0644); 89 MODULE_PARM_DESC(brokenirq, 90 "Set as 1 to use polling method instead of interrupt mode"); 91 92 #ifdef CONFIG_SDIO_TRANSFER_MAILBOX 93 /** 94 * hif_sdio_quirk_force_drive_strength() - Set SDIO drive strength 95 * @ol_sc: softc instance 96 * @func: pointer to sdio_func 97 * 98 * This function forces the driver strength of the SDIO 99 * Call this with the sdhci host claimed 100 * 101 * Return: none. 102 */ 103 void hif_sdio_quirk_force_drive_strength(struct hif_softc *ol_sc, 104 struct sdio_func *func) 105 { 106 int err = 0; 107 unsigned char value = 0; 108 uint32_t mask = 0, addr = SDIO_CCCR_DRIVE_STRENGTH; 109 110 err = func0_cmd52_read_byte(func->card, addr, &value); 111 if (err) { 112 hif_err("read driver strength 0x%02X fail %d", addr, err); 113 return; 114 } 115 116 mask = (SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT); 117 value = (value & ~mask) | SDIO_DTSx_SET_TYPE_D; 118 err = func0_cmd52_write_byte(func->card, addr, value); 119 if (err) { 120 hif_err("Write driver strength 0x%02X to 0x%02X failed: %d", 121 (uint32_t)value, addr, err); 122 return; 123 } 124 125 value = 0; 126 addr = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR; 127 err = func0_cmd52_read_byte(func->card, addr, &value); 128 if (err) { 129 hif_err("Read CCCR 0x%02X failed: %d", addr, err); 130 return; 131 } 132 133 mask = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK; 134 value = (value & ~mask) | CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A | 135 CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C | 136 CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D; 137 err = func0_cmd52_write_byte(func->card, addr, value); 138 if (err) 139 hif_err("Write CCCR 0x%02X to 0x%02X failed: %d", 140 addr, value, err); 141 } 142 143 /** 144 * hif_sdio_quirk_async_intr() - Set asynchronous interrupt settings 145 * @ol_sc: softc instance 146 * @func: pointer to sdio_func 147 * 148 * The values are taken from the module parameter asyncintdelay 149 * Call this with the sdhci host claimed 150 * 151 * Return: none. 152 */ 153 int hif_sdio_quirk_async_intr(struct hif_softc *ol_sc, struct sdio_func *func) 154 { 155 uint8_t data; 156 uint16_t manfid; 157 int set_async_irq = 0, ret = 0; 158 struct hif_sdio_dev *device = get_hif_device(ol_sc, func); 159 160 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 161 162 switch (manfid) { 163 case MANUFACTURER_ID_AR6003_BASE: 164 set_async_irq = 1; 165 ret = 166 func0_cmd52_write_byte(func->card, 167 CCCR_SDIO_IRQ_MODE_REG_AR6003, 168 SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003); 169 if (ret) 170 return ret; 171 break; 172 case MANUFACTURER_ID_AR6320_BASE: 173 case MANUFACTURER_ID_QCA9377_BASE: 174 case MANUFACTURER_ID_QCA9379_BASE: 175 set_async_irq = 1; 176 ret = func0_cmd52_read_byte(func->card, 177 CCCR_SDIO_IRQ_MODE_REG_AR6320, 178 &data); 179 if (ret) 180 return ret; 181 182 data |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320; 183 ret = func0_cmd52_write_byte(func->card, 184 CCCR_SDIO_IRQ_MODE_REG_AR6320, 185 data); 186 if (ret) 187 return ret; 188 break; 189 } 190 191 if (asyncintdelay) { 192 /* Set CCCR 0xF0[7:6] to increase async interrupt delay clock 193 * to fix interrupt missing issue on dell 8460p 194 */ 195 196 ret = func0_cmd52_read_byte(func->card, 197 CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, 198 &data); 199 if (ret) 200 return ret; 201 202 data = (data & ~CCCR_SDIO_ASYNC_INT_DELAY_MASK) | 203 ((asyncintdelay << CCCR_SDIO_ASYNC_INT_DELAY_LSB) & 204 CCCR_SDIO_ASYNC_INT_DELAY_MASK); 205 206 ret = func0_cmd52_write_byte(func->card, 207 CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, 208 data); 209 if (ret) 210 return ret; 211 } 212 213 return ret; 214 } 215 #else 216 /** 217 * hif_sdio_quirk_force_drive_strength() - Set SDIO drive strength 218 * @ol_sc: softc instance 219 * @func: pointer to sdio_func 220 * 221 * This function forces the driver strength of the SDIO 222 * Call this with the sdhci host claimed 223 * 224 * Return: none. 225 */ 226 void hif_sdio_quirk_force_drive_strength(struct hif_softc *ol_sc, 227 struct sdio_func *func) 228 { 229 } 230 231 /** 232 * hif_sdio_quirk_async_intr() - Set asynchronous interrupt settings 233 * @ol_sc: softc instance 234 * @func: pointer to sdio_func 235 * 236 * The values are taken from the module parameter asyncintdelay 237 * Call this with the sdhci host claimed 238 * 239 * Return: none. 240 */ 241 int hif_sdio_quirk_async_intr(struct hif_softc *ol_sc, struct sdio_func *func) 242 { 243 return 0; 244 } 245 #endif 246 247 /** 248 * hif_sdio_quirk_write_cccr() - write a desired CCCR register 249 * @ol_sc: softc instance 250 * @func: pointer to sdio_func 251 * 252 * The values are taken from the module parameter writecccr 253 * Call this with the sdhci host claimed 254 * 255 * Return: none. 256 */ 257 void hif_sdio_quirk_write_cccr(struct hif_softc *ol_sc, struct sdio_func *func) 258 { 259 int32_t err; 260 261 if (writecccr1) { 262 err = func0_cmd52_write_byte(func->card, writecccr1, 263 writecccr1value); 264 if (err) 265 hif_err("Write CCCR 0x%02X to 0x%02X failed: %d", 266 (unsigned int)writecccr1, 267 (unsigned int)writecccr1value, 268 err); 269 else 270 hif_info("%s Write CCCR 0x%02X to 0x%02X OK", 271 (unsigned int)writecccr1, 272 writecccr1value); 273 } 274 275 if (writecccr2) { 276 err = func0_cmd52_write_byte(func->card, writecccr2, 277 writecccr2value); 278 if (err) 279 hif_err("Write CCCR 0x%02X to 0x%02X failed: %d", 280 (unsigned int)writecccr2, 281 (unsigned int)writecccr2value, 282 err); 283 else 284 hif_info("%s Write CCCR 0x%02X to 0x%02X OK", 285 (unsigned int)writecccr2, 286 (unsigned int)writecccr2value); 287 } 288 if (writecccr3) { 289 err = func0_cmd52_write_byte(func->card, writecccr3, 290 writecccr3value); 291 if (err) 292 hif_err("Write CCCR 0x%02X to 0x%02X failed: %d", 293 (unsigned int)writecccr3, 294 (unsigned int)writecccr3value, 295 err); 296 else 297 hif_info("%s Write CCCR 0x%02X to 0x%02X OK", 298 (unsigned int)writecccr3, 299 (unsigned int)writecccr3value); 300 } 301 if (writecccr4) { 302 err = func0_cmd52_write_byte(func->card, writecccr4, 303 writecccr4value); 304 if (err) 305 hif_err("Write CCCR 0x%02X to 0x%02X failed: %d", 306 (unsigned int)writecccr4, 307 (unsigned int)writecccr4value, 308 err); 309 else 310 hif_info("%s Write CCCR 0x%02X to 0x%02X OK", 311 (unsigned int)writecccr4, 312 (unsigned int)writecccr4value); 313 } 314 } 315 316 /** 317 * hif_sdio_quirk_mod_strength() - write a desired CCCR register 318 * @ol_sc: softc instance 319 * @func: pointer to sdio_func 320 * 321 * The values are taken from the module parameter writecccr 322 * Call this with the sdhci host claimed 323 * 324 * Return: none. 325 */ 326 int hif_sdio_quirk_mod_strength(struct hif_softc *ol_sc, struct sdio_func *func) 327 { 328 int ret = 0; 329 uint32_t addr, value; 330 struct hif_sdio_dev *device = get_hif_device(ol_sc, func); 331 uint16_t manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 332 333 if (!modstrength) /* TODO: Dont set this : scn is not populated yet */ 334 return 0; 335 336 if (!scn) { 337 hif_err("scn is null"); 338 return -1; 339 } 340 341 if (!scn->hostdef) { 342 hif_err("scn->hostdef is null"); 343 return -1; 344 } 345 346 switch (manfid) { 347 case MANUFACTURER_ID_QCN7605_BASE: 348 break; 349 default: 350 addr = WINDOW_DATA_ADDRESS; 351 value = 0x0FFF; 352 ret = sdio_memcpy_toio(func, addr, &value, 4); 353 if (ret) { 354 hif_err("write 0x%x 0x%x error:%d", addr, value, ret); 355 break; 356 } 357 hif_info("addr 0x%x val 0x%x", addr, value); 358 359 addr = WINDOW_WRITE_ADDR_ADDRESS; 360 value = 0x50F8; 361 ret = sdio_memcpy_toio(func, addr, &value, 4); 362 if (ret) { 363 hif_err("write 0x%x 0x%x error:%d", addr, value, ret); 364 break; 365 } 366 hif_info("addr 0x%x val 0x%x", addr, value); 367 break; 368 } 369 370 return ret; 371 } 372 373 #if KERNEL_VERSION(3, 4, 0) <= LINUX_VERSION_CODE 374 #ifdef SDIO_BUS_WIDTH_8BIT 375 static int hif_cmd52_write_byte_8bit(struct sdio_func *func) 376 { 377 return func0_cmd52_write_byte(func->card, SDIO_CCCR_IF, 378 SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_8BIT); 379 } 380 #else 381 static int hif_cmd52_write_byte_8bit(struct sdio_func *func) 382 { 383 hif_err("8BIT Bus Width not supported"); 384 return QDF_STATUS_E_FAILURE; 385 } 386 #endif 387 #endif 388 389 /** 390 * hif_sdio_set_bus_speed() - Set the sdio bus speed 391 * @ol_sc: softc instance 392 * @func: pointer to sdio_func 393 * 394 * Return: QDF_STATUS 395 */ 396 QDF_STATUS hif_sdio_set_bus_speed(struct hif_softc *ol_sc, 397 struct sdio_func *func) 398 { 399 uint32_t clock, clock_set = 12500000; 400 struct hif_sdio_dev *device = get_hif_device(ol_sc, func); 401 uint16_t manfid; 402 403 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 404 405 if (manfid == MANUFACTURER_ID_QCN7605_BASE) 406 return QDF_STATUS_SUCCESS; 407 408 if (mmcclock > 0) 409 clock_set = mmcclock; 410 #if (KERNEL_VERSION(3, 16, 0) > LINUX_VERSION_CODE) 411 if (sdio_card_highspeed(func->card)) 412 #else 413 if (mmc_card_hs(func->card)) 414 #endif 415 clock = 50000000; 416 else 417 clock = func->card->cis.max_dtr; 418 419 if (clock > device->host->f_max) 420 clock = device->host->f_max; 421 422 hif_info("Clock setting: (%d,%d)", 423 func->card->cis.max_dtr, device->host->f_max); 424 425 /* Limit clock if specified */ 426 if (mmcclock > 0) { 427 hif_info("Limit clock from %d to %d", clock, clock_set); 428 device->host->ios.clock = clock_set; 429 device->host->ops->set_ios(device->host, 430 &device->host->ios); 431 } 432 433 return QDF_STATUS_SUCCESS; 434 } 435 436 /** 437 * hif_sdio_set_bus_width() - Set the sdio bus width 438 * @ol_sc: softc instance 439 * @func: pointer to sdio_func 440 * 441 * Return: QDF_STATUS 442 */ 443 QDF_STATUS hif_sdio_set_bus_width(struct hif_softc *ol_sc, 444 struct sdio_func *func) 445 { 446 int ret = 0; 447 uint16_t manfid; 448 uint8_t data = 0; 449 struct hif_sdio_dev *device = get_hif_device(ol_sc, func); 450 QDF_STATUS status = QDF_STATUS_SUCCESS; 451 452 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 453 454 if (manfid == MANUFACTURER_ID_QCN7605_BASE) 455 return status; 456 457 #if KERNEL_VERSION(3, 4, 0) <= LINUX_VERSION_CODE 458 if (mmcbuswidth == 0) 459 return status; 460 461 /* Set MMC Bus Width: 1-1Bit, 4-4Bit, 8-8Bit */ 462 if (mmcbuswidth == 1) { 463 data = SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_1BIT; 464 ret = func0_cmd52_write_byte(func->card, 465 SDIO_CCCR_IF, 466 data); 467 if (ret) 468 hif_err("Bus Width 0x%x failed %d", data, ret); 469 device->host->ios.bus_width = MMC_BUS_WIDTH_1; 470 device->host->ops->set_ios(device->host, 471 &device->host->ios); 472 } else if (mmcbuswidth == 4 && 473 (device->host->caps & MMC_CAP_4_BIT_DATA)) { 474 data = SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT; 475 ret = func0_cmd52_write_byte(func->card, 476 SDIO_CCCR_IF, 477 data); 478 if (ret) 479 hif_err("Bus Width 0x%x failed: %d", data, ret); 480 device->host->ios.bus_width = MMC_BUS_WIDTH_4; 481 device->host->ops->set_ios(device->host, 482 &device->host->ios); 483 } else if (mmcbuswidth == 8 && 484 (device->host->caps & MMC_CAP_8_BIT_DATA)) { 485 ret = hif_cmd52_write_byte_8bit(func); 486 if (ret) 487 hif_err("Bus Width 8 failed: %d", ret); 488 device->host->ios.bus_width = MMC_BUS_WIDTH_8; 489 device->host->ops->set_ios(device->host, 490 &device->host->ios); 491 } else { 492 hif_err("Unsupported bus width %d", mmcbuswidth); 493 status = QDF_STATUS_E_FAILURE; 494 goto out; 495 } 496 497 status = qdf_status_from_os_return(ret); 498 499 out: 500 hif_debug("Bus width: %d", mmcbuswidth); 501 #endif 502 return status; 503 } 504 505 506 /** 507 * hif_mask_interrupt() - Disable hif device irq 508 * @device: pointer to struct hif_sdio_dev 509 * 510 * 511 * Return: None. 512 */ 513 void hif_mask_interrupt(struct hif_sdio_dev *device) 514 { 515 int ret; 516 uint16_t manfid; 517 518 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 519 520 if (manfid == MANUFACTURER_ID_QCN7605_BASE) 521 return; 522 523 HIF_ENTER(); 524 525 /* Mask our function IRQ */ 526 sdio_claim_host(device->func); 527 while (atomic_read(&device->irq_handling)) { 528 sdio_release_host(device->func); 529 schedule_timeout_interruptible(HZ / 10); 530 sdio_claim_host(device->func); 531 } 532 ret = sdio_release_irq(device->func); 533 sdio_release_host(device->func); 534 if (ret) 535 hif_err("Failed %d", ret); 536 537 HIF_EXIT(); 538 } 539 540 /** 541 * hif_irq_handler() - hif-sdio interrupt handler 542 * @func: pointer to sdio_func 543 * 544 * Return: None. 545 */ 546 static void hif_irq_handler(struct sdio_func *func) 547 { 548 struct hif_sdio_dev *device = get_hif_device(NULL, func); 549 atomic_set(&device->irq_handling, 1); 550 /* release the host during intr so we can use 551 * it when we process cmds 552 */ 553 sdio_release_host(device->func); 554 device->htc_callbacks.dsr_handler(device->htc_callbacks.context); 555 sdio_claim_host(device->func); 556 atomic_set(&device->irq_handling, 0); 557 } 558 559 /** 560 * hif_un_mask_interrupt() - Re-enable hif device irq 561 * @device: pointer to struct hif_sdio_dev 562 * 563 * 564 * Return: None. 565 */ 566 void hif_un_mask_interrupt(struct hif_sdio_dev *device) 567 { 568 int ret; 569 uint16_t manfid; 570 571 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 572 573 if (manfid == MANUFACTURER_ID_QCN7605_BASE) 574 return; 575 576 HIF_ENTER(); 577 /* 578 * On HP Elitebook 8460P, interrupt mode is not stable 579 * in high throughput, so polling method should be used 580 * instead of interrupt mode. 581 */ 582 if (brokenirq) { 583 hif_info("Using broken IRQ mode"); 584 device->func->card->host->caps &= ~MMC_CAP_SDIO_IRQ; 585 } 586 /* Register the IRQ Handler */ 587 sdio_claim_host(device->func); 588 ret = sdio_claim_irq(device->func, hif_irq_handler); 589 sdio_release_host(device->func); 590 591 HIF_EXIT(); 592 } 593 594 /** 595 * hif_sdio_func_disable() - Handle device enabling as per device 596 * @device: HIF device object 597 * @func: function pointer 598 * @reset: 599 * 600 * Return success or failure 601 */ 602 QDF_STATUS hif_sdio_func_disable(struct hif_sdio_dev *device, 603 struct sdio_func *func, 604 bool reset) 605 { 606 int ret = 0; 607 uint16_t manfid; 608 QDF_STATUS status = QDF_STATUS_SUCCESS; 609 610 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 611 612 if (manfid == MANUFACTURER_ID_QCN7605_BASE) 613 return 0; 614 615 /* Disable the card */ 616 sdio_claim_host(device->func); 617 618 ret = sdio_disable_func(device->func); 619 if (ret) 620 status = QDF_STATUS_E_FAILURE; 621 622 if (reset && status == QDF_STATUS_SUCCESS) 623 ret = func0_cmd52_write_byte(device->func->card, 624 SDIO_CCCR_ABORT, 625 (1 << 3)); 626 627 if (ret) { 628 status = QDF_STATUS_E_FAILURE; 629 hif_err("reset failed: %d", ret); 630 } 631 632 sdio_release_host(device->func); 633 634 return status; 635 } 636 637 /** 638 * reinit_sdio() - re-initialize sdio bus 639 * @device: pointer to hif device 640 * 641 * Return: 0 on success, error number otherwise. 642 */ 643 QDF_STATUS reinit_sdio(struct hif_sdio_dev *device) 644 { 645 int32_t err = 0; 646 struct mmc_host *host; 647 struct mmc_card *card; 648 struct sdio_func *func; 649 uint8_t cmd52_resp; 650 uint32_t clock; 651 uint16_t manfid; 652 653 func = device->func; 654 card = func->card; 655 host = card->host; 656 657 manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; 658 659 if (manfid == MANUFACTURER_ID_QCN7605_BASE) 660 return QDF_STATUS_SUCCESS; 661 662 sdio_claim_host(func); 663 664 do { 665 /* Enable high speed */ 666 if (card->host->caps & MMC_CAP_SD_HIGHSPEED) { 667 hif_debug("Set high speed mode"); 668 err = func0_cmd52_read_byte(card, SDIO_CCCR_SPEED, 669 &cmd52_resp); 670 if (err) { 671 hif_err("CCCR speed set failed: %d", err); 672 sdio_card_state(card); 673 /* no need to break */ 674 } else { 675 err = func0_cmd52_write_byte(card, 676 SDIO_CCCR_SPEED, 677 (cmd52_resp | 678 SDIO_SPEED_EHS)); 679 if (err) { 680 hif_err("CCCR speed set failed: %d", err); 681 break; 682 } 683 sdio_card_set_highspeed(card); 684 host->ios.timing = MMC_TIMING_SD_HS; 685 host->ops->set_ios(host, &host->ios); 686 } 687 } 688 689 /* Set clock */ 690 if (sdio_card_highspeed(card)) 691 clock = 50000000; 692 else 693 clock = card->cis.max_dtr; 694 695 if (clock > host->f_max) 696 clock = host->f_max; 697 /* 698 * In fpga mode the clk should be set to 12500000, 699 * or will result in scan channel setting timeout error. 700 * So in fpga mode, please set module parameter mmcclock 701 * to 12500000. 702 */ 703 if (mmcclock > 0) 704 clock = mmcclock; 705 host->ios.clock = clock; 706 host->ops->set_ios(host, &host->ios); 707 708 if (card->host->caps & MMC_CAP_4_BIT_DATA) { 709 /* Set bus width & disable card detect resistor */ 710 err = func0_cmd52_write_byte(card, SDIO_CCCR_IF, 711 SDIO_BUS_CD_DISABLE | 712 SDIO_BUS_WIDTH_4BIT); 713 if (err) { 714 hif_err("Set bus mode failed: %d", err); 715 break; 716 } 717 host->ios.bus_width = MMC_BUS_WIDTH_4; 718 host->ops->set_ios(host, &host->ios); 719 } 720 } while (0); 721 722 sdio_release_host(func); 723 724 return (err) ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; 725 } 726