if_sdio.c 15 KB

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