blob: 46dd193f715c58cf4ff0dee9cc8ea82c5c2cd447 [file] [log] [blame]
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001/*
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +05302 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08003 *
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080019#define pr_fmt(fmt) "wlan_pld:%s:%d:: " fmt, __func__, __LINE__
20
21#include <linux/printk.h>
22#include <linux/err.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/slab.h>
26#include <linux/pm.h>
27
Yue Mae6a7a322016-08-31 11:09:23 -070028#ifdef CONFIG_PLD_SDIO_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080029#include <net/cnss.h>
30#endif
Yue Mae6a7a322016-08-31 11:09:23 -070031#ifdef CONFIG_PLD_PCIE_CNSS
Yue Mae6a7a322016-08-31 11:09:23 -070032#include <net/cnss2.h>
33#endif
Yuanyuan Liu11f526a2016-05-18 10:22:07 -070034#ifdef CONFIG_PLD_SNOC_ICNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080035#include <soc/qcom/icnss.h>
36#endif
37
38#include "pld_pcie.h"
Naman Padhiarc52e7fd2019-06-23 01:21:42 +053039#include "pld_pcie_fw_sim.h"
40#include "pld_snoc_fw_sim.h"
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080041#include "pld_snoc.h"
Govind Singh6a2fe032016-05-13 14:09:37 +053042#include "pld_sdio.h"
Mohit Khanna1d531c42016-05-12 21:35:50 -070043#include "pld_usb.h"
Vevek Venkatesan4a031242019-06-28 17:12:49 +053044#include "qwlan_version.h"
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080045
46#define PLD_PCIE_REGISTERED BIT(0)
47#define PLD_SNOC_REGISTERED BIT(1)
Govind Singh6a2fe032016-05-13 14:09:37 +053048#define PLD_SDIO_REGISTERED BIT(2)
Mohit Khanna1d531c42016-05-12 21:35:50 -070049#define PLD_USB_REGISTERED BIT(3)
Naman Padhiarc52e7fd2019-06-23 01:21:42 +053050#define PLD_SNOC_FW_SIM_REGISTERED BIT(4)
51#define PLD_PCIE_FW_SIM_REGISTERED BIT(5)
Mohit Khanna1d531c42016-05-12 21:35:50 -070052#define PLD_BUS_MASK 0xf
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080053
54static struct pld_context *pld_ctx;
55
56/**
57 * pld_init() - Initialize PLD module
58 *
59 * Return: 0 for success
60 * Non zero failure code for errors
61 */
62int pld_init(void)
63{
64 struct pld_context *pld_context;
65
66 pld_context = kzalloc(sizeof(*pld_context), GFP_KERNEL);
67 if (!pld_context)
68 return -ENOMEM;
69
70 spin_lock_init(&pld_context->pld_lock);
71
72 INIT_LIST_HEAD(&pld_context->dev_list);
73
74 pld_ctx = pld_context;
75
76 return 0;
77}
78
79/**
80 * pld_deinit() - Uninitialize PLD module
81 *
82 * Return: void
83 */
84void pld_deinit(void)
85{
86 struct dev_node *dev_node;
87 struct pld_context *pld_context;
88 unsigned long flags;
89
90 pld_context = pld_ctx;
91 if (!pld_context) {
92 pld_ctx = NULL;
93 return;
94 }
95
96 spin_lock_irqsave(&pld_context->pld_lock, flags);
97 while (!list_empty(&pld_context->dev_list)) {
98 dev_node = list_first_entry(&pld_context->dev_list,
99 struct dev_node, list);
100 list_del(&dev_node->list);
101 kfree(dev_node);
102 }
103 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
104
105 kfree(pld_context);
106
107 pld_ctx = NULL;
108}
109
110/**
111 * pld_get_global_context() - Get global context of PLD
112 *
113 * Return: PLD global context
114 */
115struct pld_context *pld_get_global_context(void)
116{
117 return pld_ctx;
118}
119
120/**
Yuanyuan Liu5e25f532016-05-25 16:26:40 -0700121 * pld_add_dev() - Add dev node to global context
122 * @pld_context: PLD global context
123 * @dev: device
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530124 * @ifdev: interface device
Yuanyuan Liu5e25f532016-05-25 16:26:40 -0700125 * @type: Bus type
126 *
127 * Return: 0 for success
128 * Non zero failure code for errors
129 */
130int pld_add_dev(struct pld_context *pld_context,
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530131 struct device *dev, struct device *ifdev,
132 enum pld_bus_type type)
Yuanyuan Liu5e25f532016-05-25 16:26:40 -0700133{
134 unsigned long flags;
135 struct dev_node *dev_node;
136
137 dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL);
Jeff Johnson753f9d72019-03-18 13:41:04 -0700138 if (!dev_node)
Yuanyuan Liu5e25f532016-05-25 16:26:40 -0700139 return -ENOMEM;
140
141 dev_node->dev = dev;
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530142 dev_node->ifdev = ifdev;
Yuanyuan Liu5e25f532016-05-25 16:26:40 -0700143 dev_node->bus_type = type;
144
145 spin_lock_irqsave(&pld_context->pld_lock, flags);
146 list_add_tail(&dev_node->list, &pld_context->dev_list);
147 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
148
149 return 0;
150}
151
152/**
153 * pld_del_dev() - Delete dev node from global context
154 * @pld_context: PLD global context
155 * @dev: device
156 *
157 * Return: void
158 */
159void pld_del_dev(struct pld_context *pld_context,
160 struct device *dev)
161{
162 unsigned long flags;
163 struct dev_node *dev_node, *tmp;
164
165 spin_lock_irqsave(&pld_context->pld_lock, flags);
166 list_for_each_entry_safe(dev_node, tmp, &pld_context->dev_list, list) {
167 if (dev_node->dev == dev) {
168 list_del(&dev_node->list);
169 kfree(dev_node);
170 }
171 }
172 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
173}
174
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530175static struct dev_node *pld_get_dev_node(struct device *dev)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800176{
177 struct pld_context *pld_context;
178 struct dev_node *dev_node;
179 unsigned long flags;
180
181 pld_context = pld_get_global_context();
182
Jeff Johnson753f9d72019-03-18 13:41:04 -0700183 if (!dev || !pld_context) {
Jeff Johnson359e6792017-09-18 08:14:42 -0700184 pr_err("Invalid info: dev %pK, context %pK\n",
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800185 dev, pld_context);
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530186 return NULL;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800187 }
188
189 spin_lock_irqsave(&pld_context->pld_lock, flags);
190 list_for_each_entry(dev_node, &pld_context->dev_list, list) {
191 if (dev_node->dev == dev) {
192 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530193 return dev_node;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800194 }
195 }
196 spin_unlock_irqrestore(&pld_context->pld_lock, flags);
197
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530198 return NULL;
199}
200
201/**
202 * pld_get_bus_type() - Bus type of the device
203 * @dev: device
204 *
205 * Return: PLD bus type
206 */
Alan Chen50582ca2019-09-12 15:45:21 -0700207enum pld_bus_type pld_get_bus_type(struct device *dev)
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530208{
209 struct dev_node *dev_node = pld_get_dev_node(dev);
210
211 if (dev_node)
212 return dev_node->bus_type;
213 else
214 return PLD_BUS_TYPE_NONE;
215}
216
217/**
218 * pld_get_if_dev() - Bus interface/pipe dev of the device
219 * @dev: device
220 *
221 * Return: Bus sub-interface or pipe dev.
222 */
223static struct device *pld_get_if_dev(struct device *dev)
224{
225 struct dev_node *dev_node = pld_get_dev_node(dev);
226
227 if (dev_node)
228 return dev_node->ifdev;
229 else
230 return NULL;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800231}
232
233/**
234 * pld_register_driver() - Register driver to kernel
235 * @ops: Callback functions that will be registered to kernel
236 *
237 * This function should be called when other modules want to
238 * register platform driver callback functions to kernel. The
239 * probe() is expected to be called after registration if the
240 * device is online.
241 *
242 * Return: 0 for success
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700243 * Non zero failure code for errors
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800244 */
245int pld_register_driver(struct pld_driver_ops *ops)
246{
247 int ret = 0;
248 struct pld_context *pld_context;
249
250 pld_context = pld_get_global_context();
251
Jeff Johnson753f9d72019-03-18 13:41:04 -0700252 if (!pld_context) {
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800253 pr_err("global context is NULL\n");
254 ret = -ENODEV;
255 goto out;
256 }
257
258 if (pld_context->ops) {
259 pr_err("driver already registered\n");
260 ret = -EEXIST;
261 goto out;
262 }
263
264 if (!ops || !ops->probe || !ops->remove ||
265 !ops->suspend || !ops->resume) {
266 pr_err("Required callback functions are missing\n");
267 ret = -EINVAL;
268 goto out;
269 }
270
271 pld_context->ops = ops;
Mohit Khanna1d531c42016-05-12 21:35:50 -0700272 pld_context->pld_driver_state = 0;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800273
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700274 ret = pld_pcie_register_driver();
275 if (ret) {
276 pr_err("Fail to register pcie driver\n");
277 goto fail_pcie;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800278 }
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700279 pld_context->pld_driver_state |= PLD_PCIE_REGISTERED;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800280
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700281 ret = pld_snoc_register_driver();
282 if (ret) {
283 pr_err("Fail to register snoc driver\n");
284 goto fail_snoc;
285 }
286 pld_context->pld_driver_state |= PLD_SNOC_REGISTERED;
287
288 ret = pld_sdio_register_driver();
289 if (ret) {
290 pr_err("Fail to register sdio driver\n");
291 goto fail_sdio;
292 }
293 pld_context->pld_driver_state |= PLD_SDIO_REGISTERED;
294
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530295 ret = pld_snoc_fw_sim_register_driver();
296 if (ret) {
297 pr_err("Fail to register snoc fw sim driver\n");
298 goto fail_snoc_fw_sim;
299 }
300 pld_context->pld_driver_state |= PLD_SNOC_FW_SIM_REGISTERED;
301
302 ret = pld_pcie_fw_sim_register_driver();
303 if (ret) {
304 pr_err("Fail to register pcie fw sim driver\n");
305 goto fail_pcie_fw_sim;
306 }
307 pld_context->pld_driver_state |= PLD_PCIE_FW_SIM_REGISTERED;
308
Mohit Khanna1d531c42016-05-12 21:35:50 -0700309 ret = pld_usb_register_driver();
310 if (ret) {
311 pr_err("Fail to register usb driver\n");
312 goto fail_usb;
313 }
314 pld_context->pld_driver_state |= PLD_USB_REGISTERED;
315
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700316 return ret;
317
Mohit Khanna1d531c42016-05-12 21:35:50 -0700318fail_usb:
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530319 pld_pcie_fw_sim_unregister_driver();
320fail_pcie_fw_sim:
321 pld_snoc_fw_sim_unregister_driver();
322fail_snoc_fw_sim:
Mohit Khanna1d531c42016-05-12 21:35:50 -0700323 pld_sdio_unregister_driver();
Yuanyuan Liua1679b62016-07-11 15:58:12 -0700324fail_sdio:
325 pld_snoc_unregister_driver();
326fail_snoc:
327 pld_pcie_unregister_driver();
328fail_pcie:
329 pld_context->pld_driver_state = 0;
330 pld_context->ops = NULL;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800331out:
332 return ret;
333}
334
335/**
336 * pld_unregister_driver() - Unregister driver to kernel
337 *
338 * This function should be called when other modules want to
339 * unregister callback functions from kernel. The remove() is
340 * expected to be called after registration.
341 *
342 * Return: void
343 */
344void pld_unregister_driver(void)
345{
346 struct pld_context *pld_context;
347
348 pld_context = pld_get_global_context();
349
Jeff Johnson753f9d72019-03-18 13:41:04 -0700350 if (!pld_context) {
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800351 pr_err("global context is NULL\n");
352 return;
353 }
354
Jeff Johnson753f9d72019-03-18 13:41:04 -0700355 if (!pld_context->ops) {
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800356 pr_err("driver not registered\n");
357 return;
358 }
359
360 pld_pcie_unregister_driver();
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530361 pld_snoc_fw_sim_unregister_driver();
362 pld_pcie_fw_sim_unregister_driver();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800363 pld_snoc_unregister_driver();
Govind Singh6a2fe032016-05-13 14:09:37 +0530364 pld_sdio_unregister_driver();
Mohit Khanna1d531c42016-05-12 21:35:50 -0700365 pld_usb_unregister_driver();
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800366
367 pld_context->pld_driver_state = 0;
368
369 pld_context->ops = NULL;
370}
371
372/**
373 * pld_wlan_enable() - Enable WLAN
374 * @dev: device
375 * @config: WLAN configuration data
376 * @mode: WLAN mode
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800377 *
378 * This function enables WLAN FW. It passed WLAN configuration data,
379 * WLAN mode and host software version to FW.
380 *
381 * Return: 0 for success
382 * Non zero failure code for errors
383 */
384int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
Vevek Venkatesan4a031242019-06-28 17:12:49 +0530385 enum pld_driver_mode mode)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800386{
387 int ret = 0;
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530388 struct device *ifdev;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800389
390 switch (pld_get_bus_type(dev)) {
391 case PLD_BUS_TYPE_PCIE:
Vevek Venkatesan4a031242019-06-28 17:12:49 +0530392 ret = pld_pcie_wlan_enable(dev, config, mode, QWLAN_VERSIONSTR);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800393 break;
394 case PLD_BUS_TYPE_SNOC:
Vevek Venkatesan4a031242019-06-28 17:12:49 +0530395 ret = pld_snoc_wlan_enable(dev, config, mode, QWLAN_VERSIONSTR);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800396 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530397 case PLD_BUS_TYPE_SNOC_FW_SIM:
398 ret = pld_snoc_fw_sim_wlan_enable(dev, config, mode,
399 QWLAN_VERSIONSTR);
400 break;
401 case PLD_BUS_TYPE_PCIE_FW_SIM:
402 ret = pld_pcie_fw_sim_wlan_enable(dev, config, mode,
403 QWLAN_VERSIONSTR);
404 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530405 case PLD_BUS_TYPE_SDIO:
Jayachandran Sreekumaran32a0d432019-05-06 15:04:53 +0530406 ret = pld_sdio_wlan_enable(dev, config, mode, QWLAN_VERSIONSTR);
Govind Singh6a2fe032016-05-13 14:09:37 +0530407 break;
Ajit Pal Singh44273d62018-07-10 19:27:06 +0530408 case PLD_BUS_TYPE_USB:
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +0530409 ifdev = pld_get_if_dev(dev);
Vevek Venkatesan4a031242019-06-28 17:12:49 +0530410 ret = pld_usb_wlan_enable(ifdev, config, mode,
411 QWLAN_VERSIONSTR);
Ajit Pal Singh44273d62018-07-10 19:27:06 +0530412 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800413 default:
414 ret = -EINVAL;
415 break;
416 }
417
418 return ret;
419}
420
421/**
422 * pld_wlan_disable() - Disable WLAN
423 * @dev: device
424 * @mode: WLAN mode
425 *
426 * This function disables WLAN FW. It passes WLAN mode to FW.
427 *
428 * Return: 0 for success
429 * Non zero failure code for errors
430 */
431int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode)
432{
433 int ret = 0;
434
435 switch (pld_get_bus_type(dev)) {
436 case PLD_BUS_TYPE_PCIE:
Yue Ma08047522016-11-08 18:53:26 -0800437 ret = pld_pcie_wlan_disable(dev, mode);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800438 break;
439 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +0530440 ret = pld_snoc_wlan_disable(dev, mode);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800441 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530442 case PLD_BUS_TYPE_SNOC_FW_SIM:
443 ret = pld_snoc_fw_sim_wlan_disable(dev, mode);
444 break;
445 case PLD_BUS_TYPE_PCIE_FW_SIM:
446 ret = pld_pcie_fw_sim_wlan_disable(dev, mode);
447 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530448 case PLD_BUS_TYPE_SDIO:
449 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800450 default:
451 ret = -EINVAL;
452 break;
453 }
454
455 return ret;
456}
457
458/**
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -0800459 * pld_set_fw_log_mode() - Set FW debug log mode
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800460 * @dev: device
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -0800461 * @fw_log_mode: 0 for No log, 1 for WMI, 2 for DIAG
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800462 *
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -0800463 * Switch Fw debug log mode between DIAG logging and WMI logging.
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800464 *
465 * Return: 0 for success
466 * Non zero failure code for errors
467 */
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -0800468int pld_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800469{
470 int ret = 0;
471
472 switch (pld_get_bus_type(dev)) {
473 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu81982b92017-04-13 14:25:19 -0700474 ret = pld_pcie_set_fw_log_mode(dev, fw_log_mode);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800475 break;
476 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +0530477 ret = pld_snoc_set_fw_log_mode(dev, fw_log_mode);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800478 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530479 case PLD_BUS_TYPE_PCIE_FW_SIM:
480 case PLD_BUS_TYPE_SNOC_FW_SIM:
Govind Singh6a2fe032016-05-13 14:09:37 +0530481 case PLD_BUS_TYPE_SDIO:
482 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800483 default:
484 ret = -EINVAL;
485 break;
486 }
487
488 return ret;
489}
490
491/**
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700492 * pld_get_default_fw_files() - Get default FW file names
493 * @pfw_files: buffer for FW file names
494 *
495 * Return default FW file names to the buffer.
496 *
497 * Return: void
498 */
499void pld_get_default_fw_files(struct pld_fw_files *pfw_files)
500{
501 memset(pfw_files, 0, sizeof(*pfw_files));
502
Qun Zhang4a83a462018-09-11 16:28:51 +0800503 strlcpy(pfw_files->image_file, PREFIX PLD_IMAGE_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700504 PLD_MAX_FILE_NAME);
Qun Zhang4a83a462018-09-11 16:28:51 +0800505 strlcpy(pfw_files->board_data, PREFIX PLD_BOARD_DATA_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700506 PLD_MAX_FILE_NAME);
Qun Zhang4a83a462018-09-11 16:28:51 +0800507 strlcpy(pfw_files->otp_data, PREFIX PLD_OTP_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700508 PLD_MAX_FILE_NAME);
Qun Zhang4a83a462018-09-11 16:28:51 +0800509 strlcpy(pfw_files->utf_file, PREFIX PLD_UTF_FIRMWARE_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700510 PLD_MAX_FILE_NAME);
Qun Zhang4a83a462018-09-11 16:28:51 +0800511 strlcpy(pfw_files->utf_board_data, PREFIX PLD_BOARD_DATA_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700512 PLD_MAX_FILE_NAME);
Qun Zhang4a83a462018-09-11 16:28:51 +0800513 strlcpy(pfw_files->epping_file, PREFIX PLD_EPPING_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700514 PLD_MAX_FILE_NAME);
Qun Zhang4a83a462018-09-11 16:28:51 +0800515 strlcpy(pfw_files->setup_file, PREFIX PLD_SETUP_FILE,
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700516 PLD_MAX_FILE_NAME);
517}
518
519/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800520 * pld_get_fw_files_for_target() - Get FW file names
521 * @dev: device
522 * @pfw_files: buffer for FW file names
523 * @target_type: target type
524 * @target_version: target version
525 *
526 * Return target specific FW file names to the buffer.
527 *
528 * Return: 0 for success
529 * Non zero failure code for errors
530 */
531int pld_get_fw_files_for_target(struct device *dev,
532 struct pld_fw_files *pfw_files,
533 u32 target_type, u32 target_version)
534{
535 int ret = 0;
536
537 switch (pld_get_bus_type(dev)) {
538 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700539 ret = pld_pcie_get_fw_files_for_target(dev, pfw_files,
540 target_type,
541 target_version);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800542 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530543 case PLD_BUS_TYPE_PCIE_FW_SIM:
544 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800545 case PLD_BUS_TYPE_SNOC:
546 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530547 case PLD_BUS_TYPE_SDIO:
548 ret = pld_sdio_get_fw_files_for_target(pfw_files,
Yue Ma85761e62017-10-30 11:13:45 -0700549 target_type,
550 target_version);
Govind Singh6a2fe032016-05-13 14:09:37 +0530551 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -0700552 case PLD_BUS_TYPE_USB:
553 ret = pld_usb_get_fw_files_for_target(pfw_files,
Yue Ma85761e62017-10-30 11:13:45 -0700554 target_type,
555 target_version);
Mohit Khanna1d531c42016-05-12 21:35:50 -0700556 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800557 default:
558 ret = -EINVAL;
559 break;
560 }
561
562 return ret;
563}
564
565/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800566 * pld_is_pci_link_down() - Notification for pci link down event
567 * @dev: device
568 *
569 * Notify platform that pci link is down.
570 *
571 * Return: void
572 */
573void pld_is_pci_link_down(struct device *dev)
574{
575 switch (pld_get_bus_type(dev)) {
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530576 case PLD_BUS_TYPE_PCIE_FW_SIM:
577 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800578 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800579 pld_pcie_link_down(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800580 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530581 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800582 case PLD_BUS_TYPE_SNOC:
583 break;
584 default:
585 pr_err("Invalid device type\n");
586 break;
587 }
588}
589
590/**
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700591 * pld_schedule_recovery_work() - Schedule recovery work
592 * @dev: device
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800593 * @reason: recovery reason
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700594 *
595 * Schedule a system self recovery work.
596 *
597 * Return: void
598 */
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800599void pld_schedule_recovery_work(struct device *dev,
600 enum pld_recovery_reason reason)
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700601{
602 switch (pld_get_bus_type(dev)) {
603 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800604 pld_pcie_schedule_recovery_work(dev, reason);
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700605 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530606 case PLD_BUS_TYPE_PCIE_FW_SIM:
607 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liu0e0aa932016-05-12 10:17:58 -0700608 case PLD_BUS_TYPE_SNOC:
609 break;
610 default:
611 pr_err("Invalid device type\n");
612 break;
613 }
614}
615
616/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800617 * pld_wlan_pm_control() - WLAN PM control on PCIE
618 * @dev: device
619 * @vote: 0 for enable PCIE PC, 1 for disable PCIE PC
620 *
621 * This is for PCIE power collaps control during suspend/resume.
622 * When PCIE power collaps is disabled, WLAN FW can access memory
623 * through PCIE when system is suspended.
624 *
625 * Return: 0 for success
626 * Non zero failure code for errors
627 */
628int pld_wlan_pm_control(struct device *dev, bool vote)
629{
630 int ret = 0;
631
632 switch (pld_get_bus_type(dev)) {
633 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700634 ret = pld_pcie_wlan_pm_control(dev, vote);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800635 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530636 case PLD_BUS_TYPE_PCIE_FW_SIM:
637 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800638 case PLD_BUS_TYPE_SNOC:
639 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530640 case PLD_BUS_TYPE_SDIO:
641 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800642 default:
643 ret = -EINVAL;
644 break;
645 }
646
647 return ret;
648}
649
650/**
651 * pld_get_virt_ramdump_mem() - Get virtual ramdump memory
652 * @dev: device
653 * @size: buffer to virtual memory size
654 *
655 * Return: virtual ramdump memory address
656 */
657void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
658{
659 void *mem = NULL;
660
661 switch (pld_get_bus_type(dev)) {
662 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700663 mem = pld_pcie_get_virt_ramdump_mem(dev, size);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800664 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530665 case PLD_BUS_TYPE_PCIE_FW_SIM:
666 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800667 case PLD_BUS_TYPE_SNOC:
668 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530669 case PLD_BUS_TYPE_SDIO:
Yu Wangc407bf72017-02-23 15:33:42 +0800670 mem = pld_sdio_get_virt_ramdump_mem(dev, size);
Govind Singh6a2fe032016-05-13 14:09:37 +0530671 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800672 default:
673 pr_err("Invalid device type\n");
674 break;
675 }
676
677 return mem;
678}
679
Yu Ouyang58648a52018-11-01 11:18:15 +0800680void pld_release_virt_ramdump_mem(struct device *dev, void *address)
681{
682 switch (pld_get_bus_type(dev)) {
683 case PLD_BUS_TYPE_PCIE:
684 pld_pcie_release_virt_ramdump_mem(address);
685 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530686 case PLD_BUS_TYPE_PCIE_FW_SIM:
687 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yu Ouyang58648a52018-11-01 11:18:15 +0800688 case PLD_BUS_TYPE_SNOC:
689 break;
690 case PLD_BUS_TYPE_SDIO:
691 pld_sdio_release_virt_ramdump_mem(address);
692 break;
693 default:
694 pr_err("Invalid device type\n");
695 break;
696 }
697}
698
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800699/**
700 * pld_device_crashed() - Notification for device crash event
701 * @dev: device
702 *
703 * Notify subsystem a device crashed event. A subsystem restart
704 * is expected to happen after calling this function.
705 *
706 * Return: void
707 */
708void pld_device_crashed(struct device *dev)
709{
710 switch (pld_get_bus_type(dev)) {
711 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700712 pld_pcie_device_crashed(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800713 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530714 case PLD_BUS_TYPE_PCIE_FW_SIM:
715 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800716 case PLD_BUS_TYPE_SNOC:
717 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530718 case PLD_BUS_TYPE_SDIO:
Yu Wangc407bf72017-02-23 15:33:42 +0800719 pld_sdio_device_crashed(dev);
Govind Singh6a2fe032016-05-13 14:09:37 +0530720 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800721 default:
722 pr_err("Invalid device type\n");
723 break;
724 }
725}
726
727/**
728 * pld_device_self_recovery() - Device self recovery
729 * @dev: device
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800730 * @reason: recovery reason
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800731 *
732 * Return: void
733 */
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800734void pld_device_self_recovery(struct device *dev,
735 enum pld_recovery_reason reason)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800736{
737 switch (pld_get_bus_type(dev)) {
738 case PLD_BUS_TYPE_PCIE:
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800739 pld_pcie_device_self_recovery(dev, reason);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800740 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530741 case PLD_BUS_TYPE_PCIE_FW_SIM:
742 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800743 case PLD_BUS_TYPE_SNOC:
744 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530745 case PLD_BUS_TYPE_SDIO:
wadesongbf708792017-09-04 15:55:43 +0800746 pld_sdio_device_self_recovery(dev);
Govind Singh6a2fe032016-05-13 14:09:37 +0530747 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800748 default:
749 pr_err("Invalid device type\n");
750 break;
751 }
752}
753
754/**
755 * pld_intr_notify_q6() - Notify Q6 FW interrupts
756 * @dev: device
757 *
758 * Notify Q6 that a FW interrupt is triggered.
759 *
760 * Return: void
761 */
762void pld_intr_notify_q6(struct device *dev)
763{
764 switch (pld_get_bus_type(dev)) {
765 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700766 pld_pcie_intr_notify_q6(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800767 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530768 case PLD_BUS_TYPE_PCIE_FW_SIM:
769 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800770 case PLD_BUS_TYPE_SNOC:
771 break;
772 default:
773 pr_err("Invalid device type\n");
774 break;
775 }
776}
777
778/**
779 * pld_request_pm_qos() - Request system PM
780 * @dev: device
781 * @qos_val: request value
782 *
783 * It votes for the value of aggregate QoS expectations.
784 *
785 * Return: void
786 */
787void pld_request_pm_qos(struct device *dev, u32 qos_val)
788{
789 switch (pld_get_bus_type(dev)) {
790 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700791 pld_pcie_request_pm_qos(dev, qos_val);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800792 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530793 case PLD_BUS_TYPE_PCIE_FW_SIM:
794 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800795 case PLD_BUS_TYPE_SNOC:
796 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530797 case PLD_BUS_TYPE_SDIO:
798 /* To do Add call cns API */
799 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -0700800 case PLD_BUS_TYPE_USB:
801 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800802 default:
803 pr_err("Invalid device type\n");
804 break;
805 }
806}
807
808/**
809 * pld_remove_pm_qos() - Remove system PM
810 * @dev: device
811 *
812 * Remove the vote request for Qos expectations.
813 *
814 * Return: void
815 */
816void pld_remove_pm_qos(struct device *dev)
817{
818 switch (pld_get_bus_type(dev)) {
819 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700820 pld_pcie_remove_pm_qos(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800821 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530822 case PLD_BUS_TYPE_PCIE_FW_SIM:
823 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800824 case PLD_BUS_TYPE_SNOC:
825 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530826 case PLD_BUS_TYPE_SDIO:
827 /* To do Add call cns API */
828 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800829 default:
830 pr_err("Invalid device type\n");
831 break;
832 }
833}
834
835/**
836 * pld_request_bus_bandwidth() - Request bus bandwidth
837 * @dev: device
838 * @bandwidth: bus bandwidth
839 *
840 * Votes for HIGH/MEDIUM/LOW bus bandwidth.
841 *
842 * Return: 0 for success
843 * Non zero failure code for errors
844 */
845int pld_request_bus_bandwidth(struct device *dev, int bandwidth)
846{
847 int ret = 0;
848
849 switch (pld_get_bus_type(dev)) {
850 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700851 ret = pld_pcie_request_bus_bandwidth(dev, bandwidth);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800852 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530853 case PLD_BUS_TYPE_PCIE_FW_SIM:
854 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800855 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;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800860 default:
861 ret = -EINVAL;
862 break;
863 }
864
865 return ret;
866}
867
868/**
869 * pld_get_platform_cap() - Get platform capabilities
870 * @dev: device
871 * @cap: buffer to the capabilities
872 *
873 * Return capabilities to the buffer.
874 *
875 * Return: 0 for success
876 * Non zero failure code for errors
877 */
878int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
879{
880 int ret = 0;
881
882 switch (pld_get_bus_type(dev)) {
883 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700884 ret = pld_pcie_get_platform_cap(dev, cap);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800885 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530886 case PLD_BUS_TYPE_PCIE_FW_SIM:
887 ret = pld_pcie_fw_sim_get_platform_cap(dev, cap);
888 break;
889 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800890 case PLD_BUS_TYPE_SNOC:
891 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530892 case PLD_BUS_TYPE_SDIO:
893 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800894 default:
895 ret = -EINVAL;
896 break;
897 }
898
899 return ret;
900}
901
902/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800903 * pld_get_sha_hash() - Get sha hash number
904 * @dev: device
905 * @data: input data
906 * @data_len: data length
907 * @hash_idx: hash index
908 * @out: output buffer
909 *
910 * Return computed hash to the out buffer.
911 *
912 * Return: 0 for success
913 * Non zero failure code for errors
914 */
915int pld_get_sha_hash(struct device *dev, const u8 *data,
916 u32 data_len, u8 *hash_idx, u8 *out)
917{
918 int ret = 0;
919
920 switch (pld_get_bus_type(dev)) {
921 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700922 ret = pld_pcie_get_sha_hash(dev, data, data_len,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800923 hash_idx, out);
924 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530925 case PLD_BUS_TYPE_PCIE_FW_SIM:
926 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800927 case PLD_BUS_TYPE_SNOC:
928 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530929 case PLD_BUS_TYPE_SDIO:
930 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800931 default:
932 ret = -EINVAL;
933 break;
934 }
935
936 return ret;
937}
938
939/**
940 * pld_get_fw_ptr() - Get secure FW memory address
941 * @dev: device
942 *
943 * Return: secure memory address
944 */
945void *pld_get_fw_ptr(struct device *dev)
946{
947 void *ptr = NULL;
948
949 switch (pld_get_bus_type(dev)) {
950 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700951 ptr = pld_pcie_get_fw_ptr(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800952 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530953 case PLD_BUS_TYPE_PCIE_FW_SIM:
954 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800955 case PLD_BUS_TYPE_SNOC:
956 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530957 case PLD_BUS_TYPE_SDIO:
958 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800959 default:
960 pr_err("Invalid device type\n");
961 break;
962 }
963
964 return ptr;
965}
966
967/**
968 * pld_auto_suspend() - Auto suspend
969 * @dev: device
970 *
971 * Return: 0 for success
972 * Non zero failure code for errors
973 */
974int pld_auto_suspend(struct device *dev)
975{
976 int ret = 0;
977
978 switch (pld_get_bus_type(dev)) {
979 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -0700980 ret = pld_pcie_auto_suspend(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800981 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +0530982 case PLD_BUS_TYPE_PCIE_FW_SIM:
983 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800984 case PLD_BUS_TYPE_SNOC:
985 break;
Govind Singh6a2fe032016-05-13 14:09:37 +0530986 case PLD_BUS_TYPE_SDIO:
987 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800988 default:
989 ret = -EINVAL;
990 break;
991 }
992
993 return ret;
994}
995
996/**
997 * pld_auto_resume() - Auto resume
998 * @dev: device
999 *
1000 * Return: 0 for success
1001 * Non zero failure code for errors
1002 */
1003int pld_auto_resume(struct device *dev)
1004{
1005 int ret = 0;
1006
1007 switch (pld_get_bus_type(dev)) {
1008 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -07001009 ret = pld_pcie_auto_resume(dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001010 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301011 case PLD_BUS_TYPE_PCIE_FW_SIM:
1012 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001013 case PLD_BUS_TYPE_SNOC:
1014 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301015 case PLD_BUS_TYPE_SDIO:
1016 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001017 default:
1018 ret = -EINVAL;
1019 break;
1020 }
1021
1022 return ret;
1023}
1024
1025/**
Yue Mafb3b78d2018-08-08 11:51:21 -07001026 * pld_force_wake_request() - Request vote to assert WAKE register
1027 * @dev: device
1028 *
1029 * Return: 0 for success
1030 * Non zero failure code for errors
1031 */
1032int pld_force_wake_request(struct device *dev)
1033{
1034 int ret = 0;
1035 enum pld_bus_type type = pld_get_bus_type(dev);
1036
1037 switch (type) {
1038 case PLD_BUS_TYPE_PCIE:
1039 ret = pld_pcie_force_wake_request(dev);
1040 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301041 case PLD_BUS_TYPE_PCIE_FW_SIM:
1042 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Mafb3b78d2018-08-08 11:51:21 -07001043 case PLD_BUS_TYPE_SNOC:
1044 case PLD_BUS_TYPE_SDIO:
1045 case PLD_BUS_TYPE_USB:
1046 break;
1047 default:
1048 pr_err("Invalid device type %d\n", type);
1049 ret = -EINVAL;
1050 break;
1051 }
1052
1053 return ret;
1054}
1055
1056/**
1057 * pld_is_device_awake() - Check if it's ready to access MMIO registers
1058 * @dev: device
1059 *
1060 * Return: True for device awake
1061 * False for device not awake
1062 * Negative failure code for errors
1063 */
1064int pld_is_device_awake(struct device *dev)
1065{
1066 int ret = true;
1067 enum pld_bus_type type = pld_get_bus_type(dev);
1068
1069 switch (type) {
1070 case PLD_BUS_TYPE_PCIE:
1071 ret = pld_pcie_is_device_awake(dev);
1072 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301073 case PLD_BUS_TYPE_PCIE_FW_SIM:
1074 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Mafb3b78d2018-08-08 11:51:21 -07001075 case PLD_BUS_TYPE_SNOC:
1076 case PLD_BUS_TYPE_SDIO:
1077 case PLD_BUS_TYPE_USB:
1078 break;
1079 default:
1080 pr_err("Invalid device type %d\n", type);
1081 ret = -EINVAL;
1082 break;
1083 }
1084
1085 return ret;
1086}
1087
1088/**
1089 * pld_force_wake_release() - Release vote to assert WAKE register
1090 * @dev: device
1091 *
1092 * Return: 0 for success
1093 * Non zero failure code for errors
1094 */
1095int pld_force_wake_release(struct device *dev)
1096{
1097 int ret = 0;
1098 enum pld_bus_type type = pld_get_bus_type(dev);
1099
1100 switch (type) {
1101 case PLD_BUS_TYPE_PCIE:
1102 ret = pld_pcie_force_wake_release(dev);
1103 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301104 case PLD_BUS_TYPE_PCIE_FW_SIM:
1105 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Mafb3b78d2018-08-08 11:51:21 -07001106 case PLD_BUS_TYPE_SNOC:
1107 case PLD_BUS_TYPE_SDIO:
1108 case PLD_BUS_TYPE_USB:
1109 break;
1110 default:
1111 pr_err("Invalid device type %d\n", type);
1112 ret = -EINVAL;
1113 break;
1114 }
1115
1116 return ret;
1117}
1118
1119/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001120 * pld_ce_request_irq() - Register IRQ for CE
1121 * @dev: device
1122 * @ce_id: CE number
1123 * @handler: IRQ callback function
1124 * @flags: IRQ flags
1125 * @name: IRQ name
1126 * @ctx: IRQ context
1127 *
1128 * Return: 0 for success
1129 * Non zero failure code for errors
1130 */
1131int pld_ce_request_irq(struct device *dev, unsigned int ce_id,
1132 irqreturn_t (*handler)(int, void *),
1133 unsigned long flags, const char *name, void *ctx)
1134{
1135 int ret = 0;
1136
1137 switch (pld_get_bus_type(dev)) {
1138 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301139 ret = pld_snoc_ce_request_irq(dev, ce_id,
1140 handler, flags, name, ctx);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001141 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301142 case PLD_BUS_TYPE_SNOC_FW_SIM:
1143 ret = pld_snoc_fw_sim_ce_request_irq(dev, ce_id,
1144 handler, flags, name, ctx);
1145 break;
1146 case PLD_BUS_TYPE_PCIE_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001147 case PLD_BUS_TYPE_PCIE:
1148 break;
1149 default:
1150 ret = -EINVAL;
1151 break;
1152 }
1153
1154 return ret;
1155}
1156
1157/**
1158 * pld_ce_free_irq() - Free IRQ for CE
1159 * @dev: device
1160 * @ce_id: CE number
1161 * @ctx: IRQ context
1162 *
1163 * Return: 0 for success
1164 * Non zero failure code for errors
1165 */
1166int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx)
1167{
1168 int ret = 0;
1169
1170 switch (pld_get_bus_type(dev)) {
1171 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301172 ret = pld_snoc_ce_free_irq(dev, ce_id, ctx);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001173 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301174 case PLD_BUS_TYPE_SNOC_FW_SIM:
1175 ret = pld_snoc_fw_sim_ce_free_irq(dev, ce_id, ctx);
1176 break;
1177 case PLD_BUS_TYPE_PCIE_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001178 case PLD_BUS_TYPE_PCIE:
1179 break;
1180 default:
1181 ret = -EINVAL;
1182 break;
1183 }
1184
1185 return ret;
1186}
1187
1188/**
1189 * pld_enable_irq() - Enable IRQ for CE
1190 * @dev: device
1191 * @ce_id: CE number
1192 *
1193 * Return: void
1194 */
1195void pld_enable_irq(struct device *dev, unsigned int ce_id)
1196{
1197 switch (pld_get_bus_type(dev)) {
1198 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301199 pld_snoc_enable_irq(dev, ce_id);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001200 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301201 case PLD_BUS_TYPE_SNOC_FW_SIM:
1202 pld_snoc_fw_sim_enable_irq(dev, ce_id);
1203 break;
1204 case PLD_BUS_TYPE_PCIE_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001205 case PLD_BUS_TYPE_PCIE:
1206 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301207 case PLD_BUS_TYPE_SDIO:
1208 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001209 default:
1210 pr_err("Invalid device type\n");
1211 break;
1212 }
1213}
1214
1215/**
1216 * pld_disable_irq() - Disable IRQ for CE
1217 * @dev: device
1218 * @ce_id: CE number
1219 *
1220 * Return: void
1221 */
1222void pld_disable_irq(struct device *dev, unsigned int ce_id)
1223{
1224 switch (pld_get_bus_type(dev)) {
1225 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301226 pld_snoc_disable_irq(dev, ce_id);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001227 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301228 case PLD_BUS_TYPE_SNOC_FW_SIM:
1229 pld_snoc_fw_sim_disable_irq(dev, ce_id);
1230 break;
1231 case PLD_BUS_TYPE_PCIE_FW_SIM:
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001232 case PLD_BUS_TYPE_PCIE:
1233 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301234 case PLD_BUS_TYPE_SDIO:
1235 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001236 default:
1237 pr_err("Invalid device type\n");
1238 break;
1239 }
1240}
1241
1242/**
1243 * pld_get_soc_info() - Get SOC information
1244 * @dev: device
1245 * @info: buffer to SOC information
1246 *
1247 * Return SOC info to the buffer.
1248 *
1249 * Return: 0 for success
1250 * Non zero failure code for errors
1251 */
1252int pld_get_soc_info(struct device *dev, struct pld_soc_info *info)
1253{
1254 int ret = 0;
1255
1256 switch (pld_get_bus_type(dev)) {
1257 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301258 ret = pld_snoc_get_soc_info(dev, info);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001259 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301260 case PLD_BUS_TYPE_SNOC_FW_SIM:
1261 ret = pld_snoc_fw_sim_get_soc_info(dev, info);
1262 break;
1263 case PLD_BUS_TYPE_PCIE_FW_SIM:
1264 ret = pld_pcie_fw_sim_get_soc_info(dev, info);
1265 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001266 case PLD_BUS_TYPE_PCIE:
Yue Macd243862016-11-04 19:21:16 -07001267 ret = pld_pcie_get_soc_info(dev, info);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001268 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301269 case PLD_BUS_TYPE_SDIO:
1270 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001271 default:
1272 ret = -EINVAL;
1273 break;
1274 }
1275
1276 return ret;
1277}
1278
1279/**
1280 * pld_get_ce_id() - Get CE number for the provided IRQ
1281 * @dev: device
1282 * @irq: IRQ number
1283 *
1284 * Return: CE number
1285 */
1286int pld_get_ce_id(struct device *dev, int irq)
1287{
1288 int ret = 0;
1289
1290 switch (pld_get_bus_type(dev)) {
1291 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301292 ret = pld_snoc_get_ce_id(dev, irq);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001293 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301294 case PLD_BUS_TYPE_SNOC_FW_SIM:
1295 ret = pld_snoc_fw_sim_get_ce_id(dev, irq);
1296 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001297 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -07001298 ret = pld_pcie_get_ce_id(dev, irq);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001299 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301300 case PLD_BUS_TYPE_PCIE_FW_SIM:
1301 break;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001302 default:
1303 ret = -EINVAL;
1304 break;
1305 }
1306
1307 return ret;
1308}
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001309
1310/**
Yuanyuan Liuf2ee05f2016-07-27 16:52:52 -07001311 * pld_get_irq() - Get IRQ number for given CE ID
1312 * @dev: device
1313 * @ce_id: CE ID
1314 *
1315 * Return: IRQ number
1316 */
1317int pld_get_irq(struct device *dev, int ce_id)
1318{
1319 int ret = 0;
1320
1321 switch (pld_get_bus_type(dev)) {
1322 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05301323 ret = pld_snoc_get_irq(dev, ce_id);
Yuanyuan Liuf2ee05f2016-07-27 16:52:52 -07001324 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301325 case PLD_BUS_TYPE_SNOC_FW_SIM:
1326 ret = pld_snoc_fw_sim_get_irq(dev, ce_id);
1327 break;
1328 case PLD_BUS_TYPE_PCIE_FW_SIM:
Yuanyuan Liuf2ee05f2016-07-27 16:52:52 -07001329 case PLD_BUS_TYPE_PCIE:
1330 default:
1331 ret = -EINVAL;
1332 break;
1333 }
1334
1335 return ret;
1336}
1337
1338/**
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001339 * pld_lock_pm_sem() - Lock PM semaphore
1340 * @dev: device
1341 *
1342 * Return: void
1343 */
1344void pld_lock_pm_sem(struct device *dev)
1345{
1346 switch (pld_get_bus_type(dev)) {
1347 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -07001348 pld_pcie_lock_pm_sem(dev);
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001349 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301350 case PLD_BUS_TYPE_PCIE_FW_SIM:
1351 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001352 case PLD_BUS_TYPE_SNOC:
1353 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301354 case PLD_BUS_TYPE_SDIO:
1355 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -07001356 case PLD_BUS_TYPE_USB:
1357 break;
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001358 default:
1359 pr_err("Invalid device type\n");
1360 break;
1361 }
1362}
1363
1364/**
1365 * pld_release_pm_sem() - Release PM semaphore
1366 * @dev: device
1367 *
1368 * Return: void
1369 */
1370void pld_release_pm_sem(struct device *dev)
1371{
1372 switch (pld_get_bus_type(dev)) {
1373 case PLD_BUS_TYPE_PCIE:
Yue Ma85761e62017-10-30 11:13:45 -07001374 pld_pcie_release_pm_sem(dev);
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001375 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301376 case PLD_BUS_TYPE_PCIE_FW_SIM:
1377 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001378 case PLD_BUS_TYPE_SNOC:
1379 break;
Govind Singh6a2fe032016-05-13 14:09:37 +05301380 case PLD_BUS_TYPE_SDIO:
1381 break;
Mohit Khanna1d531c42016-05-12 21:35:50 -07001382 case PLD_BUS_TYPE_USB:
1383 break;
Yuanyuan Liu44c44772016-04-11 11:11:27 -07001384 default:
1385 pr_err("Invalid device type\n");
1386 break;
1387 }
1388}
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301389
1390/**
1391 * pld_power_on() - Power on WLAN hardware
1392 * @dev: device
1393 *
1394 * Return: 0 for success
1395 * Non zero failure code for errors
1396 */
1397int pld_power_on(struct device *dev)
1398{
1399 int ret = 0;
1400
1401 switch (pld_get_bus_type(dev)) {
1402 case PLD_BUS_TYPE_PCIE:
Rajeev Kumar588a2542019-04-08 10:57:19 -07001403 /* cnss platform driver handles PCIe SoC
1404 * power on/off seqeunce so let CNSS driver
1405 * handle the power on sequence for PCIe SoC
1406 */
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301407 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301408 case PLD_BUS_TYPE_PCIE_FW_SIM:
1409 case PLD_BUS_TYPE_SNOC_FW_SIM:
1410 break;
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301411 case PLD_BUS_TYPE_SNOC:
1412 ret = pld_snoc_power_on(dev);
1413 break;
1414 default:
1415 pr_err("Invalid device type\n");
1416 break;
1417 }
1418
1419 return ret;
1420}
1421
1422/**
1423 * pld_power_off() - Power off WLAN hardware
1424 * @dev: device
1425 *
1426 * Return: 0 for success
1427 * Non zero failure code for errors
1428 */
1429int pld_power_off(struct device *dev)
1430{
1431 int ret = 0;
1432
1433 switch (pld_get_bus_type(dev)) {
1434 case PLD_BUS_TYPE_PCIE:
Rajeev Kumar588a2542019-04-08 10:57:19 -07001435 /* cnss platform driver handles PCIe SoC
1436 * power on/off seqeunce so let CNSS driver
1437 * handle the power off sequence for PCIe SoC
1438 */
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301439 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301440 case PLD_BUS_TYPE_PCIE_FW_SIM:
1441 case PLD_BUS_TYPE_SNOC_FW_SIM:
1442 break;
Arun Khandavalli1496fcb2016-07-25 16:53:00 +05301443 case PLD_BUS_TYPE_SNOC:
1444 ret = pld_snoc_power_off(dev);
1445 break;
1446 default:
1447 pr_err("Invalid device type\n");
1448 break;
1449 }
1450
1451 return ret;
1452}
Yuanyuan Liu5ef6bfe2016-06-16 14:13:07 -07001453
1454/**
1455 * pld_athdiag_read() - Read data from WLAN FW
1456 * @dev: device
1457 * @offset: address offset
1458 * @memtype: memory type
1459 * @datalen: data length
1460 * @output: output buffer
1461 *
1462 * Return: 0 for success
1463 * Non zero failure code for errors
1464 */
1465int pld_athdiag_read(struct device *dev, uint32_t offset,
1466 uint32_t memtype, uint32_t datalen,
1467 uint8_t *output)
1468{
1469 int ret = 0;
1470
1471 switch (pld_get_bus_type(dev)) {
1472 case PLD_BUS_TYPE_SNOC:
1473 ret = pld_snoc_athdiag_read(dev, offset, memtype,
1474 datalen, output);
1475 break;
1476 case PLD_BUS_TYPE_PCIE:
Yue Ma6dbbb182017-04-26 17:06:05 -07001477 ret = pld_pcie_athdiag_read(dev, offset, memtype,
1478 datalen, output);
1479 break;
Yuanyuan Liu5ef6bfe2016-06-16 14:13:07 -07001480 case PLD_BUS_TYPE_SDIO:
1481 case PLD_BUS_TYPE_USB:
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301482 case PLD_BUS_TYPE_PCIE_FW_SIM:
1483 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liu5ef6bfe2016-06-16 14:13:07 -07001484 break;
1485 default:
1486 ret = -EINVAL;
1487 break;
1488 }
1489
1490 return ret;
1491}
1492
1493/**
1494 * pld_athdiag_write() - Write data to WLAN FW
1495 * @dev: device
1496 * @offset: address offset
1497 * @memtype: memory type
1498 * @datalen: data length
1499 * @input: input buffer
1500 *
1501 * Return: 0 for success
1502 * Non zero failure code for errors
1503 */
1504int pld_athdiag_write(struct device *dev, uint32_t offset,
1505 uint32_t memtype, uint32_t datalen,
1506 uint8_t *input)
1507{
1508 int ret = 0;
1509
1510 switch (pld_get_bus_type(dev)) {
1511 case PLD_BUS_TYPE_SNOC:
1512 ret = pld_snoc_athdiag_write(dev, offset, memtype,
1513 datalen, input);
1514 break;
1515 case PLD_BUS_TYPE_PCIE:
Yue Ma6dbbb182017-04-26 17:06:05 -07001516 ret = pld_pcie_athdiag_write(dev, offset, memtype,
1517 datalen, input);
1518 break;
Yuanyuan Liu5ef6bfe2016-06-16 14:13:07 -07001519 case PLD_BUS_TYPE_SDIO:
1520 case PLD_BUS_TYPE_USB:
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301521 case PLD_BUS_TYPE_PCIE_FW_SIM:
1522 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liu5ef6bfe2016-06-16 14:13:07 -07001523 break;
1524 default:
1525 ret = -EINVAL;
1526 break;
1527 }
1528
1529 return ret;
1530}
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001531
1532/**
Sandeep Singh75d4b7d2019-05-15 18:56:34 +05301533 * pld_smmu_get_domain() - Get SMMU domain
1534 * @dev: device
1535 *
1536 * Return: Pointer to the domain
1537 */
1538#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
1539void *pld_smmu_get_domain(struct device *dev)
1540{
1541 void *ptr = NULL;
1542 enum pld_bus_type type = pld_get_bus_type(dev);
1543
1544 switch (type) {
1545 case PLD_BUS_TYPE_SNOC:
1546 ptr = pld_snoc_smmu_get_domain(dev);
1547 break;
Sandeep Singhb2df1382019-06-11 15:54:19 +05301548 case PLD_BUS_TYPE_PCIE:
1549 ptr = pld_pcie_smmu_get_domain(dev);
1550 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301551 case PLD_BUS_TYPE_PCIE_FW_SIM:
1552 case PLD_BUS_TYPE_SNOC_FW_SIM:
1553 break;
Sandeep Singhb2df1382019-06-11 15:54:19 +05301554 case PLD_BUS_TYPE_SDIO:
1555 case PLD_BUS_TYPE_USB:
1556 pr_err("Not supported on type %d\n", type);
1557 break;
Sandeep Singh75d4b7d2019-05-15 18:56:34 +05301558 default:
1559 pr_err("Invalid device type %d\n", type);
1560 break;
1561 }
1562
1563 return ptr;
1564}
1565#else
1566/**
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001567 * pld_smmu_get_mapping() - Get SMMU mapping context
1568 * @dev: device
1569 *
1570 * Return: Pointer to the mapping context
1571 */
1572void *pld_smmu_get_mapping(struct device *dev)
1573{
1574 void *ptr = NULL;
1575 enum pld_bus_type type = pld_get_bus_type(dev);
1576
1577 switch (type) {
1578 case PLD_BUS_TYPE_SNOC:
1579 ptr = pld_snoc_smmu_get_mapping(dev);
1580 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301581 case PLD_BUS_TYPE_PCIE_FW_SIM:
1582 case PLD_BUS_TYPE_SNOC_FW_SIM:
1583 break;
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001584 case PLD_BUS_TYPE_PCIE:
Frank Liud462d9c2018-07-27 14:43:26 +08001585 ptr = pld_pcie_smmu_get_mapping(dev);
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001586 break;
1587 default:
1588 pr_err("Invalid device type %d\n", type);
1589 break;
1590 }
1591
1592 return ptr;
1593}
Sandeep Singh75d4b7d2019-05-15 18:56:34 +05301594#endif
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001595
1596/**
1597 * pld_smmu_map() - Map SMMU
1598 * @dev: device
1599 * @paddr: physical address that needs to map to
1600 * @iova_addr: IOVA address
1601 * @size: size to be mapped
1602 *
1603 * Return: 0 for success
1604 * Non zero failure code for errors
1605 */
1606int pld_smmu_map(struct device *dev, phys_addr_t paddr,
1607 uint32_t *iova_addr, size_t size)
1608{
1609 int ret = 0;
1610 enum pld_bus_type type = pld_get_bus_type(dev);
1611
1612 switch (type) {
1613 case PLD_BUS_TYPE_SNOC:
1614 ret = pld_snoc_smmu_map(dev, paddr, iova_addr, size);
1615 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301616 case PLD_BUS_TYPE_PCIE_FW_SIM:
1617 case PLD_BUS_TYPE_SNOC_FW_SIM:
1618 break;
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001619 case PLD_BUS_TYPE_PCIE:
Frank Liud462d9c2018-07-27 14:43:26 +08001620 ret = pld_pcie_smmu_map(dev, paddr, iova_addr, size);
Yuanyuan Liu137755f2016-08-16 13:39:17 -07001621 break;
1622 default:
1623 pr_err("Invalid device type %d\n", type);
1624 ret = -EINVAL;
1625 break;
1626 }
1627
1628 return ret;
1629}
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001630
1631/**
Yue Mafd418ea2016-11-21 16:47:13 -08001632 * pld_get_user_msi_assignment() - Get MSI assignment information
1633 * @dev: device structure
1634 * @user_name: name of the user who requests the MSI assignment
1635 * @num_vectors: number of the MSI vectors assigned for the user
1636 * @user_base_data: MSI base data assigned for the user, this equals to
1637 * endpoint base data from config space plus base vector
1638 * @base_vector: base MSI vector (offset) number assigned for the user
1639 *
1640 * Return: 0 for success
1641 * Negative failure code for errors
1642 */
1643int pld_get_user_msi_assignment(struct device *dev, char *user_name,
1644 int *num_vectors, uint32_t *user_base_data,
1645 uint32_t *base_vector)
1646{
1647 int ret = 0;
1648 enum pld_bus_type type = pld_get_bus_type(dev);
1649
1650 switch (type) {
1651 case PLD_BUS_TYPE_PCIE:
1652 ret = pld_pcie_get_user_msi_assignment(dev, user_name,
1653 num_vectors,
1654 user_base_data,
1655 base_vector);
1656 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301657 case PLD_BUS_TYPE_PCIE_FW_SIM:
1658 ret = pld_pcie_fw_sim_get_user_msi_assignment(dev, user_name,
1659 num_vectors,
1660 user_base_data,
1661 base_vector);
1662 break;
Yue Mafd418ea2016-11-21 16:47:13 -08001663 case PLD_BUS_TYPE_SNOC:
1664 case PLD_BUS_TYPE_SDIO:
1665 case PLD_BUS_TYPE_USB:
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301666 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Mafd418ea2016-11-21 16:47:13 -08001667 pr_err("Not supported on type %d\n", type);
1668 ret = -ENODEV;
1669 break;
1670 default:
1671 pr_err("Invalid device type %d\n", type);
1672 ret = -EINVAL;
1673 break;
1674 }
1675
1676 return ret;
1677}
1678
1679/**
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301680 * pld_srng_request_irq() - Register IRQ for SRNG
1681 * @dev: device
1682 * @irq: IRQ number
1683 * @handler: IRQ callback function
1684 * @flags: IRQ flags
1685 * @name: IRQ name
1686 * @ctx: IRQ context
1687 *
1688 * Return: 0 for success
1689 * Non zero failure code for errors
1690 */
1691int pld_srng_request_irq(struct device *dev, int irq, irq_handler_t handler,
1692 unsigned long irqflags,
1693 const char *devname,
1694 void *dev_data)
1695{
1696 int ret = 0;
1697 enum pld_bus_type type = pld_get_bus_type(dev);
1698
1699 switch (type) {
1700 case PLD_BUS_TYPE_PCIE:
1701 ret = request_irq(irq, handler, irqflags, devname, dev_data);
1702 break;
1703 case PLD_BUS_TYPE_PCIE_FW_SIM:
1704 ret = pld_pcie_fw_sim_request_irq(dev, irq, handler,
1705 irqflags, devname,
1706 dev_data);
1707 break;
1708 case PLD_BUS_TYPE_SNOC:
1709 case PLD_BUS_TYPE_SDIO:
1710 case PLD_BUS_TYPE_USB:
1711 case PLD_BUS_TYPE_SNOC_FW_SIM:
1712 pr_err("Not supported on type %d\n", type);
1713 ret = -ENODEV;
1714 break;
1715 default:
1716 pr_err("Invalid device type %d\n", type);
1717 ret = -EINVAL;
1718 break;
1719 }
1720
1721 return ret;
1722}
1723
1724/**
1725 * pld_srng_free_irq() - Free IRQ for SRNG
1726 * @dev: device
1727 * @irq: IRQ number
1728 * @handler: IRQ callback function
1729 * @flags: IRQ flags
1730 * @name: IRQ name
1731 * @ctx: IRQ context
1732 *
1733 * Return: 0 for success
1734 * Non zero failure code for errors
1735 */
1736int pld_srng_free_irq(struct device *dev, int irq, void *dev_data)
1737{
1738 int ret = 0;
1739 enum pld_bus_type type = pld_get_bus_type(dev);
1740
1741 switch (type) {
1742 case PLD_BUS_TYPE_PCIE:
1743 free_irq(irq, dev_data);
1744 break;
1745 case PLD_BUS_TYPE_PCIE_FW_SIM:
1746 ret = pld_pcie_fw_sim_free_irq(dev, irq, dev_data);
1747 break;
1748 case PLD_BUS_TYPE_SNOC:
1749 case PLD_BUS_TYPE_SDIO:
1750 case PLD_BUS_TYPE_USB:
1751 case PLD_BUS_TYPE_SNOC_FW_SIM:
1752 pr_err("Not supported on type %d\n", type);
1753 ret = -ENODEV;
1754 break;
1755 default:
1756 pr_err("Invalid device type %d\n", type);
1757 ret = -EINVAL;
1758 break;
1759 }
1760
1761 return ret;
1762}
1763
1764/**
1765 * pld_srng_enable_irq() - Enable IRQ for SRNG
1766 * @dev: device
1767 * @irq: IRQ number
1768 *
1769 * Return: void
1770 */
1771void pld_srng_enable_irq(struct device *dev, int irq)
1772{
1773 switch (pld_get_bus_type(dev)) {
1774 case PLD_BUS_TYPE_SNOC:
1775 case PLD_BUS_TYPE_SNOC_FW_SIM:
1776 break;
1777 case PLD_BUS_TYPE_PCIE_FW_SIM:
1778 pld_pcie_fw_sim_enable_irq(dev, irq);
1779 break;
1780 case PLD_BUS_TYPE_PCIE:
1781 enable_irq(irq);
1782 break;
1783 case PLD_BUS_TYPE_SDIO:
1784 break;
1785 default:
1786 pr_err("Invalid device type\n");
1787 break;
1788 }
1789}
1790
1791/**
1792 * pld_disable_irq() - Disable IRQ for SRNG
1793 * @dev: device
1794 * @irq: IRQ number
1795 *
1796 * Return: void
1797 */
1798void pld_srng_disable_irq(struct device *dev, int irq)
1799{
1800 switch (pld_get_bus_type(dev)) {
1801 case PLD_BUS_TYPE_SNOC:
1802 case PLD_BUS_TYPE_SNOC_FW_SIM:
1803 break;
1804 case PLD_BUS_TYPE_PCIE_FW_SIM:
1805 pld_pcie_fw_sim_disable_irq(dev, irq);
1806 break;
1807 case PLD_BUS_TYPE_PCIE:
1808 disable_irq_nosync(irq);
1809 break;
1810 case PLD_BUS_TYPE_SDIO:
1811 break;
1812 default:
1813 pr_err("Invalid device type\n");
1814 break;
1815 }
1816}
1817
1818/**
1819 * pld_pci_read_config_word() - Read PCI config
1820 * @pdev: pci device
1821 * @offset: Config space offset
1822 * @val : Value
1823 *
1824 * Return: 0 for success
1825 * Non zero failure code for errors
1826 */
1827int pld_pci_read_config_word(struct pci_dev *pdev, int offset, uint16_t *val)
1828{
1829 int ret = 0;
1830
1831 switch (pld_get_bus_type(&pdev->dev)) {
1832 case PLD_BUS_TYPE_SNOC:
1833 case PLD_BUS_TYPE_SNOC_FW_SIM:
1834 break;
1835 case PLD_BUS_TYPE_PCIE_FW_SIM:
1836 break;
1837 case PLD_BUS_TYPE_PCIE:
1838 ret = pci_read_config_word(pdev, offset, val);
1839 break;
1840 case PLD_BUS_TYPE_SDIO:
1841 break;
1842 default:
1843 pr_err("Invalid device type\n");
1844 break;
1845 }
1846
1847 return ret;
1848}
1849
1850/**
1851 * pld_pci_write_config_word() - Write PCI config
1852 * @pdev: pci device
1853 * @offset: Config space offset
1854 * @val : Value
1855 *
1856 * Return: 0 for success
1857 * Non zero failure code for errors
1858 */
1859int pld_pci_write_config_word(struct pci_dev *pdev, int offset, uint16_t val)
1860{
1861 int ret = 0;
1862
1863 switch (pld_get_bus_type(&pdev->dev)) {
1864 case PLD_BUS_TYPE_SNOC:
1865 case PLD_BUS_TYPE_SNOC_FW_SIM:
1866 break;
1867 case PLD_BUS_TYPE_PCIE_FW_SIM:
1868 break;
1869 case PLD_BUS_TYPE_PCIE:
1870 ret = pci_write_config_word(pdev, offset, val);
1871 break;
1872 case PLD_BUS_TYPE_SDIO:
1873 break;
1874 default:
1875 pr_err("Invalid device type\n");
1876 break;
1877 }
1878
1879 return ret;
1880}
1881
1882/**
1883 * pld_pci_read_config_dword() - Read PCI config
1884 * @pdev: pci device
1885 * @offset: Config space offset
1886 * @val : Value
1887 *
1888 * Return: 0 for success
1889 * Non zero failure code for errors
1890 */
1891int pld_pci_read_config_dword(struct pci_dev *pdev, int offset, uint32_t *val)
1892{
1893 int ret = 0;
1894
1895 switch (pld_get_bus_type(&pdev->dev)) {
1896 case PLD_BUS_TYPE_SNOC:
1897 case PLD_BUS_TYPE_SNOC_FW_SIM:
1898 break;
1899 case PLD_BUS_TYPE_PCIE_FW_SIM:
1900 break;
1901 case PLD_BUS_TYPE_PCIE:
1902 ret = pci_read_config_dword(pdev, offset, val);
1903 break;
1904 case PLD_BUS_TYPE_SDIO:
1905 break;
1906 default:
1907 pr_err("Invalid device type\n");
1908 break;
1909 }
1910
1911 return ret;
1912}
1913
1914/**
1915 * pld_pci_write_config_dword() - Write PCI config
1916 * @pdev: pci device
1917 * @offset: Config space offset
1918 * @val : Value
1919 *
1920 * Return: 0 for success
1921 * Non zero failure code for errors
1922 */
1923int pld_pci_write_config_dword(struct pci_dev *pdev, int offset, uint32_t val)
1924{
1925 int ret = 0;
1926
1927 switch (pld_get_bus_type(&pdev->dev)) {
1928 case PLD_BUS_TYPE_SNOC:
1929 case PLD_BUS_TYPE_SNOC_FW_SIM:
1930 break;
1931 case PLD_BUS_TYPE_PCIE_FW_SIM:
1932 break;
1933 case PLD_BUS_TYPE_PCIE:
1934 ret = pci_write_config_dword(pdev, offset, val);
1935 break;
1936 case PLD_BUS_TYPE_SDIO:
1937 break;
1938 default:
1939 pr_err("Invalid device type\n");
1940 break;
1941 }
1942
1943 return ret;
1944}
1945
1946/**
Yue Mafd418ea2016-11-21 16:47:13 -08001947 * pld_get_msi_irq() - Get MSI IRQ number used for request_irq()
1948 * @dev: device structure
1949 * @vector: MSI vector (offset) number
1950 *
1951 * Return: Positive IRQ number for success
1952 * Negative failure code for errors
1953 */
1954int pld_get_msi_irq(struct device *dev, unsigned int vector)
1955{
1956 int ret = 0;
1957 enum pld_bus_type type = pld_get_bus_type(dev);
1958
1959 switch (type) {
1960 case PLD_BUS_TYPE_PCIE:
1961 ret = pld_pcie_get_msi_irq(dev, vector);
1962 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301963 case PLD_BUS_TYPE_PCIE_FW_SIM:
1964 ret = pld_pcie_fw_sim_get_msi_irq(dev, vector);
1965 break;
Yue Mafd418ea2016-11-21 16:47:13 -08001966 case PLD_BUS_TYPE_SNOC:
1967 case PLD_BUS_TYPE_SDIO:
1968 case PLD_BUS_TYPE_USB:
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301969 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Mafd418ea2016-11-21 16:47:13 -08001970 pr_err("Not supported on type %d\n", type);
1971 ret = -ENODEV;
1972 break;
1973 default:
1974 pr_err("Invalid device type %d\n", type);
1975 ret = -EINVAL;
1976 break;
1977 }
1978
1979 return ret;
1980}
1981
1982/**
1983 * pld_get_msi_address() - Get the MSI address
1984 * @dev: device structure
1985 * @msi_addr_low: lower 32-bit of the address
1986 * @msi_addr_high: higher 32-bit of the address
1987 *
1988 * Return: Void
1989 */
1990void pld_get_msi_address(struct device *dev, uint32_t *msi_addr_low,
1991 uint32_t *msi_addr_high)
1992{
1993 enum pld_bus_type type = pld_get_bus_type(dev);
1994
1995 switch (type) {
1996 case PLD_BUS_TYPE_PCIE:
1997 pld_pcie_get_msi_address(dev, msi_addr_low, msi_addr_high);
1998 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05301999 case PLD_BUS_TYPE_PCIE_FW_SIM:
2000 pld_pcie_fw_sim_get_msi_address(dev, msi_addr_low,
2001 msi_addr_high);
2002 break;
Yue Mafd418ea2016-11-21 16:47:13 -08002003 case PLD_BUS_TYPE_SNOC:
2004 case PLD_BUS_TYPE_SDIO:
2005 case PLD_BUS_TYPE_USB:
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302006 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Mafd418ea2016-11-21 16:47:13 -08002007 pr_err("Not supported on type %d\n", type);
2008 break;
2009 default:
2010 pr_err("Invalid device type %d\n", type);
2011 break;
2012 }
2013}
2014
2015/**
Yue Ma0631a752019-04-29 15:28:50 -07002016 * pld_is_drv_connected() - Check if DRV subsystem is connected
2017 * @dev: device structure
2018 *
2019 * Return: 1 DRV is connected
2020 * 0 DRV is not connected
2021 * Non zero failure code for errors
2022 */
2023int pld_is_drv_connected(struct device *dev)
2024{
2025 enum pld_bus_type type = pld_get_bus_type(dev);
2026 int ret = 0;
2027
2028 switch (type) {
2029 case PLD_BUS_TYPE_PCIE:
2030 ret = pld_pcie_is_drv_connected(dev);
2031 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302032 case PLD_BUS_TYPE_PCIE_FW_SIM:
2033 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yue Ma0631a752019-04-29 15:28:50 -07002034 case PLD_BUS_TYPE_SNOC:
2035 case PLD_BUS_TYPE_SDIO:
2036 case PLD_BUS_TYPE_USB:
2037 break;
2038 default:
2039 pr_err("Invalid device type %d\n", type);
2040 ret = -EINVAL;
2041 break;
2042 }
2043
2044 return ret;
2045}
2046
2047/**
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07002048 * pld_socinfo_get_serial_number() - Get SOC serial number
2049 * @dev: device
2050 *
2051 * Return: SOC serial number
2052 */
2053unsigned int pld_socinfo_get_serial_number(struct device *dev)
2054{
2055 unsigned int ret = 0;
2056 enum pld_bus_type type = pld_get_bus_type(dev);
2057
2058 switch (type) {
2059 case PLD_BUS_TYPE_SNOC:
2060 ret = pld_snoc_socinfo_get_serial_number(dev);
2061 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302062 case PLD_BUS_TYPE_PCIE_FW_SIM:
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07002063 case PLD_BUS_TYPE_PCIE:
2064 pr_err("Not supported on type %d\n", type);
2065 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302066 case PLD_BUS_TYPE_SNOC_FW_SIM:
2067 break;
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07002068 default:
2069 pr_err("Invalid device type %d\n", type);
2070 break;
2071 }
2072
2073 return ret;
2074}
Komal Seelam355b1472016-09-02 14:36:21 +05302075
Hardik Kantilal Patel9689e932016-10-18 19:02:39 +05302076/**
2077 * pld_is_qmi_disable() - Check QMI support is present or not
2078 * @dev: device
2079 *
2080 * Return: 1 QMI is not supported
2081 * 0 QMI is supported
2082 * Non zero failure code for errors
2083 */
2084int pld_is_qmi_disable(struct device *dev)
2085{
2086 int ret = 0;
2087 enum pld_bus_type type = pld_get_bus_type(dev);
2088
2089 switch (type) {
2090 case PLD_BUS_TYPE_SNOC:
Sarada Prasanna Garnayakf04667a2017-10-16 11:54:36 +05302091 ret = pld_snoc_is_qmi_disable(dev);
Hardik Kantilal Patel9689e932016-10-18 19:02:39 +05302092 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302093 case PLD_BUS_TYPE_SNOC_FW_SIM:
2094 break;
2095 case PLD_BUS_TYPE_PCIE_FW_SIM:
Hardik Kantilal Patel9689e932016-10-18 19:02:39 +05302096 case PLD_BUS_TYPE_PCIE:
2097 case PLD_BUS_TYPE_SDIO:
2098 pr_err("Not supported on type %d\n", type);
2099 ret = -EINVAL;
2100 break;
2101 default:
2102 pr_err("Invalid device type %d\n", type);
2103 ret = -EINVAL;
2104 break;
2105 }
2106
2107 return ret;
2108}
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002109
2110/**
Yuanyuan Liue4709772018-09-05 14:57:46 -07002111 * pld_is_fw_down() - Check WLAN fw is down or not
2112 *
2113 * @dev: device
2114 *
2115 * This API will be called to check if WLAN FW is down or not.
2116 *
Jayachandran Sreekumaran14382162018-12-19 13:43:40 +05302117 * Return: 0 FW is not down
2118 * Otherwise FW is down
Yuanyuan Liu46dc5cd2018-09-20 18:02:53 -07002119 * Always return 0 for unsupported bus type
Yuanyuan Liue4709772018-09-05 14:57:46 -07002120 */
2121int pld_is_fw_down(struct device *dev)
2122{
2123 int ret = 0;
2124 enum pld_bus_type type = pld_get_bus_type(dev);
Jayachandran Sreekumarandf553012019-04-11 17:00:36 +05302125 struct device *ifdev;
Yuanyuan Liue4709772018-09-05 14:57:46 -07002126
2127 switch (type) {
2128 case PLD_BUS_TYPE_SNOC:
2129 ret = pld_snoc_is_fw_down(dev);
2130 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302131 case PLD_BUS_TYPE_SNOC_FW_SIM:
2132 ret = pld_snoc_fw_sim_is_fw_down(dev);
2133 break;
2134 case PLD_BUS_TYPE_PCIE_FW_SIM:
2135 break;
Yuanyuan Liu46dc5cd2018-09-20 18:02:53 -07002136 case PLD_BUS_TYPE_PCIE:
Yue Ma9c0e4802018-09-11 15:34:06 -07002137 ret = pld_pcie_is_fw_down(dev);
2138 break;
Yuanyuan Liu46dc5cd2018-09-20 18:02:53 -07002139 case PLD_BUS_TYPE_SDIO:
Jayachandran Sreekumaran14382162018-12-19 13:43:40 +05302140 break;
Yuanyuan Liu46dc5cd2018-09-20 18:02:53 -07002141 case PLD_BUS_TYPE_USB:
Jayachandran Sreekumarandf553012019-04-11 17:00:36 +05302142 ifdev = pld_get_if_dev(dev);
2143 ret = pld_usb_is_fw_down(ifdev);
Yuanyuan Liu46dc5cd2018-09-20 18:02:53 -07002144 break;
Yuanyuan Liue4709772018-09-05 14:57:46 -07002145 default:
2146 pr_err("Invalid device type %d\n", type);
2147 ret = -EINVAL;
2148 break;
2149 }
2150
2151 return ret;
2152}
2153
2154/**
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002155 * pld_force_assert_target() - Send a force assert to FW.
2156 * This can use various sideband requests available at platform to
2157 * initiate a FW assert.
2158 * @dev: device
2159 *
2160 * Return: 0 if force assert of target was triggered successfully
2161 * Non zero failure code for errors
2162 */
2163int pld_force_assert_target(struct device *dev)
2164{
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002165 enum pld_bus_type type = pld_get_bus_type(dev);
2166
2167 switch (type) {
2168 case PLD_BUS_TYPE_SNOC:
Dustin Brown100201e2017-07-10 11:48:40 -07002169 return pld_snoc_force_assert_target(dev);
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002170 case PLD_BUS_TYPE_PCIE:
Dustin Brown100201e2017-07-10 11:48:40 -07002171 return pld_pcie_force_assert_target(dev);
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302172 case PLD_BUS_TYPE_PCIE_FW_SIM:
2173 return -EOPNOTSUPP;
2174 case PLD_BUS_TYPE_SNOC_FW_SIM:
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002175 case PLD_BUS_TYPE_SDIO:
Dustin Brown100201e2017-07-10 11:48:40 -07002176 return -EINVAL;
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002177 default:
2178 pr_err("Invalid device type %d\n", type);
Dustin Brown100201e2017-07-10 11:48:40 -07002179 return -EINVAL;
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002180 }
Sameer Thalappilac5d26e2017-01-10 15:32:58 -08002181}
Liangwei Dong95d6c372017-07-05 02:00:01 -04002182
2183/**
Yuanyuan Liu3ab55312018-12-03 15:41:02 -08002184 * pld_collect_rddm() - Collect ramdump before FW assert.
2185 * This can used to collect ramdump before FW assert.
2186 * @dev: device
2187 *
2188 * Return: 0 if ramdump is collected successfully
2189 * Non zero failure code for errors
2190 */
2191int pld_collect_rddm(struct device *dev)
2192{
2193 enum pld_bus_type type = pld_get_bus_type(dev);
2194
2195 switch (type) {
2196 case PLD_BUS_TYPE_PCIE:
2197 return pld_pcie_collect_rddm(dev);
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302198 case PLD_BUS_TYPE_PCIE_FW_SIM:
2199 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yuanyuan Liu3ab55312018-12-03 15:41:02 -08002200 case PLD_BUS_TYPE_SNOC:
2201 case PLD_BUS_TYPE_SDIO:
Ajit Pal Singh10372fa2019-04-05 16:22:06 +05302202 case PLD_BUS_TYPE_USB:
Yuanyuan Liu3ab55312018-12-03 15:41:02 -08002203 return 0;
2204 default:
2205 pr_err("Invalid device type %d\n", type);
2206 return -EINVAL;
2207 }
2208}
2209
2210/**
Yue Maa36c0f12019-08-22 13:47:17 -07002211 * pld_qmi_send_get() - Indicate certain data to be sent over QMI
2212 * @dev: device pointer
2213 *
2214 * This API can be used to indicate certain data to be sent over QMI.
2215 * pld_qmi_send() is expected to be called later.
2216 *
2217 * Return: 0 for success
2218 * Non zero failure code for errors
2219 */
2220int pld_qmi_send_get(struct device *dev)
2221{
2222 enum pld_bus_type type = pld_get_bus_type(dev);
2223
2224 switch (type) {
2225 case PLD_BUS_TYPE_PCIE:
2226 return pld_pcie_qmi_send_get(dev);
2227 case PLD_BUS_TYPE_SNOC:
2228 case PLD_BUS_TYPE_SDIO:
2229 case PLD_BUS_TYPE_USB:
2230 return 0;
2231 default:
2232 pr_err("Invalid device type %d\n", type);
2233 return -EINVAL;
2234 }
2235}
2236
2237/**
2238 * pld_qmi_send_put() - Indicate response sent over QMI has been processed
2239 * @dev: device pointer
2240 *
2241 * This API can be used to indicate response of the data sent over QMI has
2242 * been processed.
2243 *
2244 * Return: 0 for success
2245 * Non zero failure code for errors
2246 */
2247int pld_qmi_send_put(struct device *dev)
2248{
2249 enum pld_bus_type type = pld_get_bus_type(dev);
2250
2251 switch (type) {
2252 case PLD_BUS_TYPE_PCIE:
2253 return pld_pcie_qmi_send_put(dev);
2254 case PLD_BUS_TYPE_SNOC:
2255 case PLD_BUS_TYPE_SDIO:
2256 case PLD_BUS_TYPE_USB:
2257 return 0;
2258 default:
2259 pr_err("Invalid device type %d\n", type);
2260 return -EINVAL;
2261 }
2262}
2263
2264/**
2265 * pld_qmi_send() - Send data request over QMI
2266 * @dev: device pointer
2267 * @type: type of the send data operation
2268 * @cmd: buffer pointer of send data request command
2269 * @cmd_len: size of the command buffer
2270 * @cb_ctx: context pointer if any to pass back in callback
2271 * @cb: callback pointer to pass response back
2272 *
2273 * This API can be used to send data request over QMI.
2274 *
2275 * Return: 0 if data request sends successfully
2276 * Non zero failure code for errors
2277 */
2278int pld_qmi_send(struct device *dev, int type, void *cmd,
2279 int cmd_len, void *cb_ctx,
2280 int (*cb)(void *ctx, void *event, int event_len))
2281{
2282 enum pld_bus_type bus_type = pld_get_bus_type(dev);
2283
2284 switch (bus_type) {
2285 case PLD_BUS_TYPE_PCIE:
2286 return pld_pcie_qmi_send(dev, type, cmd, cmd_len, cb_ctx, cb);
2287 case PLD_BUS_TYPE_SNOC:
2288 case PLD_BUS_TYPE_SDIO:
2289 case PLD_BUS_TYPE_USB:
2290 return -EINVAL;
2291 default:
2292 pr_err("Invalid device type %d\n", bus_type);
2293 return -EINVAL;
2294 }
2295}
2296
2297/**
Liangwei Dong95d6c372017-07-05 02:00:01 -04002298 * pld_is_fw_dump_skipped() - get fw dump skipped status.
2299 * The subsys ssr status help the driver to decide whether to skip
2300 * the FW memory dump when FW assert.
2301 * For SDIO case, the memory dump progress takes 1 minutes to
2302 * complete, which is not acceptable in SSR enabled.
2303 *
2304 * Return: true if need to skip FW dump.
2305 */
2306bool pld_is_fw_dump_skipped(struct device *dev)
2307{
2308 bool ret = false;
2309 enum pld_bus_type type = pld_get_bus_type(dev);
2310
2311 switch (type) {
2312 case PLD_BUS_TYPE_SDIO:
2313 ret = pld_sdio_is_fw_dump_skipped();
2314 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302315 case PLD_BUS_TYPE_PCIE_FW_SIM:
2316 case PLD_BUS_TYPE_SNOC_FW_SIM:
Liangwei Dong95d6c372017-07-05 02:00:01 -04002317 default:
2318 break;
2319 }
2320 return ret;
2321}
jitiphil0e3b5922018-07-24 18:43:50 +05302322
Vevek Venkatesan789b6b32019-04-15 13:05:10 +05302323int pld_is_pdr(struct device *dev)
2324{
2325 int ret = 0;
2326 enum pld_bus_type type = pld_get_bus_type(dev);
2327
2328 switch (type) {
2329 case PLD_BUS_TYPE_SNOC:
2330 ret = pld_snoc_is_pdr();
2331 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302332 case PLD_BUS_TYPE_PCIE_FW_SIM:
2333 case PLD_BUS_TYPE_SNOC_FW_SIM:
Vevek Venkatesan789b6b32019-04-15 13:05:10 +05302334 default:
2335 break;
2336 }
2337 return ret;
2338}
2339
jitiphil0e3b5922018-07-24 18:43:50 +05302340int pld_is_fw_rejuvenate(struct device *dev)
2341{
2342 int ret = 0;
2343 enum pld_bus_type type = pld_get_bus_type(dev);
2344
2345 switch (type) {
2346 case PLD_BUS_TYPE_SNOC:
2347 ret = pld_snoc_is_fw_rejuvenate();
2348 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302349 case PLD_BUS_TYPE_PCIE_FW_SIM:
2350 case PLD_BUS_TYPE_SNOC_FW_SIM:
jitiphil0e3b5922018-07-24 18:43:50 +05302351 default:
2352 break;
2353 }
2354 return ret;
2355}
Yu Ouyang58648a52018-11-01 11:18:15 +08002356
2357bool pld_have_platform_driver_support(struct device *dev)
2358{
2359 bool ret = false;
2360
2361 switch (pld_get_bus_type(dev)) {
2362 case PLD_BUS_TYPE_PCIE:
2363 ret = pld_pcie_platform_driver_support();
2364 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302365 case PLD_BUS_TYPE_PCIE_FW_SIM:
2366 ret = true;
2367 break;
2368 case PLD_BUS_TYPE_SNOC_FW_SIM:
Yu Ouyang58648a52018-11-01 11:18:15 +08002369 case PLD_BUS_TYPE_SNOC:
2370 break;
2371 case PLD_BUS_TYPE_SDIO:
2372 ret = pld_sdio_platform_driver_support();
2373 break;
2374 default:
2375 pr_err("Invalid device type\n");
2376 break;
2377 }
2378
2379 return ret;
2380}
2381
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002382int pld_idle_shutdown(struct device *dev,
2383 int (*shutdown_cb)(struct device *dev))
Rajeev Kumare01118e2019-04-08 10:31:41 -07002384{
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002385 int errno = -EINVAL;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002386 enum pld_bus_type type;
2387
2388 if (!shutdown_cb)
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002389 return -EINVAL;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002390
2391 type = pld_get_bus_type(dev);
2392 switch (type) {
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002393 case PLD_BUS_TYPE_SDIO:
2394 case PLD_BUS_TYPE_USB:
Rajeev Kumare01118e2019-04-08 10:31:41 -07002395 case PLD_BUS_TYPE_SNOC:
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002396 errno = shutdown_cb(dev);
Rajeev Kumare01118e2019-04-08 10:31:41 -07002397 break;
Rajeev Kumar588a2542019-04-08 10:57:19 -07002398 case PLD_BUS_TYPE_PCIE:
2399 errno = pld_pcie_idle_shutdown(dev);
2400 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302401 case PLD_BUS_TYPE_PCIE_FW_SIM:
2402 errno = pld_pcie_fw_sim_idle_shutdown(dev);
2403 break;
2404 case PLD_BUS_TYPE_SNOC_FW_SIM:
2405 errno = pld_snoc_fw_sim_idle_shutdown(dev);
2406 break;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002407 default:
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002408 pr_err("Invalid device type %d\n", type);
Rajeev Kumare01118e2019-04-08 10:31:41 -07002409 break;
2410 }
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002411
2412 return errno;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002413}
2414
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002415int pld_idle_restart(struct device *dev,
2416 int (*restart_cb)(struct device *dev))
Rajeev Kumare01118e2019-04-08 10:31:41 -07002417{
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002418 int errno = -EINVAL;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002419 enum pld_bus_type type;
2420
2421 if (!restart_cb)
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002422 return -EINVAL;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002423
2424 type = pld_get_bus_type(dev);
2425 switch (type) {
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002426 case PLD_BUS_TYPE_SDIO:
2427 case PLD_BUS_TYPE_USB:
Rajeev Kumare01118e2019-04-08 10:31:41 -07002428 case PLD_BUS_TYPE_SNOC:
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002429 errno = restart_cb(dev);
Rajeev Kumare01118e2019-04-08 10:31:41 -07002430 break;
Rajeev Kumar588a2542019-04-08 10:57:19 -07002431 case PLD_BUS_TYPE_PCIE:
2432 errno = pld_pcie_idle_restart(dev);
2433 break;
Naman Padhiarc52e7fd2019-06-23 01:21:42 +05302434 case PLD_BUS_TYPE_PCIE_FW_SIM:
2435 errno = pld_pcie_fw_sim_idle_restart(dev);
2436 break;
2437 case PLD_BUS_TYPE_SNOC_FW_SIM:
2438 errno = pld_snoc_fw_sim_idle_restart(dev);
2439 break;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002440 default:
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002441 pr_err("Invalid device type %d\n", type);
Rajeev Kumare01118e2019-04-08 10:31:41 -07002442 break;
2443 }
Rajeev Kumar473f9af2019-04-05 14:25:56 -07002444
2445 return errno;
Rajeev Kumare01118e2019-04-08 10:31:41 -07002446}