Merge tag 'x86_urgent_for_v6.4_rc2' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / remoteproc / qcom_q6v5_pas.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
4  *
5  * Copyright (C) 2016 Linaro Ltd
6  * Copyright (C) 2014 Sony Mobile Communications AB
7  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
8  */
9
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/firmware.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/of_address.h>
17 #include <linux/of_device.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm_domain.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/firmware/qcom/qcom_scm.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/remoteproc.h>
24 #include <linux/soc/qcom/mdt_loader.h>
25 #include <linux/soc/qcom/smem.h>
26 #include <linux/soc/qcom/smem_state.h>
27
28 #include "qcom_common.h"
29 #include "qcom_pil_info.h"
30 #include "qcom_q6v5.h"
31 #include "remoteproc_internal.h"
32
33 #define ADSP_DECRYPT_SHUTDOWN_DELAY_MS  100
34
35 struct adsp_data {
36         int crash_reason_smem;
37         const char *firmware_name;
38         const char *dtb_firmware_name;
39         int pas_id;
40         int dtb_pas_id;
41         unsigned int minidump_id;
42         bool auto_boot;
43         bool decrypt_shutdown;
44
45         char **proxy_pd_names;
46
47         const char *load_state;
48         const char *ssr_name;
49         const char *sysmon_name;
50         int ssctl_id;
51
52         int region_assign_idx;
53 };
54
55 struct qcom_adsp {
56         struct device *dev;
57         struct rproc *rproc;
58
59         struct qcom_q6v5 q6v5;
60
61         struct clk *xo;
62         struct clk *aggre2_clk;
63
64         struct regulator *cx_supply;
65         struct regulator *px_supply;
66
67         struct device *proxy_pds[3];
68
69         int proxy_pd_count;
70
71         const char *dtb_firmware_name;
72         int pas_id;
73         int dtb_pas_id;
74         unsigned int minidump_id;
75         int crash_reason_smem;
76         bool decrypt_shutdown;
77         const char *info_name;
78
79         const struct firmware *firmware;
80         const struct firmware *dtb_firmware;
81
82         struct completion start_done;
83         struct completion stop_done;
84
85         phys_addr_t mem_phys;
86         phys_addr_t dtb_mem_phys;
87         phys_addr_t mem_reloc;
88         phys_addr_t dtb_mem_reloc;
89         phys_addr_t region_assign_phys;
90         void *mem_region;
91         void *dtb_mem_region;
92         size_t mem_size;
93         size_t dtb_mem_size;
94         size_t region_assign_size;
95
96         int region_assign_idx;
97         u64 region_assign_perms;
98
99         struct qcom_rproc_glink glink_subdev;
100         struct qcom_rproc_subdev smd_subdev;
101         struct qcom_rproc_ssr ssr_subdev;
102         struct qcom_sysmon *sysmon;
103
104         struct qcom_scm_pas_metadata pas_metadata;
105         struct qcom_scm_pas_metadata dtb_pas_metadata;
106 };
107
108 void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment,
109                        void *dest, size_t offset, size_t size)
110 {
111         struct qcom_adsp *adsp = rproc->priv;
112         int total_offset;
113
114         total_offset = segment->da + segment->offset + offset - adsp->mem_phys;
115         if (total_offset < 0 || total_offset + size > adsp->mem_size) {
116                 dev_err(adsp->dev,
117                         "invalid copy request for segment %pad with offset %zu and size %zu)\n",
118                         &segment->da, offset, size);
119                 memset(dest, 0xff, size);
120                 return;
121         }
122
123         memcpy_fromio(dest, adsp->mem_region + total_offset, size);
124 }
125
126 static void adsp_minidump(struct rproc *rproc)
127 {
128         struct qcom_adsp *adsp = rproc->priv;
129
130         if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
131                 return;
132
133         qcom_minidump(rproc, adsp->minidump_id, adsp_segment_dump);
134 }
135
136 static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
137                            size_t pd_count)
138 {
139         int ret;
140         int i;
141
142         for (i = 0; i < pd_count; i++) {
143                 dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
144                 ret = pm_runtime_get_sync(pds[i]);
145                 if (ret < 0) {
146                         pm_runtime_put_noidle(pds[i]);
147                         dev_pm_genpd_set_performance_state(pds[i], 0);
148                         goto unroll_pd_votes;
149                 }
150         }
151
152         return 0;
153
154 unroll_pd_votes:
155         for (i--; i >= 0; i--) {
156                 dev_pm_genpd_set_performance_state(pds[i], 0);
157                 pm_runtime_put(pds[i]);
158         }
159
160         return ret;
161 };
162
163 static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
164                              size_t pd_count)
165 {
166         int i;
167
168         for (i = 0; i < pd_count; i++) {
169                 dev_pm_genpd_set_performance_state(pds[i], 0);
170                 pm_runtime_put(pds[i]);
171         }
172 }
173
174 static int adsp_shutdown_poll_decrypt(struct qcom_adsp *adsp)
175 {
176         unsigned int retry_num = 50;
177         int ret;
178
179         do {
180                 msleep(ADSP_DECRYPT_SHUTDOWN_DELAY_MS);
181                 ret = qcom_scm_pas_shutdown(adsp->pas_id);
182         } while (ret == -EINVAL && --retry_num);
183
184         return ret;
185 }
186
187 static int adsp_unprepare(struct rproc *rproc)
188 {
189         struct qcom_adsp *adsp = rproc->priv;
190
191         /*
192          * adsp_load() did pass pas_metadata to the SCM driver for storing
193          * metadata context. It might have been released already if
194          * auth_and_reset() was successful, but in other cases clean it up
195          * here.
196          */
197         qcom_scm_pas_metadata_release(&adsp->pas_metadata);
198         if (adsp->dtb_pas_id)
199                 qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
200
201         return 0;
202 }
203
204 static int adsp_load(struct rproc *rproc, const struct firmware *fw)
205 {
206         struct qcom_adsp *adsp = rproc->priv;
207         int ret;
208
209         /* Store firmware handle to be used in adsp_start() */
210         adsp->firmware = fw;
211
212         if (adsp->dtb_pas_id) {
213                 ret = request_firmware(&adsp->dtb_firmware, adsp->dtb_firmware_name, adsp->dev);
214                 if (ret) {
215                         dev_err(adsp->dev, "request_firmware failed for %s: %d\n",
216                                 adsp->dtb_firmware_name, ret);
217                         return ret;
218                 }
219
220                 ret = qcom_mdt_pas_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name,
221                                         adsp->dtb_pas_id, adsp->dtb_mem_phys,
222                                         &adsp->dtb_pas_metadata);
223                 if (ret)
224                         goto release_dtb_firmware;
225
226                 ret = qcom_mdt_load_no_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name,
227                                             adsp->dtb_pas_id, adsp->dtb_mem_region,
228                                             adsp->dtb_mem_phys, adsp->dtb_mem_size,
229                                             &adsp->dtb_mem_reloc);
230                 if (ret)
231                         goto release_dtb_metadata;
232         }
233
234         return 0;
235
236 release_dtb_metadata:
237         qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
238
239 release_dtb_firmware:
240         release_firmware(adsp->dtb_firmware);
241
242         return ret;
243 }
244
245 static int adsp_start(struct rproc *rproc)
246 {
247         struct qcom_adsp *adsp = rproc->priv;
248         int ret;
249
250         ret = qcom_q6v5_prepare(&adsp->q6v5);
251         if (ret)
252                 return ret;
253
254         ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
255         if (ret < 0)
256                 goto disable_irqs;
257
258         ret = clk_prepare_enable(adsp->xo);
259         if (ret)
260                 goto disable_proxy_pds;
261
262         ret = clk_prepare_enable(adsp->aggre2_clk);
263         if (ret)
264                 goto disable_xo_clk;
265
266         if (adsp->cx_supply) {
267                 ret = regulator_enable(adsp->cx_supply);
268                 if (ret)
269                         goto disable_aggre2_clk;
270         }
271
272         if (adsp->px_supply) {
273                 ret = regulator_enable(adsp->px_supply);
274                 if (ret)
275                         goto disable_cx_supply;
276         }
277
278         if (adsp->dtb_pas_id) {
279                 ret = qcom_scm_pas_auth_and_reset(adsp->dtb_pas_id);
280                 if (ret) {
281                         dev_err(adsp->dev,
282                                 "failed to authenticate dtb image and release reset\n");
283                         goto disable_px_supply;
284                 }
285         }
286
287         ret = qcom_mdt_pas_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id,
288                                 adsp->mem_phys, &adsp->pas_metadata);
289         if (ret)
290                 goto disable_px_supply;
291
292         ret = qcom_mdt_load_no_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id,
293                                     adsp->mem_region, adsp->mem_phys, adsp->mem_size,
294                                     &adsp->mem_reloc);
295         if (ret)
296                 goto release_pas_metadata;
297
298         qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
299
300         ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
301         if (ret) {
302                 dev_err(adsp->dev,
303                         "failed to authenticate image and release reset\n");
304                 goto release_pas_metadata;
305         }
306
307         ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
308         if (ret == -ETIMEDOUT) {
309                 dev_err(adsp->dev, "start timed out\n");
310                 qcom_scm_pas_shutdown(adsp->pas_id);
311                 goto release_pas_metadata;
312         }
313
314         qcom_scm_pas_metadata_release(&adsp->pas_metadata);
315         if (adsp->dtb_pas_id)
316                 qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
317
318         /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
319         adsp->firmware = NULL;
320
321         return 0;
322
323 release_pas_metadata:
324         qcom_scm_pas_metadata_release(&adsp->pas_metadata);
325         if (adsp->dtb_pas_id)
326                 qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
327 disable_px_supply:
328         if (adsp->px_supply)
329                 regulator_disable(adsp->px_supply);
330 disable_cx_supply:
331         if (adsp->cx_supply)
332                 regulator_disable(adsp->cx_supply);
333 disable_aggre2_clk:
334         clk_disable_unprepare(adsp->aggre2_clk);
335 disable_xo_clk:
336         clk_disable_unprepare(adsp->xo);
337 disable_proxy_pds:
338         adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
339 disable_irqs:
340         qcom_q6v5_unprepare(&adsp->q6v5);
341
342         /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
343         adsp->firmware = NULL;
344
345         return ret;
346 }
347
348 static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
349 {
350         struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
351
352         if (adsp->px_supply)
353                 regulator_disable(adsp->px_supply);
354         if (adsp->cx_supply)
355                 regulator_disable(adsp->cx_supply);
356         clk_disable_unprepare(adsp->aggre2_clk);
357         clk_disable_unprepare(adsp->xo);
358         adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
359 }
360
361 static int adsp_stop(struct rproc *rproc)
362 {
363         struct qcom_adsp *adsp = rproc->priv;
364         int handover;
365         int ret;
366
367         ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
368         if (ret == -ETIMEDOUT)
369                 dev_err(adsp->dev, "timed out on wait\n");
370
371         ret = qcom_scm_pas_shutdown(adsp->pas_id);
372         if (ret && adsp->decrypt_shutdown)
373                 ret = adsp_shutdown_poll_decrypt(adsp);
374
375         if (ret)
376                 dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
377
378         if (adsp->dtb_pas_id) {
379                 ret = qcom_scm_pas_shutdown(adsp->dtb_pas_id);
380                 if (ret)
381                         dev_err(adsp->dev, "failed to shutdown dtb: %d\n", ret);
382         }
383
384         handover = qcom_q6v5_unprepare(&adsp->q6v5);
385         if (handover)
386                 qcom_pas_handover(&adsp->q6v5);
387
388         return ret;
389 }
390
391 static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
392 {
393         struct qcom_adsp *adsp = rproc->priv;
394         int offset;
395
396         offset = da - adsp->mem_reloc;
397         if (offset < 0 || offset + len > adsp->mem_size)
398                 return NULL;
399
400         if (is_iomem)
401                 *is_iomem = true;
402
403         return adsp->mem_region + offset;
404 }
405
406 static unsigned long adsp_panic(struct rproc *rproc)
407 {
408         struct qcom_adsp *adsp = rproc->priv;
409
410         return qcom_q6v5_panic(&adsp->q6v5);
411 }
412
413 static const struct rproc_ops adsp_ops = {
414         .unprepare = adsp_unprepare,
415         .start = adsp_start,
416         .stop = adsp_stop,
417         .da_to_va = adsp_da_to_va,
418         .parse_fw = qcom_register_dump_segments,
419         .load = adsp_load,
420         .panic = adsp_panic,
421 };
422
423 static const struct rproc_ops adsp_minidump_ops = {
424         .unprepare = adsp_unprepare,
425         .start = adsp_start,
426         .stop = adsp_stop,
427         .da_to_va = adsp_da_to_va,
428         .load = adsp_load,
429         .panic = adsp_panic,
430         .coredump = adsp_minidump,
431 };
432
433 static int adsp_init_clock(struct qcom_adsp *adsp)
434 {
435         int ret;
436
437         adsp->xo = devm_clk_get(adsp->dev, "xo");
438         if (IS_ERR(adsp->xo)) {
439                 ret = PTR_ERR(adsp->xo);
440                 if (ret != -EPROBE_DEFER)
441                         dev_err(adsp->dev, "failed to get xo clock");
442                 return ret;
443         }
444
445         adsp->aggre2_clk = devm_clk_get_optional(adsp->dev, "aggre2");
446         if (IS_ERR(adsp->aggre2_clk)) {
447                 ret = PTR_ERR(adsp->aggre2_clk);
448                 if (ret != -EPROBE_DEFER)
449                         dev_err(adsp->dev,
450                                 "failed to get aggre2 clock");
451                 return ret;
452         }
453
454         return 0;
455 }
456
457 static int adsp_init_regulator(struct qcom_adsp *adsp)
458 {
459         adsp->cx_supply = devm_regulator_get_optional(adsp->dev, "cx");
460         if (IS_ERR(adsp->cx_supply)) {
461                 if (PTR_ERR(adsp->cx_supply) == -ENODEV)
462                         adsp->cx_supply = NULL;
463                 else
464                         return PTR_ERR(adsp->cx_supply);
465         }
466
467         if (adsp->cx_supply)
468                 regulator_set_load(adsp->cx_supply, 100000);
469
470         adsp->px_supply = devm_regulator_get_optional(adsp->dev, "px");
471         if (IS_ERR(adsp->px_supply)) {
472                 if (PTR_ERR(adsp->px_supply) == -ENODEV)
473                         adsp->px_supply = NULL;
474                 else
475                         return PTR_ERR(adsp->px_supply);
476         }
477
478         return 0;
479 }
480
481 static int adsp_pds_attach(struct device *dev, struct device **devs,
482                            char **pd_names)
483 {
484         size_t num_pds = 0;
485         int ret;
486         int i;
487
488         if (!pd_names)
489                 return 0;
490
491         /* Handle single power domain */
492         if (dev->pm_domain) {
493                 devs[0] = dev;
494                 pm_runtime_enable(dev);
495                 return 1;
496         }
497
498         while (pd_names[num_pds])
499                 num_pds++;
500
501         for (i = 0; i < num_pds; i++) {
502                 devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
503                 if (IS_ERR_OR_NULL(devs[i])) {
504                         ret = PTR_ERR(devs[i]) ? : -ENODATA;
505                         goto unroll_attach;
506                 }
507         }
508
509         return num_pds;
510
511 unroll_attach:
512         for (i--; i >= 0; i--)
513                 dev_pm_domain_detach(devs[i], false);
514
515         return ret;
516 };
517
518 static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
519                             size_t pd_count)
520 {
521         struct device *dev = adsp->dev;
522         int i;
523
524         /* Handle single power domain */
525         if (dev->pm_domain && pd_count) {
526                 pm_runtime_disable(dev);
527                 return;
528         }
529
530         for (i = 0; i < pd_count; i++)
531                 dev_pm_domain_detach(pds[i], false);
532 }
533
534 static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
535 {
536         struct device_node *node;
537         struct resource r;
538         int ret;
539
540         node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
541         if (!node) {
542                 dev_err(adsp->dev, "no memory-region specified\n");
543                 return -EINVAL;
544         }
545
546         ret = of_address_to_resource(node, 0, &r);
547         of_node_put(node);
548         if (ret)
549                 return ret;
550
551         adsp->mem_phys = adsp->mem_reloc = r.start;
552         adsp->mem_size = resource_size(&r);
553         adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
554         if (!adsp->mem_region) {
555                 dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
556                         &r.start, adsp->mem_size);
557                 return -EBUSY;
558         }
559
560         if (!adsp->dtb_pas_id)
561                 return 0;
562
563         node = of_parse_phandle(adsp->dev->of_node, "memory-region", 1);
564         if (!node) {
565                 dev_err(adsp->dev, "no dtb memory-region specified\n");
566                 return -EINVAL;
567         }
568
569         ret = of_address_to_resource(node, 0, &r);
570         if (ret)
571                 return ret;
572
573         adsp->dtb_mem_phys = adsp->dtb_mem_reloc = r.start;
574         adsp->dtb_mem_size = resource_size(&r);
575         adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size);
576         if (!adsp->dtb_mem_region) {
577                 dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n",
578                         &r.start, adsp->dtb_mem_size);
579                 return -EBUSY;
580         }
581
582         return 0;
583 }
584
585 static int adsp_assign_memory_region(struct qcom_adsp *adsp)
586 {
587         struct qcom_scm_vmperm perm;
588         struct device_node *node;
589         struct resource r;
590         int ret;
591
592         if (!adsp->region_assign_idx)
593                 return 0;
594
595         node = of_parse_phandle(adsp->dev->of_node, "memory-region", adsp->region_assign_idx);
596         if (!node) {
597                 dev_err(adsp->dev, "missing shareable memory-region\n");
598                 return -EINVAL;
599         }
600
601         ret = of_address_to_resource(node, 0, &r);
602         if (ret)
603                 return ret;
604
605         perm.vmid = QCOM_SCM_VMID_MSS_MSA;
606         perm.perm = QCOM_SCM_PERM_RW;
607
608         adsp->region_assign_phys = r.start;
609         adsp->region_assign_size = resource_size(&r);
610         adsp->region_assign_perms = BIT(QCOM_SCM_VMID_HLOS);
611
612         ret = qcom_scm_assign_mem(adsp->region_assign_phys,
613                                   adsp->region_assign_size,
614                                   &adsp->region_assign_perms,
615                                   &perm, 1);
616         if (ret < 0) {
617                 dev_err(adsp->dev, "assign memory failed\n");
618                 return ret;
619         }
620
621         return 0;
622 }
623
624 static void adsp_unassign_memory_region(struct qcom_adsp *adsp)
625 {
626         struct qcom_scm_vmperm perm;
627         int ret;
628
629         if (!adsp->region_assign_idx)
630                 return;
631
632         perm.vmid = QCOM_SCM_VMID_HLOS;
633         perm.perm = QCOM_SCM_PERM_RW;
634
635         ret = qcom_scm_assign_mem(adsp->region_assign_phys,
636                                   adsp->region_assign_size,
637                                   &adsp->region_assign_perms,
638                                   &perm, 1);
639         if (ret < 0)
640                 dev_err(adsp->dev, "unassign memory failed\n");
641 }
642
643 static int adsp_probe(struct platform_device *pdev)
644 {
645         const struct adsp_data *desc;
646         struct qcom_adsp *adsp;
647         struct rproc *rproc;
648         const char *fw_name, *dtb_fw_name = NULL;
649         const struct rproc_ops *ops = &adsp_ops;
650         int ret;
651
652         desc = of_device_get_match_data(&pdev->dev);
653         if (!desc)
654                 return -EINVAL;
655
656         if (!qcom_scm_is_available())
657                 return -EPROBE_DEFER;
658
659         fw_name = desc->firmware_name;
660         ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
661                                       &fw_name);
662         if (ret < 0 && ret != -EINVAL)
663                 return ret;
664
665         if (desc->dtb_firmware_name) {
666                 dtb_fw_name = desc->dtb_firmware_name;
667                 ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name", 1,
668                                                     &dtb_fw_name);
669                 if (ret < 0 && ret != -EINVAL)
670                         return ret;
671         }
672
673         if (desc->minidump_id)
674                 ops = &adsp_minidump_ops;
675
676         rproc = rproc_alloc(&pdev->dev, pdev->name, ops, fw_name, sizeof(*adsp));
677
678         if (!rproc) {
679                 dev_err(&pdev->dev, "unable to allocate remoteproc\n");
680                 return -ENOMEM;
681         }
682
683         rproc->auto_boot = desc->auto_boot;
684         rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
685
686         adsp = rproc->priv;
687         adsp->dev = &pdev->dev;
688         adsp->rproc = rproc;
689         adsp->minidump_id = desc->minidump_id;
690         adsp->pas_id = desc->pas_id;
691         adsp->info_name = desc->sysmon_name;
692         adsp->decrypt_shutdown = desc->decrypt_shutdown;
693         adsp->region_assign_idx = desc->region_assign_idx;
694         if (dtb_fw_name) {
695                 adsp->dtb_firmware_name = dtb_fw_name;
696                 adsp->dtb_pas_id = desc->dtb_pas_id;
697         }
698         platform_set_drvdata(pdev, adsp);
699
700         ret = device_init_wakeup(adsp->dev, true);
701         if (ret)
702                 goto free_rproc;
703
704         ret = adsp_alloc_memory_region(adsp);
705         if (ret)
706                 goto free_rproc;
707
708         ret = adsp_assign_memory_region(adsp);
709         if (ret)
710                 goto free_rproc;
711
712         ret = adsp_init_clock(adsp);
713         if (ret)
714                 goto free_rproc;
715
716         ret = adsp_init_regulator(adsp);
717         if (ret)
718                 goto free_rproc;
719
720         ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
721                               desc->proxy_pd_names);
722         if (ret < 0)
723                 goto free_rproc;
724         adsp->proxy_pd_count = ret;
725
726         ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state,
727                              qcom_pas_handover);
728         if (ret)
729                 goto detach_proxy_pds;
730
731         qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
732         qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
733         adsp->sysmon = qcom_add_sysmon_subdev(rproc,
734                                               desc->sysmon_name,
735                                               desc->ssctl_id);
736         if (IS_ERR(adsp->sysmon)) {
737                 ret = PTR_ERR(adsp->sysmon);
738                 goto detach_proxy_pds;
739         }
740
741         qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
742         ret = rproc_add(rproc);
743         if (ret)
744                 goto detach_proxy_pds;
745
746         return 0;
747
748 detach_proxy_pds:
749         adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
750 free_rproc:
751         device_init_wakeup(adsp->dev, false);
752         rproc_free(rproc);
753
754         return ret;
755 }
756
757 static int adsp_remove(struct platform_device *pdev)
758 {
759         struct qcom_adsp *adsp = platform_get_drvdata(pdev);
760
761         rproc_del(adsp->rproc);
762
763         qcom_q6v5_deinit(&adsp->q6v5);
764         adsp_unassign_memory_region(adsp);
765         qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
766         qcom_remove_sysmon_subdev(adsp->sysmon);
767         qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
768         qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
769         adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
770         device_init_wakeup(adsp->dev, false);
771         rproc_free(adsp->rproc);
772
773         return 0;
774 }
775
776 static const struct adsp_data adsp_resource_init = {
777                 .crash_reason_smem = 423,
778                 .firmware_name = "adsp.mdt",
779                 .pas_id = 1,
780                 .auto_boot = true,
781                 .ssr_name = "lpass",
782                 .sysmon_name = "adsp",
783                 .ssctl_id = 0x14,
784 };
785
786 static const struct adsp_data sdm845_adsp_resource_init = {
787                 .crash_reason_smem = 423,
788                 .firmware_name = "adsp.mdt",
789                 .pas_id = 1,
790                 .auto_boot = true,
791                 .load_state = "adsp",
792                 .ssr_name = "lpass",
793                 .sysmon_name = "adsp",
794                 .ssctl_id = 0x14,
795 };
796
797 static const struct adsp_data sm6350_adsp_resource = {
798         .crash_reason_smem = 423,
799         .firmware_name = "adsp.mdt",
800         .pas_id = 1,
801         .auto_boot = true,
802         .proxy_pd_names = (char*[]){
803                 "lcx",
804                 "lmx",
805                 NULL
806         },
807         .load_state = "adsp",
808         .ssr_name = "lpass",
809         .sysmon_name = "adsp",
810         .ssctl_id = 0x14,
811 };
812
813 static const struct adsp_data sm8150_adsp_resource = {
814                 .crash_reason_smem = 423,
815                 .firmware_name = "adsp.mdt",
816                 .pas_id = 1,
817                 .auto_boot = true,
818                 .proxy_pd_names = (char*[]){
819                         "cx",
820                         NULL
821                 },
822                 .load_state = "adsp",
823                 .ssr_name = "lpass",
824                 .sysmon_name = "adsp",
825                 .ssctl_id = 0x14,
826 };
827
828 static const struct adsp_data sm8250_adsp_resource = {
829         .crash_reason_smem = 423,
830         .firmware_name = "adsp.mdt",
831         .pas_id = 1,
832         .auto_boot = true,
833         .proxy_pd_names = (char*[]){
834                 "lcx",
835                 "lmx",
836                 NULL
837         },
838         .load_state = "adsp",
839         .ssr_name = "lpass",
840         .sysmon_name = "adsp",
841         .ssctl_id = 0x14,
842 };
843
844 static const struct adsp_data sm8350_adsp_resource = {
845         .crash_reason_smem = 423,
846         .firmware_name = "adsp.mdt",
847         .pas_id = 1,
848         .auto_boot = true,
849         .proxy_pd_names = (char*[]){
850                 "lcx",
851                 "lmx",
852                 NULL
853         },
854         .load_state = "adsp",
855         .ssr_name = "lpass",
856         .sysmon_name = "adsp",
857         .ssctl_id = 0x14,
858 };
859
860 static const struct adsp_data msm8996_adsp_resource = {
861                 .crash_reason_smem = 423,
862                 .firmware_name = "adsp.mdt",
863                 .pas_id = 1,
864                 .auto_boot = true,
865                 .proxy_pd_names = (char*[]){
866                         "cx",
867                         NULL
868                 },
869                 .ssr_name = "lpass",
870                 .sysmon_name = "adsp",
871                 .ssctl_id = 0x14,
872 };
873
874 static const struct adsp_data cdsp_resource_init = {
875         .crash_reason_smem = 601,
876         .firmware_name = "cdsp.mdt",
877         .pas_id = 18,
878         .auto_boot = true,
879         .ssr_name = "cdsp",
880         .sysmon_name = "cdsp",
881         .ssctl_id = 0x17,
882 };
883
884 static const struct adsp_data sdm845_cdsp_resource_init = {
885         .crash_reason_smem = 601,
886         .firmware_name = "cdsp.mdt",
887         .pas_id = 18,
888         .auto_boot = true,
889         .load_state = "cdsp",
890         .ssr_name = "cdsp",
891         .sysmon_name = "cdsp",
892         .ssctl_id = 0x17,
893 };
894
895 static const struct adsp_data sm6350_cdsp_resource = {
896         .crash_reason_smem = 601,
897         .firmware_name = "cdsp.mdt",
898         .pas_id = 18,
899         .auto_boot = true,
900         .proxy_pd_names = (char*[]){
901                 "cx",
902                 "mx",
903                 NULL
904         },
905         .load_state = "cdsp",
906         .ssr_name = "cdsp",
907         .sysmon_name = "cdsp",
908         .ssctl_id = 0x17,
909 };
910
911 static const struct adsp_data sm8150_cdsp_resource = {
912         .crash_reason_smem = 601,
913         .firmware_name = "cdsp.mdt",
914         .pas_id = 18,
915         .auto_boot = true,
916         .proxy_pd_names = (char*[]){
917                 "cx",
918                 NULL
919         },
920         .load_state = "cdsp",
921         .ssr_name = "cdsp",
922         .sysmon_name = "cdsp",
923         .ssctl_id = 0x17,
924 };
925
926 static const struct adsp_data sm8250_cdsp_resource = {
927         .crash_reason_smem = 601,
928         .firmware_name = "cdsp.mdt",
929         .pas_id = 18,
930         .auto_boot = true,
931         .proxy_pd_names = (char*[]){
932                 "cx",
933                 NULL
934         },
935         .load_state = "cdsp",
936         .ssr_name = "cdsp",
937         .sysmon_name = "cdsp",
938         .ssctl_id = 0x17,
939 };
940
941 static const struct adsp_data sc8280xp_nsp0_resource = {
942         .crash_reason_smem = 601,
943         .firmware_name = "cdsp.mdt",
944         .pas_id = 18,
945         .auto_boot = true,
946         .proxy_pd_names = (char*[]){
947                 "nsp",
948                 NULL
949         },
950         .ssr_name = "cdsp0",
951         .sysmon_name = "cdsp",
952         .ssctl_id = 0x17,
953 };
954
955 static const struct adsp_data sc8280xp_nsp1_resource = {
956         .crash_reason_smem = 633,
957         .firmware_name = "cdsp.mdt",
958         .pas_id = 30,
959         .auto_boot = true,
960         .proxy_pd_names = (char*[]){
961                 "nsp",
962                 NULL
963         },
964         .ssr_name = "cdsp1",
965         .sysmon_name = "cdsp1",
966         .ssctl_id = 0x20,
967 };
968
969 static const struct adsp_data sm8350_cdsp_resource = {
970         .crash_reason_smem = 601,
971         .firmware_name = "cdsp.mdt",
972         .pas_id = 18,
973         .auto_boot = true,
974         .proxy_pd_names = (char*[]){
975                 "cx",
976                 "mxc",
977                 NULL
978         },
979         .load_state = "cdsp",
980         .ssr_name = "cdsp",
981         .sysmon_name = "cdsp",
982         .ssctl_id = 0x17,
983 };
984
985 static const struct adsp_data mpss_resource_init = {
986         .crash_reason_smem = 421,
987         .firmware_name = "modem.mdt",
988         .pas_id = 4,
989         .minidump_id = 3,
990         .auto_boot = false,
991         .proxy_pd_names = (char*[]){
992                 "cx",
993                 "mss",
994                 NULL
995         },
996         .load_state = "modem",
997         .ssr_name = "mpss",
998         .sysmon_name = "modem",
999         .ssctl_id = 0x12,
1000 };
1001
1002 static const struct adsp_data sc8180x_mpss_resource = {
1003         .crash_reason_smem = 421,
1004         .firmware_name = "modem.mdt",
1005         .pas_id = 4,
1006         .auto_boot = false,
1007         .proxy_pd_names = (char*[]){
1008                 "cx",
1009                 NULL
1010         },
1011         .load_state = "modem",
1012         .ssr_name = "mpss",
1013         .sysmon_name = "modem",
1014         .ssctl_id = 0x12,
1015 };
1016
1017 static const struct adsp_data slpi_resource_init = {
1018                 .crash_reason_smem = 424,
1019                 .firmware_name = "slpi.mdt",
1020                 .pas_id = 12,
1021                 .auto_boot = true,
1022                 .proxy_pd_names = (char*[]){
1023                         "ssc_cx",
1024                         NULL
1025                 },
1026                 .ssr_name = "dsps",
1027                 .sysmon_name = "slpi",
1028                 .ssctl_id = 0x16,
1029 };
1030
1031 static const struct adsp_data sm8150_slpi_resource = {
1032                 .crash_reason_smem = 424,
1033                 .firmware_name = "slpi.mdt",
1034                 .pas_id = 12,
1035                 .auto_boot = true,
1036                 .proxy_pd_names = (char*[]){
1037                         "lcx",
1038                         "lmx",
1039                         NULL
1040                 },
1041                 .load_state = "slpi",
1042                 .ssr_name = "dsps",
1043                 .sysmon_name = "slpi",
1044                 .ssctl_id = 0x16,
1045 };
1046
1047 static const struct adsp_data sm8250_slpi_resource = {
1048         .crash_reason_smem = 424,
1049         .firmware_name = "slpi.mdt",
1050         .pas_id = 12,
1051         .auto_boot = true,
1052         .proxy_pd_names = (char*[]){
1053                 "lcx",
1054                 "lmx",
1055                 NULL
1056         },
1057         .load_state = "slpi",
1058         .ssr_name = "dsps",
1059         .sysmon_name = "slpi",
1060         .ssctl_id = 0x16,
1061 };
1062
1063 static const struct adsp_data sm8350_slpi_resource = {
1064         .crash_reason_smem = 424,
1065         .firmware_name = "slpi.mdt",
1066         .pas_id = 12,
1067         .auto_boot = true,
1068         .proxy_pd_names = (char*[]){
1069                 "lcx",
1070                 "lmx",
1071                 NULL
1072         },
1073         .load_state = "slpi",
1074         .ssr_name = "dsps",
1075         .sysmon_name = "slpi",
1076         .ssctl_id = 0x16,
1077 };
1078
1079 static const struct adsp_data wcss_resource_init = {
1080         .crash_reason_smem = 421,
1081         .firmware_name = "wcnss.mdt",
1082         .pas_id = 6,
1083         .auto_boot = true,
1084         .ssr_name = "mpss",
1085         .sysmon_name = "wcnss",
1086         .ssctl_id = 0x12,
1087 };
1088
1089 static const struct adsp_data sdx55_mpss_resource = {
1090         .crash_reason_smem = 421,
1091         .firmware_name = "modem.mdt",
1092         .pas_id = 4,
1093         .auto_boot = true,
1094         .proxy_pd_names = (char*[]){
1095                 "cx",
1096                 "mss",
1097                 NULL
1098         },
1099         .ssr_name = "mpss",
1100         .sysmon_name = "modem",
1101         .ssctl_id = 0x22,
1102 };
1103
1104 static const struct adsp_data sm8450_mpss_resource = {
1105         .crash_reason_smem = 421,
1106         .firmware_name = "modem.mdt",
1107         .pas_id = 4,
1108         .minidump_id = 3,
1109         .auto_boot = false,
1110         .decrypt_shutdown = true,
1111         .proxy_pd_names = (char*[]){
1112                 "cx",
1113                 "mss",
1114                 NULL
1115         },
1116         .load_state = "modem",
1117         .ssr_name = "mpss",
1118         .sysmon_name = "modem",
1119         .ssctl_id = 0x12,
1120 };
1121
1122 static const struct adsp_data sm8550_adsp_resource = {
1123         .crash_reason_smem = 423,
1124         .firmware_name = "adsp.mdt",
1125         .dtb_firmware_name = "adsp_dtb.mdt",
1126         .pas_id = 1,
1127         .dtb_pas_id = 0x24,
1128         .minidump_id = 5,
1129         .auto_boot = true,
1130         .proxy_pd_names = (char*[]){
1131                 "lcx",
1132                 "lmx",
1133                 NULL
1134         },
1135         .load_state = "adsp",
1136         .ssr_name = "lpass",
1137         .sysmon_name = "adsp",
1138         .ssctl_id = 0x14,
1139 };
1140
1141 static const struct adsp_data sm8550_cdsp_resource = {
1142         .crash_reason_smem = 601,
1143         .firmware_name = "cdsp.mdt",
1144         .dtb_firmware_name = "cdsp_dtb.mdt",
1145         .pas_id = 18,
1146         .dtb_pas_id = 0x25,
1147         .minidump_id = 7,
1148         .auto_boot = true,
1149         .proxy_pd_names = (char*[]){
1150                 "cx",
1151                 "mxc",
1152                 "nsp",
1153                 NULL
1154         },
1155         .load_state = "cdsp",
1156         .ssr_name = "cdsp",
1157         .sysmon_name = "cdsp",
1158         .ssctl_id = 0x17,
1159 };
1160
1161 static const struct adsp_data sm8550_mpss_resource = {
1162         .crash_reason_smem = 421,
1163         .firmware_name = "modem.mdt",
1164         .dtb_firmware_name = "modem_dtb.mdt",
1165         .pas_id = 4,
1166         .dtb_pas_id = 0x26,
1167         .minidump_id = 3,
1168         .auto_boot = false,
1169         .decrypt_shutdown = true,
1170         .proxy_pd_names = (char*[]){
1171                 "cx",
1172                 "mss",
1173                 NULL
1174         },
1175         .load_state = "modem",
1176         .ssr_name = "mpss",
1177         .sysmon_name = "modem",
1178         .ssctl_id = 0x12,
1179         .region_assign_idx = 2,
1180 };
1181
1182 static const struct of_device_id adsp_of_match[] = {
1183         { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
1184         { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource},
1185         { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
1186         { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
1187         { .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
1188         { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
1189         { .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init},
1190         { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
1191         { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
1192         { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
1193         { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
1194         { .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
1195         { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
1196         { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
1197         { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
1198         { .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
1199         { .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
1200         { .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
1201         { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
1202         { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
1203         { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
1204         { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
1205         { .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init},
1206         { .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init},
1207         { .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource},
1208         { .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
1209         { .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
1210         { .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
1211         { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
1212         { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
1213         { .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
1214         { .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource},
1215         { .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
1216         { .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
1217         { .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
1218         { .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
1219         { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
1220         { .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource},
1221         { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
1222         { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
1223         { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
1224         { .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource},
1225         { .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
1226         { .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource},
1227         { .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource},
1228         { .compatible = "qcom,sm8550-mpss-pas", .data = &sm8550_mpss_resource},
1229         { },
1230 };
1231 MODULE_DEVICE_TABLE(of, adsp_of_match);
1232
1233 static struct platform_driver adsp_driver = {
1234         .probe = adsp_probe,
1235         .remove = adsp_remove,
1236         .driver = {
1237                 .name = "qcom_q6v5_pas",
1238                 .of_match_table = adsp_of_match,
1239         },
1240 };
1241
1242 module_platform_driver(adsp_driver);
1243 MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
1244 MODULE_LICENSE("GPL v2");