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