blob: 079fb615753dc08f3b65c040af32f95e95881edb [file] [log] [blame]
Yue Ma0317e4a2018-01-10 11:48:32 -08001/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/delay.h>
14#include <linux/jiffies.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/pm_wakeup.h>
19#include <linux/rwsem.h>
20#include <linux/suspend.h>
21#include <linux/timer.h>
22#include <soc/qcom/ramdump.h>
23#include <soc/qcom/subsystem_notif.h>
24
25#include "main.h"
Yue Mafcf60422018-05-01 16:59:56 -070026#include "bus.h"
Yue Ma0317e4a2018-01-10 11:48:32 -080027#include "debug.h"
Yue Ma0317e4a2018-01-10 11:48:32 -080028
29#define CNSS_DUMP_FORMAT_VER 0x11
30#define CNSS_DUMP_FORMAT_VER_V2 0x22
31#define CNSS_DUMP_MAGIC_VER_V2 0x42445953
32#define CNSS_DUMP_NAME "CNSS_WLAN"
33#define CNSS_DUMP_DESC_SIZE 0x1000
34#define CNSS_DUMP_SEG_VER 0x1
35#define WLAN_RECOVERY_DELAY 1000
36#define FILE_SYSTEM_READY 1
37#define FW_READY_TIMEOUT 20000
38#define FW_ASSERT_TIMEOUT 5000
39#define CNSS_EVENT_PENDING 2989
Yue Ma0317e4a2018-01-10 11:48:32 -080040
41static struct cnss_plat_data *plat_env;
42
43static DECLARE_RWSEM(cnss_pm_sem);
44
45static bool qmi_bypass;
46#ifdef CONFIG_CNSS2_DEBUG
47module_param(qmi_bypass, bool, 0600);
48MODULE_PARM_DESC(qmi_bypass, "Bypass QMI from platform driver");
49#endif
50
51static bool enable_waltest;
52#ifdef CONFIG_CNSS2_DEBUG
53module_param(enable_waltest, bool, 0600);
54MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest");
55#endif
56
Yue Ma0317e4a2018-01-10 11:48:32 -080057unsigned long quirks;
58#ifdef CONFIG_CNSS2_DEBUG
59module_param(quirks, ulong, 0600);
60MODULE_PARM_DESC(quirks, "Debug quirks for the driver");
61#endif
62
63static struct cnss_fw_files FW_FILES_QCA6174_FW_3_0 = {
64 "qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin",
65 "utfbd30.bin", "epping30.bin", "evicted30.bin"
66};
67
68static struct cnss_fw_files FW_FILES_DEFAULT = {
69 "qwlan.bin", "bdwlan.bin", "otp.bin", "utf.bin",
70 "utfbd.bin", "epping.bin", "evicted.bin"
71};
72
73struct cnss_driver_event {
74 struct list_head list;
75 enum cnss_driver_event_type type;
76 bool sync;
77 struct completion complete;
78 int ret;
79 void *data;
80};
81
Yue Ma0317e4a2018-01-10 11:48:32 -080082static void cnss_set_plat_priv(struct platform_device *plat_dev,
83 struct cnss_plat_data *plat_priv)
84{
85 plat_env = plat_priv;
86}
87
Yue Mae83a0eff2018-05-04 14:15:54 -070088struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev)
Yue Ma0317e4a2018-01-10 11:48:32 -080089{
90 return plat_env;
91}
92
Yue Ma0317e4a2018-01-10 11:48:32 -080093static int cnss_pm_notify(struct notifier_block *b,
94 unsigned long event, void *p)
95{
96 switch (event) {
97 case PM_SUSPEND_PREPARE:
98 down_write(&cnss_pm_sem);
99 break;
100 case PM_POST_SUSPEND:
101 up_write(&cnss_pm_sem);
102 break;
103 }
104
105 return NOTIFY_DONE;
106}
107
108static struct notifier_block cnss_pm_notifier = {
109 .notifier_call = cnss_pm_notify,
110};
111
112static void cnss_pm_stay_awake(struct cnss_plat_data *plat_priv)
113{
114 if (atomic_inc_return(&plat_priv->pm_count) != 1)
115 return;
116
117 cnss_pr_dbg("PM stay awake, state: 0x%lx, count: %d\n",
118 plat_priv->driver_state,
119 atomic_read(&plat_priv->pm_count));
120 pm_stay_awake(&plat_priv->plat_dev->dev);
121}
122
123static void cnss_pm_relax(struct cnss_plat_data *plat_priv)
124{
125 int r = atomic_dec_return(&plat_priv->pm_count);
126
127 WARN_ON(r < 0);
128
129 if (r != 0)
130 return;
131
132 cnss_pr_dbg("PM relax, state: 0x%lx, count: %d\n",
133 plat_priv->driver_state,
134 atomic_read(&plat_priv->pm_count));
135 pm_relax(&plat_priv->plat_dev->dev);
136}
137
138void cnss_lock_pm_sem(struct device *dev)
139{
140 down_read(&cnss_pm_sem);
141}
142EXPORT_SYMBOL(cnss_lock_pm_sem);
143
144void cnss_release_pm_sem(struct device *dev)
145{
146 up_read(&cnss_pm_sem);
147}
148EXPORT_SYMBOL(cnss_release_pm_sem);
149
150int cnss_get_fw_files_for_target(struct device *dev,
151 struct cnss_fw_files *pfw_files,
152 u32 target_type, u32 target_version)
153{
154 if (!pfw_files)
155 return -ENODEV;
156
157 switch (target_version) {
158 case QCA6174_REV3_VERSION:
159 case QCA6174_REV3_2_VERSION:
160 memcpy(pfw_files, &FW_FILES_QCA6174_FW_3_0, sizeof(*pfw_files));
161 break;
162 default:
163 memcpy(pfw_files, &FW_FILES_DEFAULT, sizeof(*pfw_files));
164 cnss_pr_err("Unknown target version, type: 0x%X, version: 0x%X",
165 target_type, target_version);
166 break;
167 }
168
169 return 0;
170}
171EXPORT_SYMBOL(cnss_get_fw_files_for_target);
172
173int cnss_request_bus_bandwidth(struct device *dev, int bandwidth)
174{
175 int ret = 0;
176 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
177 struct cnss_bus_bw_info *bus_bw_info;
178
179 if (!plat_priv)
180 return -ENODEV;
181
182 bus_bw_info = &plat_priv->bus_bw_info;
183 if (!bus_bw_info->bus_client)
184 return -EINVAL;
185
186 switch (bandwidth) {
187 case CNSS_BUS_WIDTH_NONE:
188 case CNSS_BUS_WIDTH_LOW:
189 case CNSS_BUS_WIDTH_MEDIUM:
190 case CNSS_BUS_WIDTH_HIGH:
191 ret = msm_bus_scale_client_update_request(
192 bus_bw_info->bus_client, bandwidth);
193 if (!ret)
194 bus_bw_info->current_bw_vote = bandwidth;
195 else
196 cnss_pr_err("Could not set bus bandwidth: %d, err = %d\n",
197 bandwidth, ret);
198 break;
199 default:
200 cnss_pr_err("Invalid bus bandwidth: %d", bandwidth);
201 ret = -EINVAL;
202 }
203
204 return ret;
205}
206EXPORT_SYMBOL(cnss_request_bus_bandwidth);
207
208int cnss_get_platform_cap(struct device *dev, struct cnss_platform_cap *cap)
209{
210 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
211
212 if (!plat_priv)
213 return -ENODEV;
214
215 if (cap)
216 *cap = plat_priv->cap;
217
218 return 0;
219}
220EXPORT_SYMBOL(cnss_get_platform_cap);
221
Yue Ma0317e4a2018-01-10 11:48:32 -0800222void cnss_request_pm_qos(struct device *dev, u32 qos_val)
223{
224 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
225
226 if (!plat_priv)
227 return;
228
229 pm_qos_add_request(&plat_priv->qos_request, PM_QOS_CPU_DMA_LATENCY,
230 qos_val);
231}
232EXPORT_SYMBOL(cnss_request_pm_qos);
233
234void cnss_remove_pm_qos(struct device *dev)
235{
236 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
237
238 if (!plat_priv)
239 return;
240
241 pm_qos_remove_request(&plat_priv->qos_request);
242}
243EXPORT_SYMBOL(cnss_remove_pm_qos);
244
245int cnss_wlan_enable(struct device *dev,
246 struct cnss_wlan_enable_cfg *config,
247 enum cnss_driver_mode mode,
248 const char *host_version)
249{
250 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
251 struct wlfw_wlan_cfg_req_msg_v01 req;
252 u32 i;
253 int ret = 0;
254
255 if (plat_priv->device_id == QCA6174_DEVICE_ID)
256 return 0;
257
258 if (qmi_bypass)
259 return 0;
260
261 if (!config || !host_version) {
262 cnss_pr_err("Invalid config or host_version pointer\n");
263 return -EINVAL;
264 }
265
266 cnss_pr_dbg("Mode: %d, config: %pK, host_version: %s\n",
267 mode, config, host_version);
268
269 if (mode == CNSS_WALTEST || mode == CNSS_CCPM)
270 goto skip_cfg;
271
272 memset(&req, 0, sizeof(req));
273
274 req.host_version_valid = 1;
275 strlcpy(req.host_version, host_version,
276 QMI_WLFW_MAX_STR_LEN_V01 + 1);
277
278 req.tgt_cfg_valid = 1;
279 if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
280 req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
281 else
282 req.tgt_cfg_len = config->num_ce_tgt_cfg;
283 for (i = 0; i < req.tgt_cfg_len; i++) {
284 req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
285 req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
286 req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
287 req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
288 req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
289 }
290
291 req.svc_cfg_valid = 1;
292 if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
293 req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
294 else
295 req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
296 for (i = 0; i < req.svc_cfg_len; i++) {
297 req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
298 req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
299 req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
300 }
301
302 req.shadow_reg_v2_valid = 1;
303 if (config->num_shadow_reg_v2_cfg >
304 QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
305 req.shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
306 else
307 req.shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
308
309 memcpy(req.shadow_reg_v2, config->shadow_reg_v2_cfg,
310 sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
311 * req.shadow_reg_v2_len);
312
313 ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, &req);
314 if (ret)
315 goto out;
316
317skip_cfg:
318 ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, mode);
319out:
320 return ret;
321}
322EXPORT_SYMBOL(cnss_wlan_enable);
323
324int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode)
325{
326 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
327
328 if (plat_priv->device_id == QCA6174_DEVICE_ID)
329 return 0;
330
331 if (qmi_bypass)
332 return 0;
333
334 return cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
335}
336EXPORT_SYMBOL(cnss_wlan_disable);
337
338#ifdef CONFIG_CNSS2_DEBUG
339int cnss_athdiag_read(struct device *dev, u32 offset, u32 mem_type,
340 u32 data_len, u8 *output)
341{
342 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
343 int ret = 0;
344
345 if (!plat_priv) {
346 cnss_pr_err("plat_priv is NULL!\n");
347 return -EINVAL;
348 }
349
350 if (plat_priv->device_id == QCA6174_DEVICE_ID)
351 return 0;
352
353 if (!output || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
354 cnss_pr_err("Invalid parameters for athdiag read: output %p, data_len %u\n",
355 output, data_len);
356 ret = -EINVAL;
357 goto out;
358 }
359
360 if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
361 cnss_pr_err("Invalid state for athdiag read: 0x%lx\n",
362 plat_priv->driver_state);
363 ret = -EINVAL;
364 goto out;
365 }
366
367 ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, offset, mem_type,
368 data_len, output);
369
370out:
371 return ret;
372}
373EXPORT_SYMBOL(cnss_athdiag_read);
374
375int cnss_athdiag_write(struct device *dev, u32 offset, u32 mem_type,
376 u32 data_len, u8 *input)
377{
378 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
379 int ret = 0;
380
381 if (!plat_priv) {
382 cnss_pr_err("plat_priv is NULL!\n");
383 return -EINVAL;
384 }
385
386 if (plat_priv->device_id == QCA6174_DEVICE_ID)
387 return 0;
388
389 if (!input || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
390 cnss_pr_err("Invalid parameters for athdiag write: input %p, data_len %u\n",
391 input, data_len);
392 ret = -EINVAL;
393 goto out;
394 }
395
396 if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
397 cnss_pr_err("Invalid state for athdiag write: 0x%lx\n",
398 plat_priv->driver_state);
399 ret = -EINVAL;
400 goto out;
401 }
402
403 ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, offset, mem_type,
404 data_len, input);
405
406out:
407 return ret;
408}
409EXPORT_SYMBOL(cnss_athdiag_write);
410#else
411int cnss_athdiag_read(struct device *dev, u32 offset, u32 mem_type,
412 u32 data_len, u8 *output)
413{
414 return -EPERM;
415}
416EXPORT_SYMBOL(cnss_athdiag_read);
417
418int cnss_athdiag_write(struct device *dev, u32 offset, u32 mem_type,
419 u32 data_len, u8 *input)
420{
421 return -EPERM;
422}
423EXPORT_SYMBOL(cnss_athdiag_write);
424#endif
425
426int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
427{
428 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
429
430 if (plat_priv->device_id == QCA6174_DEVICE_ID)
431 return 0;
432
433 return cnss_wlfw_ini_send_sync(plat_priv, fw_log_mode);
434}
435EXPORT_SYMBOL(cnss_set_fw_log_mode);
436
Yue Mae83a0eff2018-05-04 14:15:54 -0700437bool *cnss_get_qmi_bypass(void)
438{
439 return &qmi_bypass;
440}
441
442unsigned long *cnss_get_debug_quirks(void)
443{
444 return &quirks;
445}
446
Yue Ma0317e4a2018-01-10 11:48:32 -0800447static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
448{
449 int ret = 0;
450
451 if (!plat_priv)
452 return -ENODEV;
453
454 set_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
455
456 ret = cnss_wlfw_tgt_cap_send_sync(plat_priv);
457 if (ret)
458 goto out;
459
460 ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv);
461 if (ret)
462 goto out;
463
Yue Mafcf60422018-05-01 16:59:56 -0700464 ret = cnss_bus_load_m3(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800465 if (ret)
466 goto out;
467
468 ret = cnss_wlfw_m3_dnld_send_sync(plat_priv);
469 if (ret)
470 goto out;
471
472 return 0;
473out:
474 return ret;
475}
476
Yue Ma0317e4a2018-01-10 11:48:32 -0800477static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
478{
479 int ret = 0;
480
481 if (!plat_priv)
482 return -ENODEV;
483
484 del_timer(&plat_priv->fw_boot_timer);
485 set_bit(CNSS_FW_READY, &plat_priv->driver_state);
486
487 if (test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state)) {
488 clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
489 clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
490 }
491
492 if (enable_waltest) {
493 ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
494 QMI_WLFW_WALTEST_V01);
495 } else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
496 ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
497 QMI_WLFW_CALIBRATION_V01);
498 } else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
499 test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
Yue Mae83a0eff2018-05-04 14:15:54 -0700500 ret = cnss_bus_call_driver_probe(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800501 } else {
502 complete(&plat_priv->power_up_complete);
503 }
504
Yue Ma8bead6d2018-02-01 12:25:47 -0800505 if (ret && test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
506 goto out;
507 else if (ret)
Yue Ma0317e4a2018-01-10 11:48:32 -0800508 goto shutdown;
509
510 return 0;
511
512shutdown:
Yue Mae83a0eff2018-05-04 14:15:54 -0700513 cnss_bus_dev_shutdown(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800514
Yue Ma8bead6d2018-02-01 12:25:47 -0800515 clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
516 clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
517
518out:
Yue Ma0317e4a2018-01-10 11:48:32 -0800519 return ret;
520}
521
522static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
523{
524 switch (type) {
525 case CNSS_DRIVER_EVENT_SERVER_ARRIVE:
526 return "SERVER_ARRIVE";
527 case CNSS_DRIVER_EVENT_SERVER_EXIT:
528 return "SERVER_EXIT";
529 case CNSS_DRIVER_EVENT_REQUEST_MEM:
530 return "REQUEST_MEM";
531 case CNSS_DRIVER_EVENT_FW_MEM_READY:
532 return "FW_MEM_READY";
533 case CNSS_DRIVER_EVENT_FW_READY:
534 return "FW_READY";
535 case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START:
536 return "COLD_BOOT_CAL_START";
537 case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE:
538 return "COLD_BOOT_CAL_DONE";
539 case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
540 return "REGISTER_DRIVER";
541 case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
542 return "UNREGISTER_DRIVER";
543 case CNSS_DRIVER_EVENT_RECOVERY:
544 return "RECOVERY";
545 case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
546 return "FORCE_FW_ASSERT";
547 case CNSS_DRIVER_EVENT_POWER_UP:
548 return "POWER_UP";
549 case CNSS_DRIVER_EVENT_POWER_DOWN:
550 return "POWER_DOWN";
551 case CNSS_DRIVER_EVENT_MAX:
552 return "EVENT_MAX";
553 }
554
555 return "UNKNOWN";
556};
557
558int cnss_driver_event_post(struct cnss_plat_data *plat_priv,
559 enum cnss_driver_event_type type,
560 u32 flags, void *data)
561{
562 struct cnss_driver_event *event;
563 unsigned long irq_flags;
564 int gfp = GFP_KERNEL;
565 int ret = 0;
566
567 if (!plat_priv)
568 return -ENODEV;
569
570 cnss_pr_dbg("Posting event: %s(%d)%s, state: 0x%lx flags: 0x%0x\n",
571 cnss_driver_event_to_str(type), type,
572 flags ? "-sync" : "", plat_priv->driver_state, flags);
573
574 if (type >= CNSS_DRIVER_EVENT_MAX) {
575 cnss_pr_err("Invalid Event type: %d, can't post", type);
576 return -EINVAL;
577 }
578
579 if (in_interrupt() || irqs_disabled())
580 gfp = GFP_ATOMIC;
581
582 event = kzalloc(sizeof(*event), gfp);
583 if (!event)
584 return -ENOMEM;
585
586 cnss_pm_stay_awake(plat_priv);
587
588 event->type = type;
589 event->data = data;
590 init_completion(&event->complete);
591 event->ret = CNSS_EVENT_PENDING;
592 event->sync = !!(flags & CNSS_EVENT_SYNC);
593
594 spin_lock_irqsave(&plat_priv->event_lock, irq_flags);
595 list_add_tail(&event->list, &plat_priv->event_list);
596 spin_unlock_irqrestore(&plat_priv->event_lock, irq_flags);
597
598 queue_work(plat_priv->event_wq, &plat_priv->event_work);
599
600 if (!(flags & CNSS_EVENT_SYNC))
601 goto out;
602
603 if (flags & CNSS_EVENT_UNINTERRUPTIBLE)
604 wait_for_completion(&event->complete);
605 else
606 ret = wait_for_completion_interruptible(&event->complete);
607
608 cnss_pr_dbg("Completed event: %s(%d), state: 0x%lx, ret: %d/%d\n",
609 cnss_driver_event_to_str(type), type,
610 plat_priv->driver_state, ret, event->ret);
611 spin_lock_irqsave(&plat_priv->event_lock, irq_flags);
612 if (ret == -ERESTARTSYS && event->ret == CNSS_EVENT_PENDING) {
613 event->sync = false;
614 spin_unlock_irqrestore(&plat_priv->event_lock, irq_flags);
615 ret = -EINTR;
616 goto out;
617 }
618 spin_unlock_irqrestore(&plat_priv->event_lock, irq_flags);
619
620 ret = event->ret;
621 kfree(event);
622
623out:
624 cnss_pm_relax(plat_priv);
625 return ret;
626}
627
628int cnss_power_up(struct device *dev)
629{
630 int ret = 0;
631 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
632 unsigned int timeout;
633
634 if (!plat_priv) {
635 cnss_pr_err("plat_priv is NULL\n");
636 return -ENODEV;
637 }
638
639 cnss_pr_dbg("Powering up device\n");
640
641 ret = cnss_driver_event_post(plat_priv,
642 CNSS_DRIVER_EVENT_POWER_UP,
643 CNSS_EVENT_SYNC, NULL);
644 if (ret)
645 goto out;
646
647 if (plat_priv->device_id == QCA6174_DEVICE_ID)
648 goto out;
649
650 timeout = cnss_get_qmi_timeout();
651
652 reinit_completion(&plat_priv->power_up_complete);
653 ret = wait_for_completion_timeout(&plat_priv->power_up_complete,
654 msecs_to_jiffies(timeout) << 2);
655 if (!ret) {
656 cnss_pr_err("Timeout waiting for power up to complete\n");
657 ret = -EAGAIN;
658 goto out;
659 }
660
661 return 0;
662
663out:
664 return ret;
665}
666EXPORT_SYMBOL(cnss_power_up);
667
668int cnss_power_down(struct device *dev)
669{
670 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
671
672 if (!plat_priv) {
673 cnss_pr_err("plat_priv is NULL\n");
674 return -ENODEV;
675 }
676
677 cnss_pr_dbg("Powering down device\n");
678
679 return cnss_driver_event_post(plat_priv,
680 CNSS_DRIVER_EVENT_POWER_DOWN,
681 CNSS_EVENT_SYNC, NULL);
682}
683EXPORT_SYMBOL(cnss_power_down);
684
Yue Ma0317e4a2018-01-10 11:48:32 -0800685static int cnss_get_resources(struct cnss_plat_data *plat_priv)
686{
687 int ret = 0;
688
689 ret = cnss_get_vreg(plat_priv);
690 if (ret) {
691 cnss_pr_err("Failed to get vreg, err = %d\n", ret);
692 goto out;
693 }
694
695 ret = cnss_get_pinctrl(plat_priv);
696 if (ret) {
697 cnss_pr_err("Failed to get pinctrl, err = %d\n", ret);
698 goto out;
699 }
700
701 return 0;
702out:
703 return ret;
704}
705
706static void cnss_put_resources(struct cnss_plat_data *plat_priv)
707{
708}
709
710static int cnss_modem_notifier_nb(struct notifier_block *nb,
711 unsigned long code,
712 void *ss_handle)
713{
714 struct cnss_plat_data *plat_priv =
715 container_of(nb, struct cnss_plat_data, modem_nb);
Yue Ma0317e4a2018-01-10 11:48:32 -0800716 struct cnss_esoc_info *esoc_info;
Yue Ma0317e4a2018-01-10 11:48:32 -0800717
718 cnss_pr_dbg("Modem notifier: event %lu\n", code);
719
Yue Mae83a0eff2018-05-04 14:15:54 -0700720 if (!plat_priv)
Yue Ma0317e4a2018-01-10 11:48:32 -0800721 return NOTIFY_DONE;
722
723 esoc_info = &plat_priv->esoc_info;
724
725 if (code == SUBSYS_AFTER_POWERUP)
726 esoc_info->modem_current_status = 1;
727 else if (code == SUBSYS_BEFORE_SHUTDOWN)
728 esoc_info->modem_current_status = 0;
729 else
730 return NOTIFY_DONE;
731
Yue Mae83a0eff2018-05-04 14:15:54 -0700732 if (!cnss_bus_call_driver_modem_status(plat_priv,
733 esoc_info->modem_current_status))
Yue Ma0317e4a2018-01-10 11:48:32 -0800734 return NOTIFY_DONE;
735
Yue Ma0317e4a2018-01-10 11:48:32 -0800736 return NOTIFY_OK;
737}
738
739static int cnss_register_esoc(struct cnss_plat_data *plat_priv)
740{
741 int ret = 0;
742 struct device *dev;
743 struct cnss_esoc_info *esoc_info;
744 struct esoc_desc *esoc_desc;
745 const char *client_desc;
746
747 dev = &plat_priv->plat_dev->dev;
748 esoc_info = &plat_priv->esoc_info;
749
750 esoc_info->notify_modem_status =
751 of_property_read_bool(dev->of_node,
752 "qcom,notify-modem-status");
753
Yue Ma3eb55622018-02-22 12:14:00 -0800754 if (!esoc_info->notify_modem_status)
Yue Ma0317e4a2018-01-10 11:48:32 -0800755 goto out;
756
757 ret = of_property_read_string_index(dev->of_node, "esoc-names", 0,
758 &client_desc);
759 if (ret) {
760 cnss_pr_dbg("esoc-names is not defined in DT, skip!\n");
761 } else {
762 esoc_desc = devm_register_esoc_client(dev, client_desc);
763 if (IS_ERR_OR_NULL(esoc_desc)) {
764 ret = PTR_RET(esoc_desc);
765 cnss_pr_err("Failed to register esoc_desc, err = %d\n",
766 ret);
767 goto out;
768 }
769 esoc_info->esoc_desc = esoc_desc;
770 }
771
772 plat_priv->modem_nb.notifier_call = cnss_modem_notifier_nb;
773 esoc_info->modem_current_status = 0;
774 esoc_info->modem_notify_handler =
775 subsys_notif_register_notifier(esoc_info->esoc_desc ?
776 esoc_info->esoc_desc->name :
777 "modem", &plat_priv->modem_nb);
778 if (IS_ERR(esoc_info->modem_notify_handler)) {
779 ret = PTR_ERR(esoc_info->modem_notify_handler);
780 cnss_pr_err("Failed to register esoc notifier, err = %d\n",
781 ret);
782 goto unreg_esoc;
783 }
784
785 return 0;
786unreg_esoc:
787 if (esoc_info->esoc_desc)
788 devm_unregister_esoc_client(dev, esoc_info->esoc_desc);
789out:
790 return ret;
791}
792
793static void cnss_unregister_esoc(struct cnss_plat_data *plat_priv)
794{
795 struct device *dev;
796 struct cnss_esoc_info *esoc_info;
797
798 dev = &plat_priv->plat_dev->dev;
799 esoc_info = &plat_priv->esoc_info;
800
801 if (esoc_info->notify_modem_status)
802 subsys_notif_unregister_notifier(esoc_info->
803 modem_notify_handler,
804 &plat_priv->modem_nb);
805 if (esoc_info->esoc_desc)
806 devm_unregister_esoc_client(dev, esoc_info->esoc_desc);
807}
808
Yue Ma0317e4a2018-01-10 11:48:32 -0800809static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
810{
811 struct cnss_plat_data *plat_priv;
812
813 if (!subsys_desc->dev) {
814 cnss_pr_err("dev from subsys_desc is NULL\n");
815 return -ENODEV;
816 }
817
818 plat_priv = dev_get_drvdata(subsys_desc->dev);
819 if (!plat_priv) {
820 cnss_pr_err("plat_priv is NULL\n");
821 return -ENODEV;
822 }
823
824 if (!plat_priv->driver_state) {
825 cnss_pr_dbg("Powerup is ignored\n");
826 return 0;
827 }
828
Yue Mae83a0eff2018-05-04 14:15:54 -0700829 return cnss_bus_dev_powerup(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800830}
831
832static int cnss_subsys_shutdown(const struct subsys_desc *subsys_desc,
833 bool force_stop)
834{
835 struct cnss_plat_data *plat_priv;
836
837 if (!subsys_desc->dev) {
838 cnss_pr_err("dev from subsys_desc is NULL\n");
839 return -ENODEV;
840 }
841
842 plat_priv = dev_get_drvdata(subsys_desc->dev);
843 if (!plat_priv) {
844 cnss_pr_err("plat_priv is NULL\n");
845 return -ENODEV;
846 }
847
848 if (!plat_priv->driver_state) {
849 cnss_pr_dbg("shutdown is ignored\n");
850 return 0;
851 }
852
Yue Mae83a0eff2018-05-04 14:15:54 -0700853 return cnss_bus_dev_shutdown(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800854}
855
Yue Ma0317e4a2018-01-10 11:48:32 -0800856void cnss_device_crashed(struct device *dev)
857{
858 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
859 struct cnss_subsys_info *subsys_info;
860
861 if (!plat_priv)
862 return;
863
864 subsys_info = &plat_priv->subsys_info;
865 if (subsys_info->subsys_device) {
866 set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
867 subsys_set_crash_status(subsys_info->subsys_device, true);
868 subsystem_restart_dev(subsys_info->subsys_device);
869 }
870}
871EXPORT_SYMBOL(cnss_device_crashed);
872
873static void cnss_subsys_crash_shutdown(const struct subsys_desc *subsys_desc)
874{
875 struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
876
877 if (!plat_priv) {
Yue Mae83a0eff2018-05-04 14:15:54 -0700878 cnss_pr_err("plat_priv is NULL\n");
Yue Ma0317e4a2018-01-10 11:48:32 -0800879 return;
880 }
881
Yue Mae83a0eff2018-05-04 14:15:54 -0700882 cnss_bus_dev_crash_shutdown(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800883}
884
Yue Mae83a0eff2018-05-04 14:15:54 -0700885static int cnss_subsys_ramdump(int enable,
886 const struct subsys_desc *subsys_desc)
887{
888 struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
889
890 if (!plat_priv) {
891 cnss_pr_err("plat_priv is NULL\n");
892 return -ENODEV;
893 }
894
895 if (!enable)
896 return 0;
897
898 return cnss_bus_dev_ramdump(plat_priv);
899}
900
901void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
902{
903 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
904 struct cnss_ramdump_info *ramdump_info;
905
906 if (!plat_priv)
907 return NULL;
908
909 ramdump_info = &plat_priv->ramdump_info;
910 *size = ramdump_info->ramdump_size;
911
912 return ramdump_info->ramdump_va;
913}
914EXPORT_SYMBOL(cnss_get_virt_ramdump_mem);
915
Yue Ma0317e4a2018-01-10 11:48:32 -0800916static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
917{
918 switch (reason) {
919 case CNSS_REASON_DEFAULT:
920 return "DEFAULT";
921 case CNSS_REASON_LINK_DOWN:
922 return "LINK_DOWN";
923 case CNSS_REASON_RDDM:
924 return "RDDM";
925 case CNSS_REASON_TIMEOUT:
926 return "TIMEOUT";
927 }
928
929 return "UNKNOWN";
930};
931
932static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
933 enum cnss_recovery_reason reason)
934{
Yue Ma0317e4a2018-01-10 11:48:32 -0800935 struct cnss_subsys_info *subsys_info =
936 &plat_priv->subsys_info;
Yue Ma0317e4a2018-01-10 11:48:32 -0800937
938 plat_priv->recovery_count++;
939
940 if (plat_priv->device_id == QCA6174_DEVICE_ID)
941 goto self_recovery;
942
Yue Ma0317e4a2018-01-10 11:48:32 -0800943 if (test_bit(SKIP_RECOVERY, &quirks)) {
944 cnss_pr_dbg("Skip device recovery\n");
945 return 0;
946 }
947
948 switch (reason) {
949 case CNSS_REASON_LINK_DOWN:
950 if (test_bit(LINK_DOWN_SELF_RECOVERY, &quirks))
951 goto self_recovery;
952 break;
953 case CNSS_REASON_RDDM:
954 clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
Yue Mafcf60422018-05-01 16:59:56 -0700955 cnss_bus_collect_dump_info(plat_priv, false);
Yue Ma0317e4a2018-01-10 11:48:32 -0800956 break;
957 case CNSS_REASON_DEFAULT:
958 case CNSS_REASON_TIMEOUT:
959 break;
960 default:
961 cnss_pr_err("Unsupported recovery reason: %s(%d)\n",
962 cnss_recovery_reason_to_str(reason), reason);
963 break;
964 }
965
966 if (!subsys_info->subsys_device)
967 return 0;
968
969 subsys_set_crash_status(subsys_info->subsys_device, true);
970 subsystem_restart_dev(subsys_info->subsys_device);
971
972 return 0;
973
974self_recovery:
Yue Mae83a0eff2018-05-04 14:15:54 -0700975 cnss_bus_dev_shutdown(plat_priv);
976 cnss_bus_dev_powerup(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -0800977
978 return 0;
979}
980
981static int cnss_driver_recovery_hdlr(struct cnss_plat_data *plat_priv,
982 void *data)
983{
984 struct cnss_recovery_data *recovery_data = data;
985 int ret = 0;
986
987 cnss_pr_dbg("Driver recovery is triggered with reason: %s(%d)\n",
988 cnss_recovery_reason_to_str(recovery_data->reason),
989 recovery_data->reason);
990
991 if (!plat_priv->driver_state) {
992 cnss_pr_err("Improper driver state, ignore recovery\n");
993 ret = -EINVAL;
994 goto out;
995 }
996
997 if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
998 cnss_pr_err("Recovery is already in progress\n");
999 ret = -EINVAL;
1000 goto out;
1001 }
1002
1003 if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
1004 cnss_pr_err("Driver unload is in progress, ignore recovery\n");
1005 ret = -EINVAL;
1006 goto out;
1007 }
1008
1009 switch (plat_priv->device_id) {
1010 case QCA6174_DEVICE_ID:
1011 if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
1012 cnss_pr_err("Driver load is in progress, ignore recovery\n");
1013 ret = -EINVAL;
1014 goto out;
1015 }
1016 break;
1017 default:
1018 if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
1019 set_bit(CNSS_FW_BOOT_RECOVERY,
1020 &plat_priv->driver_state);
Yue Ma0317e4a2018-01-10 11:48:32 -08001021 }
1022 break;
1023 }
1024
1025 set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
1026 ret = cnss_do_recovery(plat_priv, recovery_data->reason);
1027
1028out:
1029 kfree(data);
1030 return ret;
1031}
1032
1033int cnss_self_recovery(struct device *dev,
1034 enum cnss_recovery_reason reason)
1035{
1036 cnss_schedule_recovery(dev, reason);
1037 return 0;
1038}
1039EXPORT_SYMBOL(cnss_self_recovery);
1040
1041void cnss_schedule_recovery(struct device *dev,
1042 enum cnss_recovery_reason reason)
1043{
1044 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1045 struct cnss_recovery_data *data;
1046 int gfp = GFP_KERNEL;
1047
1048 if (in_interrupt() || irqs_disabled())
1049 gfp = GFP_ATOMIC;
1050
1051 data = kzalloc(sizeof(*data), gfp);
1052 if (!data)
1053 return;
1054
1055 data->reason = reason;
1056 cnss_driver_event_post(plat_priv,
1057 CNSS_DRIVER_EVENT_RECOVERY,
1058 0, data);
1059}
1060EXPORT_SYMBOL(cnss_schedule_recovery);
1061
Yue Ma0317e4a2018-01-10 11:48:32 -08001062int cnss_force_fw_assert(struct device *dev)
1063{
1064 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1065
1066 if (!plat_priv) {
1067 cnss_pr_err("plat_priv is NULL\n");
1068 return -ENODEV;
1069 }
1070
1071 if (plat_priv->device_id == QCA6174_DEVICE_ID) {
1072 cnss_pr_info("Forced FW assert is not supported\n");
1073 return -EOPNOTSUPP;
1074 }
1075
1076 if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
1077 cnss_pr_info("Recovery is already in progress, ignore forced FW assert\n");
1078 return 0;
1079 }
1080
1081 cnss_driver_event_post(plat_priv,
1082 CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
1083 0, NULL);
1084
1085 return 0;
1086}
1087EXPORT_SYMBOL(cnss_force_fw_assert);
1088
Yue Ma0317e4a2018-01-10 11:48:32 -08001089static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
1090{
1091 int ret = 0;
1092
1093 set_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
Yue Mae83a0eff2018-05-04 14:15:54 -07001094 ret = cnss_bus_dev_powerup(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001095 if (ret)
1096 clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
1097
1098 return ret;
1099}
1100
1101static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
1102{
Yue Maa3e15032018-02-15 15:56:12 -08001103 plat_priv->cal_done = true;
Yue Ma0317e4a2018-01-10 11:48:32 -08001104 cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
Yue Mae83a0eff2018-05-04 14:15:54 -07001105 cnss_bus_dev_shutdown(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001106 clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
1107
1108 return 0;
1109}
1110
1111static int cnss_power_up_hdlr(struct cnss_plat_data *plat_priv)
1112{
Yue Mae83a0eff2018-05-04 14:15:54 -07001113 return cnss_bus_dev_powerup(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001114}
1115
1116static int cnss_power_down_hdlr(struct cnss_plat_data *plat_priv)
1117{
Yue Mae83a0eff2018-05-04 14:15:54 -07001118 cnss_bus_dev_shutdown(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001119
1120 return 0;
1121}
1122
1123static void cnss_driver_event_work(struct work_struct *work)
1124{
1125 struct cnss_plat_data *plat_priv =
1126 container_of(work, struct cnss_plat_data, event_work);
1127 struct cnss_driver_event *event;
1128 unsigned long flags;
1129 int ret = 0;
1130
1131 if (!plat_priv) {
1132 cnss_pr_err("plat_priv is NULL!\n");
1133 return;
1134 }
1135
1136 cnss_pm_stay_awake(plat_priv);
1137
1138 spin_lock_irqsave(&plat_priv->event_lock, flags);
1139
1140 while (!list_empty(&plat_priv->event_list)) {
1141 event = list_first_entry(&plat_priv->event_list,
1142 struct cnss_driver_event, list);
1143 list_del(&event->list);
1144 spin_unlock_irqrestore(&plat_priv->event_lock, flags);
1145
1146 cnss_pr_dbg("Processing driver event: %s%s(%d), state: 0x%lx\n",
1147 cnss_driver_event_to_str(event->type),
1148 event->sync ? "-sync" : "", event->type,
1149 plat_priv->driver_state);
1150
1151 switch (event->type) {
1152 case CNSS_DRIVER_EVENT_SERVER_ARRIVE:
1153 ret = cnss_wlfw_server_arrive(plat_priv);
1154 break;
1155 case CNSS_DRIVER_EVENT_SERVER_EXIT:
1156 ret = cnss_wlfw_server_exit(plat_priv);
1157 break;
1158 case CNSS_DRIVER_EVENT_REQUEST_MEM:
Yue Mafcf60422018-05-01 16:59:56 -07001159 ret = cnss_bus_alloc_fw_mem(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001160 if (ret)
1161 break;
1162 ret = cnss_wlfw_respond_mem_send_sync(plat_priv);
1163 break;
1164 case CNSS_DRIVER_EVENT_FW_MEM_READY:
1165 ret = cnss_fw_mem_ready_hdlr(plat_priv);
1166 break;
1167 case CNSS_DRIVER_EVENT_FW_READY:
1168 ret = cnss_fw_ready_hdlr(plat_priv);
1169 break;
1170 case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START:
1171 ret = cnss_cold_boot_cal_start_hdlr(plat_priv);
1172 break;
1173 case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE:
1174 ret = cnss_cold_boot_cal_done_hdlr(plat_priv);
1175 break;
1176 case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
Yue Mae83a0eff2018-05-04 14:15:54 -07001177 ret = cnss_bus_register_driver_hdlr(plat_priv,
1178 event->data);
Yue Ma0317e4a2018-01-10 11:48:32 -08001179 break;
1180 case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
Yue Mae83a0eff2018-05-04 14:15:54 -07001181 ret = cnss_bus_unregister_driver_hdlr(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001182 break;
1183 case CNSS_DRIVER_EVENT_RECOVERY:
1184 ret = cnss_driver_recovery_hdlr(plat_priv,
1185 event->data);
1186 break;
1187 case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
Yue Mafcf60422018-05-01 16:59:56 -07001188 ret = cnss_bus_force_fw_assert_hdlr(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001189 break;
1190 case CNSS_DRIVER_EVENT_POWER_UP:
1191 ret = cnss_power_up_hdlr(plat_priv);
1192 break;
1193 case CNSS_DRIVER_EVENT_POWER_DOWN:
1194 ret = cnss_power_down_hdlr(plat_priv);
1195 break;
1196 default:
1197 cnss_pr_err("Invalid driver event type: %d",
1198 event->type);
1199 kfree(event);
1200 spin_lock_irqsave(&plat_priv->event_lock, flags);
1201 continue;
1202 }
1203
1204 spin_lock_irqsave(&plat_priv->event_lock, flags);
1205 if (event->sync) {
1206 event->ret = ret;
1207 complete(&event->complete);
1208 continue;
1209 }
1210 spin_unlock_irqrestore(&plat_priv->event_lock, flags);
1211
1212 kfree(event);
1213
1214 spin_lock_irqsave(&plat_priv->event_lock, flags);
1215 }
1216 spin_unlock_irqrestore(&plat_priv->event_lock, flags);
1217
1218 cnss_pm_relax(plat_priv);
1219}
1220
1221int cnss_register_subsys(struct cnss_plat_data *plat_priv)
1222{
1223 int ret = 0;
1224 struct cnss_subsys_info *subsys_info;
1225
1226 subsys_info = &plat_priv->subsys_info;
1227
Yue Ma922b0352018-04-19 14:03:29 -07001228 subsys_info->subsys_desc.name = "wlan";
Yue Ma0317e4a2018-01-10 11:48:32 -08001229 subsys_info->subsys_desc.owner = THIS_MODULE;
1230 subsys_info->subsys_desc.powerup = cnss_subsys_powerup;
1231 subsys_info->subsys_desc.shutdown = cnss_subsys_shutdown;
1232 subsys_info->subsys_desc.ramdump = cnss_subsys_ramdump;
1233 subsys_info->subsys_desc.crash_shutdown = cnss_subsys_crash_shutdown;
1234 subsys_info->subsys_desc.dev = &plat_priv->plat_dev->dev;
1235
1236 subsys_info->subsys_device = subsys_register(&subsys_info->subsys_desc);
1237 if (IS_ERR(subsys_info->subsys_device)) {
1238 ret = PTR_ERR(subsys_info->subsys_device);
1239 cnss_pr_err("Failed to register subsys, err = %d\n", ret);
1240 goto out;
1241 }
1242
1243 subsys_info->subsys_handle =
1244 subsystem_get(subsys_info->subsys_desc.name);
1245 if (!subsys_info->subsys_handle) {
1246 cnss_pr_err("Failed to get subsys_handle!\n");
1247 ret = -EINVAL;
1248 goto unregister_subsys;
1249 } else if (IS_ERR(subsys_info->subsys_handle)) {
1250 ret = PTR_ERR(subsys_info->subsys_handle);
1251 cnss_pr_err("Failed to do subsystem_get, err = %d\n", ret);
1252 goto unregister_subsys;
1253 }
1254
1255 return 0;
1256
1257unregister_subsys:
1258 subsys_unregister(subsys_info->subsys_device);
1259out:
1260 return ret;
1261}
1262
1263void cnss_unregister_subsys(struct cnss_plat_data *plat_priv)
1264{
1265 struct cnss_subsys_info *subsys_info;
1266
1267 subsys_info = &plat_priv->subsys_info;
1268 subsystem_put(subsys_info->subsys_handle);
1269 subsys_unregister(subsys_info->subsys_device);
1270}
1271
1272static int cnss_init_dump_entry(struct cnss_plat_data *plat_priv)
1273{
1274 struct cnss_ramdump_info *ramdump_info;
1275 struct msm_dump_entry dump_entry;
1276
1277 ramdump_info = &plat_priv->ramdump_info;
1278 ramdump_info->dump_data.addr = ramdump_info->ramdump_pa;
1279 ramdump_info->dump_data.len = ramdump_info->ramdump_size;
1280 ramdump_info->dump_data.version = CNSS_DUMP_FORMAT_VER;
1281 ramdump_info->dump_data.magic = CNSS_DUMP_MAGIC_VER_V2;
1282 strlcpy(ramdump_info->dump_data.name, CNSS_DUMP_NAME,
1283 sizeof(ramdump_info->dump_data.name));
1284 dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
1285 dump_entry.addr = virt_to_phys(&ramdump_info->dump_data);
1286
1287 return msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
1288}
1289
1290static int cnss_qca6174_register_ramdump(struct cnss_plat_data *plat_priv)
1291{
1292 int ret = 0;
1293 struct device *dev;
1294 struct cnss_subsys_info *subsys_info;
1295 struct cnss_ramdump_info *ramdump_info;
1296 u32 ramdump_size = 0;
1297
1298 dev = &plat_priv->plat_dev->dev;
1299 subsys_info = &plat_priv->subsys_info;
1300 ramdump_info = &plat_priv->ramdump_info;
1301
1302 if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
1303 &ramdump_size) == 0) {
1304 ramdump_info->ramdump_va = dma_alloc_coherent(dev, ramdump_size,
1305 &ramdump_info->ramdump_pa, GFP_KERNEL);
1306
1307 if (ramdump_info->ramdump_va)
1308 ramdump_info->ramdump_size = ramdump_size;
1309 }
1310
1311 cnss_pr_dbg("ramdump va: %pK, pa: %pa\n",
1312 ramdump_info->ramdump_va, &ramdump_info->ramdump_pa);
1313
1314 if (ramdump_info->ramdump_size == 0) {
1315 cnss_pr_info("Ramdump will not be collected");
1316 goto out;
1317 }
1318
1319 ret = cnss_init_dump_entry(plat_priv);
1320 if (ret) {
1321 cnss_pr_err("Failed to setup dump table, err = %d\n", ret);
1322 goto free_ramdump;
1323 }
1324
1325 ramdump_info->ramdump_dev = create_ramdump_device(
1326 subsys_info->subsys_desc.name, subsys_info->subsys_desc.dev);
1327 if (!ramdump_info->ramdump_dev) {
1328 cnss_pr_err("Failed to create ramdump device!");
1329 ret = -ENOMEM;
1330 goto free_ramdump;
1331 }
1332
1333 return 0;
1334free_ramdump:
1335 dma_free_coherent(dev, ramdump_info->ramdump_size,
1336 ramdump_info->ramdump_va, ramdump_info->ramdump_pa);
1337out:
1338 return ret;
1339}
1340
1341static void cnss_qca6174_unregister_ramdump(struct cnss_plat_data *plat_priv)
1342{
1343 struct device *dev;
1344 struct cnss_ramdump_info *ramdump_info;
1345
1346 dev = &plat_priv->plat_dev->dev;
1347 ramdump_info = &plat_priv->ramdump_info;
1348
1349 if (ramdump_info->ramdump_dev)
1350 destroy_ramdump_device(ramdump_info->ramdump_dev);
1351
1352 if (ramdump_info->ramdump_va)
1353 dma_free_coherent(dev, ramdump_info->ramdump_size,
1354 ramdump_info->ramdump_va,
1355 ramdump_info->ramdump_pa);
1356}
1357
1358static int cnss_qca6290_register_ramdump(struct cnss_plat_data *plat_priv)
1359{
1360 int ret = 0;
1361 struct cnss_subsys_info *subsys_info;
1362 struct cnss_ramdump_info_v2 *info_v2;
1363 struct cnss_dump_data *dump_data;
1364 struct msm_dump_entry dump_entry;
1365 struct device *dev = &plat_priv->plat_dev->dev;
1366 u32 ramdump_size = 0;
1367
1368 subsys_info = &plat_priv->subsys_info;
1369 info_v2 = &plat_priv->ramdump_info_v2;
1370 dump_data = &info_v2->dump_data;
1371
1372 if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
1373 &ramdump_size) == 0)
1374 info_v2->ramdump_size = ramdump_size;
1375
1376 cnss_pr_dbg("Ramdump size 0x%lx\n", info_v2->ramdump_size);
1377
1378 info_v2->dump_data_vaddr = kzalloc(CNSS_DUMP_DESC_SIZE, GFP_KERNEL);
1379 if (!info_v2->dump_data_vaddr)
1380 return -ENOMEM;
1381
1382 dump_data->paddr = virt_to_phys(info_v2->dump_data_vaddr);
1383 dump_data->version = CNSS_DUMP_FORMAT_VER_V2;
1384 dump_data->magic = CNSS_DUMP_MAGIC_VER_V2;
1385 dump_data->seg_version = CNSS_DUMP_SEG_VER;
1386 strlcpy(dump_data->name, CNSS_DUMP_NAME,
1387 sizeof(dump_data->name));
1388 dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
1389 dump_entry.addr = virt_to_phys(dump_data);
1390
1391 ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
1392 if (ret) {
1393 cnss_pr_err("Failed to setup dump table, err = %d\n", ret);
1394 goto free_ramdump;
1395 }
1396
1397 info_v2->ramdump_dev =
1398 create_ramdump_device(subsys_info->subsys_desc.name,
1399 subsys_info->subsys_desc.dev);
1400 if (!info_v2->ramdump_dev) {
1401 cnss_pr_err("Failed to create ramdump device!\n");
1402 ret = -ENOMEM;
1403 goto free_ramdump;
1404 }
1405
1406 return 0;
1407
1408free_ramdump:
1409 kfree(info_v2->dump_data_vaddr);
1410 info_v2->dump_data_vaddr = NULL;
1411 return ret;
1412}
1413
1414static void cnss_qca6290_unregister_ramdump(struct cnss_plat_data *plat_priv)
1415{
1416 struct cnss_ramdump_info_v2 *info_v2;
1417
1418 info_v2 = &plat_priv->ramdump_info_v2;
1419
1420 if (info_v2->ramdump_dev)
1421 destroy_ramdump_device(info_v2->ramdump_dev);
1422
1423 kfree(info_v2->dump_data_vaddr);
1424 info_v2->dump_data_vaddr = NULL;
1425 info_v2->dump_data_valid = false;
1426}
1427
1428int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
1429{
1430 int ret = 0;
1431
1432 switch (plat_priv->device_id) {
1433 case QCA6174_DEVICE_ID:
1434 ret = cnss_qca6174_register_ramdump(plat_priv);
1435 break;
1436 case QCA6290_EMULATION_DEVICE_ID:
1437 case QCA6290_DEVICE_ID:
1438 ret = cnss_qca6290_register_ramdump(plat_priv);
1439 break;
1440 default:
1441 cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
1442 ret = -ENODEV;
1443 break;
1444 }
1445 return ret;
1446}
1447
1448void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
1449{
1450 switch (plat_priv->device_id) {
1451 case QCA6174_DEVICE_ID:
1452 cnss_qca6174_unregister_ramdump(plat_priv);
1453 break;
1454 case QCA6290_EMULATION_DEVICE_ID:
1455 case QCA6290_DEVICE_ID:
1456 cnss_qca6290_unregister_ramdump(plat_priv);
1457 break;
1458 default:
1459 cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
1460 break;
1461 }
1462}
1463
1464static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv)
1465{
1466 int ret = 0;
1467 struct cnss_bus_bw_info *bus_bw_info;
1468
1469 bus_bw_info = &plat_priv->bus_bw_info;
1470
1471 bus_bw_info->bus_scale_table =
1472 msm_bus_cl_get_pdata(plat_priv->plat_dev);
1473 if (bus_bw_info->bus_scale_table) {
1474 bus_bw_info->bus_client =
1475 msm_bus_scale_register_client(
1476 bus_bw_info->bus_scale_table);
1477 if (!bus_bw_info->bus_client) {
1478 cnss_pr_err("Failed to register bus scale client!\n");
1479 ret = -EINVAL;
1480 goto out;
1481 }
1482 }
1483
1484 return 0;
1485out:
1486 return ret;
1487}
1488
1489static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv)
1490{
1491 struct cnss_bus_bw_info *bus_bw_info;
1492
1493 bus_bw_info = &plat_priv->bus_bw_info;
1494
1495 if (bus_bw_info->bus_client)
1496 msm_bus_scale_unregister_client(bus_bw_info->bus_client);
1497}
1498
1499static ssize_t cnss_fs_ready_store(struct device *dev,
1500 struct device_attribute *attr,
1501 const char *buf,
1502 size_t count)
1503{
1504 int fs_ready = 0;
1505 struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
1506
1507 if (sscanf(buf, "%du", &fs_ready) != 1)
1508 return -EINVAL;
1509
1510 cnss_pr_dbg("File system is ready, fs_ready is %d, count is %zu\n",
1511 fs_ready, count);
1512
1513 if (qmi_bypass) {
1514 cnss_pr_dbg("QMI is bypassed.\n");
1515 return count;
1516 }
1517
1518 if (!plat_priv) {
1519 cnss_pr_err("plat_priv is NULL!\n");
1520 return count;
1521 }
1522
1523 switch (plat_priv->device_id) {
1524 case QCA6290_EMULATION_DEVICE_ID:
1525 case QCA6290_DEVICE_ID:
1526 break;
1527 default:
1528 cnss_pr_err("Not supported for device ID 0x%lx\n",
1529 plat_priv->device_id);
1530 return count;
1531 }
1532
1533 if (fs_ready == FILE_SYSTEM_READY) {
1534 cnss_driver_event_post(plat_priv,
1535 CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
1536 CNSS_EVENT_SYNC, NULL);
1537 }
1538
1539 return count;
1540}
1541
1542static DEVICE_ATTR(fs_ready, 0220, NULL, cnss_fs_ready_store);
1543
1544static int cnss_create_sysfs(struct cnss_plat_data *plat_priv)
1545{
1546 int ret = 0;
1547
1548 ret = device_create_file(&plat_priv->plat_dev->dev, &dev_attr_fs_ready);
1549 if (ret) {
1550 cnss_pr_err("Failed to create device file, err = %d\n", ret);
1551 goto out;
1552 }
1553
1554 return 0;
1555out:
1556 return ret;
1557}
1558
1559static void cnss_remove_sysfs(struct cnss_plat_data *plat_priv)
1560{
1561 device_remove_file(&plat_priv->plat_dev->dev, &dev_attr_fs_ready);
1562}
1563
1564static int cnss_event_work_init(struct cnss_plat_data *plat_priv)
1565{
1566 spin_lock_init(&plat_priv->event_lock);
1567 plat_priv->event_wq = alloc_workqueue("cnss_driver_event",
1568 WQ_UNBOUND, 1);
1569 if (!plat_priv->event_wq) {
1570 cnss_pr_err("Failed to create event workqueue!\n");
1571 return -EFAULT;
1572 }
1573
1574 INIT_WORK(&plat_priv->event_work, cnss_driver_event_work);
1575 INIT_LIST_HEAD(&plat_priv->event_list);
1576
1577 return 0;
1578}
1579
1580static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv)
1581{
1582 destroy_workqueue(plat_priv->event_wq);
1583}
1584
1585static const struct platform_device_id cnss_platform_id_table[] = {
1586 { .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
1587 { .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
1588};
1589
1590static const struct of_device_id cnss_of_match_table[] = {
1591 {
1592 .compatible = "qcom,cnss",
1593 .data = (void *)&cnss_platform_id_table[0]},
1594 {
1595 .compatible = "qcom,cnss-qca6290",
1596 .data = (void *)&cnss_platform_id_table[1]},
1597 { },
1598};
1599MODULE_DEVICE_TABLE(of, cnss_of_match_table);
1600
1601static int cnss_probe(struct platform_device *plat_dev)
1602{
1603 int ret = 0;
1604 struct cnss_plat_data *plat_priv;
1605 const struct of_device_id *of_id;
1606 const struct platform_device_id *device_id;
1607
1608 if (cnss_get_plat_priv(plat_dev)) {
1609 cnss_pr_err("Driver is already initialized!\n");
1610 ret = -EEXIST;
1611 goto out;
1612 }
1613
1614 of_id = of_match_device(cnss_of_match_table, &plat_dev->dev);
1615 if (!of_id || !of_id->data) {
1616 cnss_pr_err("Failed to find of match device!\n");
1617 ret = -ENODEV;
1618 goto out;
1619 }
1620
1621 device_id = of_id->data;
1622
1623 plat_priv = devm_kzalloc(&plat_dev->dev, sizeof(*plat_priv),
1624 GFP_KERNEL);
1625 if (!plat_priv) {
1626 ret = -ENOMEM;
1627 goto out;
1628 }
1629
1630 plat_priv->plat_dev = plat_dev;
1631 plat_priv->device_id = device_id->driver_data;
Yue Mafcf60422018-05-01 16:59:56 -07001632 plat_priv->bus_type = cnss_get_bus_type(plat_priv->device_id);
Yue Ma0317e4a2018-01-10 11:48:32 -08001633 cnss_set_plat_priv(plat_dev, plat_priv);
1634 platform_set_drvdata(plat_dev, plat_priv);
1635
1636 ret = cnss_get_resources(plat_priv);
1637 if (ret)
1638 goto reset_ctx;
1639
1640 if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) {
1641 ret = cnss_power_on_device(plat_priv);
1642 if (ret)
1643 goto free_res;
1644
Yue Mafcf60422018-05-01 16:59:56 -07001645 ret = cnss_bus_init(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001646 if (ret)
1647 goto power_off;
1648 }
1649
1650 ret = cnss_register_esoc(plat_priv);
1651 if (ret)
Yue Mafcf60422018-05-01 16:59:56 -07001652 goto deinit_bus;
Yue Ma0317e4a2018-01-10 11:48:32 -08001653
1654 ret = cnss_register_bus_scale(plat_priv);
1655 if (ret)
1656 goto unreg_esoc;
1657
1658 ret = cnss_create_sysfs(plat_priv);
1659 if (ret)
1660 goto unreg_bus_scale;
1661
1662 ret = cnss_event_work_init(plat_priv);
1663 if (ret)
1664 goto remove_sysfs;
1665
1666 ret = cnss_qmi_init(plat_priv);
1667 if (ret)
1668 goto deinit_event_work;
1669
1670 ret = cnss_debugfs_create(plat_priv);
1671 if (ret)
1672 goto deinit_qmi;
1673
Yue Mafcf60422018-05-01 16:59:56 -07001674 setup_timer(&plat_priv->fw_boot_timer, cnss_bus_fw_boot_timeout_hdlr,
1675 (unsigned long)plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001676
1677 register_pm_notifier(&cnss_pm_notifier);
1678
1679 ret = device_init_wakeup(&plat_dev->dev, true);
1680 if (ret)
1681 cnss_pr_err("Failed to init platform device wakeup source, err = %d\n",
1682 ret);
1683
1684 init_completion(&plat_priv->power_up_complete);
1685 mutex_init(&plat_priv->dev_lock);
1686
1687 cnss_pr_info("Platform driver probed successfully.\n");
1688
1689 return 0;
1690
1691deinit_qmi:
1692 cnss_qmi_deinit(plat_priv);
1693deinit_event_work:
1694 cnss_event_work_deinit(plat_priv);
1695remove_sysfs:
1696 cnss_remove_sysfs(plat_priv);
1697unreg_bus_scale:
1698 cnss_unregister_bus_scale(plat_priv);
1699unreg_esoc:
1700 cnss_unregister_esoc(plat_priv);
Yue Mafcf60422018-05-01 16:59:56 -07001701deinit_bus:
Yue Ma0317e4a2018-01-10 11:48:32 -08001702 if (!test_bit(SKIP_DEVICE_BOOT, &quirks))
Yue Mafcf60422018-05-01 16:59:56 -07001703 cnss_bus_deinit(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001704power_off:
1705 if (!test_bit(SKIP_DEVICE_BOOT, &quirks))
1706 cnss_power_off_device(plat_priv);
1707free_res:
1708 cnss_put_resources(plat_priv);
1709reset_ctx:
1710 platform_set_drvdata(plat_dev, NULL);
1711 cnss_set_plat_priv(plat_dev, NULL);
1712out:
1713 return ret;
1714}
1715
1716static int cnss_remove(struct platform_device *plat_dev)
1717{
1718 struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev);
1719
1720 complete_all(&plat_priv->power_up_complete);
1721 device_init_wakeup(&plat_dev->dev, false);
1722 unregister_pm_notifier(&cnss_pm_notifier);
1723 del_timer(&plat_priv->fw_boot_timer);
1724 cnss_debugfs_destroy(plat_priv);
1725 cnss_qmi_deinit(plat_priv);
1726 cnss_event_work_deinit(plat_priv);
1727 cnss_remove_sysfs(plat_priv);
1728 cnss_unregister_bus_scale(plat_priv);
1729 cnss_unregister_esoc(plat_priv);
Yue Mafcf60422018-05-01 16:59:56 -07001730 cnss_bus_deinit(plat_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001731 cnss_put_resources(plat_priv);
1732 platform_set_drvdata(plat_dev, NULL);
1733 plat_env = NULL;
1734
1735 return 0;
1736}
1737
1738static struct platform_driver cnss_platform_driver = {
1739 .probe = cnss_probe,
1740 .remove = cnss_remove,
1741 .driver = {
1742 .name = "cnss2",
1743 .owner = THIS_MODULE,
1744 .of_match_table = cnss_of_match_table,
1745#ifdef CONFIG_CNSS_ASYNC
1746 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
1747#endif
1748 },
1749};
1750
1751static int __init cnss_initialize(void)
1752{
1753 int ret = 0;
1754
1755 cnss_debug_init();
1756 ret = platform_driver_register(&cnss_platform_driver);
1757 if (ret)
1758 cnss_debug_deinit();
1759
1760 return ret;
1761}
1762
1763static void __exit cnss_exit(void)
1764{
1765 platform_driver_unregister(&cnss_platform_driver);
1766 cnss_debug_deinit();
1767}
1768
1769module_init(cnss_initialize);
1770module_exit(cnss_exit);
1771
1772MODULE_LICENSE("GPL v2");
1773MODULE_DESCRIPTION("CNSS2 Platform Driver");