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, adsp->minidump_id, 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(pds[i], INT_MAX); 145 ret = pm_runtime_get_sync(pds[i]); 146 if (ret < 0) { 147 pm_runtime_put_noidle(pds[i]); 148 dev_pm_genpd_set_performance_state(pds[i], 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(pds[i], 0); 158 pm_runtime_put(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(pds[i], 0); 171 pm_runtime_put(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(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(&adsp->pas_metadata); 199 if (adsp->dtb_pas_id) 200 qcom_scm_pas_metadata_release(&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(&adsp->dtb_firmware, adsp->dtb_firmware_name, 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(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name, 222 adsp->dtb_pas_id, adsp->dtb_mem_phys, 223 &adsp->dtb_pas_metadata); 224 if (ret) 225 goto release_dtb_firmware; 226 227 ret = qcom_mdt_load_no_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name, 228 adsp->dtb_pas_id, adsp->dtb_mem_region, 229 adsp->dtb_mem_phys, adsp->dtb_mem_size, 230 &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(&adsp->dtb_pas_metadata); 239 240 release_dtb_firmware: 241 release_firmware(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(&adsp->q6v5); 252 if (ret) 253 return ret; 254 255 ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); 256 if (ret < 0) 257 goto disable_irqs; 258 259 ret = clk_prepare_enable(adsp->xo); 260 if (ret) 261 goto disable_proxy_pds; 262 263 ret = clk_prepare_enable(adsp->aggre2_clk); 264 if (ret) 265 goto disable_xo_clk; 266 267 if (adsp->cx_supply) { 268 ret = regulator_enable(adsp->cx_supply); 269 if (ret) 270 goto disable_aggre2_clk; 271 } 272 273 if (adsp->px_supply) { 274 ret = regulator_enable(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(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(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id, 289 adsp->mem_phys, &adsp->pas_metadata); 290 if (ret) 291 goto disable_px_supply; 292 293 ret = qcom_mdt_load_no_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id, 294 adsp->mem_region, adsp->mem_phys, adsp->mem_size, 295 &adsp->mem_reloc); 296 if (ret) 297 goto release_pas_metadata; 298 299 qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); 300 301 ret = qcom_scm_pas_auth_and_reset(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(&adsp->q6v5, msecs_to_jiffies(5000)); 309 if (ret == -ETIMEDOUT) { 310 dev_err(adsp->dev, "start timed out\n"); 311 qcom_scm_pas_shutdown(adsp->pas_id); 312 goto release_pas_metadata; 313 } 314 315 qcom_scm_pas_metadata_release(&adsp->pas_metadata); 316 if (adsp->dtb_pas_id) 317 qcom_scm_pas_metadata_release(&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(&adsp->pas_metadata); 326 if (adsp->dtb_pas_id) 327 qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); 328 disable_px_supply: 329 if (adsp->px_supply) 330 regulator_disable(adsp->px_supply); 331 disable_cx_supply: 332 if (adsp->cx_supply) 333 regulator_disable(adsp->cx_supply); 334 disable_aggre2_clk: 335 clk_disable_unprepare(adsp->aggre2_clk); 336 disable_xo_clk: 337 clk_disable_unprepare(adsp->xo); 338 disable_proxy_pds: 339 adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); 340 disable_irqs: 341 qcom_q6v5_unprepare(&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(adsp->px_supply); 355 if (adsp->cx_supply) 356 regulator_disable(adsp->cx_supply); 357 clk_disable_unprepare(adsp->aggre2_clk); 358 clk_disable_unprepare(adsp->xo); 359 adsp_pds_disable(adsp, adsp->proxy_pds, 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(&adsp->q6v5, adsp->sysmon); 369 if (ret == -ETIMEDOUT) 370 dev_err(adsp->dev, "timed out on wait\n"); 371 372 ret = qcom_scm_pas_shutdown(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(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(&adsp->q6v5); 386 if (handover) 387 qcom_pas_handover(&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(&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(adsp->dev, "xo"); 440 if (IS_ERR(adsp->xo)) { 441 ret = PTR_ERR(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(adsp->dev, "aggre2"); 448 if (IS_ERR(adsp->aggre2_clk)) { 449 ret = PTR_ERR(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(adsp->dev, "cx"); 462 if (IS_ERR(adsp->cx_supply)) { 463 if (PTR_ERR(adsp->cx_supply) == -ENODEV) 464 adsp->cx_supply = NULL; 465 else 466 return PTR_ERR(adsp->cx_supply); 467 } 468 469 if (adsp->cx_supply) 470 regulator_set_load(adsp->cx_supply, 100000); 471 472 adsp->px_supply = devm_regulator_get_optional(adsp->dev, "px"); 473 if (IS_ERR(adsp->px_supply)) { 474 if (PTR_ERR(adsp->px_supply) == -ENODEV) 475 adsp->px_supply = NULL; 476 else 477 return PTR_ERR(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, pd_names[i]); 505 if (IS_ERR_OR_NULL(devs[i])) { 506 ret = PTR_ERR(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(devs[i], 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(pds[i], 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(adsp->dev->of_node, "memory-region", 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(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(adsp->dev, adsp->mem_phys, 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(adsp->dev->of_node, "memory-region", 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(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(adsp->dev, adsp->dtb_mem_phys, 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(adsp->dev->of_node, "memory-region", adsp->region_assign_idx); 602 if (node) 603 rmem = of_reserved_mem_lookup(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(adsp->region_assign_phys, 618 adsp->region_assign_size, 619 &adsp->region_assign_perms, 620 &perm, 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(adsp->region_assign_phys, 641 adsp->region_assign_size, 642 &adsp->region_assign_perms, 643 &perm, 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(&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(pdev->dev.of_node, "firmware-name", 666 &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(pdev->dev.of_node, "firmware-name", 1, 673 &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(&pdev->dev, pdev->name, ops, fw_name, 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, adsp); 704 705 ret = device_init_wakeup(adsp->dev, 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(&pdev->dev, adsp->proxy_pds, 726 desc->proxy_pd_names); 727 if (ret < 0) 728 goto free_rproc; 729 adsp->proxy_pd_count = ret; 730 731 ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state, 732 qcom_pas_handover); 733 if (ret) 734 goto detach_proxy_pds; 735 736 qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name); 737 qcom_add_smd_subdev(rproc, &adsp->smd_subdev); 738 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 739 desc->sysmon_name, 740 desc->ssctl_id); 741 if (IS_ERR(adsp->sysmon)) { 742 ret = PTR_ERR(adsp->sysmon); 743 goto detach_proxy_pds; 744 } 745 746 qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, 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, adsp->proxy_pds, adsp->proxy_pd_count); 755 free_rproc: 756 device_init_wakeup(adsp->dev, 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(adsp->rproc); 767 768 qcom_q6v5_deinit(&adsp->q6v5); 769 adsp_unassign_memory_region(adsp); 770 qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); 771 qcom_remove_sysmon_subdev(adsp->sysmon); 772 qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); 773 qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); 774 adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); 775 device_init_wakeup(adsp->dev, false); 776 rproc_free(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 sa8775p_adsp_resource = { 790 .crash_reason_smem = 423, 791 .firmware_name = "adsp.mbn", 792 .pas_id = 1, 793 .minidump_id = 5, 794 .auto_boot = true, 795 .proxy_pd_names = (char*[]){ 796 "lcx", 797 "lmx", 798 NULL 799 }, 800 .load_state = "adsp", 801 .ssr_name = "lpass", 802 .sysmon_name = "adsp", 803 .ssctl_id = 0x14, 804 }; 805 806 static const struct adsp_data sdm845_adsp_resource_init = { 807 .crash_reason_smem = 423, 808 .firmware_name = "adsp.mdt", 809 .pas_id = 1, 810 .auto_boot = true, 811 .load_state = "adsp", 812 .ssr_name = "lpass", 813 .sysmon_name = "adsp", 814 .ssctl_id = 0x14, 815 }; 816 817 static const struct adsp_data sm6350_adsp_resource = { 818 .crash_reason_smem = 423, 819 .firmware_name = "adsp.mdt", 820 .pas_id = 1, 821 .auto_boot = true, 822 .proxy_pd_names = (char*[]){ 823 "lcx", 824 "lmx", 825 NULL 826 }, 827 .load_state = "adsp", 828 .ssr_name = "lpass", 829 .sysmon_name = "adsp", 830 .ssctl_id = 0x14, 831 }; 832 833 static const struct adsp_data sm8150_adsp_resource = { 834 .crash_reason_smem = 423, 835 .firmware_name = "adsp.mdt", 836 .pas_id = 1, 837 .auto_boot = true, 838 .proxy_pd_names = (char*[]){ 839 "cx", 840 NULL 841 }, 842 .load_state = "adsp", 843 .ssr_name = "lpass", 844 .sysmon_name = "adsp", 845 .ssctl_id = 0x14, 846 }; 847 848 static const struct adsp_data sm8250_adsp_resource = { 849 .crash_reason_smem = 423, 850 .firmware_name = "adsp.mdt", 851 .pas_id = 1, 852 .minidump_id = 5, 853 .auto_boot = true, 854 .proxy_pd_names = (char*[]){ 855 "lcx", 856 "lmx", 857 NULL 858 }, 859 .load_state = "adsp", 860 .ssr_name = "lpass", 861 .sysmon_name = "adsp", 862 .ssctl_id = 0x14, 863 }; 864 865 static const struct adsp_data sm8350_adsp_resource = { 866 .crash_reason_smem = 423, 867 .firmware_name = "adsp.mdt", 868 .pas_id = 1, 869 .auto_boot = true, 870 .proxy_pd_names = (char*[]){ 871 "lcx", 872 "lmx", 873 NULL 874 }, 875 .load_state = "adsp", 876 .ssr_name = "lpass", 877 .sysmon_name = "adsp", 878 .ssctl_id = 0x14, 879 }; 880 881 static const struct adsp_data msm8996_adsp_resource = { 882 .crash_reason_smem = 423, 883 .firmware_name = "adsp.mdt", 884 .pas_id = 1, 885 .auto_boot = true, 886 .proxy_pd_names = (char*[]){ 887 "cx", 888 NULL 889 }, 890 .ssr_name = "lpass", 891 .sysmon_name = "adsp", 892 .ssctl_id = 0x14, 893 }; 894 895 static const struct adsp_data cdsp_resource_init = { 896 .crash_reason_smem = 601, 897 .firmware_name = "cdsp.mdt", 898 .pas_id = 18, 899 .auto_boot = true, 900 .ssr_name = "cdsp", 901 .sysmon_name = "cdsp", 902 .ssctl_id = 0x17, 903 }; 904 905 static const struct adsp_data sa8775p_cdsp0_resource = { 906 .crash_reason_smem = 601, 907 .firmware_name = "cdsp0.mbn", 908 .pas_id = 18, 909 .minidump_id = 7, 910 .auto_boot = true, 911 .proxy_pd_names = (char*[]){ 912 "cx", 913 "mxc", 914 "nsp", 915 NULL 916 }, 917 .load_state = "cdsp", 918 .ssr_name = "cdsp", 919 .sysmon_name = "cdsp", 920 .ssctl_id = 0x17, 921 }; 922 923 static const struct adsp_data sa8775p_cdsp1_resource = { 924 .crash_reason_smem = 633, 925 .firmware_name = "cdsp1.mbn", 926 .pas_id = 30, 927 .minidump_id = 20, 928 .auto_boot = true, 929 .proxy_pd_names = (char*[]){ 930 "cx", 931 "mxc", 932 "nsp", 933 NULL 934 }, 935 .load_state = "nsp", 936 .ssr_name = "cdsp1", 937 .sysmon_name = "cdsp1", 938 .ssctl_id = 0x20, 939 }; 940 941 static const struct adsp_data sdm845_cdsp_resource_init = { 942 .crash_reason_smem = 601, 943 .firmware_name = "cdsp.mdt", 944 .pas_id = 18, 945 .auto_boot = true, 946 .load_state = "cdsp", 947 .ssr_name = "cdsp", 948 .sysmon_name = "cdsp", 949 .ssctl_id = 0x17, 950 }; 951 952 static const struct adsp_data sm6350_cdsp_resource = { 953 .crash_reason_smem = 601, 954 .firmware_name = "cdsp.mdt", 955 .pas_id = 18, 956 .auto_boot = true, 957 .proxy_pd_names = (char*[]){ 958 "cx", 959 "mx", 960 NULL 961 }, 962 .load_state = "cdsp", 963 .ssr_name = "cdsp", 964 .sysmon_name = "cdsp", 965 .ssctl_id = 0x17, 966 }; 967 968 static const struct adsp_data sm8150_cdsp_resource = { 969 .crash_reason_smem = 601, 970 .firmware_name = "cdsp.mdt", 971 .pas_id = 18, 972 .auto_boot = true, 973 .proxy_pd_names = (char*[]){ 974 "cx", 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 sm8250_cdsp_resource = { 984 .crash_reason_smem = 601, 985 .firmware_name = "cdsp.mdt", 986 .pas_id = 18, 987 .auto_boot = true, 988 .proxy_pd_names = (char*[]){ 989 "cx", 990 NULL 991 }, 992 .load_state = "cdsp", 993 .ssr_name = "cdsp", 994 .sysmon_name = "cdsp", 995 .ssctl_id = 0x17, 996 }; 997 998 static const struct adsp_data sc8280xp_nsp0_resource = { 999 .crash_reason_smem = 601, 1000 .firmware_name = "cdsp.mdt", 1001 .pas_id = 18, 1002 .auto_boot = true, 1003 .proxy_pd_names = (char*[]){ 1004 "nsp", 1005 NULL 1006 }, 1007 .ssr_name = "cdsp0", 1008 .sysmon_name = "cdsp", 1009 .ssctl_id = 0x17, 1010 }; 1011 1012 static const struct adsp_data sc8280xp_nsp1_resource = { 1013 .crash_reason_smem = 633, 1014 .firmware_name = "cdsp.mdt", 1015 .pas_id = 30, 1016 .auto_boot = true, 1017 .proxy_pd_names = (char*[]){ 1018 "nsp", 1019 NULL 1020 }, 1021 .ssr_name = "cdsp1", 1022 .sysmon_name = "cdsp1", 1023 .ssctl_id = 0x20, 1024 }; 1025 1026 static const struct adsp_data sm8350_cdsp_resource = { 1027 .crash_reason_smem = 601, 1028 .firmware_name = "cdsp.mdt", 1029 .pas_id = 18, 1030 .minidump_id = 7, 1031 .auto_boot = true, 1032 .proxy_pd_names = (char*[]){ 1033 "cx", 1034 "mxc", 1035 NULL 1036 }, 1037 .load_state = "cdsp", 1038 .ssr_name = "cdsp", 1039 .sysmon_name = "cdsp", 1040 .ssctl_id = 0x17, 1041 }; 1042 1043 static const struct adsp_data sa8775p_gpdsp0_resource = { 1044 .crash_reason_smem = 640, 1045 .firmware_name = "gpdsp0.mbn", 1046 .pas_id = 39, 1047 .minidump_id = 21, 1048 .auto_boot = true, 1049 .proxy_pd_names = (char*[]){ 1050 "cx", 1051 "mxc", 1052 NULL 1053 }, 1054 .load_state = "gpdsp0", 1055 .ssr_name = "gpdsp0", 1056 .sysmon_name = "gpdsp0", 1057 .ssctl_id = 0x21, 1058 }; 1059 1060 static const struct adsp_data sa8775p_gpdsp1_resource = { 1061 .crash_reason_smem = 641, 1062 .firmware_name = "gpdsp1.mbn", 1063 .pas_id = 40, 1064 .minidump_id = 22, 1065 .auto_boot = true, 1066 .proxy_pd_names = (char*[]){ 1067 "cx", 1068 "mxc", 1069 NULL 1070 }, 1071 .load_state = "gpdsp1", 1072 .ssr_name = "gpdsp1", 1073 .sysmon_name = "gpdsp1", 1074 .ssctl_id = 0x22, 1075 }; 1076 1077 static const struct adsp_data mpss_resource_init = { 1078 .crash_reason_smem = 421, 1079 .firmware_name = "modem.mdt", 1080 .pas_id = 4, 1081 .minidump_id = 3, 1082 .auto_boot = false, 1083 .proxy_pd_names = (char*[]){ 1084 "cx", 1085 "mss", 1086 NULL 1087 }, 1088 .load_state = "modem", 1089 .ssr_name = "mpss", 1090 .sysmon_name = "modem", 1091 .ssctl_id = 0x12, 1092 }; 1093 1094 static const struct adsp_data sc8180x_mpss_resource = { 1095 .crash_reason_smem = 421, 1096 .firmware_name = "modem.mdt", 1097 .pas_id = 4, 1098 .auto_boot = false, 1099 .proxy_pd_names = (char*[]){ 1100 "cx", 1101 NULL 1102 }, 1103 .load_state = "modem", 1104 .ssr_name = "mpss", 1105 .sysmon_name = "modem", 1106 .ssctl_id = 0x12, 1107 }; 1108 1109 static const struct adsp_data msm8996_slpi_resource_init = { 1110 .crash_reason_smem = 424, 1111 .firmware_name = "slpi.mdt", 1112 .pas_id = 12, 1113 .auto_boot = true, 1114 .proxy_pd_names = (char*[]){ 1115 "ssc_cx", 1116 NULL 1117 }, 1118 .ssr_name = "dsps", 1119 .sysmon_name = "slpi", 1120 .ssctl_id = 0x16, 1121 }; 1122 1123 static const struct adsp_data sdm845_slpi_resource_init = { 1124 .crash_reason_smem = 424, 1125 .firmware_name = "slpi.mdt", 1126 .pas_id = 12, 1127 .auto_boot = true, 1128 .proxy_pd_names = (char*[]){ 1129 "lcx", 1130 "lmx", 1131 NULL 1132 }, 1133 .load_state = "slpi", 1134 .ssr_name = "dsps", 1135 .sysmon_name = "slpi", 1136 .ssctl_id = 0x16, 1137 }; 1138 1139 static const struct adsp_data wcss_resource_init = { 1140 .crash_reason_smem = 421, 1141 .firmware_name = "wcnss.mdt", 1142 .pas_id = 6, 1143 .auto_boot = true, 1144 .ssr_name = "mpss", 1145 .sysmon_name = "wcnss", 1146 .ssctl_id = 0x12, 1147 }; 1148 1149 static const struct adsp_data sdx55_mpss_resource = { 1150 .crash_reason_smem = 421, 1151 .firmware_name = "modem.mdt", 1152 .pas_id = 4, 1153 .auto_boot = true, 1154 .proxy_pd_names = (char*[]){ 1155 "cx", 1156 "mss", 1157 NULL 1158 }, 1159 .ssr_name = "mpss", 1160 .sysmon_name = "modem", 1161 .ssctl_id = 0x22, 1162 }; 1163 1164 static const struct adsp_data sm8450_mpss_resource = { 1165 .crash_reason_smem = 421, 1166 .firmware_name = "modem.mdt", 1167 .pas_id = 4, 1168 .minidump_id = 3, 1169 .auto_boot = false, 1170 .decrypt_shutdown = true, 1171 .proxy_pd_names = (char*[]){ 1172 "cx", 1173 "mss", 1174 NULL 1175 }, 1176 .load_state = "modem", 1177 .ssr_name = "mpss", 1178 .sysmon_name = "modem", 1179 .ssctl_id = 0x12, 1180 }; 1181 1182 static const struct adsp_data sm8550_adsp_resource = { 1183 .crash_reason_smem = 423, 1184 .firmware_name = "adsp.mdt", 1185 .dtb_firmware_name = "adsp_dtb.mdt", 1186 .pas_id = 1, 1187 .dtb_pas_id = 0x24, 1188 .minidump_id = 5, 1189 .auto_boot = true, 1190 .proxy_pd_names = (char*[]){ 1191 "lcx", 1192 "lmx", 1193 NULL 1194 }, 1195 .load_state = "adsp", 1196 .ssr_name = "lpass", 1197 .sysmon_name = "adsp", 1198 .ssctl_id = 0x14, 1199 }; 1200 1201 static const struct adsp_data sm8550_cdsp_resource = { 1202 .crash_reason_smem = 601, 1203 .firmware_name = "cdsp.mdt", 1204 .dtb_firmware_name = "cdsp_dtb.mdt", 1205 .pas_id = 18, 1206 .dtb_pas_id = 0x25, 1207 .minidump_id = 7, 1208 .auto_boot = true, 1209 .proxy_pd_names = (char*[]){ 1210 "cx", 1211 "mxc", 1212 "nsp", 1213 NULL 1214 }, 1215 .load_state = "cdsp", 1216 .ssr_name = "cdsp", 1217 .sysmon_name = "cdsp", 1218 .ssctl_id = 0x17, 1219 }; 1220 1221 static const struct adsp_data sm8550_mpss_resource = { 1222 .crash_reason_smem = 421, 1223 .firmware_name = "modem.mdt", 1224 .dtb_firmware_name = "modem_dtb.mdt", 1225 .pas_id = 4, 1226 .dtb_pas_id = 0x26, 1227 .minidump_id = 3, 1228 .auto_boot = false, 1229 .decrypt_shutdown = true, 1230 .proxy_pd_names = (char*[]){ 1231 "cx", 1232 "mss", 1233 NULL 1234 }, 1235 .load_state = "modem", 1236 .ssr_name = "mpss", 1237 .sysmon_name = "modem", 1238 .ssctl_id = 0x12, 1239 .region_assign_idx = 2, 1240 }; 1241 1242 static const struct of_device_id adsp_of_match[] = { 1243 { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init}, 1244 { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource}, 1245 { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, 1246 { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource}, 1247 { .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init}, 1248 { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource}, 1249 { .compatible = "qcom,msm8998-slpi-pas", .data = &msm8996_slpi_resource_init}, 1250 { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, 1251 { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, 1252 { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, 1253 { .compatible = "qcom,sa8775p-adsp-pas", .data = &sa8775p_adsp_resource}, 1254 { .compatible = "qcom,sa8775p-cdsp0-pas", .data = &sa8775p_cdsp0_resource}, 1255 { .compatible = "qcom,sa8775p-cdsp1-pas", .data = &sa8775p_cdsp1_resource}, 1256 { .compatible = "qcom,sa8775p-gpdsp0-pas", .data = &sa8775p_gpdsp0_resource}, 1257 { .compatible = "qcom,sa8775p-gpdsp1-pas", .data = &sa8775p_gpdsp1_resource}, 1258 { .compatible = "qcom,sar2130p-adsp-pas", .data = &sm8350_adsp_resource}, 1259 { .compatible = "qcom,sc7180-adsp-pas", .data = &sm8250_adsp_resource}, 1260 { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init}, 1261 { .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init}, 1262 { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource}, 1263 { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource}, 1264 { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource}, 1265 { .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource}, 1266 { .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource}, 1267 { .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource}, 1268 { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init}, 1269 { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init}, 1270 { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init}, 1271 { .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init}, 1272 { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource}, 1273 { .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init}, 1274 { .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init}, 1275 { .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource}, 1276 { .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource}, 1277 { .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource}, 1278 { .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init}, 1279 { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource}, 1280 { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource}, 1281 { .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init}, 1282 { .compatible = "qcom,sm8150-slpi-pas", .data = &sdm845_slpi_resource_init}, 1283 { .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource}, 1284 { .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource}, 1285 { .compatible = "qcom,sm8250-slpi-pas", .data = &sdm845_slpi_resource_init}, 1286 { .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource}, 1287 { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource}, 1288 { .compatible = "qcom,sm8350-slpi-pas", .data = &sdm845_slpi_resource_init}, 1289 { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init}, 1290 { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource}, 1291 { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource}, 1292 { .compatible = "qcom,sm8450-slpi-pas", .data = &sdm845_slpi_resource_init}, 1293 { .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource}, 1294 { .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource}, 1295 { .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource}, 1296 { .compatible = "qcom,sm8550-mpss-pas", .data = &sm8550_mpss_resource}, 1297 { }, 1298 }; 1299 MODULE_DEVICE_TABLE(of, adsp_of_match); 1300 1301 static struct platform_driver adsp_driver = { 1302 .probe = adsp_probe, 1303 .remove_new = adsp_remove, 1304 .driver = { 1305 .name = "qcom_q6v5_pas", 1306 .of_match_table = adsp_of_match, 1307 }, 1308 }; 1309 1310 module_platform_driver(adsp_driver); 1311 MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver"); 1312 MODULE_LICENSE("GPL v2"); 1313