blob: 60e669faa2d9b8307b45f0e0c4d6ca060aced150 [file] [log] [blame]
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001/*
2 * Copyright (c) 2016 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/*
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#define pr_fmt(fmt) "wlan_pld:%s:%d:: " fmt, __func__, __LINE__
29
30#include <linux/printk.h>
31#include <linux/err.h>
32#include <linux/string.h>
33#include <linux/list.h>
34#include <linux/slab.h>
35#include <linux/pm.h>
36
Yue Mae6a7a322016-08-31 11:09:23 -070037#ifdef CONFIG_PLD_SDIO_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080038#include <net/cnss.h>
39#endif
Yue Mae6a7a322016-08-31 11:09:23 -070040#ifdef CONFIG_PLD_PCIE_CNSS
41/*
42 * This is a hack to make sure this change can be merged before the
43 * kernel defconfig change (switching to CNSS2 platform driver) merged,
44 * otherwise the kernel change has to depend on this change to be merged.
45 * Once the kernel change is merged, these CNSS flags can be removed
46 * so that only cnss2.h is needed.
47 */
48#ifdef CONFIG_CNSS
49#include <net/cnss.h>
50#endif
51#ifdef CONFIG_CNSS2
52#include <net/cnss2.h>
53#endif
54#endif
Yuanyuan Liu11f526a2016-05-18 10:22:07 -070055#ifdef CONFIG_PLD_SNOC_ICNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080056#include <soc/qcom/icnss.h>
57#endif
58
59#include "pld_pcie.h"
60#include "pld_snoc.h"
Govind Singh6a2fe032016-05-13 14:09:37 +053061#include "pld_sdio.h"
Mohit Khanna1d531c42016-05-12 21:35:50 -070062#include "pld_usb.h"
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080063
64#define PLD_PCIE_REGISTERED BIT(0)
65#define PLD_SNOC_REGISTERED BIT(1)
Govind Singh6a2fe032016-05-13 14:09:37 +053066#define PLD_SDIO_REGISTERED BIT(2)
Mohit Khanna1d531c42016-05-12 21:35:50 -070067#define PLD_USB_REGISTERED BIT(3)
68#define PLD_BUS_MASK 0xf
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080069
70static struct pld_context *pld_ctx;
71
72/**
73 * pld_init() - Initialize PLD module
74 *
75 * Return: 0 for success
76 * Non zero failure code for errors
77 */
78int pld_init(void)
79{
80 struct pld_context *pld_context;
81
82 pld_context = kzalloc(sizeof(*pld_context), GFP_KERNEL);
83 if (!pld_context)
84 return -ENOMEM;
85
86 spin_lock_init(&pld_context->pld_lock);
87
88 INIT_LIST_HEAD(&pld_context->dev_list);
89
90 pld_ctx = pld_context;
91
92 return 0;
93}
94
95/**
96 * pld_deinit() - Uninitialize PLD module
97 *
98 * Return: void
99 */
100void pld_deinit(void)
101{
102 struct dev_node *dev_node;
103 struct pld_context *pld_context;
104 unsigned long flags;
105
106 pld_context = pld_ctx;
107 if (!pld_context) {
108 pld_ctx = NULL;
109 return;
110 }
111
112 spin_lock_irqsave(&pld_context->pld_lock, flags);
113 while (!list_empty(&pld_context->dev_list)) {
114 dev_node = list_first_entry(&pld_context->dev_list,
115 struct dev_node, list);
116 list_del(&dev_node->list);
117 kfree(dev_node);
118 }
119 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
120
121 kfree(pld_context);
122
123 pld_ctx = NULL;
124}
125
126/**
127 * pld_get_global_context() - Get global context of PLD
128 *
129 * Return: PLD global context
130 */
131struct pld_context *pld_get_global_context(void)
132{
133 return pld_ctx;
134}
135
136/**
Yuanyuan Liu5e25f532016-05-25 16:26:40 -0700137 * pld_add_dev() - Add dev node to global context
138 * @pld_context: PLD global context
139 * @dev: device
140 * @type: Bus type
141 *
142 * Return: 0 for success
143 * Non zero failure code for errors
144 */
145int pld_add_dev(struct pld_context *pld_context,
146 struct device *dev, enum pld_bus_type type)
147{
148 unsigned long flags;
149 struct dev_node *dev_node;
150
151 dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL);
152 if (dev_node == NULL)
153 return -ENOMEM;
154
155 dev_node->dev = dev;
156 dev_node->bus_type = type;
157
158 spin_lock_irqsave(&pld_context->pld_lock, flags);
159 list_add_tail(&dev_node->list, &pld_context->dev_list);
160 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
161
162 return 0;
163}
164
165/**
166 * pld_del_dev() - Delete dev node from global context
167 * @pld_context: PLD global context
168 * @dev: device
169 *
170 * Return: void
171 */
172void pld_del_dev(struct pld_context *pld_context,
173 struct device *dev)
174{
175 unsigned long flags;
176 struct dev_node *dev_node, *tmp;
177
178 spin_lock_irqsave(&pld_context->pld_lock, flags);
179 list_for_each_entry_safe(dev_node, tmp, &pld_context->dev_list, list) {
180 if (dev_node->dev == dev) {
181 list_del(&dev_node->list);
182 kfree(dev_node);
183 }
184 }
185 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
186}
187
188/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800189 * pld_get_bus_type() - Bus type of the device
190 * @dev: device
191 *
192 * Return: PLD bus type
193 */
Jeff Johnsonbbaf4e42016-10-07 12:33:22 -0700194static enum pld_bus_type pld_get_bus_type(struct device *dev)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800195{
196 struct pld_context *pld_context;
197 struct dev_node *dev_node;
198 unsigned long flags;
199
200 pld_context = pld_get_global_context();
201
202 if (dev == NULL || pld_context == NULL) {
203 pr_err("Invalid info: dev %p, context %p\n",
204 dev, pld_context);
205 return PLD_BUS_TYPE_NONE;
206 }
207
208 spin_lock_irqsave(&pld_context->pld_lock, flags);
209 list_for_each_entry(dev_node, &pld_context->dev_list, list) {
210 if (dev_node->dev == dev) {
211 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
212 return dev_node->bus_type;
213 }
214 }
215 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
216
217 return PLD_BUS_TYPE_NONE;
218}
219
220/**
221 * pld_register_driver() - Register driver to kernel
222 * @ops: Callback functions that will be registered to kernel
223 *
224 * This function should be called when other modules want to
225 * register platform driver callback functions to kernel. The
226 * probe() is expected to be called after registration if the
227 * device is online.
228 *
229 * Return: 0 for success
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700230 * Non zero failure code for errors
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800231 */
232int pld_register_driver(struct pld_driver_ops *ops)
233{
234 int ret = 0;
235 struct pld_context *pld_context;
236
237 pld_context = pld_get_global_context();
238
239 if (pld_context == NULL) {
240 pr_err("global context is NULL\n");
241 ret = -ENODEV;
242 goto out;
243 }
244
245 if (pld_context->ops) {
246 pr_err("driver already registered\n");
247 ret = -EEXIST;
248 goto out;
249 }
250
251 if (!ops || !ops->probe || !ops->remove ||
252 !ops->suspend || !ops->resume) {
253 pr_err("Required callback functions are missing\n");
254 ret = -EINVAL;
255 goto out;
256 }
257
258 pld_context->ops = ops;
Mohit Khanna1d531c42016-05-12 21:35:50 -0700259 pld_context->pld_driver_state = 0;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800260
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700261 ret = pld_pcie_register_driver();
262 if (ret) {
263 pr_err("Fail to register pcie driver\n");
264 goto fail_pcie;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800265 }
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700266 pld_context->pld_driver_state |= PLD_PCIE_REGISTERED;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800267
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700268 ret = pld_snoc_register_driver();
269 if (ret) {
270 pr_err("Fail to register snoc driver\n");
271 goto fail_snoc;
272 }
273 pld_context->pld_driver_state |= PLD_SNOC_REGISTERED;
274
275 ret = pld_sdio_register_driver();
276 if (ret) {
277 pr_err("Fail to register sdio driver\n");
278 goto fail_sdio;
279 }
280 pld_context->pld_driver_state |= PLD_SDIO_REGISTERED;
281
Mohit Khanna1d531c42016-05-12 21:35:50 -0700282 ret = pld_usb_register_driver();
283 if (ret) {
284 pr_err("Fail to register usb driver\n");
285 goto fail_usb;
286 }
287 pld_context->pld_driver_state |= PLD_USB_REGISTERED;
288
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700289 return ret;
290
Mohit Khanna1d531c42016-05-12 21:35:50 -0700291fail_usb:
292 pld_sdio_unregister_driver();
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700293fail_sdio:
294 pld_snoc_unregister_driver();
295fail_snoc:
296 pld_pcie_unregister_driver();
297fail_pcie:
298 pld_context->pld_driver_state = 0;
299 pld_context->ops = NULL;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800300out:
301 return ret;
302}
303
304/**
305 * pld_unregister_driver() - Unregister driver to kernel
306 *
307 * This function should be called when other modules want to
308 * unregister callback functions from kernel. The remove() is
309 * expected to be called after registration.
310 *
311 * Return: void
312 */
313void pld_unregister_driver(void)
314{
315 struct pld_context *pld_context;
316
317 pld_context = pld_get_global_context();
318
319 if (pld_context == NULL) {
320 pr_err("global context is NULL\n");
321 return;
322 }
323
324 if (pld_context->ops == NULL) {
325 pr_err("driver not registered\n");
326 return;
327 }
328
329 pld_pcie_unregister_driver();
330 pld_snoc_unregister_driver();
Govind Singh6a2fe032016-05-13 14:09:37 +0530331 pld_sdio_unregister_driver();
Mohit Khanna1d531c42016-05-12 21:35:50 -0700332 pld_usb_unregister_driver();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800333
334 pld_context->pld_driver_state = 0;
335
336 pld_context->ops = NULL;
337}
338
339/**
340 * pld_wlan_enable() - Enable WLAN
341 * @dev: device
342 * @config: WLAN configuration data
343 * @mode: WLAN mode
344 * @host_version: host software version
345 *
346 * This function enables WLAN FW. It passed WLAN configuration data,
347 * WLAN mode and host software version to FW.
348 *
349 * Return: 0 for success
350 * Non zero failure code for errors
351 */
352int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
353 enum pld_driver_mode mode, const char *host_version)
354{
355 int ret = 0;
356
357 switch (pld_get_bus_type(dev)) {
358 case PLD_BUS_TYPE_PCIE:
359 ret = pld_pcie_wlan_enable(config, mode, host_version);
360 break;
361 case PLD_BUS_TYPE_SNOC:
362 ret = pld_snoc_wlan_enable(config, mode, host_version);
363 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530364 case PLD_BUS_TYPE_SDIO:
365 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800366 default:
367 ret = -EINVAL;
368 break;
369 }
370
371 return ret;
372}
373
374/**
375 * pld_wlan_disable() - Disable WLAN
376 * @dev: device
377 * @mode: WLAN mode
378 *
379 * This function disables WLAN FW. It passes WLAN mode to FW.
380 *
381 * Return: 0 for success
382 * Non zero failure code for errors
383 */
384int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode)
385{
386 int ret = 0;
387
388 switch (pld_get_bus_type(dev)) {
389 case PLD_BUS_TYPE_PCIE:
390 ret = pld_pcie_wlan_disable(mode);
391 break;
392 case PLD_BUS_TYPE_SNOC:
393 ret = pld_snoc_wlan_disable(mode);
394 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530395 case PLD_BUS_TYPE_SDIO:
396 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800397 default:
398 ret = -EINVAL;
399 break;
400 }
401
402 return ret;
403}
404
405/**
406 * pld_set_fw_debug_mode() - Set FW debug mode
407 * @dev: device
408 * @enablefwlog: 0 for QXDM, 1 for WMI
409 *
410 * Switch Fw debug mode between DIAG logging and WMI logging.
411 *
412 * Return: 0 for success
413 * Non zero failure code for errors
414 */
415int pld_set_fw_debug_mode(struct device *dev, bool enablefwlog)
416{
417 int ret = 0;
418
419 switch (pld_get_bus_type(dev)) {
420 case PLD_BUS_TYPE_PCIE:
421 ret = pld_pcie_set_fw_debug_mode(enablefwlog);
422 break;
423 case PLD_BUS_TYPE_SNOC:
424 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530425 case PLD_BUS_TYPE_SDIO:
426 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800427 default:
428 ret = -EINVAL;
429 break;
430 }
431
432 return ret;
433}
434
435/**
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700436 * pld_get_default_fw_files() - Get default FW file names
437 * @pfw_files: buffer for FW file names
438 *
439 * Return default FW file names to the buffer.
440 *
441 * Return: void
442 */
443void pld_get_default_fw_files(struct pld_fw_files *pfw_files)
444{
445 memset(pfw_files, 0, sizeof(*pfw_files));
446
447 strlcpy(pfw_files->image_file, PLD_IMAGE_FILE,
448 PLD_MAX_FILE_NAME);
449 strlcpy(pfw_files->board_data, PLD_BOARD_DATA_FILE,
450 PLD_MAX_FILE_NAME);
451 strlcpy(pfw_files->otp_data, PLD_OTP_FILE,
452 PLD_MAX_FILE_NAME);
453 strlcpy(pfw_files->utf_file, PLD_UTF_FIRMWARE_FILE,
454 PLD_MAX_FILE_NAME);
455 strlcpy(pfw_files->utf_board_data, PLD_BOARD_DATA_FILE,
456 PLD_MAX_FILE_NAME);
457 strlcpy(pfw_files->epping_file, PLD_EPPING_FILE,
458 PLD_MAX_FILE_NAME);
459 strlcpy(pfw_files->setup_file, PLD_SETUP_FILE,
460 PLD_MAX_FILE_NAME);
461}
462
463/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800464 * pld_get_fw_files_for_target() - Get FW file names
465 * @dev: device
466 * @pfw_files: buffer for FW file names
467 * @target_type: target type
468 * @target_version: target version
469 *
470 * Return target specific FW file names to the buffer.
471 *
472 * Return: 0 for success
473 * Non zero failure code for errors
474 */
475int pld_get_fw_files_for_target(struct device *dev,
476 struct pld_fw_files *pfw_files,
477 u32 target_type, u32 target_version)
478{
479 int ret = 0;
480
481 switch (pld_get_bus_type(dev)) {
482 case PLD_BUS_TYPE_PCIE:
483 ret = pld_pcie_get_fw_files_for_target(pfw_files,
484 target_type, target_version);
485 break;
486 case PLD_BUS_TYPE_SNOC:
487 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530488 case PLD_BUS_TYPE_SDIO:
489 ret = pld_sdio_get_fw_files_for_target(pfw_files,
490 target_type, target_version);
491 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -0700492 case PLD_BUS_TYPE_USB:
493 ret = pld_usb_get_fw_files_for_target(pfw_files,
494 target_type, target_version);
495 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800496 default:
497 ret = -EINVAL;
498 break;
499 }
500
501 return ret;
502}
503
504/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800505 * pld_is_pci_link_down() - Notification for pci link down event
506 * @dev: device
507 *
508 * Notify platform that pci link is down.
509 *
510 * Return: void
511 */
512void pld_is_pci_link_down(struct device *dev)
513{
514 switch (pld_get_bus_type(dev)) {
515 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700516 pld_pcie_link_down();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800517 break;
518 case PLD_BUS_TYPE_SNOC:
519 break;
520 default:
521 pr_err("Invalid device type\n");
522 break;
523 }
524}
525
526/**
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700527 * pld_shadow_control() - Control pci shadow registers
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800528 * @dev: device
529 * @enable: 0 for disable, 1 for enable
530 *
531 * This function is for suspend/resume. It can control if we
532 * use pci shadow registers (for saving config space) or not.
533 * During suspend we disable it to avoid config space corruption.
534 *
535 * Return: 0 for success
536 * Non zero failure code for errors
537 */
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700538int pld_shadow_control(struct device *dev, bool enable)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800539{
540 int ret = 0;
541
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800542 switch (pld_get_bus_type(dev)) {
543 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700544 ret = pld_pcie_shadow_control(enable);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800545 break;
546 case PLD_BUS_TYPE_SNOC:
547 break;
548 default:
549 ret = -EINVAL;
550 break;
551 }
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700552
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800553 return ret;
554}
555
556/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800557 * pld_set_wlan_unsafe_channel() - Set unsafe channel
558 * @dev: device
559 * @unsafe_ch_list: unsafe channel list
560 * @ch_count: number of channel
561 *
562 * Return: 0 for success
563 * Non zero failure code for errors
564 */
565int pld_set_wlan_unsafe_channel(struct device *dev,
566 u16 *unsafe_ch_list, u16 ch_count)
567{
568 int ret = 0;
569
570 switch (pld_get_bus_type(dev)) {
571 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700572 ret = pld_pcie_set_wlan_unsafe_channel(unsafe_ch_list,
573 ch_count);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800574 break;
575 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu35084082016-08-23 13:10:59 -0700576 ret = pld_snoc_set_wlan_unsafe_channel(unsafe_ch_list,
577 ch_count);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800578 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530579 case PLD_BUS_TYPE_SDIO:
580 /* To do get unsafe channel via cnss sdio API */
581 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800582 default:
583 ret = -EINVAL;
584 break;
585 }
586
587 return ret;
588}
589
590/**
591 * pld_get_wlan_unsafe_channel() - Get unsafe channel
592 * @dev: device
593 * @unsafe_ch_list: buffer to unsafe channel list
594 * @ch_count: number of channel
595 * @buf_len: buffer length
596 *
597 * Return WLAN unsafe channel to the buffer.
598 *
599 * Return: 0 for success
600 * Non zero failure code for errors
601 */
602int pld_get_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list,
603 u16 *ch_count, u16 buf_len)
604{
605 int ret = 0;
606
607 switch (pld_get_bus_type(dev)) {
608 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700609 ret = pld_pcie_get_wlan_unsafe_channel(unsafe_ch_list,
610 ch_count, buf_len);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800611 break;
612 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu35084082016-08-23 13:10:59 -0700613 ret = pld_snoc_get_wlan_unsafe_channel(unsafe_ch_list,
614 ch_count, buf_len);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800615 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530616 case PLD_BUS_TYPE_SDIO:
617 /* To do get unsafe channel via cnss sdio API */
618 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800619 default:
620 ret = -EINVAL;
621 break;
622 }
623
624 return ret;
625}
626
627/**
628 * pld_wlan_set_dfs_nol() - Set DFS info
629 * @dev: device
630 * @info: DFS info
631 * @info_len: info length
632 *
633 * Return: 0 for success
634 * Non zero failure code for errors
635 */
636int pld_wlan_set_dfs_nol(struct device *dev, void *info, u16 info_len)
637{
638 int ret = 0;
639
640 switch (pld_get_bus_type(dev)) {
641 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700642 ret = pld_pcie_wlan_set_dfs_nol(info, info_len);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800643 break;
644 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu35084082016-08-23 13:10:59 -0700645 ret = pld_snoc_wlan_set_dfs_nol(info, info_len);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800646 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530647 case PLD_BUS_TYPE_SDIO:
648 /* To do get nol via cnss sdio API */
649 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800650 default:
651 ret = -EINVAL;
652 break;
653 }
654
655 return ret;
656}
657
658/**
659 * pld_wlan_get_dfs_nol() - Get DFS info
660 * @dev: device
661 * @info: buffer to DFS info
662 * @info_len: info length
663 *
664 * Return DFS info to the buffer.
665 *
666 * Return: 0 for success
667 * Non zero failure code for errors
668 */
669int pld_wlan_get_dfs_nol(struct device *dev, void *info, u16 info_len)
670{
671 int ret = 0;
672
673 switch (pld_get_bus_type(dev)) {
674 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700675 ret = pld_pcie_wlan_get_dfs_nol(info, info_len);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800676 break;
677 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu35084082016-08-23 13:10:59 -0700678 ret = pld_snoc_wlan_get_dfs_nol(info, info_len);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800679 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530680 case PLD_BUS_TYPE_SDIO:
681 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800682 default:
683 ret = -EINVAL;
684 break;
685 }
686
687 return ret;
688}
689
690/**
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700691 * pld_schedule_recovery_work() - Schedule recovery work
692 * @dev: device
693 *
694 * Schedule a system self recovery work.
695 *
696 * Return: void
697 */
698void pld_schedule_recovery_work(struct device *dev)
699{
700 switch (pld_get_bus_type(dev)) {
701 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700702 pld_pcie_schedule_recovery_work();
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700703 break;
704 case PLD_BUS_TYPE_SNOC:
705 break;
706 default:
707 pr_err("Invalid device type\n");
708 break;
709 }
710}
711
712/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800713 * pld_wlan_pm_control() - WLAN PM control on PCIE
714 * @dev: device
715 * @vote: 0 for enable PCIE PC, 1 for disable PCIE PC
716 *
717 * This is for PCIE power collaps control during suspend/resume.
718 * When PCIE power collaps is disabled, WLAN FW can access memory
719 * through PCIE when system is suspended.
720 *
721 * Return: 0 for success
722 * Non zero failure code for errors
723 */
724int pld_wlan_pm_control(struct device *dev, bool vote)
725{
726 int ret = 0;
727
728 switch (pld_get_bus_type(dev)) {
729 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700730 ret = pld_pcie_wlan_pm_control(vote);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800731 break;
732 case PLD_BUS_TYPE_SNOC:
733 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530734 case PLD_BUS_TYPE_SDIO:
735 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800736 default:
737 ret = -EINVAL;
738 break;
739 }
740
741 return ret;
742}
743
744/**
745 * pld_get_virt_ramdump_mem() - Get virtual ramdump memory
746 * @dev: device
747 * @size: buffer to virtual memory size
748 *
749 * Return: virtual ramdump memory address
750 */
751void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
752{
753 void *mem = NULL;
754
755 switch (pld_get_bus_type(dev)) {
756 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700757 mem = pld_pcie_get_virt_ramdump_mem(size);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800758 break;
759 case PLD_BUS_TYPE_SNOC:
760 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530761 case PLD_BUS_TYPE_SDIO:
762 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800763 default:
764 pr_err("Invalid device type\n");
765 break;
766 }
767
768 return mem;
769}
770
771/**
772 * pld_device_crashed() - Notification for device crash event
773 * @dev: device
774 *
775 * Notify subsystem a device crashed event. A subsystem restart
776 * is expected to happen after calling this function.
777 *
778 * Return: void
779 */
780void pld_device_crashed(struct device *dev)
781{
782 switch (pld_get_bus_type(dev)) {
783 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700784 pld_pcie_device_crashed();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800785 break;
786 case PLD_BUS_TYPE_SNOC:
787 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530788 case PLD_BUS_TYPE_SDIO:
789 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800790 default:
791 pr_err("Invalid device type\n");
792 break;
793 }
794}
795
796/**
797 * pld_device_self_recovery() - Device self recovery
798 * @dev: device
799 *
800 * Return: void
801 */
802void pld_device_self_recovery(struct device *dev)
803{
804 switch (pld_get_bus_type(dev)) {
805 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700806 pld_pcie_device_self_recovery();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800807 break;
808 case PLD_BUS_TYPE_SNOC:
809 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530810 case PLD_BUS_TYPE_SDIO:
811 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800812 default:
813 pr_err("Invalid device type\n");
814 break;
815 }
816}
817
818/**
819 * pld_intr_notify_q6() - Notify Q6 FW interrupts
820 * @dev: device
821 *
822 * Notify Q6 that a FW interrupt is triggered.
823 *
824 * Return: void
825 */
826void pld_intr_notify_q6(struct device *dev)
827{
828 switch (pld_get_bus_type(dev)) {
829 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700830 pld_pcie_intr_notify_q6();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800831 break;
832 case PLD_BUS_TYPE_SNOC:
833 break;
834 default:
835 pr_err("Invalid device type\n");
836 break;
837 }
838}
839
840/**
841 * pld_request_pm_qos() - Request system PM
842 * @dev: device
843 * @qos_val: request value
844 *
845 * It votes for the value of aggregate QoS expectations.
846 *
847 * Return: void
848 */
849void pld_request_pm_qos(struct device *dev, u32 qos_val)
850{
851 switch (pld_get_bus_type(dev)) {
852 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700853 pld_pcie_request_pm_qos(qos_val);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800854 break;
855 case PLD_BUS_TYPE_SNOC:
856 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530857 case PLD_BUS_TYPE_SDIO:
858 /* To do Add call cns API */
859 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -0700860 case PLD_BUS_TYPE_USB:
861 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800862 default:
863 pr_err("Invalid device type\n");
864 break;
865 }
866}
867
868/**
869 * pld_remove_pm_qos() - Remove system PM
870 * @dev: device
871 *
872 * Remove the vote request for Qos expectations.
873 *
874 * Return: void
875 */
876void pld_remove_pm_qos(struct device *dev)
877{
878 switch (pld_get_bus_type(dev)) {
879 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700880 pld_pcie_remove_pm_qos();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800881 break;
882 case PLD_BUS_TYPE_SNOC:
883 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530884 case PLD_BUS_TYPE_SDIO:
885 /* To do Add call cns API */
886 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800887 default:
888 pr_err("Invalid device type\n");
889 break;
890 }
891}
892
893/**
894 * pld_request_bus_bandwidth() - Request bus bandwidth
895 * @dev: device
896 * @bandwidth: bus bandwidth
897 *
898 * Votes for HIGH/MEDIUM/LOW bus bandwidth.
899 *
900 * Return: 0 for success
901 * Non zero failure code for errors
902 */
903int pld_request_bus_bandwidth(struct device *dev, int bandwidth)
904{
905 int ret = 0;
906
907 switch (pld_get_bus_type(dev)) {
908 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700909 ret = pld_pcie_request_bus_bandwidth(bandwidth);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800910 break;
911 case PLD_BUS_TYPE_SNOC:
912 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530913 case PLD_BUS_TYPE_SDIO:
914 /* To do Add call cns API */
915 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800916 default:
917 ret = -EINVAL;
918 break;
919 }
920
921 return ret;
922}
923
924/**
925 * pld_get_platform_cap() - Get platform capabilities
926 * @dev: device
927 * @cap: buffer to the capabilities
928 *
929 * Return capabilities to the buffer.
930 *
931 * Return: 0 for success
932 * Non zero failure code for errors
933 */
934int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
935{
936 int ret = 0;
937
938 switch (pld_get_bus_type(dev)) {
939 case PLD_BUS_TYPE_PCIE:
940 ret = pld_pcie_get_platform_cap(cap);
941 break;
942 case PLD_BUS_TYPE_SNOC:
943 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530944 case PLD_BUS_TYPE_SDIO:
945 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800946 default:
947 ret = -EINVAL;
948 break;
949 }
950
951 return ret;
952}
953
954/**
955 * pld_set_driver_status() - Set driver status
956 * @dev: device
957 * @status: driver status
958 *
959 * Return: void
960 */
961void pld_set_driver_status(struct device *dev, enum pld_driver_status status)
962{
963 switch (pld_get_bus_type(dev)) {
964 case PLD_BUS_TYPE_PCIE:
965 pld_pcie_set_driver_status(status);
966 break;
967 case PLD_BUS_TYPE_SNOC:
968 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530969 case PLD_BUS_TYPE_SDIO:
970 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800971 default:
972 pr_err("Invalid device type\n");
973 break;
974 }
975}
976
977/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800978 * pld_get_sha_hash() - Get sha hash number
979 * @dev: device
980 * @data: input data
981 * @data_len: data length
982 * @hash_idx: hash index
983 * @out: output buffer
984 *
985 * Return computed hash to the out buffer.
986 *
987 * Return: 0 for success
988 * Non zero failure code for errors
989 */
990int pld_get_sha_hash(struct device *dev, const u8 *data,
991 u32 data_len, u8 *hash_idx, u8 *out)
992{
993 int ret = 0;
994
995 switch (pld_get_bus_type(dev)) {
996 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -0700997 ret = pld_pcie_get_sha_hash(data, data_len,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800998 hash_idx, out);
999 break;
1000 case PLD_BUS_TYPE_SNOC:
1001 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301002 case PLD_BUS_TYPE_SDIO:
1003 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001004 default:
1005 ret = -EINVAL;
1006 break;
1007 }
1008
1009 return ret;
1010}
1011
1012/**
1013 * pld_get_fw_ptr() - Get secure FW memory address
1014 * @dev: device
1015 *
1016 * Return: secure memory address
1017 */
1018void *pld_get_fw_ptr(struct device *dev)
1019{
1020 void *ptr = NULL;
1021
1022 switch (pld_get_bus_type(dev)) {
1023 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001024 ptr = pld_pcie_get_fw_ptr();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001025 break;
1026 case PLD_BUS_TYPE_SNOC:
1027 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301028 case PLD_BUS_TYPE_SDIO:
1029 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001030 default:
1031 pr_err("Invalid device type\n");
1032 break;
1033 }
1034
1035 return ptr;
1036}
1037
1038/**
1039 * pld_auto_suspend() - Auto suspend
1040 * @dev: device
1041 *
1042 * Return: 0 for success
1043 * Non zero failure code for errors
1044 */
1045int pld_auto_suspend(struct device *dev)
1046{
1047 int ret = 0;
1048
1049 switch (pld_get_bus_type(dev)) {
1050 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001051 ret = pld_pcie_auto_suspend();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001052 break;
1053 case PLD_BUS_TYPE_SNOC:
1054 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301055 case PLD_BUS_TYPE_SDIO:
1056 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001057 default:
1058 ret = -EINVAL;
1059 break;
1060 }
1061
1062 return ret;
1063}
1064
1065/**
1066 * pld_auto_resume() - Auto resume
1067 * @dev: device
1068 *
1069 * Return: 0 for success
1070 * Non zero failure code for errors
1071 */
1072int pld_auto_resume(struct device *dev)
1073{
1074 int ret = 0;
1075
1076 switch (pld_get_bus_type(dev)) {
1077 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001078 ret = pld_pcie_auto_resume();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001079 break;
1080 case PLD_BUS_TYPE_SNOC:
1081 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301082 case PLD_BUS_TYPE_SDIO:
1083 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001084 default:
1085 ret = -EINVAL;
1086 break;
1087 }
1088
1089 return ret;
1090}
1091
1092/**
1093 * pld_ce_request_irq() - Register IRQ for CE
1094 * @dev: device
1095 * @ce_id: CE number
1096 * @handler: IRQ callback function
1097 * @flags: IRQ flags
1098 * @name: IRQ name
1099 * @ctx: IRQ context
1100 *
1101 * Return: 0 for success
1102 * Non zero failure code for errors
1103 */
1104int pld_ce_request_irq(struct device *dev, unsigned int ce_id,
1105 irqreturn_t (*handler)(int, void *),
1106 unsigned long flags, const char *name, void *ctx)
1107{
1108 int ret = 0;
1109
1110 switch (pld_get_bus_type(dev)) {
1111 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001112 ret = pld_snoc_ce_request_irq(ce_id, handler, flags, name, ctx);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001113 break;
1114 case PLD_BUS_TYPE_PCIE:
1115 break;
1116 default:
1117 ret = -EINVAL;
1118 break;
1119 }
1120
1121 return ret;
1122}
1123
1124/**
1125 * pld_ce_free_irq() - Free IRQ for CE
1126 * @dev: device
1127 * @ce_id: CE number
1128 * @ctx: IRQ context
1129 *
1130 * Return: 0 for success
1131 * Non zero failure code for errors
1132 */
1133int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx)
1134{
1135 int ret = 0;
1136
1137 switch (pld_get_bus_type(dev)) {
1138 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001139 ret = pld_snoc_ce_free_irq(ce_id, ctx);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001140 break;
1141 case PLD_BUS_TYPE_PCIE:
1142 break;
1143 default:
1144 ret = -EINVAL;
1145 break;
1146 }
1147
1148 return ret;
1149}
1150
1151/**
1152 * pld_enable_irq() - Enable IRQ for CE
1153 * @dev: device
1154 * @ce_id: CE number
1155 *
1156 * Return: void
1157 */
1158void pld_enable_irq(struct device *dev, unsigned int ce_id)
1159{
1160 switch (pld_get_bus_type(dev)) {
1161 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001162 pld_snoc_enable_irq(ce_id);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001163 break;
1164 case PLD_BUS_TYPE_PCIE:
1165 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301166 case PLD_BUS_TYPE_SDIO:
1167 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001168 default:
1169 pr_err("Invalid device type\n");
1170 break;
1171 }
1172}
1173
1174/**
1175 * pld_disable_irq() - Disable IRQ for CE
1176 * @dev: device
1177 * @ce_id: CE number
1178 *
1179 * Return: void
1180 */
1181void pld_disable_irq(struct device *dev, unsigned int ce_id)
1182{
1183 switch (pld_get_bus_type(dev)) {
1184 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001185 pld_snoc_disable_irq(ce_id);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001186 break;
1187 case PLD_BUS_TYPE_PCIE:
1188 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301189 case PLD_BUS_TYPE_SDIO:
1190 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001191 default:
1192 pr_err("Invalid device type\n");
1193 break;
1194 }
1195}
1196
1197/**
1198 * pld_get_soc_info() - Get SOC information
1199 * @dev: device
1200 * @info: buffer to SOC information
1201 *
1202 * Return SOC info to the buffer.
1203 *
1204 * Return: 0 for success
1205 * Non zero failure code for errors
1206 */
1207int pld_get_soc_info(struct device *dev, struct pld_soc_info *info)
1208{
1209 int ret = 0;
1210
1211 switch (pld_get_bus_type(dev)) {
1212 case PLD_BUS_TYPE_SNOC:
1213 ret = pld_snoc_get_soc_info(info);
1214 break;
1215 case PLD_BUS_TYPE_PCIE:
1216 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301217 case PLD_BUS_TYPE_SDIO:
1218 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001219 default:
1220 ret = -EINVAL;
1221 break;
1222 }
1223
1224 return ret;
1225}
1226
1227/**
1228 * pld_get_ce_id() - Get CE number for the provided IRQ
1229 * @dev: device
1230 * @irq: IRQ number
1231 *
1232 * Return: CE number
1233 */
1234int pld_get_ce_id(struct device *dev, int irq)
1235{
1236 int ret = 0;
1237
1238 switch (pld_get_bus_type(dev)) {
1239 case PLD_BUS_TYPE_SNOC:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001240 ret = pld_snoc_get_ce_id(irq);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001241 break;
1242 case PLD_BUS_TYPE_PCIE:
1243 ret = pld_pcie_get_ce_id(irq);
1244 break;
1245 default:
1246 ret = -EINVAL;
1247 break;
1248 }
1249
1250 return ret;
1251}
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001252
1253/**
Yuanyuan Liuf2ee05f2016-07-27 16:52:52 -07001254 * pld_get_irq() - Get IRQ number for given CE ID
1255 * @dev: device
1256 * @ce_id: CE ID
1257 *
1258 * Return: IRQ number
1259 */
1260int pld_get_irq(struct device *dev, int ce_id)
1261{
1262 int ret = 0;
1263
1264 switch (pld_get_bus_type(dev)) {
1265 case PLD_BUS_TYPE_SNOC:
1266 ret = pld_snoc_get_irq(ce_id);
1267 break;
1268 case PLD_BUS_TYPE_PCIE:
1269 default:
1270 ret = -EINVAL;
1271 break;
1272 }
1273
1274 return ret;
1275}
1276
1277/**
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001278 * pld_lock_pm_sem() - Lock PM semaphore
1279 * @dev: device
1280 *
1281 * Return: void
1282 */
1283void pld_lock_pm_sem(struct device *dev)
1284{
1285 switch (pld_get_bus_type(dev)) {
1286 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001287 pld_pcie_lock_pm_sem();
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001288 break;
1289 case PLD_BUS_TYPE_SNOC:
1290 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301291 case PLD_BUS_TYPE_SDIO:
1292 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -07001293 case PLD_BUS_TYPE_USB:
1294 break;
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001295 default:
1296 pr_err("Invalid device type\n");
1297 break;
1298 }
1299}
1300
1301/**
1302 * pld_release_pm_sem() - Release PM semaphore
1303 * @dev: device
1304 *
1305 * Return: void
1306 */
1307void pld_release_pm_sem(struct device *dev)
1308{
1309 switch (pld_get_bus_type(dev)) {
1310 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu59f81e02016-05-19 16:17:38 -07001311 pld_pcie_release_pm_sem();
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001312 break;
1313 case PLD_BUS_TYPE_SNOC:
1314 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301315 case PLD_BUS_TYPE_SDIO:
1316 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -07001317 case PLD_BUS_TYPE_USB:
1318 break;
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001319 default:
1320 pr_err("Invalid device type\n");
1321 break;
1322 }
1323}
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301324
1325/**
1326 * pld_power_on() - Power on WLAN hardware
1327 * @dev: device
1328 *
1329 * Return: 0 for success
1330 * Non zero failure code for errors
1331 */
1332int pld_power_on(struct device *dev)
1333{
1334 int ret = 0;
1335
1336 switch (pld_get_bus_type(dev)) {
1337 case PLD_BUS_TYPE_PCIE:
1338 ret = pld_pcie_power_on(dev);
1339 break;
1340 case PLD_BUS_TYPE_SNOC:
1341 ret = pld_snoc_power_on(dev);
1342 break;
1343 default:
1344 pr_err("Invalid device type\n");
1345 break;
1346 }
1347
1348 return ret;
1349}
1350
1351/**
1352 * pld_power_off() - Power off WLAN hardware
1353 * @dev: device
1354 *
1355 * Return: 0 for success
1356 * Non zero failure code for errors
1357 */
1358int pld_power_off(struct device *dev)
1359{
1360 int ret = 0;
1361
1362 switch (pld_get_bus_type(dev)) {
1363 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu187dcc52016-09-07 09:33:03 -07001364 ret = pld_pcie_power_off(dev);
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301365 break;
1366 case PLD_BUS_TYPE_SNOC:
1367 ret = pld_snoc_power_off(dev);
1368 break;
1369 default:
1370 pr_err("Invalid device type\n");
1371 break;
1372 }
1373
1374 return ret;
1375}
Yuanyuan Liu5ef6bfe2016-06-16 14:13:07 -07001376
1377/**
1378 * pld_athdiag_read() - Read data from WLAN FW
1379 * @dev: device
1380 * @offset: address offset
1381 * @memtype: memory type
1382 * @datalen: data length
1383 * @output: output buffer
1384 *
1385 * Return: 0 for success
1386 * Non zero failure code for errors
1387 */
1388int pld_athdiag_read(struct device *dev, uint32_t offset,
1389 uint32_t memtype, uint32_t datalen,
1390 uint8_t *output)
1391{
1392 int ret = 0;
1393
1394 switch (pld_get_bus_type(dev)) {
1395 case PLD_BUS_TYPE_SNOC:
1396 ret = pld_snoc_athdiag_read(dev, offset, memtype,
1397 datalen, output);
1398 break;
1399 case PLD_BUS_TYPE_PCIE:
1400 case PLD_BUS_TYPE_SDIO:
1401 case PLD_BUS_TYPE_USB:
1402 break;
1403 default:
1404 ret = -EINVAL;
1405 break;
1406 }
1407
1408 return ret;
1409}
1410
1411/**
1412 * pld_athdiag_write() - Write data to WLAN FW
1413 * @dev: device
1414 * @offset: address offset
1415 * @memtype: memory type
1416 * @datalen: data length
1417 * @input: input buffer
1418 *
1419 * Return: 0 for success
1420 * Non zero failure code for errors
1421 */
1422int pld_athdiag_write(struct device *dev, uint32_t offset,
1423 uint32_t memtype, uint32_t datalen,
1424 uint8_t *input)
1425{
1426 int ret = 0;
1427
1428 switch (pld_get_bus_type(dev)) {
1429 case PLD_BUS_TYPE_SNOC:
1430 ret = pld_snoc_athdiag_write(dev, offset, memtype,
1431 datalen, input);
1432 break;
1433 case PLD_BUS_TYPE_PCIE:
1434 case PLD_BUS_TYPE_SDIO:
1435 case PLD_BUS_TYPE_USB:
1436 break;
1437 default:
1438 ret = -EINVAL;
1439 break;
1440 }
1441
1442 return ret;
1443}
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001444
1445/**
1446 * pld_smmu_get_mapping() - Get SMMU mapping context
1447 * @dev: device
1448 *
1449 * Return: Pointer to the mapping context
1450 */
1451void *pld_smmu_get_mapping(struct device *dev)
1452{
1453 void *ptr = NULL;
1454 enum pld_bus_type type = pld_get_bus_type(dev);
1455
1456 switch (type) {
1457 case PLD_BUS_TYPE_SNOC:
1458 ptr = pld_snoc_smmu_get_mapping(dev);
1459 break;
1460 case PLD_BUS_TYPE_PCIE:
1461 pr_err("Not supported on type %d\n", type);
1462 break;
1463 default:
1464 pr_err("Invalid device type %d\n", type);
1465 break;
1466 }
1467
1468 return ptr;
1469}
1470
1471/**
1472 * pld_smmu_map() - Map SMMU
1473 * @dev: device
1474 * @paddr: physical address that needs to map to
1475 * @iova_addr: IOVA address
1476 * @size: size to be mapped
1477 *
1478 * Return: 0 for success
1479 * Non zero failure code for errors
1480 */
1481int pld_smmu_map(struct device *dev, phys_addr_t paddr,
1482 uint32_t *iova_addr, size_t size)
1483{
1484 int ret = 0;
1485 enum pld_bus_type type = pld_get_bus_type(dev);
1486
1487 switch (type) {
1488 case PLD_BUS_TYPE_SNOC:
1489 ret = pld_snoc_smmu_map(dev, paddr, iova_addr, size);
1490 break;
1491 case PLD_BUS_TYPE_PCIE:
1492 pr_err("Not supported on type %d\n", type);
1493 ret = -ENODEV;
1494 break;
1495 default:
1496 pr_err("Invalid device type %d\n", type);
1497 ret = -EINVAL;
1498 break;
1499 }
1500
1501 return ret;
1502}
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001503
1504/**
1505 * pld_socinfo_get_serial_number() - Get SOC serial number
1506 * @dev: device
1507 *
1508 * Return: SOC serial number
1509 */
1510unsigned int pld_socinfo_get_serial_number(struct device *dev)
1511{
1512 unsigned int ret = 0;
1513 enum pld_bus_type type = pld_get_bus_type(dev);
1514
1515 switch (type) {
1516 case PLD_BUS_TYPE_SNOC:
1517 ret = pld_snoc_socinfo_get_serial_number(dev);
1518 break;
1519 case PLD_BUS_TYPE_PCIE:
1520 pr_err("Not supported on type %d\n", type);
1521 break;
1522 default:
1523 pr_err("Invalid device type %d\n", type);
1524 break;
1525 }
1526
1527 return ret;
1528}
Komal Seelam355b1472016-09-02 14:36:21 +05301529
1530/*
1531 * pld_common_get_wlan_mac_address() - API to query MAC address from Platform
1532 * Driver
1533 * @dev: Device Structure
1534 * @num: Pointer to number of MAC address supported
1535 *
1536 * Platform Driver can have MAC address stored. This API needs to be used
1537 * to get those MAC address
1538 *
1539 * Return: Pointer to the list of MAC address
1540 */
1541uint8_t *pld_common_get_wlan_mac_address(struct device *dev, uint32_t *num)
1542{
1543 switch (pld_get_bus_type(dev)) {
1544 case PLD_BUS_TYPE_PCIE:
1545 return pld_pcie_get_wlan_mac_address(dev, num);
1546 case PLD_BUS_TYPE_SDIO:
1547 return pld_sdio_get_wlan_mac_address(dev, num);
1548 case PLD_BUS_TYPE_USB:
1549 case PLD_BUS_TYPE_SNOC:
1550 break;
1551 default:
1552 pr_err("Invalid device type\n");
1553 break;
1554 }
1555
1556 *num = 0;
1557 return NULL;
1558}
Hardik Kantilal Patel9689e932016-10-18 19:02:39 +05301559
1560/**
1561 * pld_is_qmi_disable() - Check QMI support is present or not
1562 * @dev: device
1563 *
1564 * Return: 1 QMI is not supported
1565 * 0 QMI is supported
1566 * Non zero failure code for errors
1567 */
1568int pld_is_qmi_disable(struct device *dev)
1569{
1570 int ret = 0;
1571 enum pld_bus_type type = pld_get_bus_type(dev);
1572
1573 switch (type) {
1574 case PLD_BUS_TYPE_SNOC:
1575 ret = pld_snoc_is_qmi_disable();
1576 break;
1577 case PLD_BUS_TYPE_PCIE:
1578 case PLD_BUS_TYPE_SDIO:
1579 pr_err("Not supported on type %d\n", type);
1580 ret = -EINVAL;
1581 break;
1582 default:
1583 pr_err("Invalid device type %d\n", type);
1584 ret = -EINVAL;
1585 break;
1586 }
1587
1588 return ret;
1589}