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.
8 #include <linux/delay.h>
10 #include <linux/iopoll.h>
11 #include <linux/kernel.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <linux/of_address.h>
15 #include <linux/of_reserved_mem.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/reset.h>
20 #include <linux/soc/qcom/mdt_loader.h>
21 #include "qcom_common.h"
22 #include "qcom_pil_info.h"
23 #include "qcom_q6v5.h"
25 #define WCSS_CRASH_REASON 421
27 /* Q6SS Register Offsets */
28 #define Q6SS_RESET_REG 0x014
29 #define Q6SS_GFMUX_CTL_REG 0x020
30 #define Q6SS_PWR_CTL_REG 0x030
31 #define Q6SS_MEM_PWR_CTL 0x0B0
32 #define Q6SS_STRAP_ACC 0x110
33 #define Q6SS_CGC_OVERRIDE 0x034
34 #define Q6SS_BCR_REG 0x6000
36 /* AXI Halt Register Offsets */
37 #define AXI_HALTREQ_REG 0x0
38 #define AXI_HALTACK_REG 0x4
39 #define AXI_IDLE_REG 0x8
41 #define HALT_ACK_TIMEOUT_MS 100
44 #define Q6SS_STOP_CORE BIT(0)
45 #define Q6SS_CORE_ARES BIT(1)
46 #define Q6SS_BUS_ARES_ENABLE BIT(2)
49 #define Q6SS_BRC_BLK_ARES BIT(0)
52 #define Q6SS_CLK_ENABLE BIT(1)
53 #define Q6SS_SWITCH_CLK_SRC BIT(8)
56 #define Q6SS_L2DATA_STBY_N BIT(18)
57 #define Q6SS_SLP_RET_N BIT(19)
58 #define Q6SS_CLAMP_IO BIT(20)
59 #define QDSS_BHS_ON BIT(21)
60 #define QDSS_Q6_MEMORIES GENMASK(15, 0)
63 #define Q6SS_LDO_BYP BIT(25)
64 #define Q6SS_BHS_ON BIT(24)
65 #define Q6SS_CLAMP_WL BIT(21)
66 #define Q6SS_CLAMP_QMC_MEM BIT(22)
67 #define HALT_CHECK_MAX_LOOPS 200
68 #define Q6SS_XO_CBCR GENMASK(5, 3)
69 #define Q6SS_SLEEP_CBCR GENMASK(5, 2)
71 /* Q6SS config/status registers */
72 #define TCSR_GLOBAL_CFG0 0x0
73 #define TCSR_GLOBAL_CFG1 0x4
74 #define SSCAON_CONFIG 0x8
75 #define SSCAON_STATUS 0xc
76 #define Q6SS_BHS_STATUS 0x78
77 #define Q6SS_RST_EVB 0x10
79 #define BHS_EN_REST_ACK BIT(0)
80 #define SSCAON_ENABLE BIT(13)
81 #define SSCAON_BUS_EN BIT(15)
82 #define SSCAON_BUS_MUX_MASK GENMASK(18, 16)
85 #define TCSR_WCSS_CLK_MASK 0x1F
86 #define TCSR_WCSS_CLK_ENABLE 0x14
88 #define MAX_HALT_REG 3
95 const char *firmware_name
;
96 unsigned int crash_reason_smem
;
98 bool aon_reset_required
;
99 bool wcss_q6_reset_required
;
100 const char *ssr_name
;
101 const char *sysmon_name
;
103 const struct rproc_ops
*ops
;
104 bool requires_force_stop
;
110 void __iomem
*reg_base
;
111 void __iomem
*rmb_base
;
113 struct regmap
*halt_map
;
119 struct clk
*ahbfabric_cbcr_clk
;
120 struct clk
*gcc_abhs_cbcr
;
121 struct clk
*gcc_axim_cbcr
;
122 struct clk
*lcc_csr_cbcr
;
123 struct clk
*ahbs_cbcr
;
124 struct clk
*tcm_slave_cbcr
;
125 struct clk
*qdsp6ss_abhm_cbcr
;
126 struct clk
*qdsp6ss_sleep_cbcr
;
127 struct clk
*qdsp6ss_axim_cbcr
;
128 struct clk
*qdsp6ss_xo_cbcr
;
129 struct clk
*qdsp6ss_core_gfmux
;
130 struct clk
*lcc_bcr_sleep
;
131 struct regulator
*cx_supply
;
132 struct qcom_sysmon
*sysmon
;
134 struct reset_control
*wcss_aon_reset
;
135 struct reset_control
*wcss_reset
;
136 struct reset_control
*wcss_q6_reset
;
137 struct reset_control
*wcss_q6_bcr_reset
;
139 struct qcom_q6v5 q6v5
;
141 phys_addr_t mem_phys
;
142 phys_addr_t mem_reloc
;
146 unsigned int crash_reason_smem
;
148 bool requires_force_stop
;
150 struct qcom_rproc_glink glink_subdev
;
151 struct qcom_rproc_pdm pdm_subdev
;
152 struct qcom_rproc_ssr ssr_subdev
;
155 static int q6v5_wcss_reset(struct q6v5_wcss
*wcss
)
161 /* Assert resets, stop core */
162 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
163 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
164 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
166 /* BHS require xo cbcr to be enabled */
167 val
= readl(wcss
->reg_base
+ Q6SS_XO_CBCR
);
169 writel(val
, wcss
->reg_base
+ Q6SS_XO_CBCR
);
171 /* Read CLKOFF bit to go low indicating CLK is enabled */
172 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_XO_CBCR
,
173 val
, !(val
& BIT(31)), 1,
174 HALT_CHECK_MAX_LOOPS
);
177 "xo cbcr enabling timed out (rc:%d)\n", ret
);
180 /* Enable power block headswitch and wait for it to stabilize */
181 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
183 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
186 /* Put LDO in bypass mode */
188 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
190 /* Deassert Q6 compiler memory clamp */
191 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
192 val
&= ~Q6SS_CLAMP_QMC_MEM
;
193 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
195 /* Deassert memory peripheral sleep and L2 memory standby */
196 val
|= Q6SS_L2DATA_STBY_N
| Q6SS_SLP_RET_N
;
197 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
199 /* Turn on L1, L2, ETB and JU memories 1 at a time */
200 val
= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
201 for (i
= MEM_BANKS
; i
>= 0; i
--) {
203 writel(val
, wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
205 * Read back value to ensure the write is done then
206 * wait for 1us for both memory peripheral and data
209 val
|= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
212 /* Remove word line clamp */
213 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
214 val
&= ~Q6SS_CLAMP_WL
;
215 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
217 /* Remove IO clamp */
218 val
&= ~Q6SS_CLAMP_IO
;
219 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
221 /* Bring core out of reset */
222 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
223 val
&= ~Q6SS_CORE_ARES
;
224 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
226 /* Turn on core clock */
227 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
228 val
|= Q6SS_CLK_ENABLE
;
229 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
231 /* Start core execution */
232 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
233 val
&= ~Q6SS_STOP_CORE
;
234 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
239 static int q6v5_wcss_start(struct rproc
*rproc
)
241 struct q6v5_wcss
*wcss
= rproc
->priv
;
244 qcom_q6v5_prepare(&wcss
->q6v5
);
246 /* Release Q6 and WCSS reset */
247 ret
= reset_control_deassert(wcss
->wcss_reset
);
249 dev_err(wcss
->dev
, "wcss_reset failed\n");
253 ret
= reset_control_deassert(wcss
->wcss_q6_reset
);
255 dev_err(wcss
->dev
, "wcss_q6_reset failed\n");
259 /* Lithium configuration - clock gating and bus arbitration */
260 ret
= regmap_update_bits(wcss
->halt_map
,
261 wcss
->halt_nc
+ TCSR_GLOBAL_CFG0
,
263 TCSR_WCSS_CLK_ENABLE
);
267 ret
= regmap_update_bits(wcss
->halt_map
,
268 wcss
->halt_nc
+ TCSR_GLOBAL_CFG1
,
273 /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
274 writel(rproc
->bootaddr
>> 4, wcss
->reg_base
+ Q6SS_RST_EVB
);
276 ret
= q6v5_wcss_reset(wcss
);
280 ret
= qcom_q6v5_wait_for_start(&wcss
->q6v5
, 5 * HZ
);
281 if (ret
== -ETIMEDOUT
)
282 dev_err(wcss
->dev
, "start timed out\n");
287 reset_control_assert(wcss
->wcss_q6_reset
);
290 reset_control_assert(wcss
->wcss_reset
);
295 static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss
*wcss
)
300 /* Toggle the restart */
301 reset_control_assert(wcss
->wcss_reset
);
302 usleep_range(200, 300);
303 reset_control_deassert(wcss
->wcss_reset
);
304 usleep_range(200, 300);
306 /* Enable GCC_WDSP_Q6SS_AHBS_CBCR clock */
307 ret
= clk_prepare_enable(wcss
->gcc_abhs_cbcr
);
311 /* Remove reset to the WCNSS QDSP6SS */
312 reset_control_deassert(wcss
->wcss_q6_bcr_reset
);
314 /* Enable Q6SSTOP_AHBFABRIC_CBCR clock */
315 ret
= clk_prepare_enable(wcss
->ahbfabric_cbcr_clk
);
317 goto disable_gcc_abhs_cbcr_clk
;
319 /* Enable the LCCCSR CBC clock, Q6SSTOP_Q6SSTOP_LCC_CSR_CBCR clock */
320 ret
= clk_prepare_enable(wcss
->lcc_csr_cbcr
);
322 goto disable_ahbfabric_cbcr_clk
;
324 /* Enable the Q6AHBS CBC, Q6SSTOP_Q6SS_AHBS_CBCR clock */
325 ret
= clk_prepare_enable(wcss
->ahbs_cbcr
);
327 goto disable_csr_cbcr_clk
;
329 /* Enable the TCM slave CBC, Q6SSTOP_Q6SS_TCM_SLAVE_CBCR clock */
330 ret
= clk_prepare_enable(wcss
->tcm_slave_cbcr
);
332 goto disable_ahbs_cbcr_clk
;
334 /* Enable the Q6SS AHB master CBC, Q6SSTOP_Q6SS_AHBM_CBCR clock */
335 ret
= clk_prepare_enable(wcss
->qdsp6ss_abhm_cbcr
);
337 goto disable_tcm_slave_cbcr_clk
;
339 /* Enable the Q6SS AXI master CBC, Q6SSTOP_Q6SS_AXIM_CBCR clock */
340 ret
= clk_prepare_enable(wcss
->qdsp6ss_axim_cbcr
);
342 goto disable_abhm_cbcr_clk
;
344 /* Enable the Q6SS XO CBC */
345 val
= readl(wcss
->reg_base
+ Q6SS_XO_CBCR
);
347 writel(val
, wcss
->reg_base
+ Q6SS_XO_CBCR
);
348 /* Read CLKOFF bit to go low indicating CLK is enabled */
349 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_XO_CBCR
,
350 val
, !(val
& BIT(31)), 1,
351 HALT_CHECK_MAX_LOOPS
);
354 "xo cbcr enabling timed out (rc:%d)\n", ret
);
355 goto disable_xo_cbcr_clk
;
358 writel(0, wcss
->reg_base
+ Q6SS_CGC_OVERRIDE
);
360 /* Enable QDSP6 sleep clock clock */
361 val
= readl(wcss
->reg_base
+ Q6SS_SLEEP_CBCR
);
363 writel(val
, wcss
->reg_base
+ Q6SS_SLEEP_CBCR
);
365 /* Enable the Enable the Q6 AXI clock, GCC_WDSP_Q6SS_AXIM_CBCR*/
366 ret
= clk_prepare_enable(wcss
->gcc_axim_cbcr
);
368 goto disable_sleep_cbcr_clk
;
370 /* Assert resets, stop core */
371 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
372 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
373 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
375 /* Program the QDSP6SS PWR_CTL register */
376 writel(0x01700000, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
378 writel(0x03700000, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
380 writel(0x03300000, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
382 writel(0x033C0000, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
385 * Enable memories by turning on the QDSP6 memory foot/head switch, one
386 * bank at a time to avoid in-rush current
388 for (idx
= 28; idx
>= 0; idx
--) {
389 writel((readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
) |
390 (1 << idx
)), wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
393 writel(0x031C0000, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
394 writel(0x030C0000, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
396 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
397 val
&= ~Q6SS_CORE_ARES
;
398 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
400 /* Enable the Q6 core clock at the GFM, Q6SSTOP_QDSP6SS_GFMUX_CTL */
401 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
402 val
|= Q6SS_CLK_ENABLE
| Q6SS_SWITCH_CLK_SRC
;
403 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
405 /* Enable sleep clock branch needed for BCR circuit */
406 ret
= clk_prepare_enable(wcss
->lcc_bcr_sleep
);
408 goto disable_core_gfmux_clk
;
412 disable_core_gfmux_clk
:
413 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
414 val
&= ~(Q6SS_CLK_ENABLE
| Q6SS_SWITCH_CLK_SRC
);
415 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
416 clk_disable_unprepare(wcss
->gcc_axim_cbcr
);
417 disable_sleep_cbcr_clk
:
418 val
= readl(wcss
->reg_base
+ Q6SS_SLEEP_CBCR
);
419 val
&= ~Q6SS_CLK_ENABLE
;
420 writel(val
, wcss
->reg_base
+ Q6SS_SLEEP_CBCR
);
422 val
= readl(wcss
->reg_base
+ Q6SS_XO_CBCR
);
423 val
&= ~Q6SS_CLK_ENABLE
;
424 writel(val
, wcss
->reg_base
+ Q6SS_XO_CBCR
);
425 clk_disable_unprepare(wcss
->qdsp6ss_axim_cbcr
);
426 disable_abhm_cbcr_clk
:
427 clk_disable_unprepare(wcss
->qdsp6ss_abhm_cbcr
);
428 disable_tcm_slave_cbcr_clk
:
429 clk_disable_unprepare(wcss
->tcm_slave_cbcr
);
430 disable_ahbs_cbcr_clk
:
431 clk_disable_unprepare(wcss
->ahbs_cbcr
);
432 disable_csr_cbcr_clk
:
433 clk_disable_unprepare(wcss
->lcc_csr_cbcr
);
434 disable_ahbfabric_cbcr_clk
:
435 clk_disable_unprepare(wcss
->ahbfabric_cbcr_clk
);
436 disable_gcc_abhs_cbcr_clk
:
437 clk_disable_unprepare(wcss
->gcc_abhs_cbcr
);
442 static inline int q6v5_wcss_qcs404_reset(struct q6v5_wcss
*wcss
)
446 writel(0x80800000, wcss
->reg_base
+ Q6SS_STRAP_ACC
);
448 /* Start core execution */
449 val
= readl(wcss
->reg_base
+ Q6SS_RESET_REG
);
450 val
&= ~Q6SS_STOP_CORE
;
451 writel(val
, wcss
->reg_base
+ Q6SS_RESET_REG
);
456 static int q6v5_qcs404_wcss_start(struct rproc
*rproc
)
458 struct q6v5_wcss
*wcss
= rproc
->priv
;
461 ret
= clk_prepare_enable(wcss
->xo
);
465 ret
= regulator_enable(wcss
->cx_supply
);
469 qcom_q6v5_prepare(&wcss
->q6v5
);
471 ret
= q6v5_wcss_qcs404_power_on(wcss
);
473 dev_err(wcss
->dev
, "wcss clk_enable failed\n");
474 goto disable_cx_supply
;
477 writel(rproc
->bootaddr
>> 4, wcss
->reg_base
+ Q6SS_RST_EVB
);
479 q6v5_wcss_qcs404_reset(wcss
);
481 ret
= qcom_q6v5_wait_for_start(&wcss
->q6v5
, 5 * HZ
);
482 if (ret
== -ETIMEDOUT
) {
483 dev_err(wcss
->dev
, "start timed out\n");
484 goto disable_cx_supply
;
490 regulator_disable(wcss
->cx_supply
);
492 clk_disable_unprepare(wcss
->xo
);
497 static void q6v5_wcss_halt_axi_port(struct q6v5_wcss
*wcss
,
498 struct regmap
*halt_map
,
501 unsigned long timeout
;
505 /* Check if we're already idle */
506 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
510 /* Assert halt request */
511 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 1);
514 timeout
= jiffies
+ msecs_to_jiffies(HALT_ACK_TIMEOUT_MS
);
516 ret
= regmap_read(halt_map
, offset
+ AXI_HALTACK_REG
, &val
);
517 if (ret
|| val
|| time_after(jiffies
, timeout
))
523 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
525 dev_err(wcss
->dev
, "port failed halt\n");
527 /* Clear halt request (port will remain halted until reset) */
528 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 0);
531 static int q6v5_qcs404_wcss_shutdown(struct q6v5_wcss
*wcss
)
536 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_wcss
);
538 /* assert clamps to avoid MX current inrush */
539 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
540 val
|= (Q6SS_CLAMP_IO
| Q6SS_CLAMP_WL
| Q6SS_CLAMP_QMC_MEM
);
541 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
543 /* Disable memories by turning off memory foot/headswitch */
544 writel((readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
) &
546 wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
548 /* Clear the BHS_ON bit */
549 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
551 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
553 clk_disable_unprepare(wcss
->ahbfabric_cbcr_clk
);
554 clk_disable_unprepare(wcss
->lcc_csr_cbcr
);
555 clk_disable_unprepare(wcss
->tcm_slave_cbcr
);
556 clk_disable_unprepare(wcss
->qdsp6ss_abhm_cbcr
);
557 clk_disable_unprepare(wcss
->qdsp6ss_axim_cbcr
);
559 val
= readl(wcss
->reg_base
+ Q6SS_SLEEP_CBCR
);
561 writel(val
, wcss
->reg_base
+ Q6SS_SLEEP_CBCR
);
563 val
= readl(wcss
->reg_base
+ Q6SS_XO_CBCR
);
565 writel(val
, wcss
->reg_base
+ Q6SS_XO_CBCR
);
567 clk_disable_unprepare(wcss
->ahbs_cbcr
);
568 clk_disable_unprepare(wcss
->lcc_bcr_sleep
);
570 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
571 val
&= ~(Q6SS_CLK_ENABLE
| Q6SS_SWITCH_CLK_SRC
);
572 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
574 clk_disable_unprepare(wcss
->gcc_abhs_cbcr
);
576 ret
= reset_control_assert(wcss
->wcss_reset
);
578 dev_err(wcss
->dev
, "wcss_reset failed\n");
581 usleep_range(200, 300);
583 ret
= reset_control_deassert(wcss
->wcss_reset
);
585 dev_err(wcss
->dev
, "wcss_reset failed\n");
588 usleep_range(200, 300);
590 clk_disable_unprepare(wcss
->gcc_axim_cbcr
);
595 static int q6v5_wcss_powerdown(struct q6v5_wcss
*wcss
)
600 /* 1 - Assert WCSS/Q6 HALTREQ */
601 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_wcss
);
603 /* 2 - Enable WCSSAON_CONFIG */
604 val
= readl(wcss
->rmb_base
+ SSCAON_CONFIG
);
605 val
|= SSCAON_ENABLE
;
606 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
608 /* 3 - Set SSCAON_CONFIG */
609 val
|= SSCAON_BUS_EN
;
610 val
&= ~SSCAON_BUS_MUX_MASK
;
611 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
613 /* 4 - SSCAON_CONFIG 1 */
615 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
617 /* 5 - wait for SSCAON_STATUS */
618 ret
= readl_poll_timeout(wcss
->rmb_base
+ SSCAON_STATUS
,
619 val
, (val
& 0xffff) == 0x400, 1000,
620 HALT_CHECK_MAX_LOOPS
);
623 "can't get SSCAON_STATUS rc:%d)\n", ret
);
627 /* 6 - De-assert WCSS_AON reset */
628 reset_control_assert(wcss
->wcss_aon_reset
);
630 /* 7 - Disable WCSSAON_CONFIG 13 */
631 val
= readl(wcss
->rmb_base
+ SSCAON_CONFIG
);
632 val
&= ~SSCAON_ENABLE
;
633 writel(val
, wcss
->rmb_base
+ SSCAON_CONFIG
);
635 /* 8 - De-assert WCSS/Q6 HALTREQ */
636 reset_control_assert(wcss
->wcss_reset
);
641 static int q6v5_q6_powerdown(struct q6v5_wcss
*wcss
)
647 /* 1 - Halt Q6 bus interface */
648 q6v5_wcss_halt_axi_port(wcss
, wcss
->halt_map
, wcss
->halt_q6
);
650 /* 2 - Disable Q6 Core clock */
651 val
= readl(wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
652 val
&= ~Q6SS_CLK_ENABLE
;
653 writel(val
, wcss
->reg_base
+ Q6SS_GFMUX_CTL_REG
);
656 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
657 val
|= Q6SS_CLAMP_IO
;
658 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
662 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
664 /* 5 - Clear Erase standby */
665 val
&= ~Q6SS_L2DATA_STBY_N
;
666 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
668 /* 6 - Clear Sleep RTN */
669 val
&= ~Q6SS_SLP_RET_N
;
670 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
672 /* 7 - turn off Q6 memory foot/head switch one bank at a time */
673 for (i
= 0; i
< 20; i
++) {
674 val
= readl(wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
676 writel(val
, wcss
->reg_base
+ Q6SS_MEM_PWR_CTL
);
680 /* 8 - Assert QMC memory RTN */
681 val
= readl(wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
682 val
|= Q6SS_CLAMP_QMC_MEM
;
683 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
685 /* 9 - Turn off BHS */
687 writel(val
, wcss
->reg_base
+ Q6SS_PWR_CTL_REG
);
690 /* 10 - Wait till BHS Reset is done */
691 ret
= readl_poll_timeout(wcss
->reg_base
+ Q6SS_BHS_STATUS
,
692 val
, !(val
& BHS_EN_REST_ACK
), 1000,
693 HALT_CHECK_MAX_LOOPS
);
695 dev_err(wcss
->dev
, "BHS_STATUS not OFF (rc:%d)\n", ret
);
699 /* 11 - Assert WCSS reset */
700 reset_control_assert(wcss
->wcss_reset
);
702 /* 12 - Assert Q6 reset */
703 reset_control_assert(wcss
->wcss_q6_reset
);
708 static int q6v5_wcss_stop(struct rproc
*rproc
)
710 struct q6v5_wcss
*wcss
= rproc
->priv
;
714 if (wcss
->requires_force_stop
) {
715 ret
= qcom_q6v5_request_stop(&wcss
->q6v5
, NULL
);
716 if (ret
== -ETIMEDOUT
) {
717 dev_err(wcss
->dev
, "timed out on wait\n");
722 if (wcss
->version
== WCSS_QCS404
) {
723 ret
= q6v5_qcs404_wcss_shutdown(wcss
);
727 ret
= q6v5_wcss_powerdown(wcss
);
732 ret
= q6v5_q6_powerdown(wcss
);
737 qcom_q6v5_unprepare(&wcss
->q6v5
);
742 static void *q6v5_wcss_da_to_va(struct rproc
*rproc
, u64 da
, size_t len
, bool *is_iomem
)
744 struct q6v5_wcss
*wcss
= rproc
->priv
;
747 offset
= da
- wcss
->mem_reloc
;
748 if (offset
< 0 || offset
+ len
> wcss
->mem_size
)
751 return wcss
->mem_region
+ offset
;
754 static int q6v5_wcss_load(struct rproc
*rproc
, const struct firmware
*fw
)
756 struct q6v5_wcss
*wcss
= rproc
->priv
;
759 ret
= qcom_mdt_load_no_init(wcss
->dev
, fw
, rproc
->firmware
,
760 0, wcss
->mem_region
, wcss
->mem_phys
,
761 wcss
->mem_size
, &wcss
->mem_reloc
);
765 qcom_pil_info_store("wcnss", wcss
->mem_phys
, wcss
->mem_size
);
770 static const struct rproc_ops q6v5_wcss_ipq8074_ops
= {
771 .start
= q6v5_wcss_start
,
772 .stop
= q6v5_wcss_stop
,
773 .da_to_va
= q6v5_wcss_da_to_va
,
774 .load
= q6v5_wcss_load
,
775 .get_boot_addr
= rproc_elf_get_boot_addr
,
778 static const struct rproc_ops q6v5_wcss_qcs404_ops
= {
779 .start
= q6v5_qcs404_wcss_start
,
780 .stop
= q6v5_wcss_stop
,
781 .da_to_va
= q6v5_wcss_da_to_va
,
782 .load
= q6v5_wcss_load
,
783 .get_boot_addr
= rproc_elf_get_boot_addr
,
784 .parse_fw
= qcom_register_dump_segments
,
787 static int q6v5_wcss_init_reset(struct q6v5_wcss
*wcss
,
788 const struct wcss_data
*desc
)
790 struct device
*dev
= wcss
->dev
;
792 if (desc
->aon_reset_required
) {
793 wcss
->wcss_aon_reset
= devm_reset_control_get_exclusive(dev
, "wcss_aon_reset");
794 if (IS_ERR(wcss
->wcss_aon_reset
)) {
795 dev_err(wcss
->dev
, "fail to acquire wcss_aon_reset\n");
796 return PTR_ERR(wcss
->wcss_aon_reset
);
800 wcss
->wcss_reset
= devm_reset_control_get_exclusive(dev
, "wcss_reset");
801 if (IS_ERR(wcss
->wcss_reset
)) {
802 dev_err(wcss
->dev
, "unable to acquire wcss_reset\n");
803 return PTR_ERR(wcss
->wcss_reset
);
806 if (desc
->wcss_q6_reset_required
) {
807 wcss
->wcss_q6_reset
= devm_reset_control_get_exclusive(dev
, "wcss_q6_reset");
808 if (IS_ERR(wcss
->wcss_q6_reset
)) {
809 dev_err(wcss
->dev
, "unable to acquire wcss_q6_reset\n");
810 return PTR_ERR(wcss
->wcss_q6_reset
);
814 wcss
->wcss_q6_bcr_reset
= devm_reset_control_get_exclusive(dev
, "wcss_q6_bcr_reset");
815 if (IS_ERR(wcss
->wcss_q6_bcr_reset
)) {
816 dev_err(wcss
->dev
, "unable to acquire wcss_q6_bcr_reset\n");
817 return PTR_ERR(wcss
->wcss_q6_bcr_reset
);
823 static int q6v5_wcss_init_mmio(struct q6v5_wcss
*wcss
,
824 struct platform_device
*pdev
)
826 unsigned int halt_reg
[MAX_HALT_REG
] = {0};
827 struct device_node
*syscon
;
828 struct resource
*res
;
831 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "qdsp6");
835 wcss
->reg_base
= devm_ioremap(&pdev
->dev
, res
->start
,
840 if (wcss
->version
== WCSS_IPQ8074
) {
841 wcss
->rmb_base
= devm_platform_ioremap_resource_byname(pdev
, "rmb");
842 if (IS_ERR(wcss
->rmb_base
))
843 return PTR_ERR(wcss
->rmb_base
);
846 syscon
= of_parse_phandle(pdev
->dev
.of_node
,
847 "qcom,halt-regs", 0);
849 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
853 wcss
->halt_map
= syscon_node_to_regmap(syscon
);
855 if (IS_ERR(wcss
->halt_map
))
856 return PTR_ERR(wcss
->halt_map
);
858 ret
= of_property_read_variable_u32_array(pdev
->dev
.of_node
,
863 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
867 wcss
->halt_q6
= halt_reg
[0];
868 wcss
->halt_wcss
= halt_reg
[1];
869 wcss
->halt_nc
= halt_reg
[2];
874 static int q6v5_alloc_memory_region(struct q6v5_wcss
*wcss
)
876 struct reserved_mem
*rmem
= NULL
;
877 struct device_node
*node
;
878 struct device
*dev
= wcss
->dev
;
880 node
= of_parse_phandle(dev
->of_node
, "memory-region", 0);
882 rmem
= of_reserved_mem_lookup(node
);
886 dev_err(dev
, "unable to acquire memory-region\n");
890 wcss
->mem_phys
= rmem
->base
;
891 wcss
->mem_reloc
= rmem
->base
;
892 wcss
->mem_size
= rmem
->size
;
893 wcss
->mem_region
= devm_ioremap_wc(dev
, wcss
->mem_phys
, wcss
->mem_size
);
894 if (!wcss
->mem_region
) {
895 dev_err(dev
, "unable to map memory region: %pa+%pa\n",
896 &rmem
->base
, &rmem
->size
);
903 static int q6v5_wcss_init_clock(struct q6v5_wcss
*wcss
)
905 wcss
->xo
= devm_clk_get(wcss
->dev
, "xo");
906 if (IS_ERR(wcss
->xo
))
907 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->xo
),
908 "failed to get xo clock");
910 wcss
->gcc_abhs_cbcr
= devm_clk_get(wcss
->dev
, "gcc_abhs_cbcr");
911 if (IS_ERR(wcss
->gcc_abhs_cbcr
))
912 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->gcc_abhs_cbcr
),
913 "failed to get gcc abhs clock");
915 wcss
->gcc_axim_cbcr
= devm_clk_get(wcss
->dev
, "gcc_axim_cbcr");
916 if (IS_ERR(wcss
->gcc_axim_cbcr
))
917 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->gcc_axim_cbcr
),
918 "failed to get gcc axim clock\n");
920 wcss
->ahbfabric_cbcr_clk
= devm_clk_get(wcss
->dev
,
921 "lcc_ahbfabric_cbc");
922 if (IS_ERR(wcss
->ahbfabric_cbcr_clk
))
923 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->ahbfabric_cbcr_clk
),
924 "failed to get ahbfabric clock\n");
926 wcss
->lcc_csr_cbcr
= devm_clk_get(wcss
->dev
, "tcsr_lcc_cbc");
927 if (IS_ERR(wcss
->lcc_csr_cbcr
))
928 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->lcc_csr_cbcr
),
929 "failed to get csr cbcr clk\n");
931 wcss
->ahbs_cbcr
= devm_clk_get(wcss
->dev
,
933 if (IS_ERR(wcss
->ahbs_cbcr
))
934 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->ahbs_cbcr
),
935 "failed to get ahbs_cbcr clk\n");
937 wcss
->tcm_slave_cbcr
= devm_clk_get(wcss
->dev
,
938 "lcc_tcm_slave_cbc");
939 if (IS_ERR(wcss
->tcm_slave_cbcr
))
940 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->tcm_slave_cbcr
),
941 "failed to get tcm cbcr clk\n");
943 wcss
->qdsp6ss_abhm_cbcr
= devm_clk_get(wcss
->dev
, "lcc_abhm_cbc");
944 if (IS_ERR(wcss
->qdsp6ss_abhm_cbcr
))
945 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->qdsp6ss_abhm_cbcr
),
946 "failed to get abhm cbcr clk\n");
948 wcss
->qdsp6ss_axim_cbcr
= devm_clk_get(wcss
->dev
, "lcc_axim_cbc");
949 if (IS_ERR(wcss
->qdsp6ss_axim_cbcr
))
950 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->qdsp6ss_axim_cbcr
),
951 "failed to get axim cbcr clk\n");
953 wcss
->lcc_bcr_sleep
= devm_clk_get(wcss
->dev
, "lcc_bcr_sleep");
954 if (IS_ERR(wcss
->lcc_bcr_sleep
))
955 return dev_err_probe(wcss
->dev
, PTR_ERR(wcss
->lcc_bcr_sleep
),
956 "failed to get bcr cbcr clk\n");
961 static int q6v5_wcss_init_regulator(struct q6v5_wcss
*wcss
)
963 wcss
->cx_supply
= devm_regulator_get(wcss
->dev
, "cx");
964 if (IS_ERR(wcss
->cx_supply
))
965 return PTR_ERR(wcss
->cx_supply
);
967 regulator_set_load(wcss
->cx_supply
, 100000);
972 static int q6v5_wcss_probe(struct platform_device
*pdev
)
974 const struct wcss_data
*desc
;
975 struct q6v5_wcss
*wcss
;
979 desc
= device_get_match_data(&pdev
->dev
);
983 rproc
= devm_rproc_alloc(&pdev
->dev
, pdev
->name
, desc
->ops
,
984 desc
->firmware_name
, sizeof(*wcss
));
986 dev_err(&pdev
->dev
, "failed to allocate rproc\n");
991 wcss
->dev
= &pdev
->dev
;
993 wcss
->version
= desc
->version
;
994 wcss
->requires_force_stop
= desc
->requires_force_stop
;
996 ret
= q6v5_wcss_init_mmio(wcss
, pdev
);
1000 ret
= q6v5_alloc_memory_region(wcss
);
1004 if (wcss
->version
== WCSS_QCS404
) {
1005 ret
= q6v5_wcss_init_clock(wcss
);
1009 ret
= q6v5_wcss_init_regulator(wcss
);
1014 ret
= q6v5_wcss_init_reset(wcss
, desc
);
1018 ret
= qcom_q6v5_init(&wcss
->q6v5
, pdev
, rproc
, desc
->crash_reason_smem
, NULL
, NULL
);
1022 qcom_add_glink_subdev(rproc
, &wcss
->glink_subdev
, "q6wcss");
1023 qcom_add_pdm_subdev(rproc
, &wcss
->pdm_subdev
);
1024 qcom_add_ssr_subdev(rproc
, &wcss
->ssr_subdev
, "q6wcss");
1026 if (desc
->ssctl_id
) {
1027 wcss
->sysmon
= qcom_add_sysmon_subdev(rproc
,
1030 if (IS_ERR(wcss
->sysmon
)) {
1031 ret
= PTR_ERR(wcss
->sysmon
);
1032 goto deinit_remove_subdevs
;
1036 ret
= rproc_add(rproc
);
1038 goto remove_sysmon_subdev
;
1040 platform_set_drvdata(pdev
, rproc
);
1044 remove_sysmon_subdev
:
1046 qcom_remove_sysmon_subdev(wcss
->sysmon
);
1047 deinit_remove_subdevs
:
1048 qcom_q6v5_deinit(&wcss
->q6v5
);
1049 qcom_remove_glink_subdev(rproc
, &wcss
->glink_subdev
);
1050 qcom_remove_pdm_subdev(rproc
, &wcss
->pdm_subdev
);
1051 qcom_remove_ssr_subdev(rproc
, &wcss
->ssr_subdev
);
1055 static void q6v5_wcss_remove(struct platform_device
*pdev
)
1057 struct rproc
*rproc
= platform_get_drvdata(pdev
);
1058 struct q6v5_wcss
*wcss
= rproc
->priv
;
1060 qcom_q6v5_deinit(&wcss
->q6v5
);
1061 qcom_remove_pdm_subdev(rproc
, &wcss
->pdm_subdev
);
1065 static const struct wcss_data wcss_ipq8074_res_init
= {
1066 .firmware_name
= "IPQ8074/q6_fw.mdt",
1067 .crash_reason_smem
= WCSS_CRASH_REASON
,
1068 .aon_reset_required
= true,
1069 .wcss_q6_reset_required
= true,
1070 .ops
= &q6v5_wcss_ipq8074_ops
,
1071 .requires_force_stop
= true,
1074 static const struct wcss_data wcss_qcs404_res_init
= {
1075 .crash_reason_smem
= WCSS_CRASH_REASON
,
1076 .firmware_name
= "wcnss.mdt",
1077 .version
= WCSS_QCS404
,
1078 .aon_reset_required
= false,
1079 .wcss_q6_reset_required
= false,
1081 .sysmon_name
= "wcnss",
1083 .ops
= &q6v5_wcss_qcs404_ops
,
1084 .requires_force_stop
= false,
1087 static const struct of_device_id q6v5_wcss_of_match
[] = {
1088 { .compatible
= "qcom,ipq8074-wcss-pil", .data
= &wcss_ipq8074_res_init
},
1089 { .compatible
= "qcom,qcs404-wcss-pil", .data
= &wcss_qcs404_res_init
},
1092 MODULE_DEVICE_TABLE(of
, q6v5_wcss_of_match
);
1094 static struct platform_driver q6v5_wcss_driver
= {
1095 .probe
= q6v5_wcss_probe
,
1096 .remove
= q6v5_wcss_remove
,
1098 .name
= "qcom-q6v5-wcss-pil",
1099 .of_match_table
= q6v5_wcss_of_match
,
1102 module_platform_driver(q6v5_wcss_driver
);
1104 MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
1105 MODULE_LICENSE("GPL v2");