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