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