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 sc8280xp_nsp0_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 		"nsp",
715 		NULL
716 	},
717 	.ssr_name = "cdsp0",
718 	.sysmon_name = "cdsp",
719 	.ssctl_id = 0x17,
720 };
721 
722 static const struct adsp_data sc8280xp_nsp1_resource = {
723 	.crash_reason_smem = 633,
724 	.firmware_name = "cdsp.mdt",
725 	.pas_id = 30,
726 	.has_aggre2_clk = false,
727 	.auto_boot = true,
728 	.proxy_pd_names = (char*[]){
729 		"nsp",
730 		NULL
731 	},
732 	.ssr_name = "cdsp1",
733 	.sysmon_name = "cdsp1",
734 	.ssctl_id = 0x20,
735 };
736 
737 static const struct adsp_data sm8350_cdsp_resource = {
738 	.crash_reason_smem = 601,
739 	.firmware_name = "cdsp.mdt",
740 	.pas_id = 18,
741 	.has_aggre2_clk = false,
742 	.auto_boot = true,
743 	.proxy_pd_names = (char*[]){
744 		"cx",
745 		"mxc",
746 		NULL
747 	},
748 	.load_state = "cdsp",
749 	.ssr_name = "cdsp",
750 	.sysmon_name = "cdsp",
751 	.ssctl_id = 0x17,
752 };
753 
754 static const struct adsp_data mpss_resource_init = {
755 	.crash_reason_smem = 421,
756 	.firmware_name = "modem.mdt",
757 	.pas_id = 4,
758 	.minidump_id = 3,
759 	.has_aggre2_clk = false,
760 	.auto_boot = false,
761 	.proxy_pd_names = (char*[]){
762 		"cx",
763 		"mss",
764 		NULL
765 	},
766 	.load_state = "modem",
767 	.ssr_name = "mpss",
768 	.sysmon_name = "modem",
769 	.ssctl_id = 0x12,
770 };
771 
772 static const struct adsp_data sc8180x_mpss_resource = {
773 	.crash_reason_smem = 421,
774 	.firmware_name = "modem.mdt",
775 	.pas_id = 4,
776 	.has_aggre2_clk = false,
777 	.auto_boot = false,
778 	.proxy_pd_names = (char*[]){
779 		"cx",
780 		NULL
781 	},
782 	.load_state = "modem",
783 	.ssr_name = "mpss",
784 	.sysmon_name = "modem",
785 	.ssctl_id = 0x12,
786 };
787 
788 static const struct adsp_data slpi_resource_init = {
789 		.crash_reason_smem = 424,
790 		.firmware_name = "slpi.mdt",
791 		.pas_id = 12,
792 		.has_aggre2_clk = true,
793 		.auto_boot = true,
794 		.proxy_pd_names = (char*[]){
795 			"ssc_cx",
796 			NULL
797 		},
798 		.ssr_name = "dsps",
799 		.sysmon_name = "slpi",
800 		.ssctl_id = 0x16,
801 };
802 
803 static const struct adsp_data sm8150_slpi_resource = {
804 		.crash_reason_smem = 424,
805 		.firmware_name = "slpi.mdt",
806 		.pas_id = 12,
807 		.has_aggre2_clk = false,
808 		.auto_boot = true,
809 		.proxy_pd_names = (char*[]){
810 			"lcx",
811 			"lmx",
812 			NULL
813 		},
814 		.load_state = "slpi",
815 		.ssr_name = "dsps",
816 		.sysmon_name = "slpi",
817 		.ssctl_id = 0x16,
818 };
819 
820 static const struct adsp_data sm8250_slpi_resource = {
821 	.crash_reason_smem = 424,
822 	.firmware_name = "slpi.mdt",
823 	.pas_id = 12,
824 	.has_aggre2_clk = false,
825 	.auto_boot = true,
826 	.proxy_pd_names = (char*[]){
827 		"lcx",
828 		"lmx",
829 		NULL
830 	},
831 	.load_state = "slpi",
832 	.ssr_name = "dsps",
833 	.sysmon_name = "slpi",
834 	.ssctl_id = 0x16,
835 };
836 
837 static const struct adsp_data sm8350_slpi_resource = {
838 	.crash_reason_smem = 424,
839 	.firmware_name = "slpi.mdt",
840 	.pas_id = 12,
841 	.has_aggre2_clk = false,
842 	.auto_boot = true,
843 	.proxy_pd_names = (char*[]){
844 		"lcx",
845 		"lmx",
846 		NULL
847 	},
848 	.load_state = "slpi",
849 	.ssr_name = "dsps",
850 	.sysmon_name = "slpi",
851 	.ssctl_id = 0x16,
852 };
853 
854 static const struct adsp_data wcss_resource_init = {
855 	.crash_reason_smem = 421,
856 	.firmware_name = "wcnss.mdt",
857 	.pas_id = 6,
858 	.auto_boot = true,
859 	.ssr_name = "mpss",
860 	.sysmon_name = "wcnss",
861 	.ssctl_id = 0x12,
862 };
863 
864 static const struct adsp_data sdx55_mpss_resource = {
865 	.crash_reason_smem = 421,
866 	.firmware_name = "modem.mdt",
867 	.pas_id = 4,
868 	.has_aggre2_clk = false,
869 	.auto_boot = true,
870 	.proxy_pd_names = (char*[]){
871 		"cx",
872 		"mss",
873 		NULL
874 	},
875 	.ssr_name = "mpss",
876 	.sysmon_name = "modem",
877 	.ssctl_id = 0x22,
878 };
879 
880 static const struct of_device_id adsp_of_match[] = {
881 	{ .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
882 	{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
883 	{ .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
884 	{ .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
885 	{ .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
886 	{ .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init},
887 	{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
888 	{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
889 	{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
890 	{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
891 	{ .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
892 	{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
893 	{ .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
894 	{ .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
895 	{ .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
896 	{ .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
897 	{ .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
898 	{ .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
899 	{ .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
900 	{ .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
901 	{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
902 	{ .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
903 	{ .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
904 	{ .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
905 	{ .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
906 	{ .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
907 	{ .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
908 	{ .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource},
909 	{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
910 	{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
911 	{ .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
912 	{ .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
913 	{ .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
914 	{ .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource},
915 	{ .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
916 	{ .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
917 	{ .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
918 	{ .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource},
919 	{ .compatible = "qcom,sm8450-mpss-pas", .data = &mpss_resource_init},
920 	{ },
921 };
922 MODULE_DEVICE_TABLE(of, adsp_of_match);
923 
924 static struct platform_driver adsp_driver = {
925 	.probe = adsp_probe,
926 	.remove = adsp_remove,
927 	.driver = {
928 		.name = "qcom_q6v5_pas",
929 		.of_match_table = adsp_of_match,
930 	},
931 };
932 
933 module_platform_driver(adsp_driver);
934 MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
935 MODULE_LICENSE("GPL v2");
936