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_q6v5.h"
19 #define WCSS_CRASH_REASON 421
21 /* Q6SS Register Offsets */
22 #define Q6SS_RESET_REG 0x014
23 #define Q6SS_GFMUX_CTL_REG 0x020
24 #define Q6SS_PWR_CTL_REG 0x030
25 #define Q6SS_MEM_PWR_CTL 0x0B0
27 /* AXI Halt Register Offsets */
28 #define AXI_HALTREQ_REG 0x0
29 #define AXI_HALTACK_REG 0x4
30 #define AXI_IDLE_REG 0x8
32 #define HALT_ACK_TIMEOUT_MS 100
35 #define Q6SS_STOP_CORE BIT(0)
36 #define Q6SS_CORE_ARES BIT(1)
37 #define Q6SS_BUS_ARES_ENABLE BIT(2)
40 #define Q6SS_CLK_ENABLE BIT(1)
43 #define Q6SS_L2DATA_STBY_N BIT(18)
44 #define Q6SS_SLP_RET_N BIT(19)
45 #define Q6SS_CLAMP_IO BIT(20)
46 #define QDSS_BHS_ON BIT(21)
49 #define Q6SS_LDO_BYP BIT(25)
50 #define Q6SS_BHS_ON BIT(24)
51 #define Q6SS_CLAMP_WL BIT(21)
52 #define Q6SS_CLAMP_QMC_MEM BIT(22)
53 #define HALT_CHECK_MAX_LOOPS 200
54 #define Q6SS_XO_CBCR GENMASK(5, 3)
56 /* Q6SS config/status registers */
57 #define TCSR_GLOBAL_CFG0 0x0
58 #define TCSR_GLOBAL_CFG1 0x4
59 #define SSCAON_CONFIG 0x8
60 #define SSCAON_STATUS 0xc
61 #define Q6SS_BHS_STATUS 0x78
62 #define Q6SS_RST_EVB 0x10
64 #define BHS_EN_REST_ACK BIT(0)
65 #define SSCAON_ENABLE BIT(13)
66 #define SSCAON_BUS_EN BIT(15)
67 #define SSCAON_BUS_MUX_MASK GENMASK(18, 16)
70 #define TCSR_WCSS_CLK_MASK 0x1F
71 #define TCSR_WCSS_CLK_ENABLE 0x14
76 void __iomem
*reg_base
;
77 void __iomem
*rmb_base
;
79 struct regmap
*halt_map
;
84 struct reset_control
*wcss_aon_reset
;
85 struct reset_control
*wcss_reset
;
86 struct reset_control
*wcss_q6_reset
;
88 struct qcom_q6v5 q6v5
;
91 phys_addr_t mem_reloc
;
96 static int q6v5_wcss_reset(struct q6v5_wcss
*wcss
)
102 /* Assert resets, stop core */
103 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
104 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
105 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
107 /* BHS require xo cbcr to be enabled */
108 val
= readl(wcss
->reg_base
+ Q6SS_XO_CBCR
);
110 writel(val
, wcss
->reg_base
+ Q6SS_XO_CBCR
);
112 /* Read CLKOFF bit to go low indicating CLK is enabled */
113 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_XO_CBCR
,
114 val
, !(val
& BIT(31)), 1,
115 HALT_CHECK_MAX_LOOPS
);
118 "xo cbcr enabling timed out (rc:%d)\n", ret
);
121 /* Enable power block headswitch and wait for it to stabilize */
122 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
124 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
127 /* Put LDO in bypass mode */
129 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
131 /* Deassert Q6 compiler memory clamp */
132 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
133 val
&= ~Q6SS_CLAMP_QMC_MEM
;
134 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
136 /* Deassert memory peripheral sleep and L2 memory standby */
137 val
|= Q6SS_L2DATA_STBY_N
| Q6SS_SLP_RET_N
;
138 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
140 /* Turn on L1, L2, ETB and JU memories 1 at a time */
141 val
= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
142 for (i
= MEM_BANKS
; i
>= 0; i
--) {
144 writel(val
, wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
146 * Read back value to ensure the write is done then
147 * wait for 1us for both memory peripheral and data
150 val
|= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
153 /* Remove word line clamp */
154 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
155 val
&= ~Q6SS_CLAMP_WL
;
156 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
158 /* Remove IO clamp */
159 val
&= ~Q6SS_CLAMP_IO
;
160 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
162 /* Bring core out of reset */
163 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
164 val
&= ~Q6SS_CORE_ARES
;
165 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
167 /* Turn on core clock */
168 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
169 val
|= Q6SS_CLK_ENABLE
;
170 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
172 /* Start core execution */
173 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
174 val
&= ~Q6SS_STOP_CORE
;
175 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
180 static int q6v5_wcss_start(struct rproc
*rproc
)
182 struct q6v5_wcss
*wcss
= rproc
->priv
;
185 qcom_q6v5_prepare(&wcss
->q6v5
);
187 /* Release Q6 and WCSS reset */
188 ret
= reset_control_deassert(wcss
->wcss_reset
);
190 dev_err(wcss
->dev
, "wcss_reset failed\n");
194 ret
= reset_control_deassert(wcss
->wcss_q6_reset
);
196 dev_err(wcss
->dev
, "wcss_q6_reset failed\n");
200 /* Lithium configuration - clock gating and bus arbitration */
201 ret
= regmap_update_bits(wcss
->halt_map
,
202 wcss
->halt_nc
+ TCSR_GLOBAL_CFG0
,
204 TCSR_WCSS_CLK_ENABLE
);
208 ret
= regmap_update_bits(wcss
->halt_map
,
209 wcss
->halt_nc
+ TCSR_GLOBAL_CFG1
,
214 /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
215 writel(rproc
->bootaddr
>> 4, wcss
->reg_base
+ Q6SS_RST_EVB
);
217 ret
= q6v5_wcss_reset(wcss
);
221 ret
= qcom_q6v5_wait_for_start(&wcss
->q6v5
, 5 * HZ
);
222 if (ret
== -ETIMEDOUT
)
223 dev_err(wcss
->dev
, "start timed out\n");
228 reset_control_assert(wcss
->wcss_q6_reset
);
231 reset_control_assert(wcss
->wcss_reset
);
236 static void q6v5_wcss_halt_axi_port(struct q6v5_wcss
*wcss
,
237 struct regmap
*halt_map
,
240 unsigned long timeout
;
244 /* Check if we're already idle */
245 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
249 /* Assert halt request */
250 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 1);
253 timeout
= jiffies
+ msecs_to_jiffies(HALT_ACK_TIMEOUT_MS
);
255 ret
= regmap_read(halt_map
, offset
+ AXI_HALTACK_REG
, &val
);
256 if (ret
|| val
|| time_after(jiffies
, timeout
))
262 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
264 dev_err(wcss
->dev
, "port failed halt\n");
266 /* Clear halt request (port will remain halted until reset) */
267 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 0);
270 static int q6v5_wcss_powerdown(struct q6v5_wcss
*wcss
)
275 /* 1 - Assert WCSS/Q6 HALTREQ */
276 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_wcss
);
278 /* 2 - Enable WCSSAON_CONFIG */
279 val
= readl(wcss
->rmb_base
+ SSCAON_CONFIG
);
280 val
|= SSCAON_ENABLE
;
281 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
283 /* 3 - Set SSCAON_CONFIG */
284 val
|= SSCAON_BUS_EN
;
285 val
&= ~SSCAON_BUS_MUX_MASK
;
286 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
288 /* 4 - SSCAON_CONFIG 1 */
290 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
292 /* 5 - wait for SSCAON_STATUS */
293 ret
= readl_poll_timeout(wcss
->rmb_base
+ SSCAON_STATUS
,
294 val
, (val
& 0xffff) == 0x400, 1000,
295 HALT_CHECK_MAX_LOOPS
);
298 "can't get SSCAON_STATUS rc:%d)\n", ret
);
302 /* 6 - De-assert WCSS_AON reset */
303 reset_control_assert(wcss
->wcss_aon_reset
);
305 /* 7 - Disable WCSSAON_CONFIG 13 */
306 val
= readl(wcss
->rmb_base
+ SSCAON_CONFIG
);
307 val
&= ~SSCAON_ENABLE
;
308 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
310 /* 8 - De-assert WCSS/Q6 HALTREQ */
311 reset_control_assert(wcss
->wcss_reset
);
316 static int q6v5_q6_powerdown(struct q6v5_wcss
*wcss
)
322 /* 1 - Halt Q6 bus interface */
323 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_q6
);
325 /* 2 - Disable Q6 Core clock */
326 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
327 val
&= ~Q6SS_CLK_ENABLE
;
328 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
331 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
332 val
|= Q6SS_CLAMP_IO
;
333 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
337 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
339 /* 5 - Clear Erase standby */
340 val
&= ~Q6SS_L2DATA_STBY_N
;
341 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
343 /* 6 - Clear Sleep RTN */
344 val
&= ~Q6SS_SLP_RET_N
;
345 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
347 /* 7 - turn off Q6 memory foot/head switch one bank at a time */
348 for (i
= 0; i
< 20; i
++) {
349 val
= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
351 writel(val
, wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
355 /* 8 - Assert QMC memory RTN */
356 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
357 val
|= Q6SS_CLAMP_QMC_MEM
;
358 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
360 /* 9 - Turn off BHS */
362 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
365 /* 10 - Wait till BHS Reset is done */
366 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_BHS_STATUS
,
367 val
, !(val
& BHS_EN_REST_ACK
), 1000,
368 HALT_CHECK_MAX_LOOPS
);
370 dev_err(wcss
->dev
, "BHS_STATUS not OFF (rc:%d)\n", ret
);
374 /* 11 - Assert WCSS reset */
375 reset_control_assert(wcss
->wcss_reset
);
377 /* 12 - Assert Q6 reset */
378 reset_control_assert(wcss
->wcss_q6_reset
);
383 static int q6v5_wcss_stop(struct rproc
*rproc
)
385 struct q6v5_wcss
*wcss
= rproc
->priv
;
389 ret
= qcom_q6v5_request_stop(&wcss
->q6v5
);
390 if (ret
== -ETIMEDOUT
) {
391 dev_err(wcss
->dev
, "timed out on wait\n");
395 ret
= q6v5_wcss_powerdown(wcss
);
400 ret
= q6v5_q6_powerdown(wcss
);
404 qcom_q6v5_unprepare(&wcss
->q6v5
);
409 static void *q6v5_wcss_da_to_va(struct rproc
*rproc
, u64 da
, int len
)
411 struct q6v5_wcss
*wcss
= rproc
->priv
;
414 offset
= da
- wcss
->mem_reloc
;
415 if (offset
< 0 || offset
+ len
> wcss
->mem_size
)
418 return wcss
->mem_region
+ offset
;
421 static int q6v5_wcss_load(struct rproc
*rproc
, const struct firmware
*fw
)
423 struct q6v5_wcss
*wcss
= rproc
->priv
;
425 return qcom_mdt_load_no_init(wcss
->dev
, fw
, rproc
->firmware
,
426 0, wcss
->mem_region
, wcss
->mem_phys
,
427 wcss
->mem_size
, &wcss
->mem_reloc
);
430 static const struct rproc_ops q6v5_wcss_ops
= {
431 .start
= q6v5_wcss_start
,
432 .stop
= q6v5_wcss_stop
,
433 .da_to_va
= q6v5_wcss_da_to_va
,
434 .load
= q6v5_wcss_load
,
435 .get_boot_addr
= rproc_elf_get_boot_addr
,
438 static int q6v5_wcss_init_reset(struct q6v5_wcss
*wcss
)
440 struct device
*dev
= wcss
->dev
;
442 wcss
->wcss_aon_reset
= devm_reset_control_get(dev
, "wcss_aon_reset");
443 if (IS_ERR(wcss
->wcss_aon_reset
)) {
444 dev_err(wcss
->dev
, "unable to acquire wcss_aon_reset\n");
445 return PTR_ERR(wcss
->wcss_aon_reset
);
448 wcss
->wcss_reset
= devm_reset_control_get(dev
, "wcss_reset");
449 if (IS_ERR(wcss
->wcss_reset
)) {
450 dev_err(wcss
->dev
, "unable to acquire wcss_reset\n");
451 return PTR_ERR(wcss
->wcss_reset
);
454 wcss
->wcss_q6_reset
= devm_reset_control_get(dev
, "wcss_q6_reset");
455 if (IS_ERR(wcss
->wcss_q6_reset
)) {
456 dev_err(wcss
->dev
, "unable to acquire wcss_q6_reset\n");
457 return PTR_ERR(wcss
->wcss_q6_reset
);
463 static int q6v5_wcss_init_mmio(struct q6v5_wcss
*wcss
,
464 struct platform_device
*pdev
)
466 struct of_phandle_args args
;
467 struct resource
*res
;
470 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "qdsp6");
471 wcss
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
472 if (IS_ERR(wcss
->reg_base
))
473 return PTR_ERR(wcss
->reg_base
);
475 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "rmb");
476 wcss
->rmb_base
= devm_ioremap_resource(&pdev
->dev
, res
);
477 if (IS_ERR(wcss
->rmb_base
))
478 return PTR_ERR(wcss
->rmb_base
);
480 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
481 "qcom,halt-regs", 3, 0, &args
);
483 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
487 wcss
->halt_map
= syscon_node_to_regmap(args
.np
);
488 of_node_put(args
.np
);
489 if (IS_ERR(wcss
->halt_map
))
490 return PTR_ERR(wcss
->halt_map
);
492 wcss
->halt_q6
= args
.args
[0];
493 wcss
->halt_wcss
= args
.args
[1];
494 wcss
->halt_nc
= args
.args
[2];
499 static int q6v5_alloc_memory_region(struct q6v5_wcss
*wcss
)
501 struct reserved_mem
*rmem
= NULL
;
502 struct device_node
*node
;
503 struct device
*dev
= wcss
->dev
;
505 node
= of_parse_phandle(dev
->of_node
, "memory-region", 0);
507 rmem
= of_reserved_mem_lookup(node
);
511 dev_err(dev
, "unable to acquire memory-region\n");
515 wcss
->mem_phys
= rmem
->base
;
516 wcss
->mem_reloc
= rmem
->base
;
517 wcss
->mem_size
= rmem
->size
;
518 wcss
->mem_region
= devm_ioremap_wc(dev
, wcss
->mem_phys
, wcss
->mem_size
);
519 if (!wcss
->mem_region
) {
520 dev_err(dev
, "unable to map memory region: %pa+%pa\n",
521 &rmem
->base
, &rmem
->size
);
528 static int q6v5_wcss_probe(struct platform_device
*pdev
)
530 struct q6v5_wcss
*wcss
;
534 rproc
= rproc_alloc(&pdev
->dev
, pdev
->name
, &q6v5_wcss_ops
,
535 "IPQ8074/q6_fw.mdt", sizeof(*wcss
));
537 dev_err(&pdev
->dev
, "failed to allocate rproc\n");
542 wcss
->dev
= &pdev
->dev
;
544 ret
= q6v5_wcss_init_mmio(wcss
, pdev
);
548 ret
= q6v5_alloc_memory_region(wcss
);
552 ret
= q6v5_wcss_init_reset(wcss
);
556 ret
= qcom_q6v5_init(&wcss
->q6v5
, pdev
, rproc
, WCSS_CRASH_REASON
, NULL
);
560 ret
= rproc_add(rproc
);
564 platform_set_drvdata(pdev
, rproc
);
574 static int q6v5_wcss_remove(struct platform_device
*pdev
)
576 struct rproc
*rproc
= platform_get_drvdata(pdev
);
584 static const struct of_device_id q6v5_wcss_of_match
[] = {
585 { .compatible
= "qcom,ipq8074-wcss-pil" },
588 MODULE_DEVICE_TABLE(of
, q6v5_wcss_of_match
);
590 static struct platform_driver q6v5_wcss_driver
= {
591 .probe
= q6v5_wcss_probe
,
592 .remove
= q6v5_wcss_remove
,
594 .name
= "qcom-q6v5-wcss-pil",
595 .of_match_table
= q6v5_wcss_of_match
,
598 module_platform_driver(q6v5_wcss_driver
);
600 MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
601 MODULE_LICENSE("GPL v2");