ca0155f41dac15685499f3ca08c78595ea97d01b
[platform/kernel/linux-starfive.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 void 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
774 static const struct adsp_data adsp_resource_init = {
775                 .crash_reason_smem = 423,
776                 .firmware_name = "adsp.mdt",
777                 .pas_id = 1,
778                 .auto_boot = true,
779                 .ssr_name = "lpass",
780                 .sysmon_name = "adsp",
781                 .ssctl_id = 0x14,
782 };
783
784 static const struct adsp_data sdm845_adsp_resource_init = {
785                 .crash_reason_smem = 423,
786                 .firmware_name = "adsp.mdt",
787                 .pas_id = 1,
788                 .auto_boot = true,
789                 .load_state = "adsp",
790                 .ssr_name = "lpass",
791                 .sysmon_name = "adsp",
792                 .ssctl_id = 0x14,
793 };
794
795 static const struct adsp_data sm6350_adsp_resource = {
796         .crash_reason_smem = 423,
797         .firmware_name = "adsp.mdt",
798         .pas_id = 1,
799         .auto_boot = true,
800         .proxy_pd_names = (char*[]){
801                 "lcx",
802                 "lmx",
803                 NULL
804         },
805         .load_state = "adsp",
806         .ssr_name = "lpass",
807         .sysmon_name = "adsp",
808         .ssctl_id = 0x14,
809 };
810
811 static const struct adsp_data sm8150_adsp_resource = {
812                 .crash_reason_smem = 423,
813                 .firmware_name = "adsp.mdt",
814                 .pas_id = 1,
815                 .auto_boot = true,
816                 .proxy_pd_names = (char*[]){
817                         "cx",
818                         NULL
819                 },
820                 .load_state = "adsp",
821                 .ssr_name = "lpass",
822                 .sysmon_name = "adsp",
823                 .ssctl_id = 0x14,
824 };
825
826 static const struct adsp_data sm8250_adsp_resource = {
827         .crash_reason_smem = 423,
828         .firmware_name = "adsp.mdt",
829         .pas_id = 1,
830         .auto_boot = true,
831         .proxy_pd_names = (char*[]){
832                 "lcx",
833                 "lmx",
834                 NULL
835         },
836         .load_state = "adsp",
837         .ssr_name = "lpass",
838         .sysmon_name = "adsp",
839         .ssctl_id = 0x14,
840 };
841
842 static const struct adsp_data sm8350_adsp_resource = {
843         .crash_reason_smem = 423,
844         .firmware_name = "adsp.mdt",
845         .pas_id = 1,
846         .auto_boot = true,
847         .proxy_pd_names = (char*[]){
848                 "lcx",
849                 "lmx",
850                 NULL
851         },
852         .load_state = "adsp",
853         .ssr_name = "lpass",
854         .sysmon_name = "adsp",
855         .ssctl_id = 0x14,
856 };
857
858 static const struct adsp_data msm8996_adsp_resource = {
859                 .crash_reason_smem = 423,
860                 .firmware_name = "adsp.mdt",
861                 .pas_id = 1,
862                 .auto_boot = true,
863                 .proxy_pd_names = (char*[]){
864                         "cx",
865                         NULL
866                 },
867                 .ssr_name = "lpass",
868                 .sysmon_name = "adsp",
869                 .ssctl_id = 0x14,
870 };
871
872 static const struct adsp_data cdsp_resource_init = {
873         .crash_reason_smem = 601,
874         .firmware_name = "cdsp.mdt",
875         .pas_id = 18,
876         .auto_boot = true,
877         .ssr_name = "cdsp",
878         .sysmon_name = "cdsp",
879         .ssctl_id = 0x17,
880 };
881
882 static const struct adsp_data sdm845_cdsp_resource_init = {
883         .crash_reason_smem = 601,
884         .firmware_name = "cdsp.mdt",
885         .pas_id = 18,
886         .auto_boot = true,
887         .load_state = "cdsp",
888         .ssr_name = "cdsp",
889         .sysmon_name = "cdsp",
890         .ssctl_id = 0x17,
891 };
892
893 static const struct adsp_data sm6350_cdsp_resource = {
894         .crash_reason_smem = 601,
895         .firmware_name = "cdsp.mdt",
896         .pas_id = 18,
897         .auto_boot = true,
898         .proxy_pd_names = (char*[]){
899                 "cx",
900                 "mx",
901                 NULL
902         },
903         .load_state = "cdsp",
904         .ssr_name = "cdsp",
905         .sysmon_name = "cdsp",
906         .ssctl_id = 0x17,
907 };
908
909 static const struct adsp_data sm8150_cdsp_resource = {
910         .crash_reason_smem = 601,
911         .firmware_name = "cdsp.mdt",
912         .pas_id = 18,
913         .auto_boot = true,
914         .proxy_pd_names = (char*[]){
915                 "cx",
916                 NULL
917         },
918         .load_state = "cdsp",
919         .ssr_name = "cdsp",
920         .sysmon_name = "cdsp",
921         .ssctl_id = 0x17,
922 };
923
924 static const struct adsp_data sm8250_cdsp_resource = {
925         .crash_reason_smem = 601,
926         .firmware_name = "cdsp.mdt",
927         .pas_id = 18,
928         .auto_boot = true,
929         .proxy_pd_names = (char*[]){
930                 "cx",
931                 NULL
932         },
933         .load_state = "cdsp",
934         .ssr_name = "cdsp",
935         .sysmon_name = "cdsp",
936         .ssctl_id = 0x17,
937 };
938
939 static const struct adsp_data sc8280xp_nsp0_resource = {
940         .crash_reason_smem = 601,
941         .firmware_name = "cdsp.mdt",
942         .pas_id = 18,
943         .auto_boot = true,
944         .proxy_pd_names = (char*[]){
945                 "nsp",
946                 NULL
947         },
948         .ssr_name = "cdsp0",
949         .sysmon_name = "cdsp",
950         .ssctl_id = 0x17,
951 };
952
953 static const struct adsp_data sc8280xp_nsp1_resource = {
954         .crash_reason_smem = 633,
955         .firmware_name = "cdsp.mdt",
956         .pas_id = 30,
957         .auto_boot = true,
958         .proxy_pd_names = (char*[]){
959                 "nsp",
960                 NULL
961         },
962         .ssr_name = "cdsp1",
963         .sysmon_name = "cdsp1",
964         .ssctl_id = 0x20,
965 };
966
967 static const struct adsp_data sm8350_cdsp_resource = {
968         .crash_reason_smem = 601,
969         .firmware_name = "cdsp.mdt",
970         .pas_id = 18,
971         .auto_boot = true,
972         .proxy_pd_names = (char*[]){
973                 "cx",
974                 "mxc",
975                 NULL
976         },
977         .load_state = "cdsp",
978         .ssr_name = "cdsp",
979         .sysmon_name = "cdsp",
980         .ssctl_id = 0x17,
981 };
982
983 static const struct adsp_data mpss_resource_init = {
984         .crash_reason_smem = 421,
985         .firmware_name = "modem.mdt",
986         .pas_id = 4,
987         .minidump_id = 3,
988         .auto_boot = false,
989         .proxy_pd_names = (char*[]){
990                 "cx",
991                 "mss",
992                 NULL
993         },
994         .load_state = "modem",
995         .ssr_name = "mpss",
996         .sysmon_name = "modem",
997         .ssctl_id = 0x12,
998 };
999
1000 static const struct adsp_data sc8180x_mpss_resource = {
1001         .crash_reason_smem = 421,
1002         .firmware_name = "modem.mdt",
1003         .pas_id = 4,
1004         .auto_boot = false,
1005         .proxy_pd_names = (char*[]){
1006                 "cx",
1007                 NULL
1008         },
1009         .load_state = "modem",
1010         .ssr_name = "mpss",
1011         .sysmon_name = "modem",
1012         .ssctl_id = 0x12,
1013 };
1014
1015 static const struct adsp_data slpi_resource_init = {
1016                 .crash_reason_smem = 424,
1017                 .firmware_name = "slpi.mdt",
1018                 .pas_id = 12,
1019                 .auto_boot = true,
1020                 .proxy_pd_names = (char*[]){
1021                         "ssc_cx",
1022                         NULL
1023                 },
1024                 .ssr_name = "dsps",
1025                 .sysmon_name = "slpi",
1026                 .ssctl_id = 0x16,
1027 };
1028
1029 static const struct adsp_data sm8150_slpi_resource = {
1030                 .crash_reason_smem = 424,
1031                 .firmware_name = "slpi.mdt",
1032                 .pas_id = 12,
1033                 .auto_boot = true,
1034                 .proxy_pd_names = (char*[]){
1035                         "lcx",
1036                         "lmx",
1037                         NULL
1038                 },
1039                 .load_state = "slpi",
1040                 .ssr_name = "dsps",
1041                 .sysmon_name = "slpi",
1042                 .ssctl_id = 0x16,
1043 };
1044
1045 static const struct adsp_data sm8250_slpi_resource = {
1046         .crash_reason_smem = 424,
1047         .firmware_name = "slpi.mdt",
1048         .pas_id = 12,
1049         .auto_boot = true,
1050         .proxy_pd_names = (char*[]){
1051                 "lcx",
1052                 "lmx",
1053                 NULL
1054         },
1055         .load_state = "slpi",
1056         .ssr_name = "dsps",
1057         .sysmon_name = "slpi",
1058         .ssctl_id = 0x16,
1059 };
1060
1061 static const struct adsp_data sm8350_slpi_resource = {
1062         .crash_reason_smem = 424,
1063         .firmware_name = "slpi.mdt",
1064         .pas_id = 12,
1065         .auto_boot = true,
1066         .proxy_pd_names = (char*[]){
1067                 "lcx",
1068                 "lmx",
1069                 NULL
1070         },
1071         .load_state = "slpi",
1072         .ssr_name = "dsps",
1073         .sysmon_name = "slpi",
1074         .ssctl_id = 0x16,
1075 };
1076
1077 static const struct adsp_data wcss_resource_init = {
1078         .crash_reason_smem = 421,
1079         .firmware_name = "wcnss.mdt",
1080         .pas_id = 6,
1081         .auto_boot = true,
1082         .ssr_name = "mpss",
1083         .sysmon_name = "wcnss",
1084         .ssctl_id = 0x12,
1085 };
1086
1087 static const struct adsp_data sdx55_mpss_resource = {
1088         .crash_reason_smem = 421,
1089         .firmware_name = "modem.mdt",
1090         .pas_id = 4,
1091         .auto_boot = true,
1092         .proxy_pd_names = (char*[]){
1093                 "cx",
1094                 "mss",
1095                 NULL
1096         },
1097         .ssr_name = "mpss",
1098         .sysmon_name = "modem",
1099         .ssctl_id = 0x22,
1100 };
1101
1102 static const struct adsp_data sm8450_mpss_resource = {
1103         .crash_reason_smem = 421,
1104         .firmware_name = "modem.mdt",
1105         .pas_id = 4,
1106         .minidump_id = 3,
1107         .auto_boot = false,
1108         .decrypt_shutdown = true,
1109         .proxy_pd_names = (char*[]){
1110                 "cx",
1111                 "mss",
1112                 NULL
1113         },
1114         .load_state = "modem",
1115         .ssr_name = "mpss",
1116         .sysmon_name = "modem",
1117         .ssctl_id = 0x12,
1118 };
1119
1120 static const struct adsp_data sm8550_adsp_resource = {
1121         .crash_reason_smem = 423,
1122         .firmware_name = "adsp.mdt",
1123         .dtb_firmware_name = "adsp_dtb.mdt",
1124         .pas_id = 1,
1125         .dtb_pas_id = 0x24,
1126         .minidump_id = 5,
1127         .auto_boot = true,
1128         .proxy_pd_names = (char*[]){
1129                 "lcx",
1130                 "lmx",
1131                 NULL
1132         },
1133         .load_state = "adsp",
1134         .ssr_name = "lpass",
1135         .sysmon_name = "adsp",
1136         .ssctl_id = 0x14,
1137 };
1138
1139 static const struct adsp_data sm8550_cdsp_resource = {
1140         .crash_reason_smem = 601,
1141         .firmware_name = "cdsp.mdt",
1142         .dtb_firmware_name = "cdsp_dtb.mdt",
1143         .pas_id = 18,
1144         .dtb_pas_id = 0x25,
1145         .minidump_id = 7,
1146         .auto_boot = true,
1147         .proxy_pd_names = (char*[]){
1148                 "cx",
1149                 "mxc",
1150                 "nsp",
1151                 NULL
1152         },
1153         .load_state = "cdsp",
1154         .ssr_name = "cdsp",
1155         .sysmon_name = "cdsp",
1156         .ssctl_id = 0x17,
1157 };
1158
1159 static const struct adsp_data sm8550_mpss_resource = {
1160         .crash_reason_smem = 421,
1161         .firmware_name = "modem.mdt",
1162         .dtb_firmware_name = "modem_dtb.mdt",
1163         .pas_id = 4,
1164         .dtb_pas_id = 0x26,
1165         .minidump_id = 3,
1166         .auto_boot = false,
1167         .decrypt_shutdown = true,
1168         .proxy_pd_names = (char*[]){
1169                 "cx",
1170                 "mss",
1171                 NULL
1172         },
1173         .load_state = "modem",
1174         .ssr_name = "mpss",
1175         .sysmon_name = "modem",
1176         .ssctl_id = 0x12,
1177         .region_assign_idx = 2,
1178 };
1179
1180 static const struct of_device_id adsp_of_match[] = {
1181         { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
1182         { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource},
1183         { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
1184         { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
1185         { .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
1186         { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
1187         { .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init},
1188         { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
1189         { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
1190         { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
1191         { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
1192         { .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
1193         { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
1194         { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
1195         { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
1196         { .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
1197         { .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
1198         { .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
1199         { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
1200         { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
1201         { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
1202         { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
1203         { .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init},
1204         { .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init},
1205         { .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource},
1206         { .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
1207         { .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
1208         { .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
1209         { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
1210         { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
1211         { .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
1212         { .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource},
1213         { .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
1214         { .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
1215         { .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
1216         { .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
1217         { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
1218         { .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource},
1219         { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
1220         { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
1221         { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
1222         { .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource},
1223         { .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
1224         { .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource},
1225         { .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource},
1226         { .compatible = "qcom,sm8550-mpss-pas", .data = &sm8550_mpss_resource},
1227         { },
1228 };
1229 MODULE_DEVICE_TABLE(of, adsp_of_match);
1230
1231 static struct platform_driver adsp_driver = {
1232         .probe = adsp_probe,
1233         .remove_new = adsp_remove,
1234         .driver = {
1235                 .name = "qcom_q6v5_pas",
1236                 .of_match_table = adsp_of_match,
1237         },
1238 };
1239
1240 module_platform_driver(adsp_driver);
1241 MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
1242 MODULE_LICENSE("GPL v2");