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