blob: cc9cdb322f0d114742dcd290ba9359691e62d648 [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
Yuanyuan Liu11f526a2016-05-18 10:22:07 -070037#if defined(CONFIG_PLD_PCIE_CNSS) || defined(CONFIG_PLD_SDIO_CNSS)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080038#include <net/cnss.h>
39#endif
Yuanyuan Liu11f526a2016-05-18 10:22:07 -070040#ifdef CONFIG_PLD_SNOC_ICNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080041#include <soc/qcom/icnss.h>
42#endif
43
44#include "pld_pcie.h"
45#include "pld_snoc.h"
46#include "pld_common.h"
47#include "pld_internal.h"
48
49#define PLD_PCIE_REGISTERED BIT(0)
50#define PLD_SNOC_REGISTERED BIT(1)
Yuanyuan Liu13481082016-06-02 10:28:44 -070051#define PLD_BUS_MASK 0x3
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080052
53static struct pld_context *pld_ctx;
54
55/**
56 * pld_init() - Initialize PLD module
57 *
58 * Return: 0 for success
59 * Non zero failure code for errors
60 */
61int pld_init(void)
62{
63 struct pld_context *pld_context;
64
65 pld_context = kzalloc(sizeof(*pld_context), GFP_KERNEL);
66 if (!pld_context)
67 return -ENOMEM;
68
69 spin_lock_init(&pld_context->pld_lock);
70
71 INIT_LIST_HEAD(&pld_context->dev_list);
72
73 pld_ctx = pld_context;
74
75 return 0;
76}
77
78/**
79 * pld_deinit() - Uninitialize PLD module
80 *
81 * Return: void
82 */
83void pld_deinit(void)
84{
85 struct dev_node *dev_node;
86 struct pld_context *pld_context;
87 unsigned long flags;
88
89 pld_context = pld_ctx;
90 if (!pld_context) {
91 pld_ctx = NULL;
92 return;
93 }
94
95 spin_lock_irqsave(&pld_context->pld_lock, flags);
96 while (!list_empty(&pld_context->dev_list)) {
97 dev_node = list_first_entry(&pld_context->dev_list,
98 struct dev_node, list);
99 list_del(&dev_node->list);
100 kfree(dev_node);
101 }
102 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
103
104 kfree(pld_context);
105
106 pld_ctx = NULL;
107}
108
109/**
110 * pld_get_global_context() - Get global context of PLD
111 *
112 * Return: PLD global context
113 */
114struct pld_context *pld_get_global_context(void)
115{
116 return pld_ctx;
117}
118
119/**
120 * pld_get_bus_type() - Bus type of the device
121 * @dev: device
122 *
123 * Return: PLD bus type
124 */
125enum pld_bus_type pld_get_bus_type(struct device *dev)
126{
127 struct pld_context *pld_context;
128 struct dev_node *dev_node;
129 unsigned long flags;
130
131 pld_context = pld_get_global_context();
132
133 if (dev == NULL || pld_context == NULL) {
134 pr_err("Invalid info: dev %p, context %p\n",
135 dev, pld_context);
136 return PLD_BUS_TYPE_NONE;
137 }
138
139 spin_lock_irqsave(&pld_context->pld_lock, flags);
140 list_for_each_entry(dev_node, &pld_context->dev_list, list) {
141 if (dev_node->dev == dev) {
142 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
143 return dev_node->bus_type;
144 }
145 }
146 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
147
148 return PLD_BUS_TYPE_NONE;
149}
150
151/**
152 * pld_register_driver() - Register driver to kernel
153 * @ops: Callback functions that will be registered to kernel
154 *
155 * This function should be called when other modules want to
156 * register platform driver callback functions to kernel. The
157 * probe() is expected to be called after registration if the
158 * device is online.
159 *
160 * Return: 0 for success
Yuanyuan Liu13481082016-06-02 10:28:44 -0700161 * pld_driver_state for errors
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800162 */
163int pld_register_driver(struct pld_driver_ops *ops)
164{
165 int ret = 0;
166 struct pld_context *pld_context;
167
168 pld_context = pld_get_global_context();
169
170 if (pld_context == NULL) {
171 pr_err("global context is NULL\n");
172 ret = -ENODEV;
173 goto out;
174 }
175
176 if (pld_context->ops) {
177 pr_err("driver already registered\n");
178 ret = -EEXIST;
179 goto out;
180 }
181
182 if (!ops || !ops->probe || !ops->remove ||
183 !ops->suspend || !ops->resume) {
184 pr_err("Required callback functions are missing\n");
185 ret = -EINVAL;
186 goto out;
187 }
188
189 pld_context->ops = ops;
190
191 if (0 == pld_pcie_register_driver())
192 pld_context->pld_driver_state |= PLD_PCIE_REGISTERED;
193 if (0 == pld_snoc_register_driver())
194 pld_context->pld_driver_state |= PLD_SNOC_REGISTERED;
195
Yuanyuan Liu13481082016-06-02 10:28:44 -0700196 if ((PLD_BUS_MASK & pld_context->pld_driver_state) != PLD_BUS_MASK) {
197 pr_err("driver falied to register, state %x\n",
198 pld_context->pld_driver_state);
199 ret = pld_context->pld_driver_state;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800200 }
201
202out:
203 return ret;
204}
205
206/**
207 * pld_unregister_driver() - Unregister driver to kernel
208 *
209 * This function should be called when other modules want to
210 * unregister callback functions from kernel. The remove() is
211 * expected to be called after registration.
212 *
213 * Return: void
214 */
215void pld_unregister_driver(void)
216{
217 struct pld_context *pld_context;
218
219 pld_context = pld_get_global_context();
220
221 if (pld_context == NULL) {
222 pr_err("global context is NULL\n");
223 return;
224 }
225
226 if (pld_context->ops == NULL) {
227 pr_err("driver not registered\n");
228 return;
229 }
230
231 pld_pcie_unregister_driver();
232 pld_snoc_unregister_driver();
233
234 pld_context->pld_driver_state = 0;
235
236 pld_context->ops = NULL;
237}
238
239/**
240 * pld_wlan_enable() - Enable WLAN
241 * @dev: device
242 * @config: WLAN configuration data
243 * @mode: WLAN mode
244 * @host_version: host software version
245 *
246 * This function enables WLAN FW. It passed WLAN configuration data,
247 * WLAN mode and host software version to FW.
248 *
249 * Return: 0 for success
250 * Non zero failure code for errors
251 */
252int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
253 enum pld_driver_mode mode, const char *host_version)
254{
255 int ret = 0;
256
257 switch (pld_get_bus_type(dev)) {
258 case PLD_BUS_TYPE_PCIE:
259 ret = pld_pcie_wlan_enable(config, mode, host_version);
260 break;
261 case PLD_BUS_TYPE_SNOC:
262 ret = pld_snoc_wlan_enable(config, mode, host_version);
263 break;
264 default:
265 ret = -EINVAL;
266 break;
267 }
268
269 return ret;
270}
271
272/**
273 * pld_wlan_disable() - Disable WLAN
274 * @dev: device
275 * @mode: WLAN mode
276 *
277 * This function disables WLAN FW. It passes WLAN mode to FW.
278 *
279 * Return: 0 for success
280 * Non zero failure code for errors
281 */
282int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode)
283{
284 int ret = 0;
285
286 switch (pld_get_bus_type(dev)) {
287 case PLD_BUS_TYPE_PCIE:
288 ret = pld_pcie_wlan_disable(mode);
289 break;
290 case PLD_BUS_TYPE_SNOC:
291 ret = pld_snoc_wlan_disable(mode);
292 break;
293 default:
294 ret = -EINVAL;
295 break;
296 }
297
298 return ret;
299}
300
301/**
302 * pld_set_fw_debug_mode() - Set FW debug mode
303 * @dev: device
304 * @enablefwlog: 0 for QXDM, 1 for WMI
305 *
306 * Switch Fw debug mode between DIAG logging and WMI logging.
307 *
308 * Return: 0 for success
309 * Non zero failure code for errors
310 */
311int pld_set_fw_debug_mode(struct device *dev, bool enablefwlog)
312{
313 int ret = 0;
314
315 switch (pld_get_bus_type(dev)) {
316 case PLD_BUS_TYPE_PCIE:
317 ret = pld_pcie_set_fw_debug_mode(enablefwlog);
318 break;
319 case PLD_BUS_TYPE_SNOC:
320 break;
321 default:
322 ret = -EINVAL;
323 break;
324 }
325
326 return ret;
327}
328
329/**
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700330 * pld_get_default_fw_files() - Get default FW file names
331 * @pfw_files: buffer for FW file names
332 *
333 * Return default FW file names to the buffer.
334 *
335 * Return: void
336 */
337void pld_get_default_fw_files(struct pld_fw_files *pfw_files)
338{
339 memset(pfw_files, 0, sizeof(*pfw_files));
340
341 strlcpy(pfw_files->image_file, PLD_IMAGE_FILE,
342 PLD_MAX_FILE_NAME);
343 strlcpy(pfw_files->board_data, PLD_BOARD_DATA_FILE,
344 PLD_MAX_FILE_NAME);
345 strlcpy(pfw_files->otp_data, PLD_OTP_FILE,
346 PLD_MAX_FILE_NAME);
347 strlcpy(pfw_files->utf_file, PLD_UTF_FIRMWARE_FILE,
348 PLD_MAX_FILE_NAME);
349 strlcpy(pfw_files->utf_board_data, PLD_BOARD_DATA_FILE,
350 PLD_MAX_FILE_NAME);
351 strlcpy(pfw_files->epping_file, PLD_EPPING_FILE,
352 PLD_MAX_FILE_NAME);
353 strlcpy(pfw_files->setup_file, PLD_SETUP_FILE,
354 PLD_MAX_FILE_NAME);
355}
356
357/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800358 * pld_get_fw_files_for_target() - Get FW file names
359 * @dev: device
360 * @pfw_files: buffer for FW file names
361 * @target_type: target type
362 * @target_version: target version
363 *
364 * Return target specific FW file names to the buffer.
365 *
366 * Return: 0 for success
367 * Non zero failure code for errors
368 */
369int pld_get_fw_files_for_target(struct device *dev,
370 struct pld_fw_files *pfw_files,
371 u32 target_type, u32 target_version)
372{
373 int ret = 0;
374
375 switch (pld_get_bus_type(dev)) {
376 case PLD_BUS_TYPE_PCIE:
377 ret = pld_pcie_get_fw_files_for_target(pfw_files,
378 target_type, target_version);
379 break;
380 case PLD_BUS_TYPE_SNOC:
381 break;
382 default:
383 ret = -EINVAL;
384 break;
385 }
386
387 return ret;
388}
389
390/**
391 * pld_get_fw_image() - Get FW image descriptor
392 * @dev: device
393 * @image_desc_info: buffer for image descriptor
394 *
395 * Return FW image descriptor to the buffer.
396 *
397 * Return: 0 for success
398 * Non zero failure code for errors
399 */
400int pld_get_fw_image(struct device *dev,
401 struct pld_image_desc_info *image_desc_info)
402{
403 int ret = 0;
404
405 switch (pld_get_bus_type(dev)) {
406 case PLD_BUS_TYPE_PCIE:
407 ret = pld_pcie_get_fw_image(image_desc_info);
408 break;
409 case PLD_BUS_TYPE_SNOC:
410 break;
411 default:
412 ret = -EINVAL;
413 break;
414 }
415
416 return ret;
417}
418
419/**
420 * pld_is_pci_link_down() - Notification for pci link down event
421 * @dev: device
422 *
423 * Notify platform that pci link is down.
424 *
425 * Return: void
426 */
427void pld_is_pci_link_down(struct device *dev)
428{
429 switch (pld_get_bus_type(dev)) {
430 case PLD_BUS_TYPE_PCIE:
431 cnss_wlan_pci_link_down();
432 break;
433 case PLD_BUS_TYPE_SNOC:
434 break;
435 default:
436 pr_err("Invalid device type\n");
437 break;
438 }
439}
440
441/**
442 * pld_pcie_shadow_control() - Control pci shadow registers
443 * @dev: device
444 * @enable: 0 for disable, 1 for enable
445 *
446 * This function is for suspend/resume. It can control if we
447 * use pci shadow registers (for saving config space) or not.
448 * During suspend we disable it to avoid config space corruption.
449 *
450 * Return: 0 for success
451 * Non zero failure code for errors
452 */
453int pld_pcie_shadow_control(struct device *dev, bool enable)
454{
455 int ret = 0;
456
457 /* cnss_shadow_control is not supported on BF64.0.3 kernel yet
458 switch (pld_get_bus_type(dev)) {
459 case PLD_BUS_TYPE_PCIE:
460 ret = cnss_shadow_control(enable);
461 break;
462 case PLD_BUS_TYPE_SNOC:
463 break;
464 default:
465 ret = -EINVAL;
466 break;
467 }
468 */
469 return ret;
470}
471
472/**
473 * pld_get_codeswap_struct() - Get codeswap structure
474 * @dev: device
475 * @swap_seg: buffer to codeswap information
476 *
477 * Return codeswap structure information to the buffer.
478 *
479 * Return: 0 for success
480 * Non zero failure code for errors
481 */
482int pld_get_codeswap_struct(struct device *dev,
483 struct pld_codeswap_codeseg_info *swap_seg)
484{
485 int ret = 0;
486
487 switch (pld_get_bus_type(dev)) {
488 case PLD_BUS_TYPE_PCIE:
489 ret = pld_pcie_get_codeswap_struct(swap_seg);
490 break;
491 case PLD_BUS_TYPE_SNOC:
492 break;
493 default:
494 ret = -EINVAL;
495 break;
496 }
497
498 return ret;
499}
500
501/**
502 * pld_set_wlan_unsafe_channel() - Set unsafe channel
503 * @dev: device
504 * @unsafe_ch_list: unsafe channel list
505 * @ch_count: number of channel
506 *
507 * Return: 0 for success
508 * Non zero failure code for errors
509 */
510int pld_set_wlan_unsafe_channel(struct device *dev,
511 u16 *unsafe_ch_list, u16 ch_count)
512{
513 int ret = 0;
514
515 switch (pld_get_bus_type(dev)) {
516 case PLD_BUS_TYPE_PCIE:
517 ret = cnss_set_wlan_unsafe_channel(unsafe_ch_list,
518 ch_count);
519 break;
520 case PLD_BUS_TYPE_SNOC:
521 break;
522 default:
523 ret = -EINVAL;
524 break;
525 }
526
527 return ret;
528}
529
530/**
531 * pld_get_wlan_unsafe_channel() - Get unsafe channel
532 * @dev: device
533 * @unsafe_ch_list: buffer to unsafe channel list
534 * @ch_count: number of channel
535 * @buf_len: buffer length
536 *
537 * Return WLAN unsafe channel to the buffer.
538 *
539 * Return: 0 for success
540 * Non zero failure code for errors
541 */
542int pld_get_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list,
543 u16 *ch_count, u16 buf_len)
544{
545 int ret = 0;
546
547 switch (pld_get_bus_type(dev)) {
548 case PLD_BUS_TYPE_PCIE:
549 ret = cnss_get_wlan_unsafe_channel(unsafe_ch_list,
550 ch_count, buf_len);
551 break;
552 case PLD_BUS_TYPE_SNOC:
553 break;
554 default:
555 ret = -EINVAL;
556 break;
557 }
558
559 return ret;
560}
561
562/**
563 * pld_wlan_set_dfs_nol() - Set DFS info
564 * @dev: device
565 * @info: DFS info
566 * @info_len: info length
567 *
568 * Return: 0 for success
569 * Non zero failure code for errors
570 */
571int pld_wlan_set_dfs_nol(struct device *dev, void *info, u16 info_len)
572{
573 int ret = 0;
574
575 switch (pld_get_bus_type(dev)) {
576 case PLD_BUS_TYPE_PCIE:
577 ret = cnss_wlan_set_dfs_nol(info, info_len);
578 break;
579 case PLD_BUS_TYPE_SNOC:
580 break;
581 default:
582 ret = -EINVAL;
583 break;
584 }
585
586 return ret;
587}
588
589/**
590 * pld_wlan_get_dfs_nol() - Get DFS info
591 * @dev: device
592 * @info: buffer to DFS info
593 * @info_len: info length
594 *
595 * Return DFS info to the buffer.
596 *
597 * Return: 0 for success
598 * Non zero failure code for errors
599 */
600int pld_wlan_get_dfs_nol(struct device *dev, void *info, u16 info_len)
601{
602 int ret = 0;
603
604 switch (pld_get_bus_type(dev)) {
605 case PLD_BUS_TYPE_PCIE:
606 ret = cnss_wlan_get_dfs_nol(info, info_len);
607 break;
608 case PLD_BUS_TYPE_SNOC:
609 break;
610 default:
611 ret = -EINVAL;
612 break;
613 }
614
615 return ret;
616}
617
618/**
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700619 * pld_schedule_recovery_work() - Schedule recovery work
620 * @dev: device
621 *
622 * Schedule a system self recovery work.
623 *
624 * Return: void
625 */
626void pld_schedule_recovery_work(struct device *dev)
627{
628 switch (pld_get_bus_type(dev)) {
629 case PLD_BUS_TYPE_PCIE:
630 cnss_schedule_recovery_work();
631 break;
632 case PLD_BUS_TYPE_SNOC:
633 break;
634 default:
635 pr_err("Invalid device type\n");
636 break;
637 }
638}
639
640/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800641 * pld_wlan_pm_control() - WLAN PM control on PCIE
642 * @dev: device
643 * @vote: 0 for enable PCIE PC, 1 for disable PCIE PC
644 *
645 * This is for PCIE power collaps control during suspend/resume.
646 * When PCIE power collaps is disabled, WLAN FW can access memory
647 * through PCIE when system is suspended.
648 *
649 * Return: 0 for success
650 * Non zero failure code for errors
651 */
652int pld_wlan_pm_control(struct device *dev, bool vote)
653{
654 int ret = 0;
655
656 switch (pld_get_bus_type(dev)) {
657 case PLD_BUS_TYPE_PCIE:
658 ret = cnss_wlan_pm_control(vote);
659 break;
660 case PLD_BUS_TYPE_SNOC:
661 break;
662 default:
663 ret = -EINVAL;
664 break;
665 }
666
667 return ret;
668}
669
670/**
671 * pld_get_virt_ramdump_mem() - Get virtual ramdump memory
672 * @dev: device
673 * @size: buffer to virtual memory size
674 *
675 * Return: virtual ramdump memory address
676 */
677void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
678{
679 void *mem = NULL;
680
681 switch (pld_get_bus_type(dev)) {
682 case PLD_BUS_TYPE_PCIE:
683 mem = cnss_get_virt_ramdump_mem(size);
684 break;
685 case PLD_BUS_TYPE_SNOC:
686 break;
687 default:
688 pr_err("Invalid device type\n");
689 break;
690 }
691
692 return mem;
693}
694
695/**
696 * pld_device_crashed() - Notification for device crash event
697 * @dev: device
698 *
699 * Notify subsystem a device crashed event. A subsystem restart
700 * is expected to happen after calling this function.
701 *
702 * Return: void
703 */
704void pld_device_crashed(struct device *dev)
705{
706 switch (pld_get_bus_type(dev)) {
707 case PLD_BUS_TYPE_PCIE:
708 cnss_device_crashed();
709 break;
710 case PLD_BUS_TYPE_SNOC:
711 break;
712 default:
713 pr_err("Invalid device type\n");
714 break;
715 }
716}
717
718/**
719 * pld_device_self_recovery() - Device self recovery
720 * @dev: device
721 *
722 * Return: void
723 */
724void pld_device_self_recovery(struct device *dev)
725{
726 switch (pld_get_bus_type(dev)) {
727 case PLD_BUS_TYPE_PCIE:
728 cnss_device_self_recovery();
729 break;
730 case PLD_BUS_TYPE_SNOC:
731 break;
732 default:
733 pr_err("Invalid device type\n");
734 break;
735 }
736}
737
738/**
739 * pld_intr_notify_q6() - Notify Q6 FW interrupts
740 * @dev: device
741 *
742 * Notify Q6 that a FW interrupt is triggered.
743 *
744 * Return: void
745 */
746void pld_intr_notify_q6(struct device *dev)
747{
748 switch (pld_get_bus_type(dev)) {
749 case PLD_BUS_TYPE_PCIE:
750 cnss_intr_notify_q6();
751 break;
752 case PLD_BUS_TYPE_SNOC:
753 break;
754 default:
755 pr_err("Invalid device type\n");
756 break;
757 }
758}
759
760/**
761 * pld_request_pm_qos() - Request system PM
762 * @dev: device
763 * @qos_val: request value
764 *
765 * It votes for the value of aggregate QoS expectations.
766 *
767 * Return: void
768 */
769void pld_request_pm_qos(struct device *dev, u32 qos_val)
770{
771 switch (pld_get_bus_type(dev)) {
772 case PLD_BUS_TYPE_PCIE:
773 cnss_request_pm_qos(qos_val);
774 break;
775 case PLD_BUS_TYPE_SNOC:
776 break;
777 default:
778 pr_err("Invalid device type\n");
779 break;
780 }
781}
782
783/**
784 * pld_remove_pm_qos() - Remove system PM
785 * @dev: device
786 *
787 * Remove the vote request for Qos expectations.
788 *
789 * Return: void
790 */
791void pld_remove_pm_qos(struct device *dev)
792{
793 switch (pld_get_bus_type(dev)) {
794 case PLD_BUS_TYPE_PCIE:
795 cnss_remove_pm_qos();
796 break;
797 case PLD_BUS_TYPE_SNOC:
798 break;
799 default:
800 pr_err("Invalid device type\n");
801 break;
802 }
803}
804
805/**
806 * pld_request_bus_bandwidth() - Request bus bandwidth
807 * @dev: device
808 * @bandwidth: bus bandwidth
809 *
810 * Votes for HIGH/MEDIUM/LOW bus bandwidth.
811 *
812 * Return: 0 for success
813 * Non zero failure code for errors
814 */
815int pld_request_bus_bandwidth(struct device *dev, int bandwidth)
816{
817 int ret = 0;
818
819 switch (pld_get_bus_type(dev)) {
820 case PLD_BUS_TYPE_PCIE:
821 ret = cnss_request_bus_bandwidth(bandwidth);
822 break;
823 case PLD_BUS_TYPE_SNOC:
824 break;
825 default:
826 ret = -EINVAL;
827 break;
828 }
829
830 return ret;
831}
832
833/**
834 * pld_get_platform_cap() - Get platform capabilities
835 * @dev: device
836 * @cap: buffer to the capabilities
837 *
838 * Return capabilities to the buffer.
839 *
840 * Return: 0 for success
841 * Non zero failure code for errors
842 */
843int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
844{
845 int ret = 0;
846
847 switch (pld_get_bus_type(dev)) {
848 case PLD_BUS_TYPE_PCIE:
849 ret = pld_pcie_get_platform_cap(cap);
850 break;
851 case PLD_BUS_TYPE_SNOC:
852 break;
853 default:
854 ret = -EINVAL;
855 break;
856 }
857
858 return ret;
859}
860
861/**
862 * pld_set_driver_status() - Set driver status
863 * @dev: device
864 * @status: driver status
865 *
866 * Return: void
867 */
868void pld_set_driver_status(struct device *dev, enum pld_driver_status status)
869{
870 switch (pld_get_bus_type(dev)) {
871 case PLD_BUS_TYPE_PCIE:
872 pld_pcie_set_driver_status(status);
873 break;
874 case PLD_BUS_TYPE_SNOC:
875 break;
876 default:
877 pr_err("Invalid device type\n");
878 break;
879 }
880}
881
882/**
883 * pld_get_bmi_setup() - Get BMI setup
884 * @dev: device
885 *
886 * BMI read/write test should be run if BMI test is enabled.
887 *
888 * Return: BMI test setup
889 */
890int pld_get_bmi_setup(struct device *dev)
891{
892 int ret = 0;
893
894 switch (pld_get_bus_type(dev)) {
895 case PLD_BUS_TYPE_PCIE:
896 ret = cnss_get_bmi_setup();
897 break;
898 case PLD_BUS_TYPE_SNOC:
899 break;
900 default:
901 ret = -EINVAL;
902 break;
903 }
904
905 return ret;
906}
907
908/**
909 * pld_get_sha_hash() - Get sha hash number
910 * @dev: device
911 * @data: input data
912 * @data_len: data length
913 * @hash_idx: hash index
914 * @out: output buffer
915 *
916 * Return computed hash to the out buffer.
917 *
918 * Return: 0 for success
919 * Non zero failure code for errors
920 */
921int pld_get_sha_hash(struct device *dev, const u8 *data,
922 u32 data_len, u8 *hash_idx, u8 *out)
923{
924 int ret = 0;
925
926 switch (pld_get_bus_type(dev)) {
927 case PLD_BUS_TYPE_PCIE:
928 ret = cnss_get_sha_hash(data, data_len,
929 hash_idx, out);
930 break;
931 case PLD_BUS_TYPE_SNOC:
932 break;
933 default:
934 ret = -EINVAL;
935 break;
936 }
937
938 return ret;
939}
940
941/**
942 * pld_get_fw_ptr() - Get secure FW memory address
943 * @dev: device
944 *
945 * Return: secure memory address
946 */
947void *pld_get_fw_ptr(struct device *dev)
948{
949 void *ptr = NULL;
950
951 switch (pld_get_bus_type(dev)) {
952 case PLD_BUS_TYPE_PCIE:
953 ptr = cnss_get_fw_ptr();
954 break;
955 case PLD_BUS_TYPE_SNOC:
956 break;
957 default:
958 pr_err("Invalid device type\n");
959 break;
960 }
961
962 return ptr;
963}
964
965/**
966 * pld_auto_suspend() - Auto suspend
967 * @dev: device
968 *
969 * Return: 0 for success
970 * Non zero failure code for errors
971 */
972int pld_auto_suspend(struct device *dev)
973{
974 int ret = 0;
975
976 switch (pld_get_bus_type(dev)) {
977 case PLD_BUS_TYPE_PCIE:
978 ret = cnss_auto_suspend();
979 break;
980 case PLD_BUS_TYPE_SNOC:
981 break;
982 default:
983 ret = -EINVAL;
984 break;
985 }
986
987 return ret;
988}
989
990/**
991 * pld_auto_resume() - Auto resume
992 * @dev: device
993 *
994 * Return: 0 for success
995 * Non zero failure code for errors
996 */
997int pld_auto_resume(struct device *dev)
998{
999 int ret = 0;
1000
1001 switch (pld_get_bus_type(dev)) {
1002 case PLD_BUS_TYPE_PCIE:
1003 ret = cnss_auto_resume();
1004 break;
1005 case PLD_BUS_TYPE_SNOC:
1006 break;
1007 default:
1008 ret = -EINVAL;
1009 break;
1010 }
1011
1012 return ret;
1013}
1014
1015/**
1016 * pld_ce_request_irq() - Register IRQ for CE
1017 * @dev: device
1018 * @ce_id: CE number
1019 * @handler: IRQ callback function
1020 * @flags: IRQ flags
1021 * @name: IRQ name
1022 * @ctx: IRQ context
1023 *
1024 * Return: 0 for success
1025 * Non zero failure code for errors
1026 */
1027int pld_ce_request_irq(struct device *dev, unsigned int ce_id,
1028 irqreturn_t (*handler)(int, void *),
1029 unsigned long flags, const char *name, void *ctx)
1030{
1031 int ret = 0;
1032
1033 switch (pld_get_bus_type(dev)) {
1034 case PLD_BUS_TYPE_SNOC:
1035 ret = icnss_ce_request_irq(ce_id, handler, flags, name, ctx);
1036 break;
1037 case PLD_BUS_TYPE_PCIE:
1038 break;
1039 default:
1040 ret = -EINVAL;
1041 break;
1042 }
1043
1044 return ret;
1045}
1046
1047/**
1048 * pld_ce_free_irq() - Free IRQ for CE
1049 * @dev: device
1050 * @ce_id: CE number
1051 * @ctx: IRQ context
1052 *
1053 * Return: 0 for success
1054 * Non zero failure code for errors
1055 */
1056int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx)
1057{
1058 int ret = 0;
1059
1060 switch (pld_get_bus_type(dev)) {
1061 case PLD_BUS_TYPE_SNOC:
1062 ret = icnss_ce_free_irq(ce_id, ctx);
1063 break;
1064 case PLD_BUS_TYPE_PCIE:
1065 break;
1066 default:
1067 ret = -EINVAL;
1068 break;
1069 }
1070
1071 return ret;
1072}
1073
1074/**
1075 * pld_enable_irq() - Enable IRQ for CE
1076 * @dev: device
1077 * @ce_id: CE number
1078 *
1079 * Return: void
1080 */
1081void pld_enable_irq(struct device *dev, unsigned int ce_id)
1082{
1083 switch (pld_get_bus_type(dev)) {
1084 case PLD_BUS_TYPE_SNOC:
1085 icnss_enable_irq(ce_id);
1086 break;
1087 case PLD_BUS_TYPE_PCIE:
1088 break;
1089 default:
1090 pr_err("Invalid device type\n");
1091 break;
1092 }
1093}
1094
1095/**
1096 * pld_disable_irq() - Disable IRQ for CE
1097 * @dev: device
1098 * @ce_id: CE number
1099 *
1100 * Return: void
1101 */
1102void pld_disable_irq(struct device *dev, unsigned int ce_id)
1103{
1104 switch (pld_get_bus_type(dev)) {
1105 case PLD_BUS_TYPE_SNOC:
1106 icnss_disable_irq(ce_id);
1107 break;
1108 case PLD_BUS_TYPE_PCIE:
1109 break;
1110 default:
1111 pr_err("Invalid device type\n");
1112 break;
1113 }
1114}
1115
1116/**
1117 * pld_get_soc_info() - Get SOC information
1118 * @dev: device
1119 * @info: buffer to SOC information
1120 *
1121 * Return SOC info to the buffer.
1122 *
1123 * Return: 0 for success
1124 * Non zero failure code for errors
1125 */
1126int pld_get_soc_info(struct device *dev, struct pld_soc_info *info)
1127{
1128 int ret = 0;
1129
1130 switch (pld_get_bus_type(dev)) {
1131 case PLD_BUS_TYPE_SNOC:
1132 ret = pld_snoc_get_soc_info(info);
1133 break;
1134 case PLD_BUS_TYPE_PCIE:
1135 break;
1136 default:
1137 ret = -EINVAL;
1138 break;
1139 }
1140
1141 return ret;
1142}
1143
1144/**
1145 * pld_get_ce_id() - Get CE number for the provided IRQ
1146 * @dev: device
1147 * @irq: IRQ number
1148 *
1149 * Return: CE number
1150 */
1151int pld_get_ce_id(struct device *dev, int irq)
1152{
1153 int ret = 0;
1154
1155 switch (pld_get_bus_type(dev)) {
1156 case PLD_BUS_TYPE_SNOC:
1157 ret = icnss_get_ce_id(irq);
1158 break;
1159 case PLD_BUS_TYPE_PCIE:
1160 ret = pld_pcie_get_ce_id(irq);
1161 break;
1162 default:
1163 ret = -EINVAL;
1164 break;
1165 }
1166
1167 return ret;
1168}
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001169
1170/**
1171 * pld_lock_pm_sem() - Lock PM semaphore
1172 * @dev: device
1173 *
1174 * Return: void
1175 */
1176void pld_lock_pm_sem(struct device *dev)
1177{
1178 switch (pld_get_bus_type(dev)) {
1179 case PLD_BUS_TYPE_PCIE:
1180 cnss_lock_pm_sem();
1181 break;
1182 case PLD_BUS_TYPE_SNOC:
1183 break;
1184 default:
1185 pr_err("Invalid device type\n");
1186 break;
1187 }
1188}
1189
1190/**
1191 * pld_release_pm_sem() - Release PM semaphore
1192 * @dev: device
1193 *
1194 * Return: void
1195 */
1196void pld_release_pm_sem(struct device *dev)
1197{
1198 switch (pld_get_bus_type(dev)) {
1199 case PLD_BUS_TYPE_PCIE:
1200 cnss_release_pm_sem();
1201 break;
1202 case PLD_BUS_TYPE_SNOC:
1203 break;
1204 default:
1205 pr_err("Invalid device type\n");
1206 break;
1207 }
1208}