1 /* 2 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef EXPORT_SYMTAB 20 #define EXPORT_SYMTAB 21 #endif 22 23 #include <osdep.h> 24 #include <linux/slab.h> 25 #include <linux/interrupt.h> 26 #include <linux/if_arp.h> 27 #include <linux/mmc/card.h> 28 #include <linux/mmc/mmc.h> 29 #include <linux/mmc/host.h> 30 #include <linux/mmc/sdio_func.h> 31 #include <linux/mmc/sdio_ids.h> 32 #include <linux/mmc/sdio.h> 33 #include <linux/mmc/sd.h> 34 #include <linux/wait.h> 35 #include <qdf_mem.h> 36 #include "if_sdio.h" 37 #include <qdf_trace.h> 38 #include <cds_api.h> 39 #include "regtable_sdio.h" 40 #include <hif_debug.h> 41 #include "target_type.h" 42 #include "epping_main.h" 43 #include "pld_sdio.h" 44 #include "targaddrs.h" 45 #include "sdio_api.h" 46 #ifndef REMOVE_PKT_LOG 47 #include "ol_txrx_types.h" 48 #include "pktlog_ac_api.h" 49 #include "pktlog_ac.h" 50 #endif 51 52 #ifndef ATH_BUS_PM 53 #ifdef CONFIG_PM 54 #define ATH_BUS_PM 55 #endif /* CONFIG_PM */ 56 #endif /* ATH_BUS_PM */ 57 58 #ifndef REMOVE_PKT_LOG 59 struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs; 60 #endif 61 #define HIF_SDIO_LOAD_TIMEOUT 1000 62 63 struct hif_sdio_softc *scn; 64 struct hif_softc *ol_sc; 65 static atomic_t hif_sdio_load_state; 66 /* Wait queue for MC thread */ 67 wait_queue_head_t sync_wait_queue; 68 69 /** 70 * hif_sdio_probe() - configure sdio device 71 * @context: sdio device context 72 * @hif_handle: pointer to hif handle 73 * 74 * Return: 0 for success and non-zero for failure 75 */ 76 static A_STATUS hif_sdio_probe(void *context, void *hif_handle) 77 { 78 int ret = 0; 79 struct HIF_DEVICE_OS_DEVICE_INFO os_dev_info; 80 struct sdio_func *func = NULL; 81 const struct sdio_device_id *id; 82 uint32_t target_type; 83 84 HIF_ENTER(); 85 scn = (struct hif_sdio_softc *)qdf_mem_malloc(sizeof(*scn)); 86 if (!scn) { 87 ret = -ENOMEM; 88 goto err_alloc; 89 } 90 91 scn->hif_handle = hif_handle; 92 hif_configure_device(hif_handle, HIF_DEVICE_GET_OS_DEVICE, 93 &os_dev_info, 94 sizeof(os_dev_info)); 95 96 scn->aps_osdev.device = os_dev_info.os_dev; 97 scn->aps_osdev.bc.bc_bustype = QDF_BUS_TYPE_SDIO; 98 spin_lock_init(&scn->target_lock); 99 ol_sc = qdf_mem_malloc(sizeof(*ol_sc)); 100 if (!ol_sc) { 101 ret = -ENOMEM; 102 goto err_attach; 103 } 104 OS_MEMZERO(ol_sc, sizeof(*ol_sc)); 105 106 { 107 /* 108 * Attach Target register table. This is needed early on 109 * even before BMI since PCI and HIF initialization 110 * directly access Target registers. 111 * 112 * TBDXXX: targetdef should not be global -- should be stored 113 * in per-device struct so that we can support multiple 114 * different Target types with a single Host driver. 115 * The whole notion of an "hif type" -- (not as in the hif 116 * module, but generic "Host Interface Type") is bizarre. 117 * At first, one one expect it to be things like SDIO, USB, PCI. 118 * But instead, it's an actual platform type. Inexplicably, the 119 * values used for HIF platform types are *different* from the 120 * values used for Target Types. 121 */ 122 123 #if defined(CONFIG_AR9888_SUPPORT) 124 hif_register_tbl_attach(ol_sc, HIF_TYPE_AR9888); 125 target_register_tbl_attach(ol_sc, TARGET_TYPE_AR9888); 126 target_type = TARGET_TYPE_AR9888; 127 #elif defined(CONFIG_AR6320_SUPPORT) 128 id = ((struct hif_sdio_dev *) hif_handle)->id; 129 if (((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == 130 MANUFACTURER_ID_QCA9377_BASE) || 131 ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == 132 MANUFACTURER_ID_QCA9379_BASE)) { 133 hif_register_tbl_attach(ol_sc, HIF_TYPE_AR6320V2); 134 target_register_tbl_attach(ol_sc, TARGET_TYPE_AR6320V2); 135 } else if ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) == 136 MANUFACTURER_ID_AR6320_BASE) { 137 int ar6kid = id->device & MANUFACTURER_ID_AR6K_REV_MASK; 138 139 if (ar6kid >= 1) { 140 /* v2 or higher silicon */ 141 hif_register_tbl_attach(ol_sc, 142 HIF_TYPE_AR6320V2); 143 target_register_tbl_attach(ol_sc, 144 TARGET_TYPE_AR6320V2); 145 } else { 146 /* legacy v1 silicon */ 147 hif_register_tbl_attach(ol_sc, 148 HIF_TYPE_AR6320); 149 target_register_tbl_attach(ol_sc, 150 TARGET_TYPE_AR6320); 151 } 152 } 153 target_type = TARGET_TYPE_AR6320; 154 155 #endif 156 } 157 func = ((struct hif_sdio_dev *) hif_handle)->func; 158 scn->targetdef = ol_sc->targetdef; 159 scn->hostdef = ol_sc->hostdef; 160 scn->aps_osdev.bdev = func; 161 ol_sc->bus_type = scn->aps_osdev.bc.bc_bustype; 162 scn->ol_sc = *ol_sc; 163 ol_sc->target_info.target_type = target_type; 164 165 scn->ramdump_base = pld_hif_sdio_get_virt_ramdump_mem( 166 scn->aps_osdev.device, 167 &scn->ramdump_size); 168 if (scn->ramdump_base == NULL || !scn->ramdump_size) { 169 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_ERROR, 170 "%s: Failed to get RAM dump memory address or size!\n", 171 __func__); 172 } else { 173 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_INFO, 174 "%s: ramdump base 0x%pK size %d\n", __func__, 175 scn->ramdump_base, (int)scn->ramdump_size); 176 } 177 178 if (athdiag_procfs_init(scn) != 0) { 179 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_ERROR, 180 "%s athdiag_procfs_init failed", __func__); 181 ret = QDF_STATUS_E_FAILURE; 182 goto err_attach1; 183 } 184 185 atomic_set(&hif_sdio_load_state, true); 186 wake_up_interruptible(&sync_wait_queue); 187 188 return 0; 189 190 err_attach1: 191 if (scn->ramdump_base) 192 pld_hif_sdio_release_ramdump_mem(scn->ramdump_base); 193 qdf_mem_free(ol_sc); 194 err_attach: 195 qdf_mem_free(scn); 196 scn = NULL; 197 err_alloc: 198 return ret; 199 } 200 201 /** 202 * hif_sdio_remove() - remove sdio device 203 * @conext: sdio device context 204 * @hif_handle: pointer to sdio function 205 * 206 * Return: 0 for success and non-zero for failure 207 */ 208 static A_STATUS hif_sdio_remove(void *context, void *hif_handle) 209 { 210 HIF_ENTER(); 211 212 if (!scn) { 213 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_ERROR, 214 "Global SDIO context is NULL"); 215 return A_ERROR; 216 } 217 218 atomic_set(&hif_sdio_load_state, false); 219 athdiag_procfs_remove(); 220 221 #ifndef TARGET_DUMP_FOR_NON_QC_PLATFORM 222 iounmap(scn->ramdump_base); 223 #endif 224 225 if (ol_sc) { 226 qdf_mem_free(ol_sc); 227 ol_sc = NULL; 228 } 229 230 if (scn) { 231 qdf_mem_free(scn); 232 scn = NULL; 233 } 234 235 HIF_EXIT(); 236 237 return 0; 238 } 239 240 /** 241 * hif_sdio_suspend() - sdio suspend routine 242 * @context: sdio device context 243 * 244 * Return: 0 for success and non-zero for failure 245 */ 246 static A_STATUS hif_sdio_suspend(void *context) 247 { 248 return 0; 249 } 250 251 /** 252 * hif_sdio_resume() - sdio resume routine 253 * @context: sdio device context 254 * 255 * Return: 0 for success and non-zero for failure 256 */ 257 static A_STATUS hif_sdio_resume(void *context) 258 { 259 return 0; 260 } 261 262 /** 263 * hif_sdio_power_change() - change power state of sdio bus 264 * @conext: sdio device context 265 * @config: power state configurartion 266 * 267 * Return: 0 for success and non-zero for failure 268 */ 269 static A_STATUS hif_sdio_power_change(void *context, uint32_t config) 270 { 271 return 0; 272 } 273 274 /* 275 * Module glue. 276 */ 277 #include <linux/version.h> 278 static char *version = "HIF (Atheros/multi-bss)"; 279 static char *dev_info = "ath_hif_sdio"; 280 281 /** 282 * init_ath_hif_sdio() - initialize hif sdio callbacks 283 * @param: none 284 * 285 * Return: 0 for success and non-zero for failure 286 */ 287 static int init_ath_hif_sdio(void) 288 { 289 QDF_STATUS status; 290 struct osdrv_callbacks osdrv_callbacks; 291 292 HIF_ENTER(); 293 qdf_mem_zero(&osdrv_callbacks, sizeof(osdrv_callbacks)); 294 osdrv_callbacks.device_inserted_handler = hif_sdio_probe; 295 osdrv_callbacks.device_removed_handler = hif_sdio_remove; 296 osdrv_callbacks.device_suspend_handler = hif_sdio_suspend; 297 osdrv_callbacks.device_resume_handler = hif_sdio_resume; 298 osdrv_callbacks.device_power_change_handler = hif_sdio_power_change; 299 300 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_INFO, "%s %d", __func__, 301 __LINE__); 302 status = hif_init(&osdrv_callbacks); 303 if (status != QDF_STATUS_SUCCESS) { 304 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_FATAL, 305 "%s hif_init failed!", __func__); 306 return -ENODEV; 307 } 308 QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_ERROR, 309 "%s: %s\n", dev_info, version); 310 311 return 0; 312 } 313 314 /** 315 * hif_sdio_bus_suspend() - suspend the bus 316 * 317 * This function suspends the bus, but sdio doesn't need to suspend. 318 * Therefore do nothing. 319 * 320 * Return: 0 for success and non-zero for failure 321 */ 322 int hif_sdio_bus_suspend(struct hif_softc *hif_ctx) 323 { 324 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 325 struct hif_sdio_dev *hif_device = scn->hif_handle; 326 struct device *dev = &hif_device->func->dev; 327 328 hif_device_suspend(dev); 329 return 0; 330 } 331 332 333 /** 334 * hif_sdio_bus_resume() - hif resume API 335 * 336 * This function resumes the bus. but sdio doesn't need to resume. 337 * Therefore do nothing. 338 * 339 * Return: 0 for success and non-zero for failure 340 */ 341 int hif_sdio_bus_resume(struct hif_softc *hif_ctx) 342 { 343 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 344 struct hif_sdio_dev *hif_device = scn->hif_handle; 345 struct device *dev = &hif_device->func->dev; 346 347 hif_device_resume(dev); 348 return 0; 349 } 350 351 /** 352 * hif_enable_power_gating() - enable HW power gating 353 * 354 * Return: n/a 355 */ 356 void hif_enable_power_gating(void *hif_ctx) 357 { 358 } 359 360 /** 361 * hif_sdio_close() - hif_bus_close 362 * 363 * Return: None 364 */ 365 void hif_sdio_close(struct hif_softc *hif_sc) 366 { 367 if (ol_sc) { 368 qdf_mem_free(ol_sc); 369 ol_sc = NULL; 370 } 371 372 if (scn) { 373 qdf_mem_free(scn); 374 scn = NULL; 375 } 376 } 377 378 /** 379 * hif_sdio_open() - hif_bus_open 380 * @hif_sc: hif context 381 * @bus_type: bus type 382 * 383 * Return: QDF status 384 */ 385 QDF_STATUS hif_sdio_open(struct hif_softc *hif_sc, 386 enum qdf_bus_type bus_type) 387 { 388 QDF_STATUS status; 389 390 hif_sc->bus_type = bus_type; 391 status = init_ath_hif_sdio(); 392 393 return status; 394 } 395 396 void hif_get_target_revision(struct hif_softc *ol_sc) 397 { 398 struct hif_softc *ol_sc_local = (struct hif_softc *)ol_sc; 399 struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc_local); 400 uint32_t chip_id = 0; 401 QDF_STATUS rv; 402 403 rv = hif_diag_read_access(hif_hdl, 404 (CHIP_ID_ADDRESS | RTC_SOC_BASE_ADDRESS), &chip_id); 405 if (rv != QDF_STATUS_SUCCESS) { 406 HIF_ERROR("%s[%d]: get chip id fail\n", __func__, __LINE__); 407 } else { 408 ol_sc_local->target_info.target_revision = 409 CHIP_ID_REVISION_GET(chip_id); 410 } 411 } 412 413 /** 414 * hif_sdio_enable_bus() - hif_enable_bus 415 * @hif_sc: hif context 416 * @dev: dev 417 * @bdev: bus dev 418 * @bid: bus id 419 * @type: bus type 420 * 421 * Return: QDF_STATUS 422 */ 423 QDF_STATUS hif_sdio_enable_bus(struct hif_softc *hif_sc, 424 struct device *dev, void *bdev, const struct hif_bus_id *bid, 425 enum hif_enable_type type) 426 { 427 int ret = 0; 428 const struct sdio_device_id *id = (const struct sdio_device_id *)bid; 429 struct hif_sdio_softc *sc = HIF_GET_SDIO_SOFTC(hif_sc); 430 431 init_waitqueue_head(&sync_wait_queue); 432 if (hif_sdio_device_inserted(dev, id)) { 433 HIF_ERROR("wlan: %s hif_sdio_device_inserted failed", __func__); 434 return QDF_STATUS_E_NOMEM; 435 } 436 437 wait_event_interruptible_timeout(sync_wait_queue, 438 atomic_read(&hif_sdio_load_state) == true, 439 HIF_SDIO_LOAD_TIMEOUT); 440 hif_sc->hostdef = ol_sc->hostdef; 441 hif_sc->targetdef = ol_sc->targetdef; 442 hif_sc->bus_type = ol_sc->bus_type; 443 hif_sc->target_info.target_type = ol_sc->target_info.target_type; 444 445 sc->hif_handle = scn->hif_handle; 446 sc->aps_osdev.device = scn->aps_osdev.device; 447 sc->aps_osdev.bc.bc_bustype = scn->aps_osdev.bc.bc_bustype; 448 sc->target_lock = scn->target_lock; 449 sc->targetdef = scn->targetdef; 450 sc->hostdef = scn->hostdef; 451 sc->aps_osdev.bdev = scn->aps_osdev.bdev; 452 sc->ramdump_size = scn->ramdump_size; 453 sc->ramdump_base = scn->ramdump_base; 454 455 return ret; 456 } 457 458 459 /** 460 * hif_sdio_disable_bus() - sdio disable bus 461 * @hif_sc: hif softc pointer 462 * 463 * Return: none 464 */ 465 void hif_sdio_disable_bus(struct hif_softc *hif_sc) 466 { 467 struct hif_sdio_softc *sc = HIF_GET_SDIO_SOFTC(hif_sc); 468 struct sdio_func *func = sc->aps_osdev.bdev; 469 470 hif_sdio_device_removed(func); 471 } 472 473 /** 474 * hif_sdio_get_config_item - sdio configure bus 475 * @hif_sc: hif context 476 * @opcode: configuration type 477 * @config: configuration value to set 478 * @config_len: configuration length 479 * 480 * Return: QDF_STATUS_SUCCESS for success 481 */ 482 QDF_STATUS hif_sdio_get_config_item(struct hif_softc *hif_sc, 483 int opcode, void *config, uint32_t config_len) 484 { 485 struct hif_sdio_softc *sc = HIF_GET_SDIO_SOFTC(hif_sc); 486 struct hif_sdio_dev *hif_device = sc->hif_handle; 487 488 return hif_configure_device(hif_device, 489 opcode, config, config_len); 490 } 491 492 /** 493 * hif_sdio_set_mailbox_swap - set mailbox swap 494 * @hif_sc: hif context 495 * 496 * Return: None 497 */ 498 void hif_sdio_set_mailbox_swap(struct hif_softc *hif_sc) 499 { 500 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_sc); 501 struct hif_sdio_dev *hif_device = scn->hif_handle; 502 503 hif_device->swap_mailbox = true; 504 } 505 506 /** 507 * hif_sdio_claim_device - set mailbox swap 508 * @hif_sc: hif context 509 * 510 * Return: None 511 */ 512 void hif_sdio_claim_device(struct hif_softc *hif_sc) 513 { 514 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_sc); 515 struct hif_sdio_dev *hif_device = scn->hif_handle; 516 517 hif_device->claimed_ctx = hif_sc; 518 } 519 520 /** 521 * hif_sdio_mask_interrupt_call() - disbale hif device irq 522 * @scn: pointr to softc structure 523 * 524 * Return: None 525 */ 526 void hif_sdio_mask_interrupt_call(struct hif_softc *scn) 527 { 528 struct hif_sdio_softc *hif_ctx = HIF_GET_SDIO_SOFTC(scn); 529 struct hif_sdio_dev *hif_device = hif_ctx->hif_handle; 530 531 hif_mask_interrupt(hif_device); 532 } 533 534 /** 535 * hif_trigger_dump() - trigger various dump cmd 536 * @scn: struct hif_opaque_softc 537 * @cmd_id: dump command id 538 * @start: start/stop dump 539 * 540 * Return: None 541 */ 542 void hif_trigger_dump(struct hif_opaque_softc *scn, uint8_t cmd_id, bool start) 543 { 544 } 545 546 /** 547 * hif_check_fw_reg() - check fw selfrecovery indication 548 * @hif_ctx: hif_opaque_softc 549 * 550 * Return: int 551 */ 552 int hif_check_fw_reg(struct hif_opaque_softc *hif_ctx) 553 { 554 int ret = 1; 555 uint32_t fw_indication = 0; 556 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 557 558 if (hif_diag_read_access(hif_ctx, FW_INDICATOR_ADDRESS, 559 &fw_indication) != QDF_STATUS_SUCCESS) { 560 HIF_ERROR("%s Get fw indication failed\n", __func__); 561 return 1; 562 } 563 HIF_INFO("%s: fw indication is 0x%x def 0x%x.\n", __func__, 564 fw_indication, FW_IND_HELPER); 565 if (fw_indication & FW_IND_HELPER) 566 ret = 0; 567 568 return ret; 569 } 570 571 /** 572 * hif_wlan_disable() - call the platform driver to disable wlan 573 * @scn: scn 574 * 575 * Return: void 576 */ 577 void hif_wlan_disable(struct hif_softc *scn) 578 { 579 } 580 581 /** 582 * hif_sdio_needs_bmi() - return true if the soc needs bmi through the driver 583 * @scn: hif context 584 * 585 * Return: true if soc needs driver bmi otherwise false 586 */ 587 bool hif_sdio_needs_bmi(struct hif_softc *scn) 588 { 589 return true; 590 } 591