blob: 61c57abfb1d6e21f0a0a988be20302e906442ccb [file] [log] [blame]
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001/*
Houston Hoffmancceec342015-11-11 11:37:20 -08002 * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08003 *
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#include <osdep.h>
29#include "a_types.h"
30#include "athdefs.h"
31#include "osapi_linux.h"
32#include "targcfg.h"
33#include "cdf_lock.h"
34#include "cdf_status.h"
35#include <cdf_atomic.h> /* cdf_atomic_read */
36#include <targaddrs.h>
37#include <bmi_msg.h>
38#include "hif_io32.h"
39#include <hif.h>
40#include <htc_services.h>
41#include "regtable.h"
42#define ATH_MODULE_NAME hif
43#include <a_debug.h>
44#include "hif_main.h"
45#include "hif_hw_version.h"
46#include "ce_api.h"
47#include "ce_tasklet.h"
48#include "cdf_trace.h"
49#include "cdf_status.h"
50#include "cds_api.h"
51#ifdef CONFIG_CNSS
52#include <net/cnss.h>
53#endif
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080054#include "epping_main.h"
55#include "hif_debug.h"
56#include "mp_dev.h"
57#ifdef HIF_PCI
58#include "icnss_stub.h"
59#else
60#include <soc/qcom/icnss.h>
61#endif
62
Chandrasekaran, Manishekar681d1372015-11-05 10:42:48 +053063#include "cds_concurrency.h"
64
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080065#define AGC_DUMP 1
66#define CHANINFO_DUMP 2
67#define BB_WATCHDOG_DUMP 3
68#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
69#define PCIE_ACCESS_DUMP 4
70#endif
71
72void hif_dump(struct ol_softc *scn, uint8_t cmd_id, bool start)
73{
74 switch (cmd_id) {
75 case AGC_DUMP:
76 if (start)
77 priv_start_agc(scn);
78 else
79 priv_dump_agc(scn);
80 break;
81
82 case CHANINFO_DUMP:
83 if (start)
84 priv_start_cap_chaninfo(scn);
85 else
86 priv_dump_chaninfo(scn);
87 break;
88
89 case BB_WATCHDOG_DUMP:
90 priv_dump_bbwatchdog(scn);
91 break;
92
93#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
94 case PCIE_ACCESS_DUMP:
95 hif_target_dump_access_log();
96 break;
97#endif
98 default:
99 HIF_ERROR("%s: Invalid htc dump command", __func__);
100 break;
101 }
102}
103
104/**
105 * hif_shut_down_device() - hif_shut_down_device
106 *
107 * SThis fucntion shuts down the device
108 *
109 * @scn: ol_softc
110 *
111 * Return: void
112 */
113void hif_shut_down_device(struct ol_softc *scn)
114{
115 if (scn && scn->hif_hdl) {
116 struct HIF_CE_state *hif_state =
117 (struct HIF_CE_state *)scn->hif_hdl;
118
119 hif_stop(scn);
120 cdf_mem_free(hif_state);
121 scn->hif_hdl = NULL;
122 }
123
124}
125
126
127
128/**
129 * hif_cancel_deferred_target_sleep() - cancel deferred target sleep
130 *
131 * This function cancels the defered target sleep
132 *
133 * @scn: ol_softc
134 *
135 * Return: void
136 */
137void hif_cancel_deferred_target_sleep(struct ol_softc *scn)
138{
139 hif_pci_cancel_deferred_target_sleep(scn);
140}
141
142/**
143 * hif_get_target_id(): hif_get_target_id
144 *
145 * Return the virtual memory base address to the caller
146 *
147 * @scn: ol_softc
148 *
149 * Return: A_target_id_t
150 */
151A_target_id_t hif_get_target_id(struct ol_softc *scn)
152{
153 return scn->mem;
154}
155
156/**
157 * hif_set_target_sleep(): hif_set_target_sleep
158 * @scn: scn
159 * @sleep_ok: sleep_ok
160 * @wait_for_it: wait
161 *
162 * Return: void
163 */
164void hif_set_target_sleep(struct ol_softc *scn,
165 bool sleep_ok, bool wait_for_it)
166{
167 hif_target_sleep_state_adjust(scn,
168 sleep_ok, wait_for_it);
169}
170
171/**
172 * hif_target_forced_awake(): hif_target_forced_awake
173 * @scn: scn
174 *
175 * Return: bool
176 */
177bool hif_target_forced_awake(struct ol_softc *scn)
178{
179 A_target_id_t addr = scn->mem;
180 bool awake;
181 bool forced_awake;
182
183 awake = hif_targ_is_awake(scn, addr);
184
185 forced_awake =
186 !!(hif_read32_mb
187 (addr + PCIE_LOCAL_BASE_ADDRESS +
188 PCIE_SOC_WAKE_ADDRESS) & PCIE_SOC_WAKE_V_MASK);
189
190 return awake && forced_awake;
191}
192
Houston Hoffman0dad5092015-09-28 16:25:51 -0700193
194static inline void hif_fw_event_handler(struct HIF_CE_state *hif_state)
195{
196 struct hif_msg_callbacks *msg_callbacks =
197 &hif_state->msg_callbacks_current;
198
199 if (!msg_callbacks->fwEventHandler)
200 return;
201
202 msg_callbacks->fwEventHandler(msg_callbacks->Context,
203 CDF_STATUS_E_FAILURE);
204}
205
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800206/**
207 * hif_fw_interrupt_handler(): FW interrupt handler
208 *
209 * This function is the FW interrupt handlder
210 *
211 * @irq: irq number
212 * @arg: the user pointer
213 *
214 * Return: bool
215 */
216#ifndef QCA_WIFI_3_0
217irqreturn_t hif_fw_interrupt_handler(int irq, void *arg)
218{
219 struct ol_softc *scn = arg;
220 struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl;
221 uint32_t fw_indicator_address, fw_indicator;
222
223 A_TARGET_ACCESS_BEGIN_RET(scn);
224
225 fw_indicator_address = hif_state->fw_indicator_address;
226 /* For sudden unplug this will return ~0 */
227 fw_indicator = A_TARGET_READ(scn, fw_indicator_address);
228
229 if ((fw_indicator != ~0) && (fw_indicator & FW_IND_EVENT_PENDING)) {
230 /* ACK: clear Target-side pending event */
231 A_TARGET_WRITE(scn, fw_indicator_address,
232 fw_indicator & ~FW_IND_EVENT_PENDING);
233 A_TARGET_ACCESS_END_RET(scn);
234
235 if (hif_state->started) {
Houston Hoffman0dad5092015-09-28 16:25:51 -0700236 hif_fw_event_handler(hif_state);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800237 } else {
238 /*
239 * Probable Target failure before we're prepared
240 * to handle it. Generally unexpected.
241 */
242 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
243 ("%s: Early firmware event indicated\n",
244 __func__));
245 }
246 } else {
247 A_TARGET_ACCESS_END_RET(scn);
248 }
249
250 return ATH_ISR_SCHED;
251}
252#else
253irqreturn_t hif_fw_interrupt_handler(int irq, void *arg)
254{
255 return ATH_ISR_SCHED;
256}
257#endif /* #ifdef QCA_WIFI_3_0 */
258
259/**
260 * hif_get_targetdef(): hif_get_targetdef
261 * @scn: scn
262 *
263 * Return: void *
264 */
265void *hif_get_targetdef(struct ol_softc *scn)
266{
267 return scn->targetdef;
268}
269
270/**
271 * hif_vote_link_down(): unvote for link up
272 *
273 * Call hif_vote_link_down to release a previous request made using
274 * hif_vote_link_up. A hif_vote_link_down call should only be made
275 * after a corresponding hif_vote_link_up, otherwise you could be
276 * negating a vote from another source. When no votes are present
277 * hif will not guarantee the linkstate after hif_bus_suspend.
278 *
279 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
280 * and initialization deinitialization sequencences.
281 *
282 * Return: n/a
283 */
284void hif_vote_link_down(void)
285{
286 struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF);
287 CDF_BUG(scn);
288
289 scn->linkstate_vote--;
290 if (scn->linkstate_vote == 0)
Houston Hoffmancceec342015-11-11 11:37:20 -0800291 hif_bus_prevent_linkdown(scn, false);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800292}
293
294/**
295 * hif_vote_link_up(): vote to prevent bus from suspending
296 *
297 * Makes hif guarantee that fw can message the host normally
298 * durring suspend.
299 *
300 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
301 * and initialization deinitialization sequencences.
302 *
303 * Return: n/a
304 */
305void hif_vote_link_up(void)
306{
307 struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF);
308 CDF_BUG(scn);
309
310 scn->linkstate_vote++;
311 if (scn->linkstate_vote == 1)
Houston Hoffmancceec342015-11-11 11:37:20 -0800312 hif_bus_prevent_linkdown(scn, true);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800313}
314
315/**
316 * hif_can_suspend_link(): query if hif is permitted to suspend the link
317 *
318 * Hif will ensure that the link won't be suspended if the upperlayers
319 * don't want it to.
320 *
321 * SYNCHRONIZATION: MC thread is stopped before bus suspend thus
322 * we don't need extra locking to ensure votes dont change while
323 * we are in the process of suspending or resuming.
324 *
325 * Return: false if hif will guarantee link up durring suspend.
326 */
327bool hif_can_suspend_link(void)
328{
329 struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF);
330 CDF_BUG(scn);
331
332 return scn->linkstate_vote == 0;
333}
334
335/**
336 * hif_hia_item_address(): hif_hia_item_address
337 * @target_type: target_type
338 * @item_offset: item_offset
339 *
340 * Return: n/a
341 */
342uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset)
343{
344 switch (target_type) {
345 case TARGET_TYPE_AR6002:
346 return AR6002_HOST_INTEREST_ADDRESS + item_offset;
347 case TARGET_TYPE_AR6003:
348 return AR6003_HOST_INTEREST_ADDRESS + item_offset;
349 case TARGET_TYPE_AR6004:
350 return AR6004_HOST_INTEREST_ADDRESS + item_offset;
351 case TARGET_TYPE_AR6006:
352 return AR6006_HOST_INTEREST_ADDRESS + item_offset;
353 case TARGET_TYPE_AR9888:
354 return AR9888_HOST_INTEREST_ADDRESS + item_offset;
355 case TARGET_TYPE_AR6320:
356 case TARGET_TYPE_AR6320V2:
357 return AR6320_HOST_INTEREST_ADDRESS + item_offset;
358 case TARGET_TYPE_QCA6180:
359 return QCA6180_HOST_INTEREST_ADDRESS + item_offset;
360 case TARGET_TYPE_ADRASTEA:
361 /* ADRASTEA doesn't have a host interest address */
362 ASSERT(0);
363 return 0;
364 default:
365 ASSERT(0);
366 return 0;
367 }
368}
369
370/**
371 * hif_max_num_receives_reached() - check max receive is reached
372 * @count: unsigned int.
373 *
374 * Output check status as bool
375 *
376 * Return: bool
377 */
378bool hif_max_num_receives_reached(unsigned int count)
379{
380 if (WLAN_IS_EPPING_ENABLED(cds_get_conparam()))
381 return count > 120;
382 else
383 return count > MAX_NUM_OF_RECEIVES;
384}
385
386/**
387 * init_buffer_count() - initial buffer count
388 * @maxSize: cdf_size_t
389 *
390 * routine to modify the initial buffer count to be allocated on an os
391 * platform basis. Platform owner will need to modify this as needed
392 *
393 * Return: cdf_size_t
394 */
395cdf_size_t init_buffer_count(cdf_size_t maxSize)
396{
397 return maxSize;
398}
399
400/**
401 * hif_init_cdf_ctx(): hif_init_cdf_ctx
402 * @hif_ctx: hif_ctx
403 *
404 * Return: int
405 */
406int hif_init_cdf_ctx(void *hif_ctx)
407{
408 cdf_device_t cdf_ctx;
409 struct ol_softc *scn = (struct ol_softc *)hif_ctx;
410
411 cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE);
412 if (!cdf_ctx) {
413 HIF_ERROR("%s: CDF is NULL", __func__);
414 return -ENOMEM;
415 }
416
417 cdf_ctx->drv = &scn->aps_osdev;
418 cdf_ctx->drv_hdl = scn->aps_osdev.bdev;
419 cdf_ctx->dev = scn->aps_osdev.device;
420 scn->cdf_dev = cdf_ctx;
421 return 0;
422}
423
424/**
425 * hif_deinit_cdf_ctx(): hif_deinit_cdf_ctx
426 * @hif_ctx: hif_ctx
427 *
428 * Return: void
429 */
430void hif_deinit_cdf_ctx(void *hif_ctx)
431{
432 struct ol_softc *scn = (struct ol_softc *)hif_ctx;
433
434 if (scn == NULL || !scn->cdf_dev)
435 return;
436 scn->cdf_dev = NULL;
437}
438
439/**
440 * hif_save_htc_htt_config_endpoint():
441 * hif_save_htc_htt_config_endpoint
442 * @htc_endpoint: htc_endpoint
443 *
444 * Return: void
445 */
446void hif_save_htc_htt_config_endpoint(int htc_endpoint)
447{
448 struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF);
449
450 if (!scn) {
451 HIF_ERROR("%s: error: scn or scn->hif_sc is NULL!",
452 __func__);
453 return;
454 }
455
456 scn->htc_endpoint = htc_endpoint;
457}
458
459/**
460 * hif_get_hw_name(): get a human readable name for the hardware
Komal Seelam91553ce2016-01-27 18:57:10 +0530461 * @info: Target Info
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800462 *
Komal Seelam91553ce2016-01-27 18:57:10 +0530463 * Return: human readable name for the underlying wifi hardware.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800464 */
Komal Seelam91553ce2016-01-27 18:57:10 +0530465static const char *hif_get_hw_name(struct hif_target_info *info)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800466{
467 int i;
Komal Seelam91553ce2016-01-27 18:57:10 +0530468
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800469 for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) {
Komal Seelam91553ce2016-01-27 18:57:10 +0530470 if (info->target_version == qwlan_hw_list[i].id &&
471 info->target_revision == qwlan_hw_list[i].subid) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800472 return qwlan_hw_list[i].name;
473 }
474 }
475
476 return "Unknown Device";
477}
478
479/**
480 * hif_get_hw_info(): hif_get_hw_info
481 * @scn: scn
482 * @version: version
483 * @revision: revision
484 *
485 * Return: n/a
486 */
Komal Seelam91553ce2016-01-27 18:57:10 +0530487void hif_get_hw_info(struct ol_softc *scn, u32 *version, u32 *revision,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800488 const char **target_name)
489{
Komal Seelam91553ce2016-01-27 18:57:10 +0530490 struct hif_target_info *info = hif_get_target_info_handle(scn);
491 *version = info->target_version;
492 *revision = info->target_revision;
493 *target_name = hif_get_hw_name(info);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800494}
495
496/**
497 * hif_open(): hif_open
498 *
499 * Return: scn
500 */
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800501CDF_STATUS hif_open(enum ath_hal_bus_type bus_type)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800502{
503 struct ol_softc *scn;
504 v_CONTEXT_t cds_context;
505 CDF_STATUS status = CDF_STATUS_SUCCESS;
Komal Seelam91553ce2016-01-27 18:57:10 +0530506 struct hif_config_info *cfg;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800507
508 cds_context = cds_get_global_context();
509 status = cds_alloc_context(cds_context, CDF_MODULE_ID_HIF,
510 (void **)&scn, sizeof(*scn));
511 if (status != CDF_STATUS_SUCCESS) {
512 HIF_ERROR("%s: cannot alloc ol_sc", __func__);
513 return status;
514 }
515
516 cdf_mem_zero(scn, sizeof(*scn));
Komal Seelam91553ce2016-01-27 18:57:10 +0530517 cfg = hif_get_ini_handle(scn);
518 cfg->max_no_of_peers = 1;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800519 cdf_atomic_init(&scn->wow_done);
520 cdf_atomic_init(&scn->active_tasklet_cnt);
521 cdf_atomic_init(&scn->link_suspended);
522 cdf_atomic_init(&scn->tasklet_from_intr);
523 init_waitqueue_head(&scn->aps_osdev.event_queue);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800524 scn->linkstate_vote = 0;
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800525
526 status = hif_bus_open(scn, bus_type);
527 if (status != CDF_STATUS_SUCCESS) {
528 HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d",
529 __func__, status, bus_type);
530 cds_free_context(cds_context, CDF_MODULE_ID_HIF, scn);
531 }
532
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800533 return status;
534}
535
536/**
537 * hif_close(): hif_close
538 * @hif_ctx: hif_ctx
539 *
540 * Return: n/a
541 */
542void hif_close(void *hif_ctx)
543{
544 struct ol_softc *scn = hif_ctx;
545
546 if (scn == NULL) {
547 HIF_ERROR("%s: ol_softc is NULL", __func__);
548 return;
549 }
550
551 if (scn->athdiag_procfs_inited) {
552 athdiag_procfs_remove();
553 scn->athdiag_procfs_inited = false;
554 }
555
556 if (scn->hif_hdl) {
557 cdf_mem_free(scn->hif_hdl);
558 scn->hif_hdl = NULL;
559 }
560 hif_bus_close(scn);
561 cds_free_context(cds_get_global_context(),
562 CDF_MODULE_ID_HIF, hif_ctx);
563}
564
565/**
566 * hif_enable(): hif_enable
567 * @hif_ctx: hif_ctx
568 * @dev: dev
569 * @bdev: bus dev
570 * @bid: bus ID
571 * @bus_type: bus type
572 * @type: enable type
573 *
574 * Return: CDF_STATUS
575 */
576CDF_STATUS hif_enable(void *hif_ctx, struct device *dev,
577 void *bdev, const hif_bus_id *bid,
578 enum ath_hal_bus_type bus_type,
579 enum hif_enable_type type)
580{
581 CDF_STATUS status;
582 struct ol_softc *scn = hif_ctx;
583
584 if (scn == NULL) {
585 HIF_ERROR("%s: hif_ctx = NULL", __func__);
586 return CDF_STATUS_E_NULL_VALUE;
587 }
588
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800589 status = hif_enable_bus(scn, dev, bdev, bid, type);
590 if (status != CDF_STATUS_SUCCESS) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800591 HIF_ERROR("%s: hif_enable_bus error = %d",
592 __func__, status);
593 return status;
594 }
595
596 if (ADRASTEA_BU)
597 hif_vote_link_up();
598
599 if (hif_config_ce(scn)) {
600 HIF_ERROR("%s: Target probe failed.", __func__);
601 hif_disable_bus(scn->aps_osdev.bdev);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800602 status = CDF_STATUS_E_FAILURE;
603 return status;
604 }
605 /*
606 * Flag to avoid potential unallocated memory access from MSI
607 * interrupt handler which could get scheduled as soon as MSI
608 * is enabled, i.e to take care of the race due to the order
609 * in where MSI is enabled before the memory, that will be
610 * in interrupt handlers, is allocated.
611 */
612
613#ifdef HIF_PCI
614 status = hif_configure_irq(scn->hif_sc);
615 if (status < 0) {
616 HIF_ERROR("%s: ERROR - configure_IRQ_and_CE failed, status = %d",
617 __func__, status);
618 return CDF_STATUS_E_FAILURE;
619 }
620#endif
621
622 scn->hif_init_done = true;
623
624 HIF_TRACE("%s: X OK", __func__);
625
626 return CDF_STATUS_SUCCESS;
627}
628
629/**
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800630 * hif_wlan_disable(): call the platform driver to disable wlan
631 *
632 * This function passes the con_mode to platform driver to disable
633 * wlan.
634 *
635 * Return: void
636 */
637void hif_wlan_disable(void)
638{
639 enum icnss_driver_mode mode;
640 uint32_t con_mode = cds_get_conparam();
641
Peng Xu7b962532015-10-02 17:17:03 -0700642 if (CDF_GLOBAL_FTM_MODE == con_mode)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800643 mode = ICNSS_FTM;
Peng Xu7b962532015-10-02 17:17:03 -0700644 else if (WLAN_IS_EPPING_ENABLED(cds_get_conparam()))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800645 mode = ICNSS_EPPING;
Peng Xu7b962532015-10-02 17:17:03 -0700646 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800647 mode = ICNSS_MISSION;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800648
649 icnss_wlan_disable(mode);
650}
651
652void hif_disable(void *hif_ctx, enum hif_disable_type type)
653{
654 struct ol_softc *scn = hif_ctx;
655
656 if (!scn)
657 return;
658
659 hif_nointrs(scn);
660 if (scn->hif_init_done == false)
661 hif_shut_down_device(scn);
662 else
663 hif_stop(scn);
664
665 if (ADRASTEA_BU)
666 hif_vote_link_down();
667
668 if (scn->aps_osdev.bdev)
669 hif_disable_bus(scn->aps_osdev.bdev);
670
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800671 hif_wlan_disable();
672
673 scn->notice_send = false;
674
675 HIF_INFO("%s: X", __func__);
676}
677
678
679/**
Govind Singh2443fb32016-01-13 17:44:48 +0530680 * hif_crash_shutdown_dump_bus_register() - dump bus registers
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800681 * @hif_ctx: hif_ctx
682 *
683 * Return: n/a
684 */
685#if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) \
686&& defined(HIF_PCI) && defined(DEBUG)
687
Govind Singh2443fb32016-01-13 17:44:48 +0530688static void hif_crash_shutdown_dump_bus_register(void *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800689{
690 struct ol_softc *scn = hif_ctx;
691
Govind Singh2443fb32016-01-13 17:44:48 +0530692 if (hif_check_soc_status(scn))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800693 return;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800694
Govind Singh2443fb32016-01-13 17:44:48 +0530695 if (hif_dump_registers(scn))
696 HIF_ERROR("Failed to dump bus registers!");
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800697}
698
699/**
700 * hif_crash_shutdown(): hif_crash_shutdown
701 *
702 * This function is called by the platform driver to dump CE registers
703 *
704 * @hif_ctx: hif_ctx
705 *
706 * Return: n/a
707 */
708void hif_crash_shutdown(void *hif_ctx)
709{
710 struct ol_softc *scn = hif_ctx;
711 struct HIF_CE_state *hif_state;
712
713 if (!scn)
714 return;
715
716 hif_state = (struct HIF_CE_state *)scn->hif_hdl;
717 if (!hif_state)
718 return;
719
720
721 if (OL_TRGET_STATUS_RESET == scn->target_status) {
722 HIF_INFO_MED("%s: Target is already asserted, ignore!",
723 __func__);
724 return;
725 }
726
Rajeev Kumare3b4b4b2016-01-19 15:23:52 -0800727 if (cds_is_load_or_unload_in_progress()) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800728 HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__);
729 return;
730 }
731
Govind Singh2443fb32016-01-13 17:44:48 +0530732 hif_crash_shutdown_dump_bus_register(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800733
734 if (ol_copy_ramdump(scn))
735 goto out;
736
737 HIF_INFO_MED("%s: RAM dump collecting completed!", __func__);
738
739out:
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800740 return;
741}
742#else
743void hif_crash_shutdown(void *hif_ctx)
744{
745 HIF_INFO_MED("%s: Collecting target RAM dump disabled",
746 __func__);
747 return;
748}
749#endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */
750
751#ifdef QCA_WIFI_3_0
752/**
753 * hif_check_fw_reg(): hif_check_fw_reg
754 * @scn: scn
755 * @state:
756 *
757 * Return: int
758 */
759int hif_check_fw_reg(struct ol_softc *scn)
760{
761 return 0;
762}
763#endif
764
765#ifdef IPA_OFFLOAD
766/**
767 * hif_read_phy_mem_base(): hif_read_phy_mem_base
768 * @scn: scn
769 * @phy_mem_base: physical mem base
770 *
771 * Return: n/a
772 */
773void hif_read_phy_mem_base(struct ol_softc *scn, cdf_dma_addr_t *phy_mem_base)
774{
775 *phy_mem_base = scn->mem_pa;
776}
777#endif /* IPA_OFFLOAD */
778
779/**
780 * hif_get_device_type(): hif_get_device_type
781 * @device_id: device_id
782 * @revision_id: revision_id
783 * @hif_type: returned hif_type
784 * @target_type: returned target_type
785 *
786 * Return: int
787 */
788int hif_get_device_type(uint32_t device_id,
789 uint32_t revision_id,
790 uint32_t *hif_type, uint32_t *target_type)
791{
792 int ret = 0;
793
794 switch (device_id) {
795#ifdef QCA_WIFI_3_0_ADRASTEA
796 case ADRASTEA_DEVICE_ID:
797 case ADRASTEA_DEVICE_ID_P2_E12:
798
799 *hif_type = HIF_TYPE_ADRASTEA;
800 *target_type = TARGET_TYPE_ADRASTEA;
801 break;
802#else
803 case QCA6180_DEVICE_ID:
804 *hif_type = HIF_TYPE_QCA6180;
805 *target_type = TARGET_TYPE_QCA6180;
806 break;
807#endif
808
809 case AR9888_DEVICE_ID:
810 *hif_type = HIF_TYPE_AR9888;
811 *target_type = TARGET_TYPE_AR9888;
812 break;
813
814 case AR6320_DEVICE_ID:
815 switch (revision_id) {
816 case AR6320_FW_1_1:
817 case AR6320_FW_1_3:
818 *hif_type = HIF_TYPE_AR6320;
819 *target_type = TARGET_TYPE_AR6320;
820 break;
821
822 case AR6320_FW_2_0:
823 case AR6320_FW_3_0:
824 case AR6320_FW_3_2:
825 *hif_type = HIF_TYPE_AR6320V2;
826 *target_type = TARGET_TYPE_AR6320V2;
827 break;
828
829 default:
830 HIF_ERROR("%s: error - dev_id = 0x%x, rev_id = 0x%x",
831 __func__, device_id, revision_id);
832 ret = -ENODEV;
833 goto end;
834 }
835 break;
836
837 default:
838 HIF_ERROR("%s: Unsupported device ID!", __func__);
839 ret = -ENODEV;
840 break;
841 }
842end:
843 return ret;
844}
Komal Seelam91553ce2016-01-27 18:57:10 +0530845
846/**
847 * Target info and ini parameters are global to the driver
848 * Hence these structures are exposed to all the modules in
849 * the driver and they don't need to maintains multiple copies
850 * of the same info, instead get the handle from hif and
851 * modify them in hif
852 */
853
854/**
855 * hif_get_ini_handle() - API to get hif_config_param handle
856 * @scn: HIF Context
857 *
858 * Return: pointer to hif_config_info
859 */
860struct hif_config_info *hif_get_ini_handle(struct ol_softc *scn)
861{
862 return &scn->hif_config;
863}
864
865/**
866 * hif_get_target_info_handle() - API to get hif_target_info handle
867 * @scn: HIF context
868 *
869 * Return: Pointer to hif_target_info
870 */
871struct hif_target_info *hif_get_target_info_handle(struct ol_softc *scn)
872{
873 return &scn->target_info;
874}