1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2016-2018 Linaro Ltd.
4 * Copyright (C) 2014 Sony Mobile Communications AB
5 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
7 #include <linux/iopoll.h>
8 #include <linux/kernel.h>
9 #include <linux/mfd/syscon.h>
10 #include <linux/module.h>
11 #include <linux/of_reserved_mem.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/reset.h>
15 #include <linux/soc/qcom/mdt_loader.h>
16 #include "qcom_common.h"
17 #include "qcom_pil_info.h"
18 #include "qcom_q6v5.h"
20 #define WCSS_CRASH_REASON 421
22 /* Q6SS Register Offsets */
23 #define Q6SS_RESET_REG 0x014
24 #define Q6SS_GFMUX_CTL_REG 0x020
25 #define Q6SS_PWR_CTL_REG 0x030
26 #define Q6SS_MEM_PWR_CTL 0x0B0
28 /* AXI Halt Register Offsets */
29 #define AXI_HALTREQ_REG 0x0
30 #define AXI_HALTACK_REG 0x4
31 #define AXI_IDLE_REG 0x8
33 #define HALT_ACK_TIMEOUT_MS 100
36 #define Q6SS_STOP_CORE BIT(0)
37 #define Q6SS_CORE_ARES BIT(1)
38 #define Q6SS_BUS_ARES_ENABLE BIT(2)
41 #define Q6SS_CLK_ENABLE BIT(1)
44 #define Q6SS_L2DATA_STBY_N BIT(18)
45 #define Q6SS_SLP_RET_N BIT(19)
46 #define Q6SS_CLAMP_IO BIT(20)
47 #define QDSS_BHS_ON BIT(21)
50 #define Q6SS_LDO_BYP BIT(25)
51 #define Q6SS_BHS_ON BIT(24)
52 #define Q6SS_CLAMP_WL BIT(21)
53 #define Q6SS_CLAMP_QMC_MEM BIT(22)
54 #define HALT_CHECK_MAX_LOOPS 200
55 #define Q6SS_XO_CBCR GENMASK(5, 3)
57 /* Q6SS config/status registers */
58 #define TCSR_GLOBAL_CFG0 0x0
59 #define TCSR_GLOBAL_CFG1 0x4
60 #define SSCAON_CONFIG 0x8
61 #define SSCAON_STATUS 0xc
62 #define Q6SS_BHS_STATUS 0x78
63 #define Q6SS_RST_EVB 0x10
65 #define BHS_EN_REST_ACK BIT(0)
66 #define SSCAON_ENABLE BIT(13)
67 #define SSCAON_BUS_EN BIT(15)
68 #define SSCAON_BUS_MUX_MASK GENMASK(18, 16)
71 #define TCSR_WCSS_CLK_MASK 0x1F
72 #define TCSR_WCSS_CLK_ENABLE 0x14
77 void __iomem
*reg_base
;
78 void __iomem
*rmb_base
;
80 struct regmap
*halt_map
;
85 struct reset_control
*wcss_aon_reset
;
86 struct reset_control
*wcss_reset
;
87 struct reset_control
*wcss_q6_reset
;
89 struct qcom_q6v5 q6v5
;
92 phys_addr_t mem_reloc
;
96 struct qcom_rproc_glink glink_subdev
;
97 struct qcom_rproc_ssr ssr_subdev
;
100 static int q6v5_wcss_reset(struct q6v5_wcss
*wcss
)
106 /* Assert resets, stop core */
107 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
108 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
109 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
111 /* BHS require xo cbcr to be enabled */
112 val
= readl(wcss
->reg_base
+ Q6SS_XO_CBCR
);
114 writel(val
, wcss
->reg_base
+ Q6SS_XO_CBCR
);
116 /* Read CLKOFF bit to go low indicating CLK is enabled */
117 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_XO_CBCR
,
118 val
, !(val
& BIT(31)), 1,
119 HALT_CHECK_MAX_LOOPS
);
122 "xo cbcr enabling timed out (rc:%d)\n", ret
);
125 /* Enable power block headswitch and wait for it to stabilize */
126 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
128 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
131 /* Put LDO in bypass mode */
133 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
135 /* Deassert Q6 compiler memory clamp */
136 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
137 val
&= ~Q6SS_CLAMP_QMC_MEM
;
138 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
140 /* Deassert memory peripheral sleep and L2 memory standby */
141 val
|= Q6SS_L2DATA_STBY_N
| Q6SS_SLP_RET_N
;
142 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
144 /* Turn on L1, L2, ETB and JU memories 1 at a time */
145 val
= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
146 for (i
= MEM_BANKS
; i
>= 0; i
--) {
148 writel(val
, wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
150 * Read back value to ensure the write is done then
151 * wait for 1us for both memory peripheral and data
154 val
|= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
157 /* Remove word line clamp */
158 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
159 val
&= ~Q6SS_CLAMP_WL
;
160 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
162 /* Remove IO clamp */
163 val
&= ~Q6SS_CLAMP_IO
;
164 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
166 /* Bring core out of reset */
167 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
168 val
&= ~Q6SS_CORE_ARES
;
169 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
171 /* Turn on core clock */
172 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
173 val
|= Q6SS_CLK_ENABLE
;
174 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
176 /* Start core execution */
177 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
178 val
&= ~Q6SS_STOP_CORE
;
179 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
184 static int q6v5_wcss_start(struct rproc
*rproc
)
186 struct q6v5_wcss
*wcss
= rproc
->priv
;
189 qcom_q6v5_prepare(&wcss
->q6v5
);
191 /* Release Q6 and WCSS reset */
192 ret
= reset_control_deassert(wcss
->wcss_reset
);
194 dev_err(wcss
->dev
, "wcss_reset failed\n");
198 ret
= reset_control_deassert(wcss
->wcss_q6_reset
);
200 dev_err(wcss
->dev
, "wcss_q6_reset failed\n");
204 /* Lithium configuration - clock gating and bus arbitration */
205 ret
= regmap_update_bits(wcss
->halt_map
,
206 wcss
->halt_nc
+ TCSR_GLOBAL_CFG0
,
208 TCSR_WCSS_CLK_ENABLE
);
212 ret
= regmap_update_bits(wcss
->halt_map
,
213 wcss
->halt_nc
+ TCSR_GLOBAL_CFG1
,
218 /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
219 writel(rproc
->bootaddr
>> 4, wcss
->reg_base
+ Q6SS_RST_EVB
);
221 ret
= q6v5_wcss_reset(wcss
);
225 ret
= qcom_q6v5_wait_for_start(&wcss
->q6v5
, 5 * HZ
);
226 if (ret
== -ETIMEDOUT
)
227 dev_err(wcss
->dev
, "start timed out\n");
232 reset_control_assert(wcss
->wcss_q6_reset
);
235 reset_control_assert(wcss
->wcss_reset
);
240 static void q6v5_wcss_halt_axi_port(struct q6v5_wcss
*wcss
,
241 struct regmap
*halt_map
,
244 unsigned long timeout
;
248 /* Check if we're already idle */
249 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
253 /* Assert halt request */
254 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 1);
257 timeout
= jiffies
+ msecs_to_jiffies(HALT_ACK_TIMEOUT_MS
);
259 ret
= regmap_read(halt_map
, offset
+ AXI_HALTACK_REG
, &val
);
260 if (ret
|| val
|| time_after(jiffies
, timeout
))
266 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
268 dev_err(wcss
->dev
, "port failed halt\n");
270 /* Clear halt request (port will remain halted until reset) */
271 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 0);
274 static int q6v5_wcss_powerdown(struct q6v5_wcss
*wcss
)
279 /* 1 - Assert WCSS/Q6 HALTREQ */
280 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_wcss
);
282 /* 2 - Enable WCSSAON_CONFIG */
283 val
= readl(wcss
->rmb_base
+ SSCAON_CONFIG
);
284 val
|= SSCAON_ENABLE
;
285 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
287 /* 3 - Set SSCAON_CONFIG */
288 val
|= SSCAON_BUS_EN
;
289 val
&= ~SSCAON_BUS_MUX_MASK
;
290 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
292 /* 4 - SSCAON_CONFIG 1 */
294 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
296 /* 5 - wait for SSCAON_STATUS */
297 ret
= readl_poll_timeout(wcss
->rmb_base
+ SSCAON_STATUS
,
298 val
, (val
& 0xffff) == 0x400, 1000,
299 HALT_CHECK_MAX_LOOPS
);
302 "can't get SSCAON_STATUS rc:%d)\n", ret
);
306 /* 6 - De-assert WCSS_AON reset */
307 reset_control_assert(wcss
->wcss_aon_reset
);
309 /* 7 - Disable WCSSAON_CONFIG 13 */
310 val
= readl(wcss
->rmb_base
+ SSCAON_CONFIG
);
311 val
&= ~SSCAON_ENABLE
;
312 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
314 /* 8 - De-assert WCSS/Q6 HALTREQ */
315 reset_control_assert(wcss
->wcss_reset
);
320 static int q6v5_q6_powerdown(struct q6v5_wcss
*wcss
)
326 /* 1 - Halt Q6 bus interface */
327 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_q6
);
329 /* 2 - Disable Q6 Core clock */
330 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
331 val
&= ~Q6SS_CLK_ENABLE
;
332 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
335 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
336 val
|= Q6SS_CLAMP_IO
;
337 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
341 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
343 /* 5 - Clear Erase standby */
344 val
&= ~Q6SS_L2DATA_STBY_N
;
345 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
347 /* 6 - Clear Sleep RTN */
348 val
&= ~Q6SS_SLP_RET_N
;
349 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
351 /* 7 - turn off Q6 memory foot/head switch one bank at a time */
352 for (i
= 0; i
< 20; i
++) {
353 val
= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
355 writel(val
, wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
359 /* 8 - Assert QMC memory RTN */
360 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
361 val
|= Q6SS_CLAMP_QMC_MEM
;
362 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
364 /* 9 - Turn off BHS */
366 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
369 /* 10 - Wait till BHS Reset is done */
370 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_BHS_STATUS
,
371 val
, !(val
& BHS_EN_REST_ACK
), 1000,
372 HALT_CHECK_MAX_LOOPS
);
374 dev_err(wcss
->dev
, "BHS_STATUS not OFF (rc:%d)\n", ret
);
378 /* 11 - Assert WCSS reset */
379 reset_control_assert(wcss
->wcss_reset
);
381 /* 12 - Assert Q6 reset */
382 reset_control_assert(wcss
->wcss_q6_reset
);
387 static int q6v5_wcss_stop(struct rproc
*rproc
)
389 struct q6v5_wcss
*wcss
= rproc
->priv
;
393 ret
= qcom_q6v5_request_stop(&wcss
->q6v5
, NULL
);
394 if (ret
== -ETIMEDOUT
) {
395 dev_err(wcss
->dev
, "timed out on wait\n");
399 ret
= q6v5_wcss_powerdown(wcss
);
404 ret
= q6v5_q6_powerdown(wcss
);
408 qcom_q6v5_unprepare(&wcss
->q6v5
);
413 static void *q6v5_wcss_da_to_va(struct rproc
*rproc
, u64 da
, size_t len
)
415 struct q6v5_wcss
*wcss
= rproc
->priv
;
418 offset
= da
- wcss
->mem_reloc
;
419 if (offset
< 0 || offset
+ len
> wcss
->mem_size
)
422 return wcss
->mem_region
+ offset
;
425 static int q6v5_wcss_load(struct rproc
*rproc
, const struct firmware
*fw
)
427 struct q6v5_wcss
*wcss
= rproc
->priv
;
430 ret
= qcom_mdt_load_no_init(wcss
->dev
, fw
, rproc
->firmware
,
431 0, wcss
->mem_region
, wcss
->mem_phys
,
432 wcss
->mem_size
, &wcss
->mem_reloc
);
436 qcom_pil_info_store("wcnss", wcss
->mem_phys
, wcss
->mem_size
);
441 static const struct rproc_ops q6v5_wcss_ops
= {
442 .start
= q6v5_wcss_start
,
443 .stop
= q6v5_wcss_stop
,
444 .da_to_va
= q6v5_wcss_da_to_va
,
445 .load
= q6v5_wcss_load
,
446 .get_boot_addr
= rproc_elf_get_boot_addr
,
449 static int q6v5_wcss_init_reset(struct q6v5_wcss
*wcss
)
451 struct device
*dev
= wcss
->dev
;
453 wcss
->wcss_aon_reset
= devm_reset_control_get(dev
, "wcss_aon_reset");
454 if (IS_ERR(wcss
->wcss_aon_reset
)) {
455 dev_err(wcss
->dev
, "unable to acquire wcss_aon_reset\n");
456 return PTR_ERR(wcss
->wcss_aon_reset
);
459 wcss
->wcss_reset
= devm_reset_control_get(dev
, "wcss_reset");
460 if (IS_ERR(wcss
->wcss_reset
)) {
461 dev_err(wcss
->dev
, "unable to acquire wcss_reset\n");
462 return PTR_ERR(wcss
->wcss_reset
);
465 wcss
->wcss_q6_reset
= devm_reset_control_get(dev
, "wcss_q6_reset");
466 if (IS_ERR(wcss
->wcss_q6_reset
)) {
467 dev_err(wcss
->dev
, "unable to acquire wcss_q6_reset\n");
468 return PTR_ERR(wcss
->wcss_q6_reset
);
474 static int q6v5_wcss_init_mmio(struct q6v5_wcss
*wcss
,
475 struct platform_device
*pdev
)
477 struct of_phandle_args args
;
478 struct resource
*res
;
481 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "qdsp6");
482 wcss
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
483 if (IS_ERR(wcss
->reg_base
))
484 return PTR_ERR(wcss
->reg_base
);
486 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "rmb");
487 wcss
->rmb_base
= devm_ioremap_resource(&pdev
->dev
, res
);
488 if (IS_ERR(wcss
->rmb_base
))
489 return PTR_ERR(wcss
->rmb_base
);
491 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
492 "qcom,halt-regs", 3, 0, &args
);
494 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
498 wcss
->halt_map
= syscon_node_to_regmap(args
.np
);
499 of_node_put(args
.np
);
500 if (IS_ERR(wcss
->halt_map
))
501 return PTR_ERR(wcss
->halt_map
);
503 wcss
->halt_q6
= args
.args
[0];
504 wcss
->halt_wcss
= args
.args
[1];
505 wcss
->halt_nc
= args
.args
[2];
510 static int q6v5_alloc_memory_region(struct q6v5_wcss
*wcss
)
512 struct reserved_mem
*rmem
= NULL
;
513 struct device_node
*node
;
514 struct device
*dev
= wcss
->dev
;
516 node
= of_parse_phandle(dev
->of_node
, "memory-region", 0);
518 rmem
= of_reserved_mem_lookup(node
);
522 dev_err(dev
, "unable to acquire memory-region\n");
526 wcss
->mem_phys
= rmem
->base
;
527 wcss
->mem_reloc
= rmem
->base
;
528 wcss
->mem_size
= rmem
->size
;
529 wcss
->mem_region
= devm_ioremap_wc(dev
, wcss
->mem_phys
, wcss
->mem_size
);
530 if (!wcss
->mem_region
) {
531 dev_err(dev
, "unable to map memory region: %pa+%pa\n",
532 &rmem
->base
, &rmem
->size
);
539 static int q6v5_wcss_probe(struct platform_device
*pdev
)
541 struct q6v5_wcss
*wcss
;
545 rproc
= rproc_alloc(&pdev
->dev
, pdev
->name
, &q6v5_wcss_ops
,
546 "IPQ8074/q6_fw.mdt", sizeof(*wcss
));
548 dev_err(&pdev
->dev
, "failed to allocate rproc\n");
553 wcss
->dev
= &pdev
->dev
;
555 ret
= q6v5_wcss_init_mmio(wcss
, pdev
);
559 ret
= q6v5_alloc_memory_region(wcss
);
563 ret
= q6v5_wcss_init_reset(wcss
);
567 ret
= qcom_q6v5_init(&wcss
->q6v5
, pdev
, rproc
, WCSS_CRASH_REASON
, NULL
);
571 qcom_add_glink_subdev(rproc
, &wcss
->glink_subdev
, "q6wcss");
572 qcom_add_ssr_subdev(rproc
, &wcss
->ssr_subdev
, "q6wcss");
574 ret
= rproc_add(rproc
);
578 platform_set_drvdata(pdev
, rproc
);
588 static int q6v5_wcss_remove(struct platform_device
*pdev
)
590 struct rproc
*rproc
= platform_get_drvdata(pdev
);
598 static const struct of_device_id q6v5_wcss_of_match
[] = {
599 { .compatible
= "qcom,ipq8074-wcss-pil" },
602 MODULE_DEVICE_TABLE(of
, q6v5_wcss_of_match
);
604 static struct platform_driver q6v5_wcss_driver
= {
605 .probe
= q6v5_wcss_probe
,
606 .remove
= q6v5_wcss_remove
,
608 .name
= "qcom-q6v5-wcss-pil",
609 .of_match_table
= q6v5_wcss_of_match
,
612 module_platform_driver(q6v5_wcss_driver
);
614 MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
615 MODULE_LICENSE("GPL v2");