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/firmware.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of_address.h>
16 #include <linux/of_device.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_domain.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/qcom_scm.h>
21 #include <linux/regulator/consumer.h>
22 #include <linux/remoteproc.h>
23 #include <linux/soc/qcom/mdt_loader.h>
24 #include <linux/soc/qcom/smem.h>
25 #include <linux/soc/qcom/smem_state.h>
26 
27 #include "qcom_common.h"
28 #include "qcom_pil_info.h"
29 #include "qcom_q6v5.h"
30 #include "remoteproc_internal.h"
31 
32 struct adsp_data {
33 	int crash_reason_smem;
34 	const char *firmware_name;
35 	int pas_id;
36 	unsigned int minidump_id;
37 	bool has_aggre2_clk;
38 	bool auto_boot;
39 
40 	char **proxy_pd_names;
41 
42 	const char *load_state;
43 	const char *ssr_name;
44 	const char *sysmon_name;
45 	int ssctl_id;
46 };
47 
48 struct qcom_adsp {
49 	struct device *dev;
50 	struct rproc *rproc;
51 
52 	struct qcom_q6v5 q6v5;
53 
54 	struct clk *xo;
55 	struct clk *aggre2_clk;
56 
57 	struct regulator *cx_supply;
58 	struct regulator *px_supply;
59 
60 	struct device *proxy_pds[3];
61 
62 	int proxy_pd_count;
63 
64 	int pas_id;
65 	unsigned int minidump_id;
66 	int crash_reason_smem;
67 	bool has_aggre2_clk;
68 	const char *info_name;
69 
70 	struct completion start_done;
71 	struct completion stop_done;
72 
73 	phys_addr_t mem_phys;
74 	phys_addr_t mem_reloc;
75 	void *mem_region;
76 	size_t mem_size;
77 
78 	struct qcom_rproc_glink glink_subdev;
79 	struct qcom_rproc_subdev smd_subdev;
80 	struct qcom_rproc_ssr ssr_subdev;
81 	struct qcom_sysmon *sysmon;
82 
83 	struct qcom_scm_pas_metadata pas_metadata;
84 };
85 
86 static void adsp_minidump(struct rproc *rproc)
87 {
88 	struct qcom_adsp *adsp = rproc->priv;
89 
90 	qcom_minidump(rproc, adsp->minidump_id);
91 }
92 
93 static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
94 			   size_t pd_count)
95 {
96 	int ret;
97 	int i;
98 
99 	for (i = 0; i < pd_count; i++) {
100 		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
101 		ret = pm_runtime_get_sync(pds[i]);
102 		if (ret < 0) {
103 			pm_runtime_put_noidle(pds[i]);
104 			dev_pm_genpd_set_performance_state(pds[i], 0);
105 			goto unroll_pd_votes;
106 		}
107 	}
108 
109 	return 0;
110 
111 unroll_pd_votes:
112 	for (i--; i >= 0; i--) {
113 		dev_pm_genpd_set_performance_state(pds[i], 0);
114 		pm_runtime_put(pds[i]);
115 	}
116 
117 	return ret;
118 };
119 
120 static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
121 			     size_t pd_count)
122 {
123 	int i;
124 
125 	for (i = 0; i < pd_count; i++) {
126 		dev_pm_genpd_set_performance_state(pds[i], 0);
127 		pm_runtime_put(pds[i]);
128 	}
129 }
130 
131 static int adsp_unprepare(struct rproc *rproc)
132 {
133 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
134 
135 	/*
136 	 * adsp_load() did pass pas_metadata to the SCM driver for storing
137 	 * metadata context. It might have been released already if
138 	 * auth_and_reset() was successful, but in other cases clean it up
139 	 * here.
140 	 */
141 	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
142 
143 	return 0;
144 }
145 
146 static int adsp_load(struct rproc *rproc, const struct firmware *fw)
147 {
148 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
149 	int ret;
150 
151 	ret = qcom_mdt_pas_init(adsp->dev, fw, rproc->firmware, adsp->pas_id,
152 				adsp->mem_phys, &adsp->pas_metadata);
153 	if (ret)
154 		return ret;
155 
156 	ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, adsp->pas_id,
157 				    adsp->mem_region, adsp->mem_phys, adsp->mem_size,
158 				    &adsp->mem_reloc);
159 	if (ret)
160 		return ret;
161 
162 	qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
163 
164 	return 0;
165 }
166 
167 static int adsp_start(struct rproc *rproc)
168 {
169 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
170 	int ret;
171 
172 	ret = qcom_q6v5_prepare(&adsp->q6v5);
173 	if (ret)
174 		return ret;
175 
176 	ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
177 	if (ret < 0)
178 		goto disable_irqs;
179 
180 	ret = clk_prepare_enable(adsp->xo);
181 	if (ret)
182 		goto disable_proxy_pds;
183 
184 	ret = clk_prepare_enable(adsp->aggre2_clk);
185 	if (ret)
186 		goto disable_xo_clk;
187 
188 	ret = regulator_enable(adsp->cx_supply);
189 	if (ret)
190 		goto disable_aggre2_clk;
191 
192 	ret = regulator_enable(adsp->px_supply);
193 	if (ret)
194 		goto disable_cx_supply;
195 
196 	ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
197 	if (ret) {
198 		dev_err(adsp->dev,
199 			"failed to authenticate image and release reset\n");
200 		goto disable_px_supply;
201 	}
202 
203 	ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
204 	if (ret == -ETIMEDOUT) {
205 		dev_err(adsp->dev, "start timed out\n");
206 		qcom_scm_pas_shutdown(adsp->pas_id);
207 		goto disable_px_supply;
208 	}
209 
210 	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
211 
212 	return 0;
213 
214 disable_px_supply:
215 	regulator_disable(adsp->px_supply);
216 disable_cx_supply:
217 	regulator_disable(adsp->cx_supply);
218 disable_aggre2_clk:
219 	clk_disable_unprepare(adsp->aggre2_clk);
220 disable_xo_clk:
221 	clk_disable_unprepare(adsp->xo);
222 disable_proxy_pds:
223 	adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
224 disable_irqs:
225 	qcom_q6v5_unprepare(&adsp->q6v5);
226 
227 	return ret;
228 }
229 
230 static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
231 {
232 	struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
233 
234 	regulator_disable(adsp->px_supply);
235 	regulator_disable(adsp->cx_supply);
236 	clk_disable_unprepare(adsp->aggre2_clk);
237 	clk_disable_unprepare(adsp->xo);
238 	adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
239 }
240 
241 static int adsp_stop(struct rproc *rproc)
242 {
243 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
244 	int handover;
245 	int ret;
246 
247 	ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
248 	if (ret == -ETIMEDOUT)
249 		dev_err(adsp->dev, "timed out on wait\n");
250 
251 	ret = qcom_scm_pas_shutdown(adsp->pas_id);
252 	if (ret)
253 		dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
254 
255 	handover = qcom_q6v5_unprepare(&adsp->q6v5);
256 	if (handover)
257 		qcom_pas_handover(&adsp->q6v5);
258 
259 	return ret;
260 }
261 
262 static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
263 {
264 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
265 	int offset;
266 
267 	offset = da - adsp->mem_reloc;
268 	if (offset < 0 || offset + len > adsp->mem_size)
269 		return NULL;
270 
271 	return adsp->mem_region + offset;
272 }
273 
274 static unsigned long adsp_panic(struct rproc *rproc)
275 {
276 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
277 
278 	return qcom_q6v5_panic(&adsp->q6v5);
279 }
280 
281 static const struct rproc_ops adsp_ops = {
282 	.unprepare = adsp_unprepare,
283 	.start = adsp_start,
284 	.stop = adsp_stop,
285 	.da_to_va = adsp_da_to_va,
286 	.parse_fw = qcom_register_dump_segments,
287 	.load = adsp_load,
288 	.panic = adsp_panic,
289 };
290 
291 static const struct rproc_ops adsp_minidump_ops = {
292 	.unprepare = adsp_unprepare,
293 	.start = adsp_start,
294 	.stop = adsp_stop,
295 	.da_to_va = adsp_da_to_va,
296 	.load = adsp_load,
297 	.panic = adsp_panic,
298 	.coredump = adsp_minidump,
299 };
300 
301 static int adsp_init_clock(struct qcom_adsp *adsp)
302 {
303 	int ret;
304 
305 	adsp->xo = devm_clk_get(adsp->dev, "xo");
306 	if (IS_ERR(adsp->xo)) {
307 		ret = PTR_ERR(adsp->xo);
308 		if (ret != -EPROBE_DEFER)
309 			dev_err(adsp->dev, "failed to get xo clock");
310 		return ret;
311 	}
312 
313 	if (adsp->has_aggre2_clk) {
314 		adsp->aggre2_clk = devm_clk_get(adsp->dev, "aggre2");
315 		if (IS_ERR(adsp->aggre2_clk)) {
316 			ret = PTR_ERR(adsp->aggre2_clk);
317 			if (ret != -EPROBE_DEFER)
318 				dev_err(adsp->dev,
319 					"failed to get aggre2 clock");
320 			return ret;
321 		}
322 	}
323 
324 	return 0;
325 }
326 
327 static int adsp_init_regulator(struct qcom_adsp *adsp)
328 {
329 	adsp->cx_supply = devm_regulator_get(adsp->dev, "cx");
330 	if (IS_ERR(adsp->cx_supply))
331 		return PTR_ERR(adsp->cx_supply);
332 
333 	regulator_set_load(adsp->cx_supply, 100000);
334 
335 	adsp->px_supply = devm_regulator_get(adsp->dev, "px");
336 	return PTR_ERR_OR_ZERO(adsp->px_supply);
337 }
338 
339 static int adsp_pds_attach(struct device *dev, struct device **devs,
340 			   char **pd_names)
341 {
342 	size_t num_pds = 0;
343 	int ret;
344 	int i;
345 
346 	if (!pd_names)
347 		return 0;
348 
349 	/* Handle single power domain */
350 	if (dev->pm_domain) {
351 		devs[0] = dev;
352 		pm_runtime_enable(dev);
353 		return 1;
354 	}
355 
356 	while (pd_names[num_pds])
357 		num_pds++;
358 
359 	for (i = 0; i < num_pds; i++) {
360 		devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
361 		if (IS_ERR_OR_NULL(devs[i])) {
362 			ret = PTR_ERR(devs[i]) ? : -ENODATA;
363 			goto unroll_attach;
364 		}
365 	}
366 
367 	return num_pds;
368 
369 unroll_attach:
370 	for (i--; i >= 0; i--)
371 		dev_pm_domain_detach(devs[i], false);
372 
373 	return ret;
374 };
375 
376 static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
377 			    size_t pd_count)
378 {
379 	struct device *dev = adsp->dev;
380 	int i;
381 
382 	/* Handle single power domain */
383 	if (dev->pm_domain && pd_count) {
384 		pm_runtime_disable(dev);
385 		return;
386 	}
387 
388 	for (i = 0; i < pd_count; i++)
389 		dev_pm_domain_detach(pds[i], false);
390 }
391 
392 static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
393 {
394 	struct device_node *node;
395 	struct resource r;
396 	int ret;
397 
398 	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
399 	if (!node) {
400 		dev_err(adsp->dev, "no memory-region specified\n");
401 		return -EINVAL;
402 	}
403 
404 	ret = of_address_to_resource(node, 0, &r);
405 	if (ret)
406 		return ret;
407 
408 	adsp->mem_phys = adsp->mem_reloc = r.start;
409 	adsp->mem_size = resource_size(&r);
410 	adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
411 	if (!adsp->mem_region) {
412 		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
413 			&r.start, adsp->mem_size);
414 		return -EBUSY;
415 	}
416 
417 	return 0;
418 }
419 
420 static int adsp_probe(struct platform_device *pdev)
421 {
422 	const struct adsp_data *desc;
423 	struct qcom_adsp *adsp;
424 	struct rproc *rproc;
425 	const char *fw_name;
426 	const struct rproc_ops *ops = &adsp_ops;
427 	int ret;
428 
429 	desc = of_device_get_match_data(&pdev->dev);
430 	if (!desc)
431 		return -EINVAL;
432 
433 	if (!qcom_scm_is_available())
434 		return -EPROBE_DEFER;
435 
436 	fw_name = desc->firmware_name;
437 	ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
438 				      &fw_name);
439 	if (ret < 0 && ret != -EINVAL)
440 		return ret;
441 
442 	if (desc->minidump_id)
443 		ops = &adsp_minidump_ops;
444 
445 	rproc = rproc_alloc(&pdev->dev, pdev->name, ops, fw_name, sizeof(*adsp));
446 
447 	if (!rproc) {
448 		dev_err(&pdev->dev, "unable to allocate remoteproc\n");
449 		return -ENOMEM;
450 	}
451 
452 	rproc->auto_boot = desc->auto_boot;
453 	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
454 
455 	adsp = (struct qcom_adsp *)rproc->priv;
456 	adsp->dev = &pdev->dev;
457 	adsp->rproc = rproc;
458 	adsp->minidump_id = desc->minidump_id;
459 	adsp->pas_id = desc->pas_id;
460 	adsp->has_aggre2_clk = desc->has_aggre2_clk;
461 	adsp->info_name = desc->sysmon_name;
462 	platform_set_drvdata(pdev, adsp);
463 
464 	device_wakeup_enable(adsp->dev);
465 
466 	ret = adsp_alloc_memory_region(adsp);
467 	if (ret)
468 		goto free_rproc;
469 
470 	ret = adsp_init_clock(adsp);
471 	if (ret)
472 		goto free_rproc;
473 
474 	ret = adsp_init_regulator(adsp);
475 	if (ret)
476 		goto free_rproc;
477 
478 	ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
479 			      desc->proxy_pd_names);
480 	if (ret < 0)
481 		goto free_rproc;
482 	adsp->proxy_pd_count = ret;
483 
484 	ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state,
485 			     qcom_pas_handover);
486 	if (ret)
487 		goto detach_proxy_pds;
488 
489 	qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
490 	qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
491 	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
492 	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
493 					      desc->sysmon_name,
494 					      desc->ssctl_id);
495 	if (IS_ERR(adsp->sysmon)) {
496 		ret = PTR_ERR(adsp->sysmon);
497 		goto detach_proxy_pds;
498 	}
499 
500 	ret = rproc_add(rproc);
501 	if (ret)
502 		goto detach_proxy_pds;
503 
504 	return 0;
505 
506 detach_proxy_pds:
507 	adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
508 free_rproc:
509 	rproc_free(rproc);
510 
511 	return ret;
512 }
513 
514 static int adsp_remove(struct platform_device *pdev)
515 {
516 	struct qcom_adsp *adsp = platform_get_drvdata(pdev);
517 
518 	rproc_del(adsp->rproc);
519 
520 	qcom_q6v5_deinit(&adsp->q6v5);
521 	qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
522 	qcom_remove_sysmon_subdev(adsp->sysmon);
523 	qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
524 	qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
525 	rproc_free(adsp->rproc);
526 
527 	return 0;
528 }
529 
530 static const struct adsp_data adsp_resource_init = {
531 		.crash_reason_smem = 423,
532 		.firmware_name = "adsp.mdt",
533 		.pas_id = 1,
534 		.has_aggre2_clk = false,
535 		.auto_boot = true,
536 		.ssr_name = "lpass",
537 		.sysmon_name = "adsp",
538 		.ssctl_id = 0x14,
539 };
540 
541 static const struct adsp_data sdm845_adsp_resource_init = {
542 		.crash_reason_smem = 423,
543 		.firmware_name = "adsp.mdt",
544 		.pas_id = 1,
545 		.has_aggre2_clk = false,
546 		.auto_boot = true,
547 		.load_state = "adsp",
548 		.ssr_name = "lpass",
549 		.sysmon_name = "adsp",
550 		.ssctl_id = 0x14,
551 };
552 
553 static const struct adsp_data sm6350_adsp_resource = {
554 	.crash_reason_smem = 423,
555 	.firmware_name = "adsp.mdt",
556 	.pas_id = 1,
557 	.has_aggre2_clk = false,
558 	.auto_boot = true,
559 	.proxy_pd_names = (char*[]){
560 		"lcx",
561 		"lmx",
562 		NULL
563 	},
564 	.load_state = "adsp",
565 	.ssr_name = "lpass",
566 	.sysmon_name = "adsp",
567 	.ssctl_id = 0x14,
568 };
569 
570 static const struct adsp_data sm8150_adsp_resource = {
571 		.crash_reason_smem = 423,
572 		.firmware_name = "adsp.mdt",
573 		.pas_id = 1,
574 		.has_aggre2_clk = false,
575 		.auto_boot = true,
576 		.proxy_pd_names = (char*[]){
577 			"cx",
578 			NULL
579 		},
580 		.load_state = "adsp",
581 		.ssr_name = "lpass",
582 		.sysmon_name = "adsp",
583 		.ssctl_id = 0x14,
584 };
585 
586 static const struct adsp_data sm8250_adsp_resource = {
587 	.crash_reason_smem = 423,
588 	.firmware_name = "adsp.mdt",
589 	.pas_id = 1,
590 	.has_aggre2_clk = false,
591 	.auto_boot = true,
592 	.proxy_pd_names = (char*[]){
593 		"lcx",
594 		"lmx",
595 		NULL
596 	},
597 	.load_state = "adsp",
598 	.ssr_name = "lpass",
599 	.sysmon_name = "adsp",
600 	.ssctl_id = 0x14,
601 };
602 
603 static const struct adsp_data sm8350_adsp_resource = {
604 	.crash_reason_smem = 423,
605 	.firmware_name = "adsp.mdt",
606 	.pas_id = 1,
607 	.has_aggre2_clk = false,
608 	.auto_boot = true,
609 	.proxy_pd_names = (char*[]){
610 		"lcx",
611 		"lmx",
612 		NULL
613 	},
614 	.load_state = "adsp",
615 	.ssr_name = "lpass",
616 	.sysmon_name = "adsp",
617 	.ssctl_id = 0x14,
618 };
619 
620 static const struct adsp_data msm8996_adsp_resource = {
621 		.crash_reason_smem = 423,
622 		.firmware_name = "adsp.mdt",
623 		.pas_id = 1,
624 		.has_aggre2_clk = false,
625 		.auto_boot = true,
626 		.proxy_pd_names = (char*[]){
627 			"cx",
628 			NULL
629 		},
630 		.ssr_name = "lpass",
631 		.sysmon_name = "adsp",
632 		.ssctl_id = 0x14,
633 };
634 
635 static const struct adsp_data cdsp_resource_init = {
636 	.crash_reason_smem = 601,
637 	.firmware_name = "cdsp.mdt",
638 	.pas_id = 18,
639 	.has_aggre2_clk = false,
640 	.auto_boot = true,
641 	.ssr_name = "cdsp",
642 	.sysmon_name = "cdsp",
643 	.ssctl_id = 0x17,
644 };
645 
646 static const struct adsp_data sdm845_cdsp_resource_init = {
647 	.crash_reason_smem = 601,
648 	.firmware_name = "cdsp.mdt",
649 	.pas_id = 18,
650 	.has_aggre2_clk = false,
651 	.auto_boot = true,
652 	.load_state = "cdsp",
653 	.ssr_name = "cdsp",
654 	.sysmon_name = "cdsp",
655 	.ssctl_id = 0x17,
656 };
657 
658 static const struct adsp_data sm6350_cdsp_resource = {
659 	.crash_reason_smem = 601,
660 	.firmware_name = "cdsp.mdt",
661 	.pas_id = 18,
662 	.has_aggre2_clk = false,
663 	.auto_boot = true,
664 	.proxy_pd_names = (char*[]){
665 		"cx",
666 		"mx",
667 		NULL
668 	},
669 	.load_state = "cdsp",
670 	.ssr_name = "cdsp",
671 	.sysmon_name = "cdsp",
672 	.ssctl_id = 0x17,
673 };
674 
675 static const struct adsp_data sm8150_cdsp_resource = {
676 	.crash_reason_smem = 601,
677 	.firmware_name = "cdsp.mdt",
678 	.pas_id = 18,
679 	.has_aggre2_clk = false,
680 	.auto_boot = true,
681 	.proxy_pd_names = (char*[]){
682 		"cx",
683 		NULL
684 	},
685 	.load_state = "cdsp",
686 	.ssr_name = "cdsp",
687 	.sysmon_name = "cdsp",
688 	.ssctl_id = 0x17,
689 };
690 
691 static const struct adsp_data sm8250_cdsp_resource = {
692 	.crash_reason_smem = 601,
693 	.firmware_name = "cdsp.mdt",
694 	.pas_id = 18,
695 	.has_aggre2_clk = false,
696 	.auto_boot = true,
697 	.proxy_pd_names = (char*[]){
698 		"cx",
699 		NULL
700 	},
701 	.load_state = "cdsp",
702 	.ssr_name = "cdsp",
703 	.sysmon_name = "cdsp",
704 	.ssctl_id = 0x17,
705 };
706 
707 static const struct adsp_data sm8350_cdsp_resource = {
708 	.crash_reason_smem = 601,
709 	.firmware_name = "cdsp.mdt",
710 	.pas_id = 18,
711 	.has_aggre2_clk = false,
712 	.auto_boot = true,
713 	.proxy_pd_names = (char*[]){
714 		"cx",
715 		"mxc",
716 		NULL
717 	},
718 	.load_state = "cdsp",
719 	.ssr_name = "cdsp",
720 	.sysmon_name = "cdsp",
721 	.ssctl_id = 0x17,
722 };
723 
724 static const struct adsp_data mpss_resource_init = {
725 	.crash_reason_smem = 421,
726 	.firmware_name = "modem.mdt",
727 	.pas_id = 4,
728 	.minidump_id = 3,
729 	.has_aggre2_clk = false,
730 	.auto_boot = false,
731 	.proxy_pd_names = (char*[]){
732 		"cx",
733 		"mss",
734 		NULL
735 	},
736 	.load_state = "modem",
737 	.ssr_name = "mpss",
738 	.sysmon_name = "modem",
739 	.ssctl_id = 0x12,
740 };
741 
742 static const struct adsp_data sc8180x_mpss_resource = {
743 	.crash_reason_smem = 421,
744 	.firmware_name = "modem.mdt",
745 	.pas_id = 4,
746 	.has_aggre2_clk = false,
747 	.auto_boot = false,
748 	.proxy_pd_names = (char*[]){
749 		"cx",
750 		NULL
751 	},
752 	.load_state = "modem",
753 	.ssr_name = "mpss",
754 	.sysmon_name = "modem",
755 	.ssctl_id = 0x12,
756 };
757 
758 static const struct adsp_data slpi_resource_init = {
759 		.crash_reason_smem = 424,
760 		.firmware_name = "slpi.mdt",
761 		.pas_id = 12,
762 		.has_aggre2_clk = true,
763 		.auto_boot = true,
764 		.proxy_pd_names = (char*[]){
765 			"ssc_cx",
766 			NULL
767 		},
768 		.ssr_name = "dsps",
769 		.sysmon_name = "slpi",
770 		.ssctl_id = 0x16,
771 };
772 
773 static const struct adsp_data sm8150_slpi_resource = {
774 		.crash_reason_smem = 424,
775 		.firmware_name = "slpi.mdt",
776 		.pas_id = 12,
777 		.has_aggre2_clk = false,
778 		.auto_boot = true,
779 		.proxy_pd_names = (char*[]){
780 			"lcx",
781 			"lmx",
782 			NULL
783 		},
784 		.load_state = "slpi",
785 		.ssr_name = "dsps",
786 		.sysmon_name = "slpi",
787 		.ssctl_id = 0x16,
788 };
789 
790 static const struct adsp_data sm8250_slpi_resource = {
791 	.crash_reason_smem = 424,
792 	.firmware_name = "slpi.mdt",
793 	.pas_id = 12,
794 	.has_aggre2_clk = false,
795 	.auto_boot = true,
796 	.proxy_pd_names = (char*[]){
797 		"lcx",
798 		"lmx",
799 		NULL
800 	},
801 	.load_state = "slpi",
802 	.ssr_name = "dsps",
803 	.sysmon_name = "slpi",
804 	.ssctl_id = 0x16,
805 };
806 
807 static const struct adsp_data sm8350_slpi_resource = {
808 	.crash_reason_smem = 424,
809 	.firmware_name = "slpi.mdt",
810 	.pas_id = 12,
811 	.has_aggre2_clk = false,
812 	.auto_boot = true,
813 	.proxy_pd_names = (char*[]){
814 		"lcx",
815 		"lmx",
816 		NULL
817 	},
818 	.load_state = "slpi",
819 	.ssr_name = "dsps",
820 	.sysmon_name = "slpi",
821 	.ssctl_id = 0x16,
822 };
823 
824 static const struct adsp_data wcss_resource_init = {
825 	.crash_reason_smem = 421,
826 	.firmware_name = "wcnss.mdt",
827 	.pas_id = 6,
828 	.auto_boot = true,
829 	.ssr_name = "mpss",
830 	.sysmon_name = "wcnss",
831 	.ssctl_id = 0x12,
832 };
833 
834 static const struct adsp_data sdx55_mpss_resource = {
835 	.crash_reason_smem = 421,
836 	.firmware_name = "modem.mdt",
837 	.pas_id = 4,
838 	.has_aggre2_clk = false,
839 	.auto_boot = true,
840 	.proxy_pd_names = (char*[]){
841 		"cx",
842 		"mss",
843 		NULL
844 	},
845 	.ssr_name = "mpss",
846 	.sysmon_name = "modem",
847 	.ssctl_id = 0x22,
848 };
849 
850 static const struct of_device_id adsp_of_match[] = {
851 	{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
852 	{ .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
853 	{ .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
854 	{ .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
855 	{ .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init},
856 	{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
857 	{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
858 	{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
859 	{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
860 	{ .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
861 	{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
862 	{ .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
863 	{ .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
864 	{ .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
865 	{ .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
866 	{ .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
867 	{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
868 	{ .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
869 	{ .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
870 	{ .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
871 	{ .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
872 	{ .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
873 	{ .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
874 	{ .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource},
875 	{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
876 	{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
877 	{ .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
878 	{ .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
879 	{ .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
880 	{ .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource},
881 	{ .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
882 	{ .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
883 	{ .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
884 	{ .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource},
885 	{ .compatible = "qcom,sm8450-mpss-pas", .data = &mpss_resource_init},
886 	{ },
887 };
888 MODULE_DEVICE_TABLE(of, adsp_of_match);
889 
890 static struct platform_driver adsp_driver = {
891 	.probe = adsp_probe,
892 	.remove = adsp_remove,
893 	.driver = {
894 		.name = "qcom_q6v5_pas",
895 		.of_match_table = adsp_of_match,
896 	},
897 };
898 
899 module_platform_driver(adsp_driver);
900 MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
901 MODULE_LICENSE("GPL v2");
902