blob: d3819b631a52fe432d3d159d40d9e7a951ce5844 [file] [log] [blame]
Kyle Yan3d6600c2017-01-06 14:04:26 -08001/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Kyle Yane45fa022016-08-29 11:40:26 -07002 *
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/kernel.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/of.h>
19#include <linux/clk.h>
20#include <linux/regulator/consumer.h>
21#include <linux/interrupt.h>
22#include <linux/of_gpio.h>
23#include <linux/delay.h>
24
25#include <linux/msm-bus-board.h>
26#include <linux/msm-bus.h>
27#include <linux/dma-mapping.h>
28
29#include <soc/qcom/subsystem_restart.h>
30#include <soc/qcom/ramdump.h>
31#include <soc/qcom/scm.h>
32
33#include <soc/qcom/smem.h>
34
35#include "peripheral-loader.h"
36
37#define XO_FREQ 19200000
38#define PROXY_TIMEOUT_MS 10000
Kyle Yanfe3813e2017-06-06 17:03:58 -070039#define MAX_SSR_REASON_LEN 256U
Kyle Yane45fa022016-08-29 11:40:26 -070040#define STOP_ACK_TIMEOUT_MS 1000
41#define CRASH_STOP_ACK_TO_MS 200
42
43#define ERR_READY 0
44#define PBL_DONE 1
Avaneesh Kumar Dwivedi94619d92017-10-05 17:58:38 +053045#define QDSP6SS_NMI_STATUS 0x44
Kyle Yane45fa022016-08-29 11:40:26 -070046
47#define desc_to_data(d) container_of(d, struct pil_tz_data, desc)
48#define subsys_to_data(d) container_of(d, struct pil_tz_data, subsys_desc)
49
Kyle Yan95180af2017-12-01 17:05:59 -080050struct pil_map_fw_info {
51 void *region;
52 unsigned long attrs;
53 phys_addr_t base_addr;
54 struct device *dev;
55};
56
Kyle Yane45fa022016-08-29 11:40:26 -070057/**
58 * struct reg_info - regulator info
59 * @reg: regulator handle
60 * @uV: voltage in uV
61 * @uA: current in uA
62 */
63struct reg_info {
64 struct regulator *reg;
65 int uV;
66 int uA;
67};
68
69/**
70 * struct pil_tz_data
71 * @regs: regulators that should be always on when the subsystem is
72 * brought out of reset
73 * @proxy_regs: regulators that should be on during pil proxy voting
74 * @clks: clocks that should be always on when the subsystem is
75 * brought out of reset
76 * @proxy_clks: clocks that should be on during pil proxy voting
77 * @reg_count: the number of always on regulators
78 * @proxy_reg_count: the number of proxy voting regulators
79 * @clk_count: the number of always on clocks
80 * @proxy_clk_count: the number of proxy voting clocks
81 * @smem_id: the smem id used for read the subsystem crash reason
82 * @ramdump_dev: ramdump device pointer
83 * @pas_id: the PAS id for tz
84 * @bus_client: bus client id
85 * @enable_bus_scaling: set to true if PIL needs to vote for
86 * bus bandwidth
87 * @keep_proxy_regs_on: If set, during proxy unvoting, PIL removes the
88 * voltage/current vote for proxy regulators but leaves
89 * them enabled.
90 * @stop_ack: state of completion of stop ack
91 * @desc: PIL descriptor
92 * @subsys: subsystem device pointer
93 * @subsys_desc: subsystem descriptor
94 * @u32 bits_arr[2]: array of bit positions in SCSR registers
95 */
96struct pil_tz_data {
97 struct reg_info *regs;
98 struct reg_info *proxy_regs;
99 struct clk **clks;
100 struct clk **proxy_clks;
101 int reg_count;
102 int proxy_reg_count;
103 int clk_count;
104 int proxy_clk_count;
105 int smem_id;
106 void *ramdump_dev;
107 u32 pas_id;
108 u32 bus_client;
109 bool enable_bus_scaling;
110 bool keep_proxy_regs_on;
111 struct completion stop_ack;
112 struct pil_desc desc;
113 struct subsys_device *subsys;
114 struct subsys_desc subsys_desc;
115 void __iomem *irq_status;
116 void __iomem *irq_clear;
117 void __iomem *irq_mask;
118 void __iomem *err_status;
119 void __iomem *err_status_spare;
Avaneesh Kumar Dwivedi94619d92017-10-05 17:58:38 +0530120 void __iomem *reg_base;
Kyle Yane45fa022016-08-29 11:40:26 -0700121 u32 bits_arr[2];
122};
123
124enum scm_cmd {
125 PAS_INIT_IMAGE_CMD = 1,
126 PAS_MEM_SETUP_CMD,
127 PAS_AUTH_AND_RESET_CMD = 5,
128 PAS_SHUTDOWN_CMD,
129};
130
131enum pas_id {
132 PAS_MODEM,
133 PAS_Q6,
134 PAS_DSPS,
135 PAS_TZAPPS,
136 PAS_MODEM_SW,
137 PAS_MODEM_FW,
138 PAS_WCNSS,
139 PAS_SECAPP,
140 PAS_GSS,
141 PAS_VIDC,
142 PAS_VPU,
143 PAS_BCSS,
144};
145
146static struct msm_bus_paths scm_pas_bw_tbl[] = {
147 {
148 .vectors = (struct msm_bus_vectors[]){
149 {
150 .src = MSM_BUS_MASTER_SPS,
151 .dst = MSM_BUS_SLAVE_EBI_CH0,
152 },
153 },
154 .num_paths = 1,
155 },
156 {
157 .vectors = (struct msm_bus_vectors[]){
158 {
159 .src = MSM_BUS_MASTER_SPS,
160 .dst = MSM_BUS_SLAVE_EBI_CH0,
161 .ib = 492 * 8 * 1000000UL,
162 .ab = 492 * 8 * 100000UL,
163 },
164 },
165 .num_paths = 1,
166 },
167};
168
169static struct msm_bus_scale_pdata scm_pas_bus_pdata = {
170 .usecase = scm_pas_bw_tbl,
171 .num_usecases = ARRAY_SIZE(scm_pas_bw_tbl),
172 .name = "scm_pas",
173};
174
175static uint32_t scm_perf_client;
176static int scm_pas_bw_count;
177static DEFINE_MUTEX(scm_pas_bw_mutex);
178
179static int scm_pas_enable_bw(void)
180{
181 int ret = 0;
182
183 if (!scm_perf_client)
184 return -EINVAL;
185
186 mutex_lock(&scm_pas_bw_mutex);
187 if (!scm_pas_bw_count) {
188 ret = msm_bus_scale_client_update_request(scm_perf_client, 1);
189 if (ret)
190 goto err_bus;
191 scm_pas_bw_count++;
192 }
193
194 mutex_unlock(&scm_pas_bw_mutex);
195 return ret;
196
197err_bus:
198 pr_err("scm-pas; Bandwidth request failed (%d)\n", ret);
199 msm_bus_scale_client_update_request(scm_perf_client, 0);
200
201 mutex_unlock(&scm_pas_bw_mutex);
202 return ret;
203}
204
205static void scm_pas_disable_bw(void)
206{
207 mutex_lock(&scm_pas_bw_mutex);
208 if (scm_pas_bw_count-- == 1)
209 msm_bus_scale_client_update_request(scm_perf_client, 0);
210 mutex_unlock(&scm_pas_bw_mutex);
211}
212
213static void scm_pas_init(int id)
214{
215 static int is_inited;
216
217 if (is_inited)
218 return;
219
220 scm_pas_bw_tbl[0].vectors[0].src = id;
221 scm_pas_bw_tbl[1].vectors[0].src = id;
222
223 scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
224 if (!scm_perf_client)
225 pr_warn("scm-pas: Unable to register bus client\n");
226
227 is_inited = 1;
228}
229
230static int of_read_clocks(struct device *dev, struct clk ***clks_ref,
231 const char *propname)
232{
233 long clk_count;
234 int i, len;
235 struct clk **clks;
236
237 if (!of_find_property(dev->of_node, propname, &len))
238 return 0;
239
240 clk_count = of_property_count_strings(dev->of_node, propname);
241 if (IS_ERR_VALUE(clk_count)) {
242 dev_err(dev, "Failed to get clock names\n");
243 return -EINVAL;
244 }
245
246 clks = devm_kzalloc(dev, sizeof(struct clk *) * clk_count,
247 GFP_KERNEL);
248 if (!clks)
249 return -ENOMEM;
250
251 for (i = 0; i < clk_count; i++) {
252 const char *clock_name;
253 char clock_freq_name[50];
254 u32 clock_rate = XO_FREQ;
255
256 of_property_read_string_index(dev->of_node,
257 propname, i,
258 &clock_name);
259 snprintf(clock_freq_name, ARRAY_SIZE(clock_freq_name),
260 "qcom,%s-freq", clock_name);
261 if (of_find_property(dev->of_node, clock_freq_name, &len))
262 if (of_property_read_u32(dev->of_node, clock_freq_name,
263 &clock_rate)) {
264 dev_err(dev, "Failed to read %s clock's freq\n",
265 clock_freq_name);
266 return -EINVAL;
267 }
268
269 clks[i] = devm_clk_get(dev, clock_name);
270 if (IS_ERR(clks[i])) {
271 int rc = PTR_ERR(clks[i]);
272
273 if (rc != -EPROBE_DEFER)
274 dev_err(dev, "Failed to get %s clock\n",
275 clock_name);
276 return rc;
277 }
278
279 /* Make sure rate-settable clocks' rates are set */
280 if (clk_get_rate(clks[i]) == 0)
281 clk_set_rate(clks[i], clk_round_rate(clks[i],
282 clock_rate));
283 }
284
285 *clks_ref = clks;
286 return clk_count;
287}
288
289static int of_read_regs(struct device *dev, struct reg_info **regs_ref,
290 const char *propname)
291{
292 long reg_count;
293 int i, len, rc;
294 struct reg_info *regs;
295
296 if (!of_find_property(dev->of_node, propname, &len))
297 return 0;
298
299 reg_count = of_property_count_strings(dev->of_node, propname);
300 if (IS_ERR_VALUE(reg_count)) {
301 dev_err(dev, "Failed to get regulator names\n");
302 return -EINVAL;
303 }
304
305 regs = devm_kzalloc(dev, sizeof(struct reg_info) * reg_count,
306 GFP_KERNEL);
307 if (!regs)
308 return -ENOMEM;
309
310 for (i = 0; i < reg_count; i++) {
311 const char *reg_name;
312 char reg_uV_uA_name[50];
313 u32 vdd_uV_uA[2];
314
315 of_property_read_string_index(dev->of_node,
316 propname, i,
317 &reg_name);
318
319 regs[i].reg = devm_regulator_get(dev, reg_name);
320 if (IS_ERR(regs[i].reg)) {
321 int rc = PTR_ERR(regs[i].reg);
322
323 if (rc != -EPROBE_DEFER)
324 dev_err(dev, "Failed to get %s\n regulator",
325 reg_name);
326 return rc;
327 }
328
329 /*
330 * Read the voltage and current values for the corresponding
331 * regulator. The device tree property name is "qcom," +
332 * "regulator_name" + "-uV-uA".
333 */
334 rc = snprintf(reg_uV_uA_name, ARRAY_SIZE(reg_uV_uA_name),
335 "qcom,%s-uV-uA", reg_name);
336 if (rc < strlen(reg_name) + 6) {
337 dev_err(dev, "Failed to hold reg_uV_uA_name\n");
338 return -EINVAL;
339 }
340
341 if (!of_find_property(dev->of_node, reg_uV_uA_name, &len))
342 continue;
343
344 len /= sizeof(vdd_uV_uA[0]);
345
346 /* There should be two entries: one for uV and one for uA */
347 if (len != 2) {
348 dev_err(dev, "Missing uV/uA value\n");
349 return -EINVAL;
350 }
351
352 rc = of_property_read_u32_array(dev->of_node, reg_uV_uA_name,
353 vdd_uV_uA, len);
354 if (rc) {
355 dev_err(dev, "Failed to read uV/uA values(rc:%d)\n",
356 rc);
357 return rc;
358 }
359
360 regs[i].uV = vdd_uV_uA[0];
361 regs[i].uA = vdd_uV_uA[1];
362 }
363
364 *regs_ref = regs;
365 return reg_count;
366}
367
368static int of_read_bus_pdata(struct platform_device *pdev,
369 struct pil_tz_data *d)
370{
371 struct msm_bus_scale_pdata *pdata;
372
373 pdata = msm_bus_cl_get_pdata(pdev);
374
375 if (!pdata)
376 return -EINVAL;
377
378 d->bus_client = msm_bus_scale_register_client(pdata);
379 if (!d->bus_client)
380 pr_warn("%s: Unable to register bus client\n", __func__);
381
382 return 0;
383}
384
385static int piltz_resc_init(struct platform_device *pdev, struct pil_tz_data *d)
386{
387 int len, count, rc;
388 struct device *dev = &pdev->dev;
389
390 count = of_read_clocks(dev, &d->clks, "qcom,active-clock-names");
391 if (count < 0) {
392 dev_err(dev, "Failed to setup clocks.\n");
393 return count;
394 }
395 d->clk_count = count;
396
397 count = of_read_clocks(dev, &d->proxy_clks, "qcom,proxy-clock-names");
398 if (count < 0) {
399 dev_err(dev, "Failed to setup proxy clocks.\n");
400 return count;
401 }
402 d->proxy_clk_count = count;
403
404 count = of_read_regs(dev, &d->regs, "qcom,active-reg-names");
405 if (count < 0) {
406 dev_err(dev, "Failed to setup regulators.\n");
407 return count;
408 }
409 d->reg_count = count;
410
411 count = of_read_regs(dev, &d->proxy_regs, "qcom,proxy-reg-names");
412 if (count < 0) {
413 dev_err(dev, "Failed to setup proxy regulators.\n");
414 return count;
415 }
416 d->proxy_reg_count = count;
417
418 if (of_find_property(dev->of_node, "qcom,msm-bus,name", &len)) {
419 d->enable_bus_scaling = true;
420 rc = of_read_bus_pdata(pdev, d);
421 if (rc) {
422 dev_err(dev, "Failed to setup bus scaling client.\n");
423 return rc;
424 }
425 }
426
427 return 0;
428}
429
430static int enable_regulators(struct pil_tz_data *d, struct device *dev,
431 struct reg_info *regs, int reg_count,
432 bool reg_no_enable)
433{
434 int i, rc = 0;
435
436 for (i = 0; i < reg_count; i++) {
437 if (regs[i].uV > 0) {
438 rc = regulator_set_voltage(regs[i].reg,
439 regs[i].uV, INT_MAX);
440 if (rc) {
441 dev_err(dev, "Failed to request voltage(rc:%d)\n",
442 rc);
443 goto err_voltage;
444 }
445 }
446
447 if (regs[i].uA > 0) {
448 rc = regulator_set_load(regs[i].reg,
449 regs[i].uA);
450 if (rc < 0) {
451 dev_err(dev, "Failed to set regulator mode(rc:%d)\n",
452 rc);
453 goto err_mode;
454 }
455 }
456
457 if (d->keep_proxy_regs_on && reg_no_enable)
458 continue;
459
460 rc = regulator_enable(regs[i].reg);
461 if (rc) {
462 dev_err(dev, "Regulator enable failed(rc:%d)\n", rc);
463 goto err_enable;
464 }
465 }
466
467 return 0;
468err_enable:
469 if (regs[i].uA > 0) {
470 regulator_set_voltage(regs[i].reg, 0, INT_MAX);
471 regulator_set_load(regs[i].reg, 0);
472 }
473err_mode:
474 if (regs[i].uV > 0)
475 regulator_set_voltage(regs[i].reg, 0, INT_MAX);
476err_voltage:
477 for (i--; i >= 0; i--) {
478 if (regs[i].uV > 0)
479 regulator_set_voltage(regs[i].reg, 0, INT_MAX);
480
481 if (regs[i].uA > 0)
482 regulator_set_load(regs[i].reg, 0);
483
484 if (d->keep_proxy_regs_on && reg_no_enable)
485 continue;
486 regulator_disable(regs[i].reg);
487 }
488
489 return rc;
490}
491
492static void disable_regulators(struct pil_tz_data *d, struct reg_info *regs,
493 int reg_count, bool reg_no_disable)
494{
495 int i;
496
497 for (i = 0; i < reg_count; i++) {
498 if (regs[i].uV > 0)
499 regulator_set_voltage(regs[i].reg, 0, INT_MAX);
500
501 if (regs[i].uA > 0)
502 regulator_set_load(regs[i].reg, 0);
503
504 if (d->keep_proxy_regs_on && reg_no_disable)
505 continue;
506 regulator_disable(regs[i].reg);
507 }
508}
509
510static int prepare_enable_clocks(struct device *dev, struct clk **clks,
511 int clk_count)
512{
513 int rc = 0;
514 int i;
515
516 for (i = 0; i < clk_count; i++) {
517 rc = clk_prepare_enable(clks[i]);
518 if (rc) {
519 dev_err(dev, "Clock enable failed(rc:%d)\n", rc);
520 goto err;
521 }
522 }
523
524 return 0;
525err:
526 for (i--; i >= 0; i--)
527 clk_disable_unprepare(clks[i]);
528
529 return rc;
530}
531
532static void disable_unprepare_clocks(struct clk **clks, int clk_count)
533{
534 int i;
535
536 for (i = --clk_count; i >= 0; i--)
537 clk_disable_unprepare(clks[i]);
538}
539
540static int pil_make_proxy_vote(struct pil_desc *pil)
541{
542 struct pil_tz_data *d = desc_to_data(pil);
543 int rc;
544
545 if (d->subsys_desc.no_auth)
546 return 0;
547
Kyle Yanf995ef62017-04-13 19:13:39 -0700548 if (d->bus_client) {
549 rc = msm_bus_scale_client_update_request(d->bus_client, 1);
550 if (rc) {
551 dev_err(pil->dev, "bandwidth request failed(rc:%d)\n",
552 rc);
553 return rc;
554 }
555 } else
556 WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
557 d->subsys_desc.name);
558
Kyle Yane45fa022016-08-29 11:40:26 -0700559 rc = enable_regulators(d, pil->dev, d->proxy_regs,
560 d->proxy_reg_count, false);
561 if (rc)
562 return rc;
563
564 rc = prepare_enable_clocks(pil->dev, d->proxy_clks,
565 d->proxy_clk_count);
566 if (rc)
567 goto err_clks;
568
Kyle Yane45fa022016-08-29 11:40:26 -0700569 return 0;
Kyle Yanf995ef62017-04-13 19:13:39 -0700570
Kyle Yane45fa022016-08-29 11:40:26 -0700571err_clks:
572 disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false);
573
574 return rc;
575}
576
577static void pil_remove_proxy_vote(struct pil_desc *pil)
578{
579 struct pil_tz_data *d = desc_to_data(pil);
580
581 if (d->subsys_desc.no_auth)
582 return;
583
Kyle Yanf995ef62017-04-13 19:13:39 -0700584 disable_unprepare_clocks(d->proxy_clks, d->proxy_clk_count);
585
586 disable_regulators(d, d->proxy_regs, d->proxy_reg_count, true);
587
Kyle Yane45fa022016-08-29 11:40:26 -0700588 if (d->bus_client)
589 msm_bus_scale_client_update_request(d->bus_client, 0);
590 else
591 WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
592 d->subsys_desc.name);
Kyle Yane45fa022016-08-29 11:40:26 -0700593}
594
595static int pil_init_image_trusted(struct pil_desc *pil,
Kyle Yan95180af2017-12-01 17:05:59 -0800596 const u8 *metadata, size_t size, phys_addr_t mdata_phys,
597 void *region)
Kyle Yane45fa022016-08-29 11:40:26 -0700598{
599 struct pil_tz_data *d = desc_to_data(pil);
600 struct pas_init_image_req {
601 u32 proc;
602 u32 image_addr;
603 } request;
604 u32 scm_ret = 0;
605 void *mdata_buf;
Kyle Yane45fa022016-08-29 11:40:26 -0700606 int ret;
Kyle Yane45fa022016-08-29 11:40:26 -0700607 struct scm_desc desc = {0};
Kyle Yan95180af2017-12-01 17:05:59 -0800608 struct pil_map_fw_info map_fw_info = {
609 .attrs = pil->attrs,
610 .region = region,
611 .base_addr = mdata_phys,
612 .dev = pil->dev,
613 };
614 void *map_data = pil->map_data ? pil->map_data : &map_fw_info;
Kyle Yane45fa022016-08-29 11:40:26 -0700615
616 if (d->subsys_desc.no_auth)
617 return 0;
618
619 ret = scm_pas_enable_bw();
620 if (ret)
621 return ret;
Kyle Yane45fa022016-08-29 11:40:26 -0700622
Kyle Yan95180af2017-12-01 17:05:59 -0800623 mdata_buf = pil->map_fw_mem(mdata_phys, size, map_data);
Kyle Yane45fa022016-08-29 11:40:26 -0700624 if (!mdata_buf) {
Kyle Yan95180af2017-12-01 17:05:59 -0800625 dev_err(pil->dev, "Failed to map memory for metadata.\n");
Kyle Yane45fa022016-08-29 11:40:26 -0700626 scm_pas_disable_bw();
627 return -ENOMEM;
628 }
629
630 memcpy(mdata_buf, metadata, size);
631
632 request.proc = d->pas_id;
633 request.image_addr = mdata_phys;
634
635 if (!is_scm_armv8()) {
636 ret = scm_call(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &request,
637 sizeof(request), &scm_ret, sizeof(scm_ret));
638 } else {
639 desc.args[0] = d->pas_id;
640 desc.args[1] = mdata_phys;
641 desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_RW);
642 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD),
643 &desc);
644 scm_ret = desc.ret[0];
645 }
646
Kyle Yan95180af2017-12-01 17:05:59 -0800647 pil->unmap_fw_mem(mdata_buf, size, map_data);
Kyle Yane45fa022016-08-29 11:40:26 -0700648 scm_pas_disable_bw();
649 if (ret)
650 return ret;
651 return scm_ret;
652}
653
654static int pil_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
655 size_t size)
656{
657 struct pil_tz_data *d = desc_to_data(pil);
658 struct pas_init_image_req {
659 u32 proc;
660 u32 start_addr;
661 u32 len;
662 } request;
663 u32 scm_ret = 0;
664 int ret;
665 struct scm_desc desc = {0};
666
667 if (d->subsys_desc.no_auth)
668 return 0;
669
670 request.proc = d->pas_id;
671 request.start_addr = addr;
672 request.len = size;
673
674 if (!is_scm_armv8()) {
675 ret = scm_call(SCM_SVC_PIL, PAS_MEM_SETUP_CMD, &request,
676 sizeof(request), &scm_ret, sizeof(scm_ret));
677 } else {
678 desc.args[0] = d->pas_id;
679 desc.args[1] = addr;
680 desc.args[2] = size;
681 desc.arginfo = SCM_ARGS(3);
682 ret = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_MEM_SETUP_CMD),
683 &desc);
684 scm_ret = desc.ret[0];
685 }
686 if (ret)
687 return ret;
688 return scm_ret;
689}
690
691static int pil_auth_and_reset(struct pil_desc *pil)
692{
693 struct pil_tz_data *d = desc_to_data(pil);
694 int rc;
695 u32 proc, scm_ret = 0;
696 struct scm_desc desc = {0};
697
698 if (d->subsys_desc.no_auth)
699 return 0;
700
701 desc.args[0] = proc = d->pas_id;
702 desc.arginfo = SCM_ARGS(1);
703
Kyle Yanf995ef62017-04-13 19:13:39 -0700704 rc = scm_pas_enable_bw();
705 if (rc)
706 return rc;
707
Kyle Yane45fa022016-08-29 11:40:26 -0700708 rc = enable_regulators(d, pil->dev, d->regs, d->reg_count, false);
709 if (rc)
710 return rc;
711
712 rc = prepare_enable_clocks(pil->dev, d->clks, d->clk_count);
713 if (rc)
714 goto err_clks;
715
Kyle Yane45fa022016-08-29 11:40:26 -0700716 if (!is_scm_armv8()) {
717 rc = scm_call(SCM_SVC_PIL, PAS_AUTH_AND_RESET_CMD, &proc,
718 sizeof(proc), &scm_ret, sizeof(scm_ret));
719 } else {
720 rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL,
721 PAS_AUTH_AND_RESET_CMD), &desc);
722 scm_ret = desc.ret[0];
723 }
724 scm_pas_disable_bw();
725 if (rc)
726 goto err_reset;
727
728 return scm_ret;
729err_reset:
730 disable_unprepare_clocks(d->clks, d->clk_count);
731err_clks:
732 disable_regulators(d, d->regs, d->reg_count, false);
733
734 return rc;
735}
736
737static int pil_shutdown_trusted(struct pil_desc *pil)
738{
739 struct pil_tz_data *d = desc_to_data(pil);
740 u32 proc, scm_ret = 0;
741 int rc;
742 struct scm_desc desc = {0};
743
744 if (d->subsys_desc.no_auth)
745 return 0;
746
747 desc.args[0] = proc = d->pas_id;
748 desc.arginfo = SCM_ARGS(1);
749
Kyle Yan5cb0e082017-04-21 18:13:25 -0700750 if (d->bus_client) {
751 rc = msm_bus_scale_client_update_request(d->bus_client, 1);
752 if (rc) {
753 dev_err(pil->dev, "bandwidth request failed(rc:%d)\n",
754 rc);
755 return rc;
756 }
757 } else
758 WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
759 d->subsys_desc.name);
760
Kyle Yane45fa022016-08-29 11:40:26 -0700761 rc = enable_regulators(d, pil->dev, d->proxy_regs,
762 d->proxy_reg_count, true);
763 if (rc)
Kyle Yan5cb0e082017-04-21 18:13:25 -0700764 goto err_regulators;
Kyle Yane45fa022016-08-29 11:40:26 -0700765
766 rc = prepare_enable_clocks(pil->dev, d->proxy_clks,
767 d->proxy_clk_count);
768 if (rc)
769 goto err_clks;
770
771 if (!is_scm_armv8()) {
772 rc = scm_call(SCM_SVC_PIL, PAS_SHUTDOWN_CMD, &proc,
773 sizeof(proc), &scm_ret, sizeof(scm_ret));
774 } else {
775 rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD),
776 &desc);
777 scm_ret = desc.ret[0];
778 }
779
780 disable_unprepare_clocks(d->proxy_clks, d->proxy_clk_count);
781 disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false);
Kyle Yan5cb0e082017-04-21 18:13:25 -0700782 if (d->bus_client)
783 msm_bus_scale_client_update_request(d->bus_client, 0);
784 else
785 WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
786 d->subsys_desc.name);
Kyle Yane45fa022016-08-29 11:40:26 -0700787
788 if (rc)
789 return rc;
790
791 disable_unprepare_clocks(d->clks, d->clk_count);
792 disable_regulators(d, d->regs, d->reg_count, false);
793
794 return scm_ret;
Kyle Yan5cb0e082017-04-21 18:13:25 -0700795
Kyle Yane45fa022016-08-29 11:40:26 -0700796err_clks:
797 disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false);
Kyle Yan5cb0e082017-04-21 18:13:25 -0700798err_regulators:
799 if (d->bus_client)
800 msm_bus_scale_client_update_request(d->bus_client, 0);
801 else
802 WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
803 d->subsys_desc.name);
Kyle Yane45fa022016-08-29 11:40:26 -0700804 return rc;
805}
806
Kyle Yan5ea38952017-08-03 16:05:55 -0700807static int pil_deinit_image_trusted(struct pil_desc *pil)
808{
809 struct pil_tz_data *d = desc_to_data(pil);
810 u32 proc, scm_ret = 0;
811 int rc;
812 struct scm_desc desc = {0};
813
814 if (d->subsys_desc.no_auth)
815 return 0;
816
817 desc.args[0] = proc = d->pas_id;
818 desc.arginfo = SCM_ARGS(1);
819
820 if (!is_scm_armv8()) {
821 rc = scm_call(SCM_SVC_PIL, PAS_SHUTDOWN_CMD, &proc,
822 sizeof(proc), &scm_ret, sizeof(scm_ret));
823 } else {
824 rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD),
825 &desc);
826 scm_ret = desc.ret[0];
827 }
828
829 if (rc)
830 return rc;
831 return scm_ret;
832}
833
Kyle Yane45fa022016-08-29 11:40:26 -0700834static struct pil_reset_ops pil_ops_trusted = {
835 .init_image = pil_init_image_trusted,
836 .mem_setup = pil_mem_setup_trusted,
837 .auth_and_reset = pil_auth_and_reset,
838 .shutdown = pil_shutdown_trusted,
839 .proxy_vote = pil_make_proxy_vote,
840 .proxy_unvote = pil_remove_proxy_vote,
Kyle Yan5ea38952017-08-03 16:05:55 -0700841 .deinit_image = pil_deinit_image_trusted,
Kyle Yane45fa022016-08-29 11:40:26 -0700842};
843
844static void log_failure_reason(const struct pil_tz_data *d)
845{
846 u32 size;
847 char *smem_reason, reason[MAX_SSR_REASON_LEN];
848 const char *name = d->subsys_desc.name;
849
850 if (d->smem_id == -1)
851 return;
852
853 smem_reason = smem_get_entry_no_rlock(d->smem_id, &size, 0,
854 SMEM_ANY_HOST_FLAG);
855 if (!smem_reason || !size) {
856 pr_err("%s SFR: (unknown, smem_get_entry_no_rlock failed).\n",
857 name);
858 return;
859 }
860 if (!smem_reason[0]) {
861 pr_err("%s SFR: (unknown, empty string found).\n", name);
862 return;
863 }
864
865 strlcpy(reason, smem_reason, min(size, MAX_SSR_REASON_LEN));
866 pr_err("%s subsystem failure reason: %s.\n", name, reason);
Kyle Yane45fa022016-08-29 11:40:26 -0700867}
868
869static int subsys_shutdown(const struct subsys_desc *subsys, bool force_stop)
870{
871 struct pil_tz_data *d = subsys_to_data(subsys);
872 int ret;
873
874 if (!subsys_get_crash_status(d->subsys) && force_stop &&
875 subsys->force_stop_gpio) {
876 gpio_set_value(subsys->force_stop_gpio, 1);
877 ret = wait_for_completion_timeout(&d->stop_ack,
878 msecs_to_jiffies(STOP_ACK_TIMEOUT_MS));
879 if (!ret)
880 pr_warn("Timed out on stop ack from %s.\n",
881 subsys->name);
882 gpio_set_value(subsys->force_stop_gpio, 0);
883 }
884
885 pil_shutdown(&d->desc);
886 return 0;
887}
888
889static int subsys_powerup(const struct subsys_desc *subsys)
890{
891 struct pil_tz_data *d = subsys_to_data(subsys);
892 int ret = 0;
893
894 if (subsys->stop_ack_irq)
895 reinit_completion(&d->stop_ack);
896
897 d->desc.fw_name = subsys->fw_name;
898 ret = pil_boot(&d->desc);
899
900 return ret;
901}
902
903static int subsys_ramdump(int enable, const struct subsys_desc *subsys)
904{
905 struct pil_tz_data *d = subsys_to_data(subsys);
906
907 if (!enable)
908 return 0;
909
910 return pil_do_ramdump(&d->desc, d->ramdump_dev);
911}
912
913static void subsys_free_memory(const struct subsys_desc *subsys)
914{
915 struct pil_tz_data *d = subsys_to_data(subsys);
916
917 pil_free_memory(&d->desc);
918}
919
920static void subsys_crash_shutdown(const struct subsys_desc *subsys)
921{
922 struct pil_tz_data *d = subsys_to_data(subsys);
923
924 if (subsys->force_stop_gpio > 0 &&
925 !subsys_get_crash_status(d->subsys)) {
926 gpio_set_value(subsys->force_stop_gpio, 1);
927 mdelay(CRASH_STOP_ACK_TO_MS);
928 }
929}
930
931static irqreturn_t subsys_err_fatal_intr_handler (int irq, void *dev_id)
932{
933 struct pil_tz_data *d = subsys_to_data(dev_id);
Avaneesh Kumar Dwivedi94619d92017-10-05 17:58:38 +0530934 u32 nmi_status = 0;
Kyle Yane45fa022016-08-29 11:40:26 -0700935
Avaneesh Kumar Dwivedi94619d92017-10-05 17:58:38 +0530936 if (d->reg_base)
937 nmi_status = readl_relaxed(d->reg_base +
938 QDSP6SS_NMI_STATUS);
939
940 if (nmi_status & 0x04)
941 pr_err("%s: Fatal error on the %s due to TZ NMI\n",
942 __func__, d->subsys_desc.name);
943 else
944 pr_err("%s Fatal error on the %s\n",
945 __func__, d->subsys_desc.name);
946
Kyle Yane45fa022016-08-29 11:40:26 -0700947 if (subsys_get_crash_status(d->subsys)) {
948 pr_err("%s: Ignoring error fatal, restart in progress\n",
949 d->subsys_desc.name);
950 return IRQ_HANDLED;
951 }
Satya Durga Srinivasu Prabhala30af7d02016-12-15 13:33:39 -0800952 subsys_set_crash_status(d->subsys, CRASH_STATUS_ERR_FATAL);
Kyle Yane45fa022016-08-29 11:40:26 -0700953 log_failure_reason(d);
954 subsystem_restart_dev(d->subsys);
955
956 return IRQ_HANDLED;
957}
958
959static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id)
960{
961 struct pil_tz_data *d = subsys_to_data(dev_id);
962
963 if (subsys_get_crash_status(d->subsys))
964 return IRQ_HANDLED;
965 pr_err("Watchdog bite received from %s!\n", d->subsys_desc.name);
966
967 if (d->subsys_desc.system_debug &&
968 !gpio_get_value(d->subsys_desc.err_fatal_gpio))
969 panic("%s: System ramdump requested. Triggering device restart!\n",
970 __func__);
Satya Durga Srinivasu Prabhala30af7d02016-12-15 13:33:39 -0800971 subsys_set_crash_status(d->subsys, CRASH_STATUS_WDOG_BITE);
Kyle Yane45fa022016-08-29 11:40:26 -0700972 log_failure_reason(d);
973 subsystem_restart_dev(d->subsys);
974
975 return IRQ_HANDLED;
976}
977
978static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id)
979{
980 struct pil_tz_data *d = subsys_to_data(dev_id);
981
982 pr_info("Received stop ack interrupt from %s\n", d->subsys_desc.name);
983 complete(&d->stop_ack);
984 return IRQ_HANDLED;
985}
986
Puja Gupta557f5292016-11-28 14:01:03 -0800987static void clear_pbl_done(struct pil_tz_data *d)
Kyle Yane45fa022016-08-29 11:40:26 -0700988{
989 uint32_t err_value;
990
991 err_value = __raw_readl(d->err_status);
992 pr_debug("PBL_DONE received from %s!\n", d->subsys_desc.name);
993 if (err_value) {
994 uint32_t rmb_err_spare0;
995 uint32_t rmb_err_spare1;
996 uint32_t rmb_err_spare2;
997
998 rmb_err_spare2 = __raw_readl(d->err_status_spare);
999 rmb_err_spare1 = __raw_readl(d->err_status_spare-4);
1000 rmb_err_spare0 = __raw_readl(d->err_status_spare-8);
1001
1002 pr_err("PBL error status register: 0x%08x\n", err_value);
1003
1004 pr_err("PBL error status spare0 register: 0x%08x\n",
1005 rmb_err_spare0);
1006 pr_err("PBL error status spare1 register: 0x%08x\n",
1007 rmb_err_spare1);
1008 pr_err("PBL error status spare2 register: 0x%08x\n",
1009 rmb_err_spare2);
1010 }
1011 __raw_writel(BIT(d->bits_arr[PBL_DONE]), d->irq_clear);
1012}
1013
Puja Gupta557f5292016-11-28 14:01:03 -08001014static void clear_err_ready(struct pil_tz_data *d)
Kyle Yane45fa022016-08-29 11:40:26 -07001015{
Puja Gupta557f5292016-11-28 14:01:03 -08001016 pr_debug("Subsystem error services up received from %s\n",
Kyle Yane45fa022016-08-29 11:40:26 -07001017 d->subsys_desc.name);
Puja Gupta557f5292016-11-28 14:01:03 -08001018 __raw_writel(BIT(d->bits_arr[ERR_READY]), d->irq_clear);
1019 complete_err_ready(d->subsys);
1020}
1021
1022static void clear_wdog(struct pil_tz_data *d)
1023{
1024 /* Check crash status to know if device is restarting*/
1025 if (!subsys_get_crash_status(d->subsys)) {
Kyle Yane45fa022016-08-29 11:40:26 -07001026 pr_err("wdog bite received from %s!\n", d->subsys_desc.name);
1027 __raw_writel(BIT(d->bits_arr[ERR_READY]), d->irq_clear);
Satya Durga Srinivasu Prabhala30af7d02016-12-15 13:33:39 -08001028 subsys_set_crash_status(d->subsys, CRASH_STATUS_WDOG_BITE);
Kyle Yane45fa022016-08-29 11:40:26 -07001029 log_failure_reason(d);
1030 subsystem_restart_dev(d->subsys);
1031 }
1032}
1033
1034static irqreturn_t subsys_generic_handler(int irq, void *dev_id)
1035{
1036 struct pil_tz_data *d = subsys_to_data(dev_id);
Puja Gupta557f5292016-11-28 14:01:03 -08001037 uint32_t status_val, err_value;
Kyle Yane45fa022016-08-29 11:40:26 -07001038
Puja Gupta557f5292016-11-28 14:01:03 -08001039 err_value = __raw_readl(d->err_status_spare);
Kyle Yane45fa022016-08-29 11:40:26 -07001040 status_val = __raw_readl(d->irq_status);
1041
Puja Gupta557f5292016-11-28 14:01:03 -08001042 if ((status_val & BIT(d->bits_arr[ERR_READY])) && !err_value)
1043 clear_err_ready(d);
1044
1045 if ((status_val & BIT(d->bits_arr[ERR_READY])) &&
1046 err_value == 0x44554d50)
1047 clear_wdog(d);
1048
1049 if (status_val & BIT(d->bits_arr[PBL_DONE]))
1050 clear_pbl_done(d);
1051
Kyle Yane45fa022016-08-29 11:40:26 -07001052 return IRQ_HANDLED;
1053}
1054
1055static void mask_scsr_irqs(struct pil_tz_data *d)
1056{
1057 uint32_t mask_val;
1058 /* Masking all interrupts not handled by HLOS */
1059 mask_val = ~0;
1060 __raw_writel(mask_val & ~BIT(d->bits_arr[ERR_READY]) &
1061 ~BIT(d->bits_arr[PBL_DONE]), d->irq_mask);
1062}
1063
1064static int pil_tz_driver_probe(struct platform_device *pdev)
1065{
1066 struct pil_tz_data *d;
1067 struct resource *res;
1068 u32 proxy_timeout;
1069 int len, rc;
1070
1071 d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
1072 if (!d)
1073 return -ENOMEM;
1074 platform_set_drvdata(pdev, d);
1075
1076 if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-no-auth"))
1077 d->subsys_desc.no_auth = true;
1078
1079 d->keep_proxy_regs_on = of_property_read_bool(pdev->dev.of_node,
1080 "qcom,keep-proxy-regs-on");
1081
Avaneesh Kumar Dwivedi94619d92017-10-05 17:58:38 +05301082 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base_reg");
1083 d->reg_base = devm_ioremap_resource(&pdev->dev, res);
1084 if (IS_ERR(d->reg_base)) {
1085 dev_err(&pdev->dev, "Failed to ioremap base register\n");
1086 d->reg_base = NULL;
1087 }
1088
Kyle Yane45fa022016-08-29 11:40:26 -07001089 rc = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
1090 &d->desc.name);
1091 if (rc)
1092 return rc;
1093
1094 /* Defaulting smem_id to be not present */
1095 d->smem_id = -1;
1096
1097 if (of_find_property(pdev->dev.of_node, "qcom,smem-id", &len)) {
1098 rc = of_property_read_u32(pdev->dev.of_node, "qcom,smem-id",
1099 &d->smem_id);
1100 if (rc) {
1101 dev_err(&pdev->dev, "Failed to get the smem_id(rc:%d)\n",
1102 rc);
1103 return rc;
1104 }
1105 }
1106
1107 d->desc.dev = &pdev->dev;
1108 d->desc.owner = THIS_MODULE;
1109 d->desc.ops = &pil_ops_trusted;
1110
1111 d->desc.proxy_timeout = PROXY_TIMEOUT_MS;
Avaneesh Kumar Dwivedi7b506d22017-03-17 16:41:13 +05301112 d->desc.clear_fw_region = true;
Kyle Yane45fa022016-08-29 11:40:26 -07001113
1114 rc = of_property_read_u32(pdev->dev.of_node, "qcom,proxy-timeout-ms",
1115 &proxy_timeout);
1116 if (!rc)
1117 d->desc.proxy_timeout = proxy_timeout;
1118
1119 if (!d->subsys_desc.no_auth) {
1120 rc = piltz_resc_init(pdev, d);
1121 if (rc)
Kyle Yan3d6600c2017-01-06 14:04:26 -08001122 return rc;
Kyle Yane45fa022016-08-29 11:40:26 -07001123
1124 rc = of_property_read_u32(pdev->dev.of_node, "qcom,pas-id",
1125 &d->pas_id);
1126 if (rc) {
1127 dev_err(&pdev->dev, "Failed to find the pas_id(rc:%d)\n",
1128 rc);
1129 return rc;
1130 }
Kyle Yan9f57f572017-03-28 10:31:54 -07001131 scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE_0);
Kyle Yane45fa022016-08-29 11:40:26 -07001132 }
1133
1134 rc = pil_desc_init(&d->desc);
1135 if (rc)
1136 return rc;
1137
1138 init_completion(&d->stop_ack);
1139
1140 d->subsys_desc.name = d->desc.name;
1141 d->subsys_desc.owner = THIS_MODULE;
1142 d->subsys_desc.dev = &pdev->dev;
1143 d->subsys_desc.shutdown = subsys_shutdown;
1144 d->subsys_desc.powerup = subsys_powerup;
1145 d->subsys_desc.ramdump = subsys_ramdump;
1146 d->subsys_desc.free_memory = subsys_free_memory;
1147 d->subsys_desc.crash_shutdown = subsys_crash_shutdown;
1148 if (of_property_read_bool(pdev->dev.of_node,
1149 "qcom,pil-generic-irq-handler")) {
1150 d->subsys_desc.generic_handler = subsys_generic_handler;
1151 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1152 "sp2soc_irq_status");
1153 d->irq_status = devm_ioremap_resource(&pdev->dev, res);
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301154 if (IS_ERR(d->irq_status)) {
1155 dev_err(&pdev->dev, "Invalid resource for sp2soc_irq_status\n");
1156 rc = PTR_ERR(d->irq_status);
1157 goto err_ramdump;
1158 }
1159
Kyle Yane45fa022016-08-29 11:40:26 -07001160 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1161 "sp2soc_irq_clr");
1162 d->irq_clear = devm_ioremap_resource(&pdev->dev, res);
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301163 if (IS_ERR(d->irq_clear)) {
1164 dev_err(&pdev->dev, "Invalid resource for sp2soc_irq_clr\n");
1165 rc = PTR_ERR(d->irq_clear);
1166 goto err_ramdump;
1167 }
1168
Kyle Yane45fa022016-08-29 11:40:26 -07001169 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1170 "sp2soc_irq_mask");
1171 d->irq_mask = devm_ioremap_resource(&pdev->dev, res);
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301172 if (IS_ERR(d->irq_mask)) {
1173 dev_err(&pdev->dev, "Invalid resource for sp2soc_irq_mask\n");
1174 rc = PTR_ERR(d->irq_mask);
1175 goto err_ramdump;
1176 }
1177
Kyle Yane45fa022016-08-29 11:40:26 -07001178 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1179 "rmb_err");
1180 d->err_status = devm_ioremap_resource(&pdev->dev, res);
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301181 if (IS_ERR(d->err_status)) {
1182 dev_err(&pdev->dev, "Invalid resource for rmb_err\n");
1183 rc = PTR_ERR(d->err_status);
1184 goto err_ramdump;
1185 }
1186
Kyle Yane45fa022016-08-29 11:40:26 -07001187 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1188 "rmb_err_spare2");
1189 d->err_status_spare = devm_ioremap_resource(&pdev->dev, res);
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301190 if (IS_ERR(d->err_status_spare)) {
1191 dev_err(&pdev->dev, "Invalid resource for rmb_err_spare2\n");
1192 rc = PTR_ERR(d->err_status_spare);
1193 goto err_ramdump;
1194 }
1195
Kyle Yane45fa022016-08-29 11:40:26 -07001196 rc = of_property_read_u32_array(pdev->dev.of_node,
1197 "qcom,spss-scsr-bits", d->bits_arr, sizeof(d->bits_arr)/
1198 sizeof(d->bits_arr[0]));
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301199 if (rc) {
Kyle Yane45fa022016-08-29 11:40:26 -07001200 dev_err(&pdev->dev, "Failed to read qcom,spss-scsr-bits");
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301201 goto err_ramdump;
1202 }
Kyle Yane45fa022016-08-29 11:40:26 -07001203 mask_scsr_irqs(d);
1204
1205 } else {
1206 d->subsys_desc.err_fatal_handler =
1207 subsys_err_fatal_intr_handler;
1208 d->subsys_desc.wdog_bite_handler = subsys_wdog_bite_irq_handler;
1209 d->subsys_desc.stop_ack_handler = subsys_stop_ack_intr_handler;
1210 }
Kyle Yan0ceeb642017-09-13 11:21:35 -07001211 d->desc.signal_aop = of_property_read_bool(pdev->dev.of_node,
1212 "qcom,signal-aop");
1213 if (d->desc.signal_aop) {
1214 d->desc.cl.dev = &pdev->dev;
1215 d->desc.cl.tx_block = true;
1216 d->desc.cl.tx_tout = 1000;
1217 d->desc.cl.knows_txdone = false;
1218 d->desc.mbox = mbox_request_channel(&d->desc.cl, 0);
1219 if (IS_ERR(d->desc.mbox)) {
1220 rc = PTR_ERR(d->desc.mbox);
1221 dev_err(&pdev->dev, "Failed to get mailbox channel %pK %d\n",
1222 d->desc.mbox, rc);
1223 goto err_ramdump;
1224 }
1225 }
1226
Kyle Yane45fa022016-08-29 11:40:26 -07001227 d->ramdump_dev = create_ramdump_device(d->subsys_desc.name,
1228 &pdev->dev);
1229 if (!d->ramdump_dev) {
1230 rc = -ENOMEM;
1231 goto err_ramdump;
1232 }
1233
1234 d->subsys = subsys_register(&d->subsys_desc);
1235 if (IS_ERR(d->subsys)) {
1236 rc = PTR_ERR(d->subsys);
1237 goto err_subsys;
1238 }
1239
1240 return 0;
1241err_subsys:
1242 destroy_ramdump_device(d->ramdump_dev);
1243err_ramdump:
1244 pil_desc_release(&d->desc);
Jitendra Sharma76e0c842017-10-25 16:16:36 +05301245 platform_set_drvdata(pdev, NULL);
Kyle Yane45fa022016-08-29 11:40:26 -07001246
1247 return rc;
1248}
1249
1250static int pil_tz_driver_exit(struct platform_device *pdev)
1251{
1252 struct pil_tz_data *d = platform_get_drvdata(pdev);
1253
1254 subsys_unregister(d->subsys);
1255 destroy_ramdump_device(d->ramdump_dev);
1256 pil_desc_release(&d->desc);
1257
1258 return 0;
1259}
1260
1261static const struct of_device_id pil_tz_match_table[] = {
1262 {.compatible = "qcom,pil-tz-generic"},
1263 {}
1264};
1265
1266static struct platform_driver pil_tz_driver = {
1267 .probe = pil_tz_driver_probe,
1268 .remove = pil_tz_driver_exit,
1269 .driver = {
1270 .name = "subsys-pil-tz",
1271 .of_match_table = pil_tz_match_table,
1272 .owner = THIS_MODULE,
1273 },
1274};
1275
1276static int __init pil_tz_init(void)
1277{
1278 return platform_driver_register(&pil_tz_driver);
1279}
1280module_init(pil_tz_init);
1281
1282static void __exit pil_tz_exit(void)
1283{
1284 platform_driver_unregister(&pil_tz_driver);
1285}
1286module_exit(pil_tz_exit);
1287
1288MODULE_DESCRIPTION("Support for booting subsystems");
1289MODULE_LICENSE("GPL v2");