1 // SPDX-License-Identifier: GPL-2.0
3 * Qualcomm Technology Inc. ADSP Peripheral Image Loader for SDM845.
4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
8 #include <linux/delay.h>
9 #include <linux/firmware.h>
10 #include <linux/interrupt.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>
28 #include "qcom_common.h"
29 #include "qcom_q6v5.h"
30 #include "remoteproc_internal.h"
33 #define ACK_TIMEOUT 1000
34 #define BOOT_FSM_TIMEOUT 10000
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
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",
55 struct adsp_pil_data
{
56 int crash_reason_smem
;
57 const char *firmware_name
;
60 const char *sysmon_name
;
68 struct qcom_q6v5 q6v5
;
73 struct clk_bulk_data
*clks
;
75 void __iomem
*qdsp6ss_base
;
77 struct reset_control
*pdc_sync_reset
;
78 struct reset_control
*cc_lpass_restart
;
80 struct regmap
*halt_map
;
81 unsigned int halt_lpass
;
83 int crash_reason_smem
;
85 struct completion start_done
;
86 struct completion stop_done
;
89 phys_addr_t mem_reloc
;
93 struct qcom_rproc_glink glink_subdev
;
94 struct qcom_rproc_ssr ssr_subdev
;
95 struct qcom_sysmon
*sysmon
;
98 static int qcom_adsp_shutdown(struct qcom_adsp
*adsp
)
100 unsigned long timeout
;
104 /* Reset the retention logic */
105 val
= readl(adsp
->qdsp6ss_base
+ RET_CFG_REG
);
107 writel(val
, adsp
->qdsp6ss_base
+ RET_CFG_REG
);
109 clk_bulk_disable_unprepare(adsp
->num_clks
, adsp
->clks
);
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
);
117 ret
= regmap_read(adsp
->halt_map
,
118 adsp
->halt_lpass
+ LPASS_MASTER_IDLE_REG
,
123 regmap_write(adsp
->halt_map
,
124 adsp
->halt_lpass
+ LPASS_HALTREQ_REG
, 1);
126 /* Wait for halt ACK from QDSP6 */
127 timeout
= jiffies
+ msecs_to_jiffies(ACK_TIMEOUT
);
129 ret
= regmap_read(adsp
->halt_map
,
130 adsp
->halt_lpass
+ LPASS_HALTACK_REG
, &val
);
131 if (ret
|| val
|| time_after(jiffies
, timeout
))
134 usleep_range(1000, 1100);
137 ret
= regmap_read(adsp
->halt_map
,
138 adsp
->halt_lpass
+ LPASS_MASTER_IDLE_REG
, &val
);
140 dev_err(adsp
->dev
, "port failed halt\n");
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);
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);
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);
163 static int adsp_load(struct rproc
*rproc
, const struct firmware
*fw
)
165 struct qcom_adsp
*adsp
= (struct qcom_adsp
*)rproc
->priv
;
167 return qcom_mdt_load_no_init(adsp
->dev
, fw
, rproc
->firmware
, 0,
168 adsp
->mem_region
, adsp
->mem_phys
, adsp
->mem_size
,
172 static int adsp_start(struct rproc
*rproc
)
174 struct qcom_adsp
*adsp
= (struct qcom_adsp
*)rproc
->priv
;
178 qcom_q6v5_prepare(&adsp
->q6v5
);
180 ret
= clk_prepare_enable(adsp
->xo
);
184 dev_pm_genpd_set_performance_state(adsp
->dev
, INT_MAX
);
185 ret
= pm_runtime_get_sync(adsp
->dev
);
189 ret
= clk_bulk_prepare_enable(adsp
->num_clks
, adsp
->clks
);
191 dev_err(adsp
->dev
, "adsp clk_enable failed\n");
192 goto disable_power_domain
;
195 /* Program boot address */
196 writel(adsp
->mem_phys
>> 4, adsp
->qdsp6ss_base
+ RST_EVB_REG
);
198 /* De-assert QDSP6 stop core. QDSP6 will execute after out of reset */
199 writel(0x1, adsp
->qdsp6ss_base
+ CORE_START_REG
);
201 /* Trigger boot FSM to start QDSP6 */
202 writel(0x1, adsp
->qdsp6ss_base
+ BOOT_CMD_REG
);
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
);
208 dev_err(adsp
->dev
, "failed to bootup adsp\n");
209 goto disable_adsp_clks
;
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
;
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
);
226 clk_disable_unprepare(adsp
->xo
);
228 qcom_q6v5_unprepare(&adsp
->q6v5
);
233 static void qcom_adsp_pil_handover(struct qcom_q6v5
*q6v5
)
235 struct qcom_adsp
*adsp
= container_of(q6v5
, struct qcom_adsp
, q6v5
);
237 clk_disable_unprepare(adsp
->xo
);
238 dev_pm_genpd_set_performance_state(adsp
->dev
, 0);
239 pm_runtime_put(adsp
->dev
);
242 static int adsp_stop(struct rproc
*rproc
)
244 struct qcom_adsp
*adsp
= (struct qcom_adsp
*)rproc
->priv
;
248 ret
= qcom_q6v5_request_stop(&adsp
->q6v5
);
249 if (ret
== -ETIMEDOUT
)
250 dev_err(adsp
->dev
, "timed out on wait\n");
252 ret
= qcom_adsp_shutdown(adsp
);
254 dev_err(adsp
->dev
, "failed to shutdown: %d\n", ret
);
256 handover
= qcom_q6v5_unprepare(&adsp
->q6v5
);
258 qcom_adsp_pil_handover(&adsp
->q6v5
);
263 static void *adsp_da_to_va(struct rproc
*rproc
, u64 da
, int len
)
265 struct qcom_adsp
*adsp
= (struct qcom_adsp
*)rproc
->priv
;
268 offset
= da
- adsp
->mem_reloc
;
269 if (offset
< 0 || offset
+ len
> adsp
->mem_size
)
272 return adsp
->mem_region
+ offset
;
275 static const struct rproc_ops adsp_ops
= {
278 .da_to_va
= adsp_da_to_va
,
279 .parse_fw
= qcom_register_dump_segments
,
283 static int adsp_init_clock(struct qcom_adsp
*adsp
)
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");
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
);
301 for (i
= 0; i
< adsp
->num_clks
; i
++)
302 adsp
->clks
[i
].id
= adsp_clk_id
[i
];
304 return devm_clk_bulk_get(adsp
->dev
, adsp
->num_clks
, adsp
->clks
);
307 static int adsp_init_reset(struct qcom_adsp
*adsp
)
309 adsp
->pdc_sync_reset
= devm_reset_control_get_exclusive(adsp
->dev
,
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
);
316 adsp
->cc_lpass_restart
= devm_reset_control_get_exclusive(adsp
->dev
,
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
);
326 static int adsp_init_mmio(struct qcom_adsp
*adsp
,
327 struct platform_device
*pdev
)
329 struct device_node
*syscon
;
330 struct resource
*res
;
333 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
334 adsp
->qdsp6ss_base
= devm_ioremap(&pdev
->dev
, res
->start
,
336 if (!adsp
->qdsp6ss_base
) {
337 dev_err(adsp
->dev
, "failed to map QDSP6SS registers\n");
341 syscon
= of_parse_phandle(pdev
->dev
.of_node
, "qcom,halt-regs", 0);
343 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
347 adsp
->halt_map
= syscon_node_to_regmap(syscon
);
349 if (IS_ERR(adsp
->halt_map
))
350 return PTR_ERR(adsp
->halt_map
);
352 ret
= of_property_read_u32_index(pdev
->dev
.of_node
, "qcom,halt-regs",
353 1, &adsp
->halt_lpass
);
355 dev_err(&pdev
->dev
, "no offset in syscon\n");
362 static int adsp_alloc_memory_region(struct qcom_adsp
*adsp
)
364 struct device_node
*node
;
368 node
= of_parse_phandle(adsp
->dev
->of_node
, "memory-region", 0);
370 dev_err(adsp
->dev
, "no memory-region specified\n");
374 ret
= of_address_to_resource(node
, 0, &r
);
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
);
391 static int adsp_probe(struct platform_device
*pdev
)
393 const struct adsp_pil_data
*desc
;
394 struct qcom_adsp
*adsp
;
398 desc
= of_device_get_match_data(&pdev
->dev
);
402 rproc
= rproc_alloc(&pdev
->dev
, pdev
->name
, &adsp_ops
,
403 desc
->firmware_name
, sizeof(*adsp
));
405 dev_err(&pdev
->dev
, "unable to allocate remoteproc\n");
409 adsp
= (struct qcom_adsp
*)rproc
->priv
;
410 adsp
->dev
= &pdev
->dev
;
412 platform_set_drvdata(pdev
, adsp
);
414 ret
= adsp_alloc_memory_region(adsp
);
418 ret
= adsp_init_clock(adsp
);
422 pm_runtime_enable(adsp
->dev
);
424 ret
= adsp_init_reset(adsp
);
428 ret
= adsp_init_mmio(adsp
, pdev
);
432 ret
= qcom_q6v5_init(&adsp
->q6v5
, pdev
, rproc
, desc
->crash_reason_smem
,
433 qcom_adsp_pil_handover
);
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
,
442 if (IS_ERR(adsp
->sysmon
)) {
443 ret
= PTR_ERR(adsp
->sysmon
);
447 ret
= rproc_add(rproc
);
454 pm_runtime_disable(adsp
->dev
);
461 static int adsp_remove(struct platform_device
*pdev
)
463 struct qcom_adsp
*adsp
= platform_get_drvdata(pdev
);
465 rproc_del(adsp
->rproc
);
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
);
476 static const struct adsp_pil_data adsp_resource_init
= {
477 .crash_reason_smem
= 423,
478 .firmware_name
= "adsp.mdt",
480 .sysmon_name
= "adsp",
484 static const struct of_device_id adsp_of_match
[] = {
485 { .compatible
= "qcom,sdm845-adsp-pil", .data
= &adsp_resource_init
},
488 MODULE_DEVICE_TABLE(of
, adsp_of_match
);
490 static struct platform_driver adsp_pil_driver
= {
492 .remove
= adsp_remove
,
494 .name
= "qcom_q6v5_adsp",
495 .of_match_table
= adsp_of_match
,
499 module_platform_driver(adsp_pil_driver
);
500 MODULE_DESCRIPTION("QTI SDM845 ADSP Peripheral Image Loader");
501 MODULE_LICENSE("GPL v2");