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