xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/sdio/if_sdio.c (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
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