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