0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/delay.h>
0009 #include <linux/firmware.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/io.h>
0012 #include <linux/iopoll.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mfd/syscon.h>
0015 #include <linux/module.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_device.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/pm_domain.h>
0020 #include <linux/pm_runtime.h>
0021 #include <linux/regmap.h>
0022 #include <linux/remoteproc.h>
0023 #include <linux/reset.h>
0024 #include <linux/soc/qcom/mdt_loader.h>
0025 #include <linux/soc/qcom/smem.h>
0026 #include <linux/soc/qcom/smem_state.h>
0027
0028 #include "qcom_common.h"
0029 #include "qcom_pil_info.h"
0030 #include "qcom_q6v5.h"
0031 #include "remoteproc_internal.h"
0032
0033
0034 #define ACK_TIMEOUT 1000
0035 #define ACK_TIMEOUT_US 1000000
0036 #define BOOT_FSM_TIMEOUT 10000
0037
0038 #define EVB_MASK GENMASK(27, 4)
0039
0040 #define RST_EVB_REG 0x10
0041 #define CORE_START_REG 0x400
0042 #define BOOT_CMD_REG 0x404
0043 #define BOOT_STATUS_REG 0x408
0044 #define RET_CFG_REG 0x1C
0045
0046 #define LPASS_MASTER_IDLE_REG 0x8
0047 #define LPASS_HALTACK_REG 0x4
0048 #define LPASS_PWR_ON_REG 0x10
0049 #define LPASS_HALTREQ_REG 0x0
0050
0051 #define QDSP6SS_XO_CBCR 0x38
0052 #define QDSP6SS_CORE_CBCR 0x20
0053 #define QDSP6SS_SLEEP_CBCR 0x3c
0054
0055 #define QCOM_Q6V5_RPROC_PROXY_PD_MAX 3
0056
0057 struct adsp_pil_data {
0058 int crash_reason_smem;
0059 const char *firmware_name;
0060
0061 const char *ssr_name;
0062 const char *sysmon_name;
0063 int ssctl_id;
0064 bool is_wpss;
0065 bool auto_boot;
0066
0067 const char **clk_ids;
0068 int num_clks;
0069 const char **proxy_pd_names;
0070 const char *load_state;
0071 };
0072
0073 struct qcom_adsp {
0074 struct device *dev;
0075 struct rproc *rproc;
0076
0077 struct qcom_q6v5 q6v5;
0078
0079 struct clk *xo;
0080
0081 int num_clks;
0082 struct clk_bulk_data *clks;
0083
0084 void __iomem *qdsp6ss_base;
0085
0086 struct reset_control *pdc_sync_reset;
0087 struct reset_control *restart;
0088
0089 struct regmap *halt_map;
0090 unsigned int halt_lpass;
0091
0092 int crash_reason_smem;
0093 const char *info_name;
0094
0095 struct completion start_done;
0096 struct completion stop_done;
0097
0098 phys_addr_t mem_phys;
0099 phys_addr_t mem_reloc;
0100 void *mem_region;
0101 size_t mem_size;
0102
0103 struct device *proxy_pds[QCOM_Q6V5_RPROC_PROXY_PD_MAX];
0104 size_t proxy_pd_count;
0105
0106 struct qcom_rproc_glink glink_subdev;
0107 struct qcom_rproc_ssr ssr_subdev;
0108 struct qcom_sysmon *sysmon;
0109
0110 int (*shutdown)(struct qcom_adsp *adsp);
0111 };
0112
0113 static int qcom_rproc_pds_attach(struct device *dev, struct qcom_adsp *adsp,
0114 const char **pd_names)
0115 {
0116 struct device **devs = adsp->proxy_pds;
0117 size_t num_pds = 0;
0118 int ret;
0119 int i;
0120
0121 if (!pd_names)
0122 return 0;
0123
0124
0125 if (dev->pm_domain) {
0126 devs[0] = dev;
0127 pm_runtime_enable(dev);
0128 return 1;
0129 }
0130
0131 while (pd_names[num_pds])
0132 num_pds++;
0133
0134 if (num_pds > ARRAY_SIZE(adsp->proxy_pds))
0135 return -E2BIG;
0136
0137 for (i = 0; i < num_pds; i++) {
0138 devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
0139 if (IS_ERR_OR_NULL(devs[i])) {
0140 ret = PTR_ERR(devs[i]) ? : -ENODATA;
0141 goto unroll_attach;
0142 }
0143 }
0144
0145 return num_pds;
0146
0147 unroll_attach:
0148 for (i--; i >= 0; i--)
0149 dev_pm_domain_detach(devs[i], false);
0150
0151 return ret;
0152 }
0153
0154 static void qcom_rproc_pds_detach(struct qcom_adsp *adsp, struct device **pds,
0155 size_t pd_count)
0156 {
0157 struct device *dev = adsp->dev;
0158 int i;
0159
0160
0161 if (dev->pm_domain && pd_count) {
0162 pm_runtime_disable(dev);
0163 return;
0164 }
0165
0166 for (i = 0; i < pd_count; i++)
0167 dev_pm_domain_detach(pds[i], false);
0168 }
0169
0170 static int qcom_rproc_pds_enable(struct qcom_adsp *adsp, struct device **pds,
0171 size_t pd_count)
0172 {
0173 int ret;
0174 int i;
0175
0176 for (i = 0; i < pd_count; i++) {
0177 dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
0178 ret = pm_runtime_resume_and_get(pds[i]);
0179 if (ret < 0) {
0180 dev_pm_genpd_set_performance_state(pds[i], 0);
0181 goto unroll_pd_votes;
0182 }
0183 }
0184
0185 return 0;
0186
0187 unroll_pd_votes:
0188 for (i--; i >= 0; i--) {
0189 dev_pm_genpd_set_performance_state(pds[i], 0);
0190 pm_runtime_put(pds[i]);
0191 }
0192
0193 return ret;
0194 }
0195
0196 static void qcom_rproc_pds_disable(struct qcom_adsp *adsp, struct device **pds,
0197 size_t pd_count)
0198 {
0199 int i;
0200
0201 for (i = 0; i < pd_count; i++) {
0202 dev_pm_genpd_set_performance_state(pds[i], 0);
0203 pm_runtime_put(pds[i]);
0204 }
0205 }
0206
0207 static int qcom_wpss_shutdown(struct qcom_adsp *adsp)
0208 {
0209 unsigned int val;
0210
0211 regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 1);
0212
0213
0214 regmap_read_poll_timeout(adsp->halt_map,
0215 adsp->halt_lpass + LPASS_HALTACK_REG, val,
0216 val, 1000, ACK_TIMEOUT_US);
0217
0218
0219 reset_control_assert(adsp->pdc_sync_reset);
0220
0221
0222 reset_control_assert(adsp->restart);
0223
0224
0225 usleep_range(200, 205);
0226
0227
0228 reset_control_deassert(adsp->restart);
0229
0230
0231 reset_control_deassert(adsp->pdc_sync_reset);
0232
0233 usleep_range(100, 105);
0234
0235 clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
0236
0237 regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0);
0238
0239
0240 regmap_read_poll_timeout(adsp->halt_map,
0241 adsp->halt_lpass + LPASS_HALTACK_REG, val,
0242 !val, 1000, ACK_TIMEOUT_US);
0243
0244 return 0;
0245 }
0246
0247 static int qcom_adsp_shutdown(struct qcom_adsp *adsp)
0248 {
0249 unsigned long timeout;
0250 unsigned int val;
0251 int ret;
0252
0253
0254 val = readl(adsp->qdsp6ss_base + RET_CFG_REG);
0255 val |= 0x1;
0256 writel(val, adsp->qdsp6ss_base + RET_CFG_REG);
0257
0258 clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
0259
0260
0261 ret = regmap_read(adsp->halt_map,
0262 adsp->halt_lpass + LPASS_PWR_ON_REG, &val);
0263 if (ret || !val)
0264 goto reset;
0265
0266 ret = regmap_read(adsp->halt_map,
0267 adsp->halt_lpass + LPASS_MASTER_IDLE_REG,
0268 &val);
0269 if (ret || val)
0270 goto reset;
0271
0272 regmap_write(adsp->halt_map,
0273 adsp->halt_lpass + LPASS_HALTREQ_REG, 1);
0274
0275
0276 timeout = jiffies + msecs_to_jiffies(ACK_TIMEOUT);
0277 for (;;) {
0278 ret = regmap_read(adsp->halt_map,
0279 adsp->halt_lpass + LPASS_HALTACK_REG, &val);
0280 if (ret || val || time_after(jiffies, timeout))
0281 break;
0282
0283 usleep_range(1000, 1100);
0284 }
0285
0286 ret = regmap_read(adsp->halt_map,
0287 adsp->halt_lpass + LPASS_MASTER_IDLE_REG, &val);
0288 if (ret || !val)
0289 dev_err(adsp->dev, "port failed halt\n");
0290
0291 reset:
0292
0293 reset_control_assert(adsp->pdc_sync_reset);
0294
0295 reset_control_assert(adsp->restart);
0296
0297 usleep_range(200, 300);
0298
0299
0300 regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0);
0301
0302
0303 reset_control_deassert(adsp->pdc_sync_reset);
0304
0305 reset_control_deassert(adsp->restart);
0306
0307 usleep_range(200, 300);
0308
0309 return 0;
0310 }
0311
0312 static int adsp_load(struct rproc *rproc, const struct firmware *fw)
0313 {
0314 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
0315 int ret;
0316
0317 ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0,
0318 adsp->mem_region, adsp->mem_phys,
0319 adsp->mem_size, &adsp->mem_reloc);
0320 if (ret)
0321 return ret;
0322
0323 qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
0324
0325 return 0;
0326 }
0327
0328 static int adsp_start(struct rproc *rproc)
0329 {
0330 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
0331 int ret;
0332 unsigned int val;
0333
0334 ret = qcom_q6v5_prepare(&adsp->q6v5);
0335 if (ret)
0336 return ret;
0337
0338 ret = clk_prepare_enable(adsp->xo);
0339 if (ret)
0340 goto disable_irqs;
0341
0342 ret = qcom_rproc_pds_enable(adsp, adsp->proxy_pds,
0343 adsp->proxy_pd_count);
0344 if (ret < 0)
0345 goto disable_xo_clk;
0346
0347 ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks);
0348 if (ret) {
0349 dev_err(adsp->dev, "adsp clk_enable failed\n");
0350 goto disable_power_domain;
0351 }
0352
0353
0354 writel(1, adsp->qdsp6ss_base + QDSP6SS_XO_CBCR);
0355
0356
0357 writel(1, adsp->qdsp6ss_base + QDSP6SS_SLEEP_CBCR);
0358
0359
0360 writel(1, adsp->qdsp6ss_base + QDSP6SS_CORE_CBCR);
0361
0362
0363 writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG);
0364
0365
0366 writel(0x1, adsp->qdsp6ss_base + CORE_START_REG);
0367
0368
0369 writel(0x1, adsp->qdsp6ss_base + BOOT_CMD_REG);
0370
0371
0372 ret = readl_poll_timeout(adsp->qdsp6ss_base + BOOT_STATUS_REG,
0373 val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
0374 if (ret) {
0375 dev_err(adsp->dev, "failed to bootup adsp\n");
0376 goto disable_adsp_clks;
0377 }
0378
0379 ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5 * HZ));
0380 if (ret == -ETIMEDOUT) {
0381 dev_err(adsp->dev, "start timed out\n");
0382 goto disable_adsp_clks;
0383 }
0384
0385 return 0;
0386
0387 disable_adsp_clks:
0388 clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
0389 disable_power_domain:
0390 qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
0391 disable_xo_clk:
0392 clk_disable_unprepare(adsp->xo);
0393 disable_irqs:
0394 qcom_q6v5_unprepare(&adsp->q6v5);
0395
0396 return ret;
0397 }
0398
0399 static void qcom_adsp_pil_handover(struct qcom_q6v5 *q6v5)
0400 {
0401 struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
0402
0403 clk_disable_unprepare(adsp->xo);
0404 qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
0405 }
0406
0407 static int adsp_stop(struct rproc *rproc)
0408 {
0409 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
0410 int handover;
0411 int ret;
0412
0413 ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
0414 if (ret == -ETIMEDOUT)
0415 dev_err(adsp->dev, "timed out on wait\n");
0416
0417 ret = adsp->shutdown(adsp);
0418 if (ret)
0419 dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
0420
0421 handover = qcom_q6v5_unprepare(&adsp->q6v5);
0422 if (handover)
0423 qcom_adsp_pil_handover(&adsp->q6v5);
0424
0425 return ret;
0426 }
0427
0428 static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
0429 {
0430 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
0431 int offset;
0432
0433 offset = da - adsp->mem_reloc;
0434 if (offset < 0 || offset + len > adsp->mem_size)
0435 return NULL;
0436
0437 return adsp->mem_region + offset;
0438 }
0439
0440 static unsigned long adsp_panic(struct rproc *rproc)
0441 {
0442 struct qcom_adsp *adsp = rproc->priv;
0443
0444 return qcom_q6v5_panic(&adsp->q6v5);
0445 }
0446
0447 static const struct rproc_ops adsp_ops = {
0448 .start = adsp_start,
0449 .stop = adsp_stop,
0450 .da_to_va = adsp_da_to_va,
0451 .parse_fw = qcom_register_dump_segments,
0452 .load = adsp_load,
0453 .panic = adsp_panic,
0454 };
0455
0456 static int adsp_init_clock(struct qcom_adsp *adsp, const char **clk_ids)
0457 {
0458 int num_clks = 0;
0459 int i, ret;
0460
0461 adsp->xo = devm_clk_get(adsp->dev, "xo");
0462 if (IS_ERR(adsp->xo)) {
0463 ret = PTR_ERR(adsp->xo);
0464 if (ret != -EPROBE_DEFER)
0465 dev_err(adsp->dev, "failed to get xo clock");
0466 return ret;
0467 }
0468
0469 for (i = 0; clk_ids[i]; i++)
0470 num_clks++;
0471
0472 adsp->num_clks = num_clks;
0473 adsp->clks = devm_kcalloc(adsp->dev, adsp->num_clks,
0474 sizeof(*adsp->clks), GFP_KERNEL);
0475 if (!adsp->clks)
0476 return -ENOMEM;
0477
0478 for (i = 0; i < adsp->num_clks; i++)
0479 adsp->clks[i].id = clk_ids[i];
0480
0481 return devm_clk_bulk_get(adsp->dev, adsp->num_clks, adsp->clks);
0482 }
0483
0484 static int adsp_init_reset(struct qcom_adsp *adsp)
0485 {
0486 adsp->pdc_sync_reset = devm_reset_control_get_optional_exclusive(adsp->dev,
0487 "pdc_sync");
0488 if (IS_ERR(adsp->pdc_sync_reset)) {
0489 dev_err(adsp->dev, "failed to acquire pdc_sync reset\n");
0490 return PTR_ERR(adsp->pdc_sync_reset);
0491 }
0492
0493 adsp->restart = devm_reset_control_get_optional_exclusive(adsp->dev, "restart");
0494
0495
0496 if (!adsp->restart)
0497 adsp->restart = devm_reset_control_get_exclusive(adsp->dev, "cc_lpass");
0498
0499 if (IS_ERR(adsp->restart)) {
0500 dev_err(adsp->dev, "failed to acquire restart\n");
0501 return PTR_ERR(adsp->restart);
0502 }
0503
0504 return 0;
0505 }
0506
0507 static int adsp_init_mmio(struct qcom_adsp *adsp,
0508 struct platform_device *pdev)
0509 {
0510 struct device_node *syscon;
0511 int ret;
0512
0513 adsp->qdsp6ss_base = devm_platform_ioremap_resource(pdev, 0);
0514 if (IS_ERR(adsp->qdsp6ss_base)) {
0515 dev_err(adsp->dev, "failed to map QDSP6SS registers\n");
0516 return PTR_ERR(adsp->qdsp6ss_base);
0517 }
0518
0519 syscon = of_parse_phandle(pdev->dev.of_node, "qcom,halt-regs", 0);
0520 if (!syscon) {
0521 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
0522 return -EINVAL;
0523 }
0524
0525 adsp->halt_map = syscon_node_to_regmap(syscon);
0526 of_node_put(syscon);
0527 if (IS_ERR(adsp->halt_map))
0528 return PTR_ERR(adsp->halt_map);
0529
0530 ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,halt-regs",
0531 1, &adsp->halt_lpass);
0532 if (ret < 0) {
0533 dev_err(&pdev->dev, "no offset in syscon\n");
0534 return ret;
0535 }
0536
0537 return 0;
0538 }
0539
0540 static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
0541 {
0542 struct device_node *node;
0543 struct resource r;
0544 int ret;
0545
0546 node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
0547 if (!node) {
0548 dev_err(adsp->dev, "no memory-region specified\n");
0549 return -EINVAL;
0550 }
0551
0552 ret = of_address_to_resource(node, 0, &r);
0553 of_node_put(node);
0554 if (ret)
0555 return ret;
0556
0557 adsp->mem_phys = adsp->mem_reloc = r.start;
0558 adsp->mem_size = resource_size(&r);
0559 adsp->mem_region = devm_ioremap_wc(adsp->dev,
0560 adsp->mem_phys, adsp->mem_size);
0561 if (!adsp->mem_region) {
0562 dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
0563 &r.start, adsp->mem_size);
0564 return -EBUSY;
0565 }
0566
0567 return 0;
0568 }
0569
0570 static int adsp_probe(struct platform_device *pdev)
0571 {
0572 const struct adsp_pil_data *desc;
0573 const char *firmware_name;
0574 struct qcom_adsp *adsp;
0575 struct rproc *rproc;
0576 int ret;
0577
0578 desc = of_device_get_match_data(&pdev->dev);
0579 if (!desc)
0580 return -EINVAL;
0581
0582 firmware_name = desc->firmware_name;
0583 ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
0584 &firmware_name);
0585 if (ret < 0 && ret != -EINVAL) {
0586 dev_err(&pdev->dev, "unable to read firmware-name\n");
0587 return ret;
0588 }
0589
0590 rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
0591 firmware_name, sizeof(*adsp));
0592 if (!rproc) {
0593 dev_err(&pdev->dev, "unable to allocate remoteproc\n");
0594 return -ENOMEM;
0595 }
0596
0597 rproc->auto_boot = desc->auto_boot;
0598 rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
0599
0600 adsp = (struct qcom_adsp *)rproc->priv;
0601 adsp->dev = &pdev->dev;
0602 adsp->rproc = rproc;
0603 adsp->info_name = desc->sysmon_name;
0604 platform_set_drvdata(pdev, adsp);
0605
0606 if (desc->is_wpss)
0607 adsp->shutdown = qcom_wpss_shutdown;
0608 else
0609 adsp->shutdown = qcom_adsp_shutdown;
0610
0611 ret = adsp_alloc_memory_region(adsp);
0612 if (ret)
0613 goto free_rproc;
0614
0615 ret = adsp_init_clock(adsp, desc->clk_ids);
0616 if (ret)
0617 goto free_rproc;
0618
0619 ret = qcom_rproc_pds_attach(adsp->dev, adsp,
0620 desc->proxy_pd_names);
0621 if (ret < 0) {
0622 dev_err(&pdev->dev, "Failed to attach proxy power domains\n");
0623 goto free_rproc;
0624 }
0625 adsp->proxy_pd_count = ret;
0626
0627 ret = adsp_init_reset(adsp);
0628 if (ret)
0629 goto disable_pm;
0630
0631 ret = adsp_init_mmio(adsp, pdev);
0632 if (ret)
0633 goto disable_pm;
0634
0635 ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
0636 desc->load_state, qcom_adsp_pil_handover);
0637 if (ret)
0638 goto disable_pm;
0639
0640 qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
0641 qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
0642 adsp->sysmon = qcom_add_sysmon_subdev(rproc,
0643 desc->sysmon_name,
0644 desc->ssctl_id);
0645 if (IS_ERR(adsp->sysmon)) {
0646 ret = PTR_ERR(adsp->sysmon);
0647 goto disable_pm;
0648 }
0649
0650 ret = rproc_add(rproc);
0651 if (ret)
0652 goto disable_pm;
0653
0654 return 0;
0655
0656 disable_pm:
0657 qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
0658
0659 free_rproc:
0660 rproc_free(rproc);
0661
0662 return ret;
0663 }
0664
0665 static int adsp_remove(struct platform_device *pdev)
0666 {
0667 struct qcom_adsp *adsp = platform_get_drvdata(pdev);
0668
0669 rproc_del(adsp->rproc);
0670
0671 qcom_q6v5_deinit(&adsp->q6v5);
0672 qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
0673 qcom_remove_sysmon_subdev(adsp->sysmon);
0674 qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
0675 qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
0676 rproc_free(adsp->rproc);
0677
0678 return 0;
0679 }
0680
0681 static const struct adsp_pil_data adsp_resource_init = {
0682 .crash_reason_smem = 423,
0683 .firmware_name = "adsp.mdt",
0684 .ssr_name = "lpass",
0685 .sysmon_name = "adsp",
0686 .ssctl_id = 0x14,
0687 .is_wpss = false,
0688 .auto_boot = true,
0689 .clk_ids = (const char*[]) {
0690 "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
0691 "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", NULL
0692 },
0693 .num_clks = 7,
0694 .proxy_pd_names = (const char*[]) {
0695 "cx", NULL
0696 },
0697 };
0698
0699 static const struct adsp_pil_data cdsp_resource_init = {
0700 .crash_reason_smem = 601,
0701 .firmware_name = "cdsp.mdt",
0702 .ssr_name = "cdsp",
0703 .sysmon_name = "cdsp",
0704 .ssctl_id = 0x17,
0705 .is_wpss = false,
0706 .auto_boot = true,
0707 .clk_ids = (const char*[]) {
0708 "sway", "tbu", "bimc", "ahb_aon", "q6ss_slave", "q6ss_master",
0709 "q6_axim", NULL
0710 },
0711 .num_clks = 7,
0712 .proxy_pd_names = (const char*[]) {
0713 "cx", NULL
0714 },
0715 };
0716
0717 static const struct adsp_pil_data wpss_resource_init = {
0718 .crash_reason_smem = 626,
0719 .firmware_name = "wpss.mdt",
0720 .ssr_name = "wpss",
0721 .sysmon_name = "wpss",
0722 .ssctl_id = 0x19,
0723 .is_wpss = true,
0724 .auto_boot = false,
0725 .load_state = "wpss",
0726 .clk_ids = (const char*[]) {
0727 "ahb_bdg", "ahb", "rscp", NULL
0728 },
0729 .num_clks = 3,
0730 .proxy_pd_names = (const char*[]) {
0731 "cx", "mx", NULL
0732 },
0733 };
0734
0735 static const struct of_device_id adsp_of_match[] = {
0736 { .compatible = "qcom,qcs404-cdsp-pil", .data = &cdsp_resource_init },
0737 { .compatible = "qcom,sc7280-wpss-pil", .data = &wpss_resource_init },
0738 { .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init },
0739 { },
0740 };
0741 MODULE_DEVICE_TABLE(of, adsp_of_match);
0742
0743 static struct platform_driver adsp_pil_driver = {
0744 .probe = adsp_probe,
0745 .remove = adsp_remove,
0746 .driver = {
0747 .name = "qcom_q6v5_adsp",
0748 .of_match_table = adsp_of_match,
0749 },
0750 };
0751
0752 module_platform_driver(adsp_pil_driver);
0753 MODULE_DESCRIPTION("QTI SDM845 ADSP Peripheral Image Loader");
0754 MODULE_LICENSE("GPL v2");