1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Qualcomm Technology Inc. ADSP Peripheral Image Loader for SDM845. 4 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/delay.h> 9 #include <linux/firmware.h> 10 #include <linux/interrupt.h> 11 #include <linux/io.h> 12 #include <linux/iopoll.h> 13 #include <linux/kernel.h> 14 #include <linux/mfd/syscon.h> 15 #include <linux/module.h> 16 #include <linux/of_address.h> 17 #include <linux/of_device.h> 18 #include <linux/platform_device.h> 19 #include <linux/pm_domain.h> 20 #include <linux/pm_runtime.h> 21 #include <linux/regmap.h> 22 #include <linux/remoteproc.h> 23 #include <linux/reset.h> 24 #include <linux/soc/qcom/mdt_loader.h> 25 #include <linux/soc/qcom/smem.h> 26 #include <linux/soc/qcom/smem_state.h> 27 28 #include "qcom_common.h" 29 #include "qcom_q6v5.h" 30 #include "remoteproc_internal.h" 31 32 /* time out value */ 33 #define ACK_TIMEOUT 1000 34 #define BOOT_FSM_TIMEOUT 10000 35 /* mask values */ 36 #define EVB_MASK GENMASK(27, 4) 37 /*QDSP6SS register offsets*/ 38 #define RST_EVB_REG 0x10 39 #define CORE_START_REG 0x400 40 #define BOOT_CMD_REG 0x404 41 #define BOOT_STATUS_REG 0x408 42 #define RET_CFG_REG 0x1C 43 /*TCSR register offsets*/ 44 #define LPASS_MASTER_IDLE_REG 0x8 45 #define LPASS_HALTACK_REG 0x4 46 #define LPASS_PWR_ON_REG 0x10 47 #define LPASS_HALTREQ_REG 0x0 48 49 /* list of clocks required by ADSP PIL */ 50 static const char * const adsp_clk_id[] = { 51 "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr", 52 "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", 53 }; 54 55 struct adsp_pil_data { 56 int crash_reason_smem; 57 const char *firmware_name; 58 59 const char *ssr_name; 60 const char *sysmon_name; 61 int ssctl_id; 62 }; 63 64 struct qcom_adsp { 65 struct device *dev; 66 struct rproc *rproc; 67 68 struct qcom_q6v5 q6v5; 69 70 struct clk *xo; 71 72 int num_clks; 73 struct clk_bulk_data *clks; 74 75 void __iomem *qdsp6ss_base; 76 77 struct reset_control *pdc_sync_reset; 78 struct reset_control *cc_lpass_restart; 79 80 struct regmap *halt_map; 81 unsigned int halt_lpass; 82 83 int crash_reason_smem; 84 85 struct completion start_done; 86 struct completion stop_done; 87 88 phys_addr_t mem_phys; 89 phys_addr_t mem_reloc; 90 void *mem_region; 91 size_t mem_size; 92 93 struct qcom_rproc_glink glink_subdev; 94 struct qcom_rproc_ssr ssr_subdev; 95 struct qcom_sysmon *sysmon; 96 }; 97 98 static int qcom_adsp_shutdown(struct qcom_adsp *adsp) 99 { 100 unsigned long timeout; 101 unsigned int val; 102 int ret; 103 104 /* Reset the retention logic */ 105 val = readl(adsp->qdsp6ss_base + RET_CFG_REG); 106 val |= 0x1; 107 writel(val, adsp->qdsp6ss_base + RET_CFG_REG); 108 109 clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks); 110 111 /* QDSP6 master port needs to be explicitly halted */ 112 ret = regmap_read(adsp->halt_map, 113 adsp->halt_lpass + LPASS_PWR_ON_REG, &val); 114 if (ret || !val) 115 goto reset; 116 117 ret = regmap_read(adsp->halt_map, 118 adsp->halt_lpass + LPASS_MASTER_IDLE_REG, 119 &val); 120 if (ret || val) 121 goto reset; 122 123 regmap_write(adsp->halt_map, 124 adsp->halt_lpass + LPASS_HALTREQ_REG, 1); 125 126 /* Wait for halt ACK from QDSP6 */ 127 timeout = jiffies + msecs_to_jiffies(ACK_TIMEOUT); 128 for (;;) { 129 ret = regmap_read(adsp->halt_map, 130 adsp->halt_lpass + LPASS_HALTACK_REG, &val); 131 if (ret || val || time_after(jiffies, timeout)) 132 break; 133 134 usleep_range(1000, 1100); 135 } 136 137 ret = regmap_read(adsp->halt_map, 138 adsp->halt_lpass + LPASS_MASTER_IDLE_REG, &val); 139 if (ret || !val) 140 dev_err(adsp->dev, "port failed halt\n"); 141 142 reset: 143 /* Assert the LPASS PDC Reset */ 144 reset_control_assert(adsp->pdc_sync_reset); 145 /* Place the LPASS processor into reset */ 146 reset_control_assert(adsp->cc_lpass_restart); 147 /* wait after asserting subsystem restart from AOSS */ 148 usleep_range(200, 300); 149 150 /* Clear the halt request for the AXIM and AHBM for Q6 */ 151 regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0); 152 153 /* De-assert the LPASS PDC Reset */ 154 reset_control_deassert(adsp->pdc_sync_reset); 155 /* Remove the LPASS reset */ 156 reset_control_deassert(adsp->cc_lpass_restart); 157 /* wait after de-asserting subsystem restart from AOSS */ 158 usleep_range(200, 300); 159 160 return 0; 161 } 162 163 static int adsp_load(struct rproc *rproc, const struct firmware *fw) 164 { 165 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; 166 167 return qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0, 168 adsp->mem_region, adsp->mem_phys, adsp->mem_size, 169 &adsp->mem_reloc); 170 } 171 172 static int adsp_start(struct rproc *rproc) 173 { 174 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; 175 int ret; 176 unsigned int val; 177 178 qcom_q6v5_prepare(&adsp->q6v5); 179 180 ret = clk_prepare_enable(adsp->xo); 181 if (ret) 182 goto disable_irqs; 183 184 dev_pm_genpd_set_performance_state(adsp->dev, INT_MAX); 185 ret = pm_runtime_get_sync(adsp->dev); 186 if (ret) 187 goto disable_xo_clk; 188 189 ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks); 190 if (ret) { 191 dev_err(adsp->dev, "adsp clk_enable failed\n"); 192 goto disable_power_domain; 193 } 194 195 /* Program boot address */ 196 writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG); 197 198 /* De-assert QDSP6 stop core. QDSP6 will execute after out of reset */ 199 writel(0x1, adsp->qdsp6ss_base + CORE_START_REG); 200 201 /* Trigger boot FSM to start QDSP6 */ 202 writel(0x1, adsp->qdsp6ss_base + BOOT_CMD_REG); 203 204 /* Wait for core to come out of reset */ 205 ret = readl_poll_timeout(adsp->qdsp6ss_base + BOOT_STATUS_REG, 206 val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT); 207 if (ret) { 208 dev_err(adsp->dev, "failed to bootup adsp\n"); 209 goto disable_adsp_clks; 210 } 211 212 ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5 * HZ)); 213 if (ret == -ETIMEDOUT) { 214 dev_err(adsp->dev, "start timed out\n"); 215 goto disable_adsp_clks; 216 } 217 218 return 0; 219 220 disable_adsp_clks: 221 clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks); 222 disable_power_domain: 223 dev_pm_genpd_set_performance_state(adsp->dev, 0); 224 pm_runtime_put(adsp->dev); 225 disable_xo_clk: 226 clk_disable_unprepare(adsp->xo); 227 disable_irqs: 228 qcom_q6v5_unprepare(&adsp->q6v5); 229 230 return ret; 231 } 232 233 static void qcom_adsp_pil_handover(struct qcom_q6v5 *q6v5) 234 { 235 struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5); 236 237 clk_disable_unprepare(adsp->xo); 238 dev_pm_genpd_set_performance_state(adsp->dev, 0); 239 pm_runtime_put(adsp->dev); 240 } 241 242 static int adsp_stop(struct rproc *rproc) 243 { 244 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; 245 int handover; 246 int ret; 247 248 ret = qcom_q6v5_request_stop(&adsp->q6v5); 249 if (ret == -ETIMEDOUT) 250 dev_err(adsp->dev, "timed out on wait\n"); 251 252 ret = qcom_adsp_shutdown(adsp); 253 if (ret) 254 dev_err(adsp->dev, "failed to shutdown: %d\n", ret); 255 256 handover = qcom_q6v5_unprepare(&adsp->q6v5); 257 if (handover) 258 qcom_adsp_pil_handover(&adsp->q6v5); 259 260 return ret; 261 } 262 263 static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len) 264 { 265 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; 266 int offset; 267 268 offset = da - adsp->mem_reloc; 269 if (offset < 0 || offset + len > adsp->mem_size) 270 return NULL; 271 272 return adsp->mem_region + offset; 273 } 274 275 static const struct rproc_ops adsp_ops = { 276 .start = adsp_start, 277 .stop = adsp_stop, 278 .da_to_va = adsp_da_to_va, 279 .parse_fw = qcom_register_dump_segments, 280 .load = adsp_load, 281 }; 282 283 static int adsp_init_clock(struct qcom_adsp *adsp) 284 { 285 int i, ret; 286 287 adsp->xo = devm_clk_get(adsp->dev, "xo"); 288 if (IS_ERR(adsp->xo)) { 289 ret = PTR_ERR(adsp->xo); 290 if (ret != -EPROBE_DEFER) 291 dev_err(adsp->dev, "failed to get xo clock"); 292 return ret; 293 } 294 295 adsp->num_clks = ARRAY_SIZE(adsp_clk_id); 296 adsp->clks = devm_kcalloc(adsp->dev, adsp->num_clks, 297 sizeof(*adsp->clks), GFP_KERNEL); 298 if (!adsp->clks) 299 return -ENOMEM; 300 301 for (i = 0; i < adsp->num_clks; i++) 302 adsp->clks[i].id = adsp_clk_id[i]; 303 304 return devm_clk_bulk_get(adsp->dev, adsp->num_clks, adsp->clks); 305 } 306 307 static int adsp_init_reset(struct qcom_adsp *adsp) 308 { 309 adsp->pdc_sync_reset = devm_reset_control_get_exclusive(adsp->dev, 310 "pdc_sync"); 311 if (IS_ERR(adsp->pdc_sync_reset)) { 312 dev_err(adsp->dev, "failed to acquire pdc_sync reset\n"); 313 return PTR_ERR(adsp->pdc_sync_reset); 314 } 315 316 adsp->cc_lpass_restart = devm_reset_control_get_exclusive(adsp->dev, 317 "cc_lpass"); 318 if (IS_ERR(adsp->cc_lpass_restart)) { 319 dev_err(adsp->dev, "failed to acquire cc_lpass restart\n"); 320 return PTR_ERR(adsp->cc_lpass_restart); 321 } 322 323 return 0; 324 } 325 326 static int adsp_init_mmio(struct qcom_adsp *adsp, 327 struct platform_device *pdev) 328 { 329 struct device_node *syscon; 330 struct resource *res; 331 int ret; 332 333 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 334 adsp->qdsp6ss_base = devm_ioremap(&pdev->dev, res->start, 335 resource_size(res)); 336 if (!adsp->qdsp6ss_base) { 337 dev_err(adsp->dev, "failed to map QDSP6SS registers\n"); 338 return -ENOMEM; 339 } 340 341 syscon = of_parse_phandle(pdev->dev.of_node, "qcom,halt-regs", 0); 342 if (!syscon) { 343 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n"); 344 return -EINVAL; 345 } 346 347 adsp->halt_map = syscon_node_to_regmap(syscon); 348 of_node_put(syscon); 349 if (IS_ERR(adsp->halt_map)) 350 return PTR_ERR(adsp->halt_map); 351 352 ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,halt-regs", 353 1, &adsp->halt_lpass); 354 if (ret < 0) { 355 dev_err(&pdev->dev, "no offset in syscon\n"); 356 return ret; 357 } 358 359 return 0; 360 } 361 362 static int adsp_alloc_memory_region(struct qcom_adsp *adsp) 363 { 364 struct device_node *node; 365 struct resource r; 366 int ret; 367 368 node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0); 369 if (!node) { 370 dev_err(adsp->dev, "no memory-region specified\n"); 371 return -EINVAL; 372 } 373 374 ret = of_address_to_resource(node, 0, &r); 375 if (ret) 376 return ret; 377 378 adsp->mem_phys = adsp->mem_reloc = r.start; 379 adsp->mem_size = resource_size(&r); 380 adsp->mem_region = devm_ioremap_wc(adsp->dev, 381 adsp->mem_phys, adsp->mem_size); 382 if (!adsp->mem_region) { 383 dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n", 384 &r.start, adsp->mem_size); 385 return -EBUSY; 386 } 387 388 return 0; 389 } 390 391 static int adsp_probe(struct platform_device *pdev) 392 { 393 const struct adsp_pil_data *desc; 394 struct qcom_adsp *adsp; 395 struct rproc *rproc; 396 int ret; 397 398 desc = of_device_get_match_data(&pdev->dev); 399 if (!desc) 400 return -EINVAL; 401 402 rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops, 403 desc->firmware_name, sizeof(*adsp)); 404 if (!rproc) { 405 dev_err(&pdev->dev, "unable to allocate remoteproc\n"); 406 return -ENOMEM; 407 } 408 409 adsp = (struct qcom_adsp *)rproc->priv; 410 adsp->dev = &pdev->dev; 411 adsp->rproc = rproc; 412 platform_set_drvdata(pdev, adsp); 413 414 ret = adsp_alloc_memory_region(adsp); 415 if (ret) 416 goto free_rproc; 417 418 ret = adsp_init_clock(adsp); 419 if (ret) 420 goto free_rproc; 421 422 pm_runtime_enable(adsp->dev); 423 424 ret = adsp_init_reset(adsp); 425 if (ret) 426 goto disable_pm; 427 428 ret = adsp_init_mmio(adsp, pdev); 429 if (ret) 430 goto disable_pm; 431 432 ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, 433 qcom_adsp_pil_handover); 434 if (ret) 435 goto disable_pm; 436 437 qcom_add_glink_subdev(rproc, &adsp->glink_subdev); 438 qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); 439 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 440 desc->sysmon_name, 441 desc->ssctl_id); 442 if (IS_ERR(adsp->sysmon)) { 443 ret = PTR_ERR(adsp->sysmon); 444 goto disable_pm; 445 } 446 447 ret = rproc_add(rproc); 448 if (ret) 449 goto disable_pm; 450 451 return 0; 452 453 disable_pm: 454 pm_runtime_disable(adsp->dev); 455 free_rproc: 456 rproc_free(rproc); 457 458 return ret; 459 } 460 461 static int adsp_remove(struct platform_device *pdev) 462 { 463 struct qcom_adsp *adsp = platform_get_drvdata(pdev); 464 465 rproc_del(adsp->rproc); 466 467 qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); 468 qcom_remove_sysmon_subdev(adsp->sysmon); 469 qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); 470 pm_runtime_disable(adsp->dev); 471 rproc_free(adsp->rproc); 472 473 return 0; 474 } 475 476 static const struct adsp_pil_data adsp_resource_init = { 477 .crash_reason_smem = 423, 478 .firmware_name = "adsp.mdt", 479 .ssr_name = "lpass", 480 .sysmon_name = "adsp", 481 .ssctl_id = 0x14, 482 }; 483 484 static const struct of_device_id adsp_of_match[] = { 485 { .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init }, 486 { }, 487 }; 488 MODULE_DEVICE_TABLE(of, adsp_of_match); 489 490 static struct platform_driver adsp_pil_driver = { 491 .probe = adsp_probe, 492 .remove = adsp_remove, 493 .driver = { 494 .name = "qcom_q6v5_adsp", 495 .of_match_table = adsp_of_match, 496 }, 497 }; 498 499 module_platform_driver(adsp_pil_driver); 500 MODULE_DESCRIPTION("QTI SDM845 ADSP Peripheral Image Loader"); 501 MODULE_LICENSE("GPL v2"); 502