1 /*
2  * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <linux/platform_device.h>
21 #include <linux/err.h>
22 #include <linux/mmc/sdio_func.h>
23 #include <linux/list.h>
24 #include <linux/slab.h>
25 
26 #ifdef CONFIG_PLD_SDIO_CNSS
27 #include <net/cnss.h>
28 #endif
29 #ifdef CONFIG_PLD_SDIO_CNSS2
30 #include <net/cnss2.h>
31 #endif
32 
33 #include "pld_common.h"
34 #include "pld_internal.h"
35 #include "pld_sdio.h"
36 #include "osif_psoc_sync.h"
37 
38 #ifdef CONFIG_SDIO
39 /* SDIO manufacturer ID and Codes */
40 #define MANUFACTURER_ID_AR6320_BASE        0x500
41 #define MANUFACTURER_ID_QCA9377_BASE       0x700
42 #define MANUFACTURER_ID_QCA9379_BASE       0x800
43 #define MANUFACTURER_CODE                  0x271
44 
45 #ifndef CONFIG_CNSS
46 static const struct pld_fw_files fw_files_qca6174_fw_1_1 = {
47 	PREFIX "qwlan11.bin", PREFIX  "bdwlan11.bin", PREFIX "otp11.bin",
48 	PREFIX  "utf11.bin", PREFIX "utfbd11.bin", PREFIX "qsetup11.bin",
49 	PREFIX "epping11.bin", ""};
50 static const struct pld_fw_files fw_files_qca6174_fw_2_0 = {
51 	PREFIX "qwlan20.bin", PREFIX "bdwlan20.bin", PREFIX "otp20.bin",
52 	PREFIX "utf20.bin", PREFIX "utfbd20.bin", PREFIX "qsetup20.bin",
53 	PREFIX "epping20.bin", ""};
54 static const struct pld_fw_files fw_files_qca6174_fw_1_3 = {
55 	PREFIX "qwlan13.bin", PREFIX "bdwlan13.bin", PREFIX "otp13.bin",
56 	PREFIX "utf13.bin", PREFIX "utfbd13.bin", PREFIX "qsetup13.bin",
57 	PREFIX "epping13.bin", ""};
58 static const struct pld_fw_files fw_files_qca6174_fw_3_0 = {
59 	PREFIX "qwlan30.bin", PREFIX "bdwlan30.bin", PREFIX "otp30.bin",
60 	PREFIX "utf30.bin", PREFIX "utfbd30.bin", PREFIX "qsetup30.bin",
61 	PREFIX "epping30.bin", PREFIX "qwlan30i.bin"};
62 static const struct pld_fw_files fw_files_default = {
63 	PREFIX "qwlan.bin", PREFIX "bdwlan.bin", PREFIX "otp.bin",
64 	PREFIX "utf.bin", PREFIX "utfbd.bin", PREFIX "qsetup.bin",
65 	PREFIX "epping.bin", ""};
66 #endif
67 
68 /**
69  * pld_sdio_probe() - Probe function for SDIO platform driver
70  * @sdio_func: pointer to sdio device function
71  * @id: SDIO device ID table
72  *
73  * The probe function will be called when SDIO device provided
74  * in the ID table is detected.
75  *
76  * Return: int
77  */
pld_sdio_probe(struct sdio_func * sdio_func,const struct sdio_device_id * id)78 static int pld_sdio_probe(struct sdio_func *sdio_func,
79 			  const struct sdio_device_id *id)
80 {
81 	struct pld_context *pld_context;
82 	struct device *dev;
83 	int ret;
84 
85 	pld_context = pld_get_global_context();
86 	if (!pld_context || !sdio_func) {
87 		ret = -ENODEV;
88 		goto out;
89 	}
90 
91 	dev = &sdio_func->dev;
92 	ret = pld_add_dev(pld_context, dev, NULL, PLD_BUS_TYPE_SDIO);
93 	if (ret)
94 		goto out;
95 
96 	return pld_context->ops->probe(dev, PLD_BUS_TYPE_SDIO,
97 		       sdio_func, (void *)id);
98 
99 out:
100 	return ret;
101 }
102 
103 
104 /**
105  * pld_sdio_remove() - Remove function for SDIO device
106  * @sdio_func: pointer to sdio device function
107  *
108  * The remove function will be called when SDIO device is disconnected
109  *
110  * Return: void
111  */
pld_sdio_remove(struct sdio_func * sdio_func)112 static void pld_sdio_remove(struct sdio_func *sdio_func)
113 {
114 	struct pld_context *pld_context;
115 	struct device *dev = &sdio_func->dev;
116 	int errno;
117 	struct osif_psoc_sync *psoc_sync;
118 
119 	errno = osif_psoc_sync_trans_start_wait(dev, &psoc_sync);
120 	if (errno)
121 		return;
122 
123 	osif_psoc_sync_unregister(dev);
124 	osif_psoc_sync_wait_for_ops(psoc_sync);
125 
126 	pld_context = pld_get_global_context();
127 
128 	if (!pld_context)
129 		goto out;
130 
131 	pld_context->ops->remove(dev, PLD_BUS_TYPE_SDIO);
132 	pld_del_dev(pld_context, dev);
133 
134 out:
135 	osif_psoc_sync_trans_stop(psoc_sync);
136 	osif_psoc_sync_destroy(psoc_sync);
137 }
138 
139 #ifdef CONFIG_PLD_SDIO_CNSS
140 /**
141  * pld_sdio_reinit() - SSR re-initialize function for SDIO device
142  * @sdio_func: pointer to sdio device function
143  * @id: SDIO device ID
144  *
145  * During subsystem restart(SSR), this function will be called to
146  * re-initialize SDIO device.
147  *
148  * Return: int
149  */
pld_sdio_reinit(struct sdio_func * sdio_func,const struct sdio_device_id * id)150 static int pld_sdio_reinit(struct sdio_func *sdio_func,
151 			  const struct sdio_device_id *id)
152 {
153 	struct pld_context *pld_context;
154 	struct device *dev = &sdio_func->dev;
155 
156 	pld_context = pld_get_global_context();
157 	if (pld_context->ops->reinit)
158 		return pld_context->ops->reinit(dev, PLD_BUS_TYPE_SDIO,
159 		       sdio_func, (void *)id);
160 
161 	return -ENODEV;
162 }
163 
164 /**
165  * pld_sdio_shutdown() - SSR shutdown function for SDIO device
166  * @sdio_func: pointer to sdio device function
167  *
168  * During SSR, this function will be called to shutdown SDIO device.
169  *
170  * Return: void
171  */
pld_sdio_shutdown(struct sdio_func * sdio_func)172 static void pld_sdio_shutdown(struct sdio_func *sdio_func)
173 {
174 	struct pld_context *pld_context;
175 	struct device *dev = &sdio_func->dev;
176 
177 	pld_context = pld_get_global_context();
178 	if (pld_context->ops->shutdown)
179 		pld_context->ops->shutdown(dev, PLD_BUS_TYPE_SDIO);
180 }
181 
182 /**
183  * pld_sdio_crash_shutdown() - Crash shutdown function for SDIO device
184  * @sdio_func: pointer to sdio device function
185  *
186  * This function will be called when a crash is detected, it will shutdown
187  * the SDIO device.
188  *
189  * Return: void
190  */
pld_sdio_crash_shutdown(struct sdio_func * sdio_func)191 static void pld_sdio_crash_shutdown(struct sdio_func *sdio_func)
192 {
193 	struct pld_context *pld_context;
194 	struct device *dev = &sdio_func->dev;
195 
196 	pld_context = pld_get_global_context();
197 	if (pld_context->ops->crash_shutdown)
198 		pld_context->ops->crash_shutdown(dev, PLD_BUS_TYPE_SDIO);
199 }
200 
201 #endif
202 
203 #ifdef CONFIG_PM
204 /**
205  * pld_sdio_suspend() - Suspend callback function for power management
206  * @dev: SDIO device
207  *
208  * This function is to suspend the SDIO device when power management is
209  * enabled.
210  *
211  * Return: void
212  */
pld_sdio_suspend(struct device * dev)213 static int pld_sdio_suspend(struct device *dev)
214 {
215 	struct pld_context *pld_context;
216 	pm_message_t state = { .event = PM_EVENT_SUSPEND };
217 
218 	pld_context = pld_get_global_context();
219 	return pld_context->ops->suspend(dev,
220 					 PLD_BUS_TYPE_SDIO, state);
221 }
222 
223 /**
224  * pld_sdio_resume() - Resume callback function for power management
225  * @dev: SDIO device
226  *
227  * This function is to resume the SDIO device when power management is
228  * enabled.
229  *
230  * Return: void
231  */
pld_sdio_resume(struct device * dev)232 static int pld_sdio_resume(struct device *dev)
233 {
234 	struct pld_context *pld_context;
235 
236 	pld_context = pld_get_global_context();
237 	return pld_context->ops->resume(dev, PLD_BUS_TYPE_SDIO);
238 }
239 #endif
240 
241 static struct sdio_device_id pld_sdio_id_table[] = {
242 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x0))},
243 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x1))},
244 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x2))},
245 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x3))},
246 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x4))},
247 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x5))},
248 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x6))},
249 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x7))},
250 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x8))},
251 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x9))},
252 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xA))},
253 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xB))},
254 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xC))},
255 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xD))},
256 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xE))},
257 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xF))},
258 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x0))},
259 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x1))},
260 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x2))},
261 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x3))},
262 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x4))},
263 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x5))},
264 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x6))},
265 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x7))},
266 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x8))},
267 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x9))},
268 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xA))},
269 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xB))},
270 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xC))},
271 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD))},
272 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE))},
273 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF))},
274 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x0))},
275 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x1))},
276 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x2))},
277 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x3))},
278 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x4))},
279 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x5))},
280 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x6))},
281 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x7))},
282 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x8))},
283 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x9))},
284 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xA))},
285 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xB))},
286 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xC))},
287 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xD))},
288 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xE))},
289 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xF))},
290 	{},
291 };
292 
293 #ifdef CONFIG_PLD_SDIO_CNSS2
294 /**
295  * pld_sdio_reinit() - SSR re-initialize function for SDIO device
296  * @sdio_func: pointer to sdio device function
297  * @id: SDIO device ID
298  *
299  * During subsystem restart(SSR), this function will be called to
300  * re-initialize SDIO device.
301  *
302  * Return: int
303  */
pld_sdio_reinit(struct sdio_func * sdio_func,const struct sdio_device_id * id)304 static int pld_sdio_reinit(struct sdio_func *sdio_func,
305 			   const struct sdio_device_id *id)
306 {
307 	/* TODO */
308 	return -ENODEV;
309 }
310 
311 /**
312  * pld_sdio_shutdown() - SSR shutdown function for SDIO device
313  * @sdio_func: pointer to sdio device function
314  *
315  * During SSR, this function will be called to shutdown SDIO device.
316  *
317  * Return: void
318  */
pld_sdio_shutdown(struct sdio_func * sdio_func)319 static void pld_sdio_shutdown(struct sdio_func *sdio_func)
320 {
321 	/* TODO */
322 }
323 
324 /**
325  * pld_sdio_crash_shutdown() - Crash shutdown function for SDIO device
326  * @sdio_func: pointer to sdio device function
327  *
328  * This function will be called when a crash is detected, it will shutdown
329  * the SDIO device.
330  *
331  * Return: void
332  */
pld_sdio_crash_shutdown(struct sdio_func * sdio_func)333 static void pld_sdio_crash_shutdown(struct sdio_func *sdio_func)
334 {
335 	/* TODO */
336 }
337 
pld_sdio_uevent(struct sdio_func * sdio_func,uint32_t status)338 static void pld_sdio_uevent(struct sdio_func *sdio_func, uint32_t status)
339 {
340 	struct pld_context *pld_context;
341 	struct device *dev = &sdio_func->dev;
342 	struct pld_uevent_data data = {0};
343 
344 	pld_context = pld_get_global_context();
345 
346 	if (!pld_context)
347 		return;
348 
349 	switch (status) {
350 	case CNSS_RECOVERY:
351 		data.uevent = PLD_FW_RECOVERY_START;
352 		break;
353 	case CNSS_FW_DOWN:
354 		data.uevent = PLD_FW_DOWN;
355 		break;
356 	default:
357 		goto out;
358 	}
359 
360 	if (pld_context->ops->uevent)
361 		pld_context->ops->uevent(dev, &data);
362 out:
363 	return;
364 }
365 
366 struct cnss_sdio_wlan_driver pld_sdio_ops = {
367 	.name       = "pld_sdio",
368 	.id_table   = pld_sdio_id_table,
369 	.probe      = pld_sdio_probe,
370 	.remove     = pld_sdio_remove,
371 	.reinit     = pld_sdio_reinit,
372 	.shutdown   = pld_sdio_shutdown,
373 	.crash_shutdown = pld_sdio_crash_shutdown,
374 	.update_status  = pld_sdio_uevent,
375 #ifdef CONFIG_PM
376 	.suspend    = pld_sdio_suspend,
377 	.resume     = pld_sdio_resume,
378 #endif
379 };
380 
pld_sdio_register_driver(void)381 int pld_sdio_register_driver(void)
382 {
383 	return cnss_sdio_wlan_register_driver(&pld_sdio_ops);
384 }
385 
pld_sdio_unregister_driver(void)386 void pld_sdio_unregister_driver(void)
387 {
388 	cnss_sdio_wlan_unregister_driver(&pld_sdio_ops);
389 }
390 
pld_sdio_wlan_enable(struct device * dev,struct pld_wlan_enable_cfg * config,enum pld_driver_mode mode,const char * host_version)391 int pld_sdio_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
392 			 enum pld_driver_mode mode, const char *host_version)
393 {
394 	struct cnss_wlan_enable_cfg cfg;
395 	enum cnss_driver_mode cnss_mode;
396 
397 	switch (mode) {
398 	case PLD_FTM:
399 		cnss_mode = CNSS_FTM;
400 		break;
401 	case PLD_EPPING:
402 		cnss_mode = CNSS_EPPING;
403 		break;
404 	default:
405 		cnss_mode = CNSS_MISSION;
406 		break;
407 	}
408 	return cnss_wlan_enable(dev, &cfg, cnss_mode, host_version);
409 }
410 
411 #else
412 
413 #ifdef CONFIG_PM
414 static const struct dev_pm_ops pld_device_pm_ops = {
415 	.suspend = pld_sdio_suspend,
416 	.resume = pld_sdio_resume,
417 };
418 #endif
419 
420 struct sdio_driver pld_sdio_ops = {
421 	.name       = "pld_sdio",
422 	.id_table   = pld_sdio_id_table,
423 	.probe      = pld_sdio_probe,
424 	.remove     = pld_sdio_remove,
425 #if defined(CONFIG_PM)
426 	.drv = {
427 		.pm = &pld_device_pm_ops,
428 	}
429 #endif
430 };
431 
pld_sdio_register_driver(void)432 int pld_sdio_register_driver(void)
433 {
434 	return sdio_register_driver(&pld_sdio_ops);
435 }
436 
pld_sdio_unregister_driver(void)437 void pld_sdio_unregister_driver(void)
438 {
439 	sdio_unregister_driver(&pld_sdio_ops);
440 }
441 #endif
442 
443 #ifdef CONFIG_PLD_SDIO_CNSS
444 #ifdef CONFIG_TUFELLO_DUAL_FW_SUPPORT
pld_sdio_is_tufello_dual_fw_supported(void)445 static inline int pld_sdio_is_tufello_dual_fw_supported(void)
446 {
447 	return 1;
448 }
449 #else
pld_sdio_is_tufello_dual_fw_supported(void)450 static inline int pld_sdio_is_tufello_dual_fw_supported(void)
451 {
452 	return 0;
453 #endif
454 }
455 
pld_sdio_get_fw_files_for_target(struct pld_fw_files * pfw_files,u32 target_type,u32 target_version)456 int pld_sdio_get_fw_files_for_target(struct pld_fw_files *pfw_files,
457 				     u32 target_type, u32 target_version)
458 {
459 	int ret = 0;
460 	struct cnss_fw_files cnss_fw_files;
461 
462 	if (!pfw_files)
463 		return -ENODEV;
464 
465 	memset(pfw_files, 0, sizeof(*pfw_files));
466 
467 	if (target_version == PLD_QCA9377_REV1_1_VERSION) {
468 		cnss_get_qca9377_fw_files(&cnss_fw_files, PLD_MAX_FILE_NAME,
469 			pld_sdio_is_tufello_dual_fw_supported());
470 	} else {
471 		ret = cnss_get_fw_files_for_target(&cnss_fw_files,
472 					   target_type, target_version);
473 	}
474 	if (0 != ret)
475 		return ret;
476 
477 	snprintf(pfw_files->image_file, PLD_MAX_FILE_NAME, PREFIX "%s",
478 		cnss_fw_files.image_file);
479 	snprintf(pfw_files->board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
480 		cnss_fw_files.board_data);
481 	snprintf(pfw_files->otp_data, PLD_MAX_FILE_NAME, PREFIX "%s",
482 		cnss_fw_files.otp_data);
483 	snprintf(pfw_files->utf_file, PLD_MAX_FILE_NAME, PREFIX "%s",
484 		cnss_fw_files.utf_file);
485 	snprintf(pfw_files->utf_board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
486 		cnss_fw_files.utf_board_data);
487 	snprintf(pfw_files->epping_file, PLD_MAX_FILE_NAME, PREFIX "%s",
488 		cnss_fw_files.epping_file);
489 	snprintf(pfw_files->evicted_data, PLD_MAX_FILE_NAME, PREFIX "%s",
490 		cnss_fw_files.evicted_data);
491 
492 	return ret;
493 }
494 #else
495 #ifdef CONFIG_TUFELLO_DUAL_FW_SUPPORT
get_qca9377_fw_files(struct pld_fw_files * pfw_files,u32 size)496 static inline void get_qca9377_fw_files(struct pld_fw_files *pfw_files,
497 					u32 size)
498 {
499 		memcpy(pfw_files, &fw_files_default, sizeof(*pfw_files));
500 }
501 #else
get_qca9377_fw_files(struct pld_fw_files * pfw_files,u32 size)502 static inline void get_qca9377_fw_files(struct pld_fw_files *pfw_files,
503 					u32 size)
504 {
505 		memcpy(pfw_files, &fw_files_qca6174_fw_3_0, sizeof(*pfw_files));
506 }
507 #endif
508 
pld_sdio_get_fw_files_for_target(struct pld_fw_files * pfw_files,u32 target_type,u32 target_version)509 int pld_sdio_get_fw_files_for_target(struct pld_fw_files *pfw_files,
510 				     u32 target_type, u32 target_version)
511 {
512 	if (!pfw_files)
513 		return -ENODEV;
514 
515 	switch (target_version) {
516 	case PLD_AR6320_REV1_VERSION:
517 	case PLD_AR6320_REV1_1_VERSION:
518 		memcpy(pfw_files, &fw_files_qca6174_fw_1_1, sizeof(*pfw_files));
519 		break;
520 	case PLD_AR6320_REV1_3_VERSION:
521 		memcpy(pfw_files, &fw_files_qca6174_fw_1_3, sizeof(*pfw_files));
522 		break;
523 	case PLD_AR6320_REV2_1_VERSION:
524 		memcpy(pfw_files, &fw_files_qca6174_fw_2_0, sizeof(*pfw_files));
525 		break;
526 	case PLD_AR6320_REV3_VERSION:
527 	case PLD_AR6320_REV3_2_VERSION:
528 		memcpy(pfw_files, &fw_files_qca6174_fw_3_0, sizeof(*pfw_files));
529 		break;
530 	case PLD_QCA9377_REV1_1_VERSION:
531 	case PLD_QCA9379_REV1_VERSION:
532 		get_qca9377_fw_files(pfw_files, sizeof(*pfw_files));
533 		break;
534 	default:
535 		memcpy(pfw_files, &fw_files_default, sizeof(*pfw_files));
536 		pr_err("%s version mismatch 0x%X ",
537 				__func__, target_version);
538 		break;
539 	}
540 
541 	return 0;
542 }
543 #endif
544 #endif
545