Loading...
1// SPDX-License-Identifier: GPL-2.0
2/*
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.
6 */
7#include <linux/clk.h>
8#include <linux/delay.h>
9#include <linux/io.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"
24
25#define WCSS_CRASH_REASON 421
26
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
35
36/* AXI Halt Register Offsets */
37#define AXI_HALTREQ_REG 0x0
38#define AXI_HALTACK_REG 0x4
39#define AXI_IDLE_REG 0x8
40
41#define HALT_ACK_TIMEOUT_MS 100
42
43/* Q6SS_RESET */
44#define Q6SS_STOP_CORE BIT(0)
45#define Q6SS_CORE_ARES BIT(1)
46#define Q6SS_BUS_ARES_ENABLE BIT(2)
47
48/* Q6SS_BRC_RESET */
49#define Q6SS_BRC_BLK_ARES BIT(0)
50
51/* Q6SS_GFMUX_CTL */
52#define Q6SS_CLK_ENABLE BIT(1)
53#define Q6SS_SWITCH_CLK_SRC BIT(8)
54
55/* Q6SS_PWR_CTL */
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)
61
62/* Q6SS parameters */
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)
70
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
78
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)
83
84#define MEM_BANKS 19
85#define TCSR_WCSS_CLK_MASK 0x1F
86#define TCSR_WCSS_CLK_ENABLE 0x14
87
88#define MAX_HALT_REG 3
89enum {
90 WCSS_IPQ8074,
91 WCSS_QCS404,
92};
93
94struct wcss_data {
95 const char *firmware_name;
96 unsigned int crash_reason_smem;
97 u32 version;
98 bool aon_reset_required;
99 bool wcss_q6_reset_required;
100 const char *ssr_name;
101 const char *sysmon_name;
102 int ssctl_id;
103 const struct rproc_ops *ops;
104 bool requires_force_stop;
105};
106
107struct q6v5_wcss {
108 struct device *dev;
109
110 void __iomem *reg_base;
111 void __iomem *rmb_base;
112
113 struct regmap *halt_map;
114 u32 halt_q6;
115 u32 halt_wcss;
116 u32 halt_nc;
117
118 struct clk *xo;
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;
133
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;
138
139 struct qcom_q6v5 q6v5;
140
141 phys_addr_t mem_phys;
142 phys_addr_t mem_reloc;
143 void *mem_region;
144 size_t mem_size;
145
146 unsigned int crash_reason_smem;
147 u32 version;
148 bool requires_force_stop;
149
150 struct qcom_rproc_glink glink_subdev;
151 struct qcom_rproc_ssr ssr_subdev;
152};
153
154static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
155{
156 int ret;
157 u32 val;
158 int i;
159
160 /* Assert resets, stop core */
161 val = readl(wcss->reg_base + Q6SS_RESET_REG);
162 val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
163 writel(val, wcss->reg_base + Q6SS_RESET_REG);
164
165 /* BHS require xo cbcr to be enabled */
166 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
167 val |= 0x1;
168 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
169
170 /* Read CLKOFF bit to go low indicating CLK is enabled */
171 ret = readl_poll_timeout(wcss->reg_base + Q6SS_XO_CBCR,
172 val, !(val & BIT(31)), 1,
173 HALT_CHECK_MAX_LOOPS);
174 if (ret) {
175 dev_err(wcss->dev,
176 "xo cbcr enabling timed out (rc:%d)\n", ret);
177 return ret;
178 }
179 /* Enable power block headswitch and wait for it to stabilize */
180 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
181 val |= Q6SS_BHS_ON;
182 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
183 udelay(1);
184
185 /* Put LDO in bypass mode */
186 val |= Q6SS_LDO_BYP;
187 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
188
189 /* Deassert Q6 compiler memory clamp */
190 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
191 val &= ~Q6SS_CLAMP_QMC_MEM;
192 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
193
194 /* Deassert memory peripheral sleep and L2 memory standby */
195 val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N;
196 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
197
198 /* Turn on L1, L2, ETB and JU memories 1 at a time */
199 val = readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
200 for (i = MEM_BANKS; i >= 0; i--) {
201 val |= BIT(i);
202 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
203 /*
204 * Read back value to ensure the write is done then
205 * wait for 1us for both memory peripheral and data
206 * array to turn on.
207 */
208 val |= readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
209 udelay(1);
210 }
211 /* Remove word line clamp */
212 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
213 val &= ~Q6SS_CLAMP_WL;
214 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
215
216 /* Remove IO clamp */
217 val &= ~Q6SS_CLAMP_IO;
218 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
219
220 /* Bring core out of reset */
221 val = readl(wcss->reg_base + Q6SS_RESET_REG);
222 val &= ~Q6SS_CORE_ARES;
223 writel(val, wcss->reg_base + Q6SS_RESET_REG);
224
225 /* Turn on core clock */
226 val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
227 val |= Q6SS_CLK_ENABLE;
228 writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
229
230 /* Start core execution */
231 val = readl(wcss->reg_base + Q6SS_RESET_REG);
232 val &= ~Q6SS_STOP_CORE;
233 writel(val, wcss->reg_base + Q6SS_RESET_REG);
234
235 return 0;
236}
237
238static int q6v5_wcss_start(struct rproc *rproc)
239{
240 struct q6v5_wcss *wcss = rproc->priv;
241 int ret;
242
243 qcom_q6v5_prepare(&wcss->q6v5);
244
245 /* Release Q6 and WCSS reset */
246 ret = reset_control_deassert(wcss->wcss_reset);
247 if (ret) {
248 dev_err(wcss->dev, "wcss_reset failed\n");
249 return ret;
250 }
251
252 ret = reset_control_deassert(wcss->wcss_q6_reset);
253 if (ret) {
254 dev_err(wcss->dev, "wcss_q6_reset failed\n");
255 goto wcss_reset;
256 }
257
258 /* Lithium configuration - clock gating and bus arbitration */
259 ret = regmap_update_bits(wcss->halt_map,
260 wcss->halt_nc + TCSR_GLOBAL_CFG0,
261 TCSR_WCSS_CLK_MASK,
262 TCSR_WCSS_CLK_ENABLE);
263 if (ret)
264 goto wcss_q6_reset;
265
266 ret = regmap_update_bits(wcss->halt_map,
267 wcss->halt_nc + TCSR_GLOBAL_CFG1,
268 1, 0);
269 if (ret)
270 goto wcss_q6_reset;
271
272 /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
273 writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB);
274
275 ret = q6v5_wcss_reset(wcss);
276 if (ret)
277 goto wcss_q6_reset;
278
279 ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ);
280 if (ret == -ETIMEDOUT)
281 dev_err(wcss->dev, "start timed out\n");
282
283 return ret;
284
285wcss_q6_reset:
286 reset_control_assert(wcss->wcss_q6_reset);
287
288wcss_reset:
289 reset_control_assert(wcss->wcss_reset);
290
291 return ret;
292}
293
294static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss)
295{
296 unsigned long val;
297 int ret, idx;
298
299 /* Toggle the restart */
300 reset_control_assert(wcss->wcss_reset);
301 usleep_range(200, 300);
302 reset_control_deassert(wcss->wcss_reset);
303 usleep_range(200, 300);
304
305 /* Enable GCC_WDSP_Q6SS_AHBS_CBCR clock */
306 ret = clk_prepare_enable(wcss->gcc_abhs_cbcr);
307 if (ret)
308 return ret;
309
310 /* Remove reset to the WCNSS QDSP6SS */
311 reset_control_deassert(wcss->wcss_q6_bcr_reset);
312
313 /* Enable Q6SSTOP_AHBFABRIC_CBCR clock */
314 ret = clk_prepare_enable(wcss->ahbfabric_cbcr_clk);
315 if (ret)
316 goto disable_gcc_abhs_cbcr_clk;
317
318 /* Enable the LCCCSR CBC clock, Q6SSTOP_Q6SSTOP_LCC_CSR_CBCR clock */
319 ret = clk_prepare_enable(wcss->lcc_csr_cbcr);
320 if (ret)
321 goto disable_ahbfabric_cbcr_clk;
322
323 /* Enable the Q6AHBS CBC, Q6SSTOP_Q6SS_AHBS_CBCR clock */
324 ret = clk_prepare_enable(wcss->ahbs_cbcr);
325 if (ret)
326 goto disable_csr_cbcr_clk;
327
328 /* Enable the TCM slave CBC, Q6SSTOP_Q6SS_TCM_SLAVE_CBCR clock */
329 ret = clk_prepare_enable(wcss->tcm_slave_cbcr);
330 if (ret)
331 goto disable_ahbs_cbcr_clk;
332
333 /* Enable the Q6SS AHB master CBC, Q6SSTOP_Q6SS_AHBM_CBCR clock */
334 ret = clk_prepare_enable(wcss->qdsp6ss_abhm_cbcr);
335 if (ret)
336 goto disable_tcm_slave_cbcr_clk;
337
338 /* Enable the Q6SS AXI master CBC, Q6SSTOP_Q6SS_AXIM_CBCR clock */
339 ret = clk_prepare_enable(wcss->qdsp6ss_axim_cbcr);
340 if (ret)
341 goto disable_abhm_cbcr_clk;
342
343 /* Enable the Q6SS XO CBC */
344 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
345 val |= BIT(0);
346 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
347 /* Read CLKOFF bit to go low indicating CLK is enabled */
348 ret = readl_poll_timeout(wcss->reg_base + Q6SS_XO_CBCR,
349 val, !(val & BIT(31)), 1,
350 HALT_CHECK_MAX_LOOPS);
351 if (ret) {
352 dev_err(wcss->dev,
353 "xo cbcr enabling timed out (rc:%d)\n", ret);
354 goto disable_xo_cbcr_clk;
355 }
356
357 writel(0, wcss->reg_base + Q6SS_CGC_OVERRIDE);
358
359 /* Enable QDSP6 sleep clock clock */
360 val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR);
361 val |= BIT(0);
362 writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR);
363
364 /* Enable the Enable the Q6 AXI clock, GCC_WDSP_Q6SS_AXIM_CBCR*/
365 ret = clk_prepare_enable(wcss->gcc_axim_cbcr);
366 if (ret)
367 goto disable_sleep_cbcr_clk;
368
369 /* Assert resets, stop core */
370 val = readl(wcss->reg_base + Q6SS_RESET_REG);
371 val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
372 writel(val, wcss->reg_base + Q6SS_RESET_REG);
373
374 /* Program the QDSP6SS PWR_CTL register */
375 writel(0x01700000, wcss->reg_base + Q6SS_PWR_CTL_REG);
376
377 writel(0x03700000, wcss->reg_base + Q6SS_PWR_CTL_REG);
378
379 writel(0x03300000, wcss->reg_base + Q6SS_PWR_CTL_REG);
380
381 writel(0x033C0000, wcss->reg_base + Q6SS_PWR_CTL_REG);
382
383 /*
384 * Enable memories by turning on the QDSP6 memory foot/head switch, one
385 * bank at a time to avoid in-rush current
386 */
387 for (idx = 28; idx >= 0; idx--) {
388 writel((readl(wcss->reg_base + Q6SS_MEM_PWR_CTL) |
389 (1 << idx)), wcss->reg_base + Q6SS_MEM_PWR_CTL);
390 }
391
392 writel(0x031C0000, wcss->reg_base + Q6SS_PWR_CTL_REG);
393 writel(0x030C0000, wcss->reg_base + Q6SS_PWR_CTL_REG);
394
395 val = readl(wcss->reg_base + Q6SS_RESET_REG);
396 val &= ~Q6SS_CORE_ARES;
397 writel(val, wcss->reg_base + Q6SS_RESET_REG);
398
399 /* Enable the Q6 core clock at the GFM, Q6SSTOP_QDSP6SS_GFMUX_CTL */
400 val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
401 val |= Q6SS_CLK_ENABLE | Q6SS_SWITCH_CLK_SRC;
402 writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
403
404 /* Enable sleep clock branch needed for BCR circuit */
405 ret = clk_prepare_enable(wcss->lcc_bcr_sleep);
406 if (ret)
407 goto disable_core_gfmux_clk;
408
409 return 0;
410
411disable_core_gfmux_clk:
412 val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
413 val &= ~(Q6SS_CLK_ENABLE | Q6SS_SWITCH_CLK_SRC);
414 writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
415 clk_disable_unprepare(wcss->gcc_axim_cbcr);
416disable_sleep_cbcr_clk:
417 val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR);
418 val &= ~Q6SS_CLK_ENABLE;
419 writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR);
420disable_xo_cbcr_clk:
421 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
422 val &= ~Q6SS_CLK_ENABLE;
423 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
424 clk_disable_unprepare(wcss->qdsp6ss_axim_cbcr);
425disable_abhm_cbcr_clk:
426 clk_disable_unprepare(wcss->qdsp6ss_abhm_cbcr);
427disable_tcm_slave_cbcr_clk:
428 clk_disable_unprepare(wcss->tcm_slave_cbcr);
429disable_ahbs_cbcr_clk:
430 clk_disable_unprepare(wcss->ahbs_cbcr);
431disable_csr_cbcr_clk:
432 clk_disable_unprepare(wcss->lcc_csr_cbcr);
433disable_ahbfabric_cbcr_clk:
434 clk_disable_unprepare(wcss->ahbfabric_cbcr_clk);
435disable_gcc_abhs_cbcr_clk:
436 clk_disable_unprepare(wcss->gcc_abhs_cbcr);
437
438 return ret;
439}
440
441static inline int q6v5_wcss_qcs404_reset(struct q6v5_wcss *wcss)
442{
443 unsigned long val;
444
445 writel(0x80800000, wcss->reg_base + Q6SS_STRAP_ACC);
446
447 /* Start core execution */
448 val = readl(wcss->reg_base + Q6SS_RESET_REG);
449 val &= ~Q6SS_STOP_CORE;
450 writel(val, wcss->reg_base + Q6SS_RESET_REG);
451
452 return 0;
453}
454
455static int q6v5_qcs404_wcss_start(struct rproc *rproc)
456{
457 struct q6v5_wcss *wcss = rproc->priv;
458 int ret;
459
460 ret = clk_prepare_enable(wcss->xo);
461 if (ret)
462 return ret;
463
464 ret = regulator_enable(wcss->cx_supply);
465 if (ret)
466 goto disable_xo_clk;
467
468 qcom_q6v5_prepare(&wcss->q6v5);
469
470 ret = q6v5_wcss_qcs404_power_on(wcss);
471 if (ret) {
472 dev_err(wcss->dev, "wcss clk_enable failed\n");
473 goto disable_cx_supply;
474 }
475
476 writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB);
477
478 q6v5_wcss_qcs404_reset(wcss);
479
480 ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ);
481 if (ret == -ETIMEDOUT) {
482 dev_err(wcss->dev, "start timed out\n");
483 goto disable_cx_supply;
484 }
485
486 return 0;
487
488disable_cx_supply:
489 regulator_disable(wcss->cx_supply);
490disable_xo_clk:
491 clk_disable_unprepare(wcss->xo);
492
493 return ret;
494}
495
496static void q6v5_wcss_halt_axi_port(struct q6v5_wcss *wcss,
497 struct regmap *halt_map,
498 u32 offset)
499{
500 unsigned long timeout;
501 unsigned int val;
502 int ret;
503
504 /* Check if we're already idle */
505 ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
506 if (!ret && val)
507 return;
508
509 /* Assert halt request */
510 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
511
512 /* Wait for halt */
513 timeout = jiffies + msecs_to_jiffies(HALT_ACK_TIMEOUT_MS);
514 for (;;) {
515 ret = regmap_read(halt_map, offset + AXI_HALTACK_REG, &val);
516 if (ret || val || time_after(jiffies, timeout))
517 break;
518
519 msleep(1);
520 }
521
522 ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
523 if (ret || !val)
524 dev_err(wcss->dev, "port failed halt\n");
525
526 /* Clear halt request (port will remain halted until reset) */
527 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
528}
529
530static int q6v5_qcs404_wcss_shutdown(struct q6v5_wcss *wcss)
531{
532 unsigned long val;
533 int ret;
534
535 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss);
536
537 /* assert clamps to avoid MX current inrush */
538 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
539 val |= (Q6SS_CLAMP_IO | Q6SS_CLAMP_WL | Q6SS_CLAMP_QMC_MEM);
540 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
541
542 /* Disable memories by turning off memory foot/headswitch */
543 writel((readl(wcss->reg_base + Q6SS_MEM_PWR_CTL) &
544 ~QDSS_Q6_MEMORIES),
545 wcss->reg_base + Q6SS_MEM_PWR_CTL);
546
547 /* Clear the BHS_ON bit */
548 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
549 val &= ~Q6SS_BHS_ON;
550 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
551
552 clk_disable_unprepare(wcss->ahbfabric_cbcr_clk);
553 clk_disable_unprepare(wcss->lcc_csr_cbcr);
554 clk_disable_unprepare(wcss->tcm_slave_cbcr);
555 clk_disable_unprepare(wcss->qdsp6ss_abhm_cbcr);
556 clk_disable_unprepare(wcss->qdsp6ss_axim_cbcr);
557
558 val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR);
559 val &= ~BIT(0);
560 writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR);
561
562 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
563 val &= ~BIT(0);
564 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
565
566 clk_disable_unprepare(wcss->ahbs_cbcr);
567 clk_disable_unprepare(wcss->lcc_bcr_sleep);
568
569 val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
570 val &= ~(Q6SS_CLK_ENABLE | Q6SS_SWITCH_CLK_SRC);
571 writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
572
573 clk_disable_unprepare(wcss->gcc_abhs_cbcr);
574
575 ret = reset_control_assert(wcss->wcss_reset);
576 if (ret) {
577 dev_err(wcss->dev, "wcss_reset failed\n");
578 return ret;
579 }
580 usleep_range(200, 300);
581
582 ret = reset_control_deassert(wcss->wcss_reset);
583 if (ret) {
584 dev_err(wcss->dev, "wcss_reset failed\n");
585 return ret;
586 }
587 usleep_range(200, 300);
588
589 clk_disable_unprepare(wcss->gcc_axim_cbcr);
590
591 return 0;
592}
593
594static int q6v5_wcss_powerdown(struct q6v5_wcss *wcss)
595{
596 int ret;
597 u32 val;
598
599 /* 1 - Assert WCSS/Q6 HALTREQ */
600 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss);
601
602 /* 2 - Enable WCSSAON_CONFIG */
603 val = readl(wcss->rmb_base + SSCAON_CONFIG);
604 val |= SSCAON_ENABLE;
605 writel(val, wcss->rmb_base + SSCAON_CONFIG);
606
607 /* 3 - Set SSCAON_CONFIG */
608 val |= SSCAON_BUS_EN;
609 val &= ~SSCAON_BUS_MUX_MASK;
610 writel(val, wcss->rmb_base + SSCAON_CONFIG);
611
612 /* 4 - SSCAON_CONFIG 1 */
613 val |= BIT(1);
614 writel(val, wcss->rmb_base + SSCAON_CONFIG);
615
616 /* 5 - wait for SSCAON_STATUS */
617 ret = readl_poll_timeout(wcss->rmb_base + SSCAON_STATUS,
618 val, (val & 0xffff) == 0x400, 1000,
619 HALT_CHECK_MAX_LOOPS);
620 if (ret) {
621 dev_err(wcss->dev,
622 "can't get SSCAON_STATUS rc:%d)\n", ret);
623 return ret;
624 }
625
626 /* 6 - De-assert WCSS_AON reset */
627 reset_control_assert(wcss->wcss_aon_reset);
628
629 /* 7 - Disable WCSSAON_CONFIG 13 */
630 val = readl(wcss->rmb_base + SSCAON_CONFIG);
631 val &= ~SSCAON_ENABLE;
632 writel(val, wcss->rmb_base + SSCAON_CONFIG);
633
634 /* 8 - De-assert WCSS/Q6 HALTREQ */
635 reset_control_assert(wcss->wcss_reset);
636
637 return 0;
638}
639
640static int q6v5_q6_powerdown(struct q6v5_wcss *wcss)
641{
642 int ret;
643 u32 val;
644 int i;
645
646 /* 1 - Halt Q6 bus interface */
647 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_q6);
648
649 /* 2 - Disable Q6 Core clock */
650 val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
651 val &= ~Q6SS_CLK_ENABLE;
652 writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
653
654 /* 3 - Clamp I/O */
655 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
656 val |= Q6SS_CLAMP_IO;
657 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
658
659 /* 4 - Clamp WL */
660 val |= QDSS_BHS_ON;
661 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
662
663 /* 5 - Clear Erase standby */
664 val &= ~Q6SS_L2DATA_STBY_N;
665 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
666
667 /* 6 - Clear Sleep RTN */
668 val &= ~Q6SS_SLP_RET_N;
669 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
670
671 /* 7 - turn off Q6 memory foot/head switch one bank at a time */
672 for (i = 0; i < 20; i++) {
673 val = readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
674 val &= ~BIT(i);
675 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
676 mdelay(1);
677 }
678
679 /* 8 - Assert QMC memory RTN */
680 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
681 val |= Q6SS_CLAMP_QMC_MEM;
682 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
683
684 /* 9 - Turn off BHS */
685 val &= ~Q6SS_BHS_ON;
686 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
687 udelay(1);
688
689 /* 10 - Wait till BHS Reset is done */
690 ret = readl_poll_timeout(wcss->reg_base + Q6SS_BHS_STATUS,
691 val, !(val & BHS_EN_REST_ACK), 1000,
692 HALT_CHECK_MAX_LOOPS);
693 if (ret) {
694 dev_err(wcss->dev, "BHS_STATUS not OFF (rc:%d)\n", ret);
695 return ret;
696 }
697
698 /* 11 - Assert WCSS reset */
699 reset_control_assert(wcss->wcss_reset);
700
701 /* 12 - Assert Q6 reset */
702 reset_control_assert(wcss->wcss_q6_reset);
703
704 return 0;
705}
706
707static int q6v5_wcss_stop(struct rproc *rproc)
708{
709 struct q6v5_wcss *wcss = rproc->priv;
710 int ret;
711
712 /* WCSS powerdown */
713 if (wcss->requires_force_stop) {
714 ret = qcom_q6v5_request_stop(&wcss->q6v5, NULL);
715 if (ret == -ETIMEDOUT) {
716 dev_err(wcss->dev, "timed out on wait\n");
717 return ret;
718 }
719 }
720
721 if (wcss->version == WCSS_QCS404) {
722 ret = q6v5_qcs404_wcss_shutdown(wcss);
723 if (ret)
724 return ret;
725 } else {
726 ret = q6v5_wcss_powerdown(wcss);
727 if (ret)
728 return ret;
729
730 /* Q6 Power down */
731 ret = q6v5_q6_powerdown(wcss);
732 if (ret)
733 return ret;
734 }
735
736 qcom_q6v5_unprepare(&wcss->q6v5);
737
738 return 0;
739}
740
741static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
742{
743 struct q6v5_wcss *wcss = rproc->priv;
744 int offset;
745
746 offset = da - wcss->mem_reloc;
747 if (offset < 0 || offset + len > wcss->mem_size)
748 return NULL;
749
750 return wcss->mem_region + offset;
751}
752
753static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
754{
755 struct q6v5_wcss *wcss = rproc->priv;
756 int ret;
757
758 ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware,
759 0, wcss->mem_region, wcss->mem_phys,
760 wcss->mem_size, &wcss->mem_reloc);
761 if (ret)
762 return ret;
763
764 qcom_pil_info_store("wcnss", wcss->mem_phys, wcss->mem_size);
765
766 return ret;
767}
768
769static const struct rproc_ops q6v5_wcss_ipq8074_ops = {
770 .start = q6v5_wcss_start,
771 .stop = q6v5_wcss_stop,
772 .da_to_va = q6v5_wcss_da_to_va,
773 .load = q6v5_wcss_load,
774 .get_boot_addr = rproc_elf_get_boot_addr,
775};
776
777static const struct rproc_ops q6v5_wcss_qcs404_ops = {
778 .start = q6v5_qcs404_wcss_start,
779 .stop = q6v5_wcss_stop,
780 .da_to_va = q6v5_wcss_da_to_va,
781 .load = q6v5_wcss_load,
782 .get_boot_addr = rproc_elf_get_boot_addr,
783 .parse_fw = qcom_register_dump_segments,
784};
785
786static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss,
787 const struct wcss_data *desc)
788{
789 struct device *dev = wcss->dev;
790
791 if (desc->aon_reset_required) {
792 wcss->wcss_aon_reset = devm_reset_control_get_exclusive(dev, "wcss_aon_reset");
793 if (IS_ERR(wcss->wcss_aon_reset)) {
794 dev_err(wcss->dev, "fail to acquire wcss_aon_reset\n");
795 return PTR_ERR(wcss->wcss_aon_reset);
796 }
797 }
798
799 wcss->wcss_reset = devm_reset_control_get_exclusive(dev, "wcss_reset");
800 if (IS_ERR(wcss->wcss_reset)) {
801 dev_err(wcss->dev, "unable to acquire wcss_reset\n");
802 return PTR_ERR(wcss->wcss_reset);
803 }
804
805 if (desc->wcss_q6_reset_required) {
806 wcss->wcss_q6_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_reset");
807 if (IS_ERR(wcss->wcss_q6_reset)) {
808 dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n");
809 return PTR_ERR(wcss->wcss_q6_reset);
810 }
811 }
812
813 wcss->wcss_q6_bcr_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_bcr_reset");
814 if (IS_ERR(wcss->wcss_q6_bcr_reset)) {
815 dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n");
816 return PTR_ERR(wcss->wcss_q6_bcr_reset);
817 }
818
819 return 0;
820}
821
822static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,
823 struct platform_device *pdev)
824{
825 unsigned int halt_reg[MAX_HALT_REG] = {0};
826 struct device_node *syscon;
827 struct resource *res;
828 int ret;
829
830 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6");
831 if (!res)
832 return -EINVAL;
833
834 wcss->reg_base = devm_ioremap(&pdev->dev, res->start,
835 resource_size(res));
836 if (!wcss->reg_base)
837 return -ENOMEM;
838
839 if (wcss->version == WCSS_IPQ8074) {
840 wcss->rmb_base = devm_platform_ioremap_resource_byname(pdev, "rmb");
841 if (IS_ERR(wcss->rmb_base))
842 return PTR_ERR(wcss->rmb_base);
843 }
844
845 syscon = of_parse_phandle(pdev->dev.of_node,
846 "qcom,halt-regs", 0);
847 if (!syscon) {
848 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
849 return -EINVAL;
850 }
851
852 wcss->halt_map = syscon_node_to_regmap(syscon);
853 of_node_put(syscon);
854 if (IS_ERR(wcss->halt_map))
855 return PTR_ERR(wcss->halt_map);
856
857 ret = of_property_read_variable_u32_array(pdev->dev.of_node,
858 "qcom,halt-regs",
859 halt_reg, 0,
860 MAX_HALT_REG);
861 if (ret < 0) {
862 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
863 return -EINVAL;
864 }
865
866 wcss->halt_q6 = halt_reg[0];
867 wcss->halt_wcss = halt_reg[1];
868 wcss->halt_nc = halt_reg[2];
869
870 return 0;
871}
872
873static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss)
874{
875 struct reserved_mem *rmem = NULL;
876 struct device_node *node;
877 struct device *dev = wcss->dev;
878
879 node = of_parse_phandle(dev->of_node, "memory-region", 0);
880 if (node)
881 rmem = of_reserved_mem_lookup(node);
882 of_node_put(node);
883
884 if (!rmem) {
885 dev_err(dev, "unable to acquire memory-region\n");
886 return -EINVAL;
887 }
888
889 wcss->mem_phys = rmem->base;
890 wcss->mem_reloc = rmem->base;
891 wcss->mem_size = rmem->size;
892 wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
893 if (!wcss->mem_region) {
894 dev_err(dev, "unable to map memory region: %pa+%pa\n",
895 &rmem->base, &rmem->size);
896 return -EBUSY;
897 }
898
899 return 0;
900}
901
902static int q6v5_wcss_init_clock(struct q6v5_wcss *wcss)
903{
904 int ret;
905
906 wcss->xo = devm_clk_get(wcss->dev, "xo");
907 if (IS_ERR(wcss->xo)) {
908 ret = PTR_ERR(wcss->xo);
909 if (ret != -EPROBE_DEFER)
910 dev_err(wcss->dev, "failed to get xo clock");
911 return ret;
912 }
913
914 wcss->gcc_abhs_cbcr = devm_clk_get(wcss->dev, "gcc_abhs_cbcr");
915 if (IS_ERR(wcss->gcc_abhs_cbcr)) {
916 ret = PTR_ERR(wcss->gcc_abhs_cbcr);
917 if (ret != -EPROBE_DEFER)
918 dev_err(wcss->dev, "failed to get gcc abhs clock");
919 return ret;
920 }
921
922 wcss->gcc_axim_cbcr = devm_clk_get(wcss->dev, "gcc_axim_cbcr");
923 if (IS_ERR(wcss->gcc_axim_cbcr)) {
924 ret = PTR_ERR(wcss->gcc_axim_cbcr);
925 if (ret != -EPROBE_DEFER)
926 dev_err(wcss->dev, "failed to get gcc axim clock\n");
927 return ret;
928 }
929
930 wcss->ahbfabric_cbcr_clk = devm_clk_get(wcss->dev,
931 "lcc_ahbfabric_cbc");
932 if (IS_ERR(wcss->ahbfabric_cbcr_clk)) {
933 ret = PTR_ERR(wcss->ahbfabric_cbcr_clk);
934 if (ret != -EPROBE_DEFER)
935 dev_err(wcss->dev, "failed to get ahbfabric clock\n");
936 return ret;
937 }
938
939 wcss->lcc_csr_cbcr = devm_clk_get(wcss->dev, "tcsr_lcc_cbc");
940 if (IS_ERR(wcss->lcc_csr_cbcr)) {
941 ret = PTR_ERR(wcss->lcc_csr_cbcr);
942 if (ret != -EPROBE_DEFER)
943 dev_err(wcss->dev, "failed to get csr cbcr clk\n");
944 return ret;
945 }
946
947 wcss->ahbs_cbcr = devm_clk_get(wcss->dev,
948 "lcc_abhs_cbc");
949 if (IS_ERR(wcss->ahbs_cbcr)) {
950 ret = PTR_ERR(wcss->ahbs_cbcr);
951 if (ret != -EPROBE_DEFER)
952 dev_err(wcss->dev, "failed to get ahbs_cbcr clk\n");
953 return ret;
954 }
955
956 wcss->tcm_slave_cbcr = devm_clk_get(wcss->dev,
957 "lcc_tcm_slave_cbc");
958 if (IS_ERR(wcss->tcm_slave_cbcr)) {
959 ret = PTR_ERR(wcss->tcm_slave_cbcr);
960 if (ret != -EPROBE_DEFER)
961 dev_err(wcss->dev, "failed to get tcm cbcr clk\n");
962 return ret;
963 }
964
965 wcss->qdsp6ss_abhm_cbcr = devm_clk_get(wcss->dev, "lcc_abhm_cbc");
966 if (IS_ERR(wcss->qdsp6ss_abhm_cbcr)) {
967 ret = PTR_ERR(wcss->qdsp6ss_abhm_cbcr);
968 if (ret != -EPROBE_DEFER)
969 dev_err(wcss->dev, "failed to get abhm cbcr clk\n");
970 return ret;
971 }
972
973 wcss->qdsp6ss_axim_cbcr = devm_clk_get(wcss->dev, "lcc_axim_cbc");
974 if (IS_ERR(wcss->qdsp6ss_axim_cbcr)) {
975 ret = PTR_ERR(wcss->qdsp6ss_axim_cbcr);
976 if (ret != -EPROBE_DEFER)
977 dev_err(wcss->dev, "failed to get axim cbcr clk\n");
978 return ret;
979 }
980
981 wcss->lcc_bcr_sleep = devm_clk_get(wcss->dev, "lcc_bcr_sleep");
982 if (IS_ERR(wcss->lcc_bcr_sleep)) {
983 ret = PTR_ERR(wcss->lcc_bcr_sleep);
984 if (ret != -EPROBE_DEFER)
985 dev_err(wcss->dev, "failed to get bcr cbcr clk\n");
986 return ret;
987 }
988
989 return 0;
990}
991
992static int q6v5_wcss_init_regulator(struct q6v5_wcss *wcss)
993{
994 wcss->cx_supply = devm_regulator_get(wcss->dev, "cx");
995 if (IS_ERR(wcss->cx_supply))
996 return PTR_ERR(wcss->cx_supply);
997
998 regulator_set_load(wcss->cx_supply, 100000);
999
1000 return 0;
1001}
1002
1003static int q6v5_wcss_probe(struct platform_device *pdev)
1004{
1005 const struct wcss_data *desc;
1006 struct q6v5_wcss *wcss;
1007 struct rproc *rproc;
1008 int ret;
1009
1010 desc = device_get_match_data(&pdev->dev);
1011 if (!desc)
1012 return -EINVAL;
1013
1014 rproc = rproc_alloc(&pdev->dev, pdev->name, desc->ops,
1015 desc->firmware_name, sizeof(*wcss));
1016 if (!rproc) {
1017 dev_err(&pdev->dev, "failed to allocate rproc\n");
1018 return -ENOMEM;
1019 }
1020
1021 wcss = rproc->priv;
1022 wcss->dev = &pdev->dev;
1023 wcss->version = desc->version;
1024
1025 wcss->version = desc->version;
1026 wcss->requires_force_stop = desc->requires_force_stop;
1027
1028 ret = q6v5_wcss_init_mmio(wcss, pdev);
1029 if (ret)
1030 goto free_rproc;
1031
1032 ret = q6v5_alloc_memory_region(wcss);
1033 if (ret)
1034 goto free_rproc;
1035
1036 if (wcss->version == WCSS_QCS404) {
1037 ret = q6v5_wcss_init_clock(wcss);
1038 if (ret)
1039 goto free_rproc;
1040
1041 ret = q6v5_wcss_init_regulator(wcss);
1042 if (ret)
1043 goto free_rproc;
1044 }
1045
1046 ret = q6v5_wcss_init_reset(wcss, desc);
1047 if (ret)
1048 goto free_rproc;
1049
1050 ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, NULL, NULL);
1051 if (ret)
1052 goto free_rproc;
1053
1054 qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
1055 qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
1056
1057 if (desc->ssctl_id)
1058 wcss->sysmon = qcom_add_sysmon_subdev(rproc,
1059 desc->sysmon_name,
1060 desc->ssctl_id);
1061
1062 ret = rproc_add(rproc);
1063 if (ret)
1064 goto free_rproc;
1065
1066 platform_set_drvdata(pdev, rproc);
1067
1068 return 0;
1069
1070free_rproc:
1071 rproc_free(rproc);
1072
1073 return ret;
1074}
1075
1076static void q6v5_wcss_remove(struct platform_device *pdev)
1077{
1078 struct rproc *rproc = platform_get_drvdata(pdev);
1079 struct q6v5_wcss *wcss = rproc->priv;
1080
1081 qcom_q6v5_deinit(&wcss->q6v5);
1082 rproc_del(rproc);
1083 rproc_free(rproc);
1084}
1085
1086static const struct wcss_data wcss_ipq8074_res_init = {
1087 .firmware_name = "IPQ8074/q6_fw.mdt",
1088 .crash_reason_smem = WCSS_CRASH_REASON,
1089 .aon_reset_required = true,
1090 .wcss_q6_reset_required = true,
1091 .ops = &q6v5_wcss_ipq8074_ops,
1092 .requires_force_stop = true,
1093};
1094
1095static const struct wcss_data wcss_qcs404_res_init = {
1096 .crash_reason_smem = WCSS_CRASH_REASON,
1097 .firmware_name = "wcnss.mdt",
1098 .version = WCSS_QCS404,
1099 .aon_reset_required = false,
1100 .wcss_q6_reset_required = false,
1101 .ssr_name = "mpss",
1102 .sysmon_name = "wcnss",
1103 .ssctl_id = 0x12,
1104 .ops = &q6v5_wcss_qcs404_ops,
1105 .requires_force_stop = false,
1106};
1107
1108static const struct of_device_id q6v5_wcss_of_match[] = {
1109 { .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init },
1110 { .compatible = "qcom,qcs404-wcss-pil", .data = &wcss_qcs404_res_init },
1111 { },
1112};
1113MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match);
1114
1115static struct platform_driver q6v5_wcss_driver = {
1116 .probe = q6v5_wcss_probe,
1117 .remove_new = q6v5_wcss_remove,
1118 .driver = {
1119 .name = "qcom-q6v5-wcss-pil",
1120 .of_match_table = q6v5_wcss_of_match,
1121 },
1122};
1123module_platform_driver(q6v5_wcss_driver);
1124
1125MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
1126MODULE_LICENSE("GPL v2");
1// SPDX-License-Identifier: GPL-2.0
2/*
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.
6 */
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"
18
19#define WCSS_CRASH_REASON 421
20
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
26
27/* AXI Halt Register Offsets */
28#define AXI_HALTREQ_REG 0x0
29#define AXI_HALTACK_REG 0x4
30#define AXI_IDLE_REG 0x8
31
32#define HALT_ACK_TIMEOUT_MS 100
33
34/* Q6SS_RESET */
35#define Q6SS_STOP_CORE BIT(0)
36#define Q6SS_CORE_ARES BIT(1)
37#define Q6SS_BUS_ARES_ENABLE BIT(2)
38
39/* Q6SS_GFMUX_CTL */
40#define Q6SS_CLK_ENABLE BIT(1)
41
42/* Q6SS_PWR_CTL */
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)
47
48/* Q6SS parameters */
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)
55
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
63
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)
68
69#define MEM_BANKS 19
70#define TCSR_WCSS_CLK_MASK 0x1F
71#define TCSR_WCSS_CLK_ENABLE 0x14
72
73struct q6v5_wcss {
74 struct device *dev;
75
76 void __iomem *reg_base;
77 void __iomem *rmb_base;
78
79 struct regmap *halt_map;
80 u32 halt_q6;
81 u32 halt_wcss;
82 u32 halt_nc;
83
84 struct reset_control *wcss_aon_reset;
85 struct reset_control *wcss_reset;
86 struct reset_control *wcss_q6_reset;
87
88 struct qcom_q6v5 q6v5;
89
90 phys_addr_t mem_phys;
91 phys_addr_t mem_reloc;
92 void *mem_region;
93 size_t mem_size;
94};
95
96static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
97{
98 int ret;
99 u32 val;
100 int i;
101
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);
106
107 /* BHS require xo cbcr to be enabled */
108 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
109 val |= 0x1;
110 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
111
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);
116 if (ret) {
117 dev_err(wcss->dev,
118 "xo cbcr enabling timed out (rc:%d)\n", ret);
119 return ret;
120 }
121 /* Enable power block headswitch and wait for it to stabilize */
122 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
123 val |= Q6SS_BHS_ON;
124 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
125 udelay(1);
126
127 /* Put LDO in bypass mode */
128 val |= Q6SS_LDO_BYP;
129 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
130
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);
135
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);
139
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--) {
143 val |= BIT(i);
144 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
145 /*
146 * Read back value to ensure the write is done then
147 * wait for 1us for both memory peripheral and data
148 * array to turn on.
149 */
150 val |= readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
151 udelay(1);
152 }
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);
157
158 /* Remove IO clamp */
159 val &= ~Q6SS_CLAMP_IO;
160 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
161
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);
166
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);
171
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);
176
177 return 0;
178}
179
180static int q6v5_wcss_start(struct rproc *rproc)
181{
182 struct q6v5_wcss *wcss = rproc->priv;
183 int ret;
184
185 qcom_q6v5_prepare(&wcss->q6v5);
186
187 /* Release Q6 and WCSS reset */
188 ret = reset_control_deassert(wcss->wcss_reset);
189 if (ret) {
190 dev_err(wcss->dev, "wcss_reset failed\n");
191 return ret;
192 }
193
194 ret = reset_control_deassert(wcss->wcss_q6_reset);
195 if (ret) {
196 dev_err(wcss->dev, "wcss_q6_reset failed\n");
197 goto wcss_reset;
198 }
199
200 /* Lithium configuration - clock gating and bus arbitration */
201 ret = regmap_update_bits(wcss->halt_map,
202 wcss->halt_nc + TCSR_GLOBAL_CFG0,
203 TCSR_WCSS_CLK_MASK,
204 TCSR_WCSS_CLK_ENABLE);
205 if (ret)
206 goto wcss_q6_reset;
207
208 ret = regmap_update_bits(wcss->halt_map,
209 wcss->halt_nc + TCSR_GLOBAL_CFG1,
210 1, 0);
211 if (ret)
212 goto wcss_q6_reset;
213
214 /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
215 writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB);
216
217 ret = q6v5_wcss_reset(wcss);
218 if (ret)
219 goto wcss_q6_reset;
220
221 ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ);
222 if (ret == -ETIMEDOUT)
223 dev_err(wcss->dev, "start timed out\n");
224
225 return ret;
226
227wcss_q6_reset:
228 reset_control_assert(wcss->wcss_q6_reset);
229
230wcss_reset:
231 reset_control_assert(wcss->wcss_reset);
232
233 return ret;
234}
235
236static void q6v5_wcss_halt_axi_port(struct q6v5_wcss *wcss,
237 struct regmap *halt_map,
238 u32 offset)
239{
240 unsigned long timeout;
241 unsigned int val;
242 int ret;
243
244 /* Check if we're already idle */
245 ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
246 if (!ret && val)
247 return;
248
249 /* Assert halt request */
250 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
251
252 /* Wait for halt */
253 timeout = jiffies + msecs_to_jiffies(HALT_ACK_TIMEOUT_MS);
254 for (;;) {
255 ret = regmap_read(halt_map, offset + AXI_HALTACK_REG, &val);
256 if (ret || val || time_after(jiffies, timeout))
257 break;
258
259 msleep(1);
260 }
261
262 ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
263 if (ret || !val)
264 dev_err(wcss->dev, "port failed halt\n");
265
266 /* Clear halt request (port will remain halted until reset) */
267 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
268}
269
270static int q6v5_wcss_powerdown(struct q6v5_wcss *wcss)
271{
272 int ret;
273 u32 val;
274
275 /* 1 - Assert WCSS/Q6 HALTREQ */
276 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss);
277
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);
282
283 /* 3 - Set SSCAON_CONFIG */
284 val |= SSCAON_BUS_EN;
285 val &= ~SSCAON_BUS_MUX_MASK;
286 writel(val, wcss->rmb_base + SSCAON_CONFIG);
287
288 /* 4 - SSCAON_CONFIG 1 */
289 val |= BIT(1);
290 writel(val, wcss->rmb_base + SSCAON_CONFIG);
291
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);
296 if (ret) {
297 dev_err(wcss->dev,
298 "can't get SSCAON_STATUS rc:%d)\n", ret);
299 return ret;
300 }
301
302 /* 6 - De-assert WCSS_AON reset */
303 reset_control_assert(wcss->wcss_aon_reset);
304
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);
309
310 /* 8 - De-assert WCSS/Q6 HALTREQ */
311 reset_control_assert(wcss->wcss_reset);
312
313 return 0;
314}
315
316static int q6v5_q6_powerdown(struct q6v5_wcss *wcss)
317{
318 int ret;
319 u32 val;
320 int i;
321
322 /* 1 - Halt Q6 bus interface */
323 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_q6);
324
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);
329
330 /* 3 - Clamp I/O */
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);
334
335 /* 4 - Clamp WL */
336 val |= QDSS_BHS_ON;
337 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
338
339 /* 5 - Clear Erase standby */
340 val &= ~Q6SS_L2DATA_STBY_N;
341 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
342
343 /* 6 - Clear Sleep RTN */
344 val &= ~Q6SS_SLP_RET_N;
345 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
346
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);
350 val &= ~BIT(i);
351 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
352 mdelay(1);
353 }
354
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);
359
360 /* 9 - Turn off BHS */
361 val &= ~Q6SS_BHS_ON;
362 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
363 udelay(1);
364
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);
369 if (ret) {
370 dev_err(wcss->dev, "BHS_STATUS not OFF (rc:%d)\n", ret);
371 return ret;
372 }
373
374 /* 11 - Assert WCSS reset */
375 reset_control_assert(wcss->wcss_reset);
376
377 /* 12 - Assert Q6 reset */
378 reset_control_assert(wcss->wcss_q6_reset);
379
380 return 0;
381}
382
383static int q6v5_wcss_stop(struct rproc *rproc)
384{
385 struct q6v5_wcss *wcss = rproc->priv;
386 int ret;
387
388 /* WCSS powerdown */
389 ret = qcom_q6v5_request_stop(&wcss->q6v5);
390 if (ret == -ETIMEDOUT) {
391 dev_err(wcss->dev, "timed out on wait\n");
392 return ret;
393 }
394
395 ret = q6v5_wcss_powerdown(wcss);
396 if (ret)
397 return ret;
398
399 /* Q6 Power down */
400 ret = q6v5_q6_powerdown(wcss);
401 if (ret)
402 return ret;
403
404 qcom_q6v5_unprepare(&wcss->q6v5);
405
406 return 0;
407}
408
409static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
410{
411 struct q6v5_wcss *wcss = rproc->priv;
412 int offset;
413
414 offset = da - wcss->mem_reloc;
415 if (offset < 0 || offset + len > wcss->mem_size)
416 return NULL;
417
418 return wcss->mem_region + offset;
419}
420
421static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
422{
423 struct q6v5_wcss *wcss = rproc->priv;
424
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);
428}
429
430static 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,
436};
437
438static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss)
439{
440 struct device *dev = wcss->dev;
441
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);
446 }
447
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);
452 }
453
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);
458 }
459
460 return 0;
461}
462
463static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,
464 struct platform_device *pdev)
465{
466 struct of_phandle_args args;
467 struct resource *res;
468 int ret;
469
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);
474
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);
479
480 ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
481 "qcom,halt-regs", 3, 0, &args);
482 if (ret < 0) {
483 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
484 return -EINVAL;
485 }
486
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);
491
492 wcss->halt_q6 = args.args[0];
493 wcss->halt_wcss = args.args[1];
494 wcss->halt_nc = args.args[2];
495
496 return 0;
497}
498
499static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss)
500{
501 struct reserved_mem *rmem = NULL;
502 struct device_node *node;
503 struct device *dev = wcss->dev;
504
505 node = of_parse_phandle(dev->of_node, "memory-region", 0);
506 if (node)
507 rmem = of_reserved_mem_lookup(node);
508 of_node_put(node);
509
510 if (!rmem) {
511 dev_err(dev, "unable to acquire memory-region\n");
512 return -EINVAL;
513 }
514
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);
522 return -EBUSY;
523 }
524
525 return 0;
526}
527
528static int q6v5_wcss_probe(struct platform_device *pdev)
529{
530 struct q6v5_wcss *wcss;
531 struct rproc *rproc;
532 int ret;
533
534 rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_wcss_ops,
535 "IPQ8074/q6_fw.mdt", sizeof(*wcss));
536 if (!rproc) {
537 dev_err(&pdev->dev, "failed to allocate rproc\n");
538 return -ENOMEM;
539 }
540
541 wcss = rproc->priv;
542 wcss->dev = &pdev->dev;
543
544 ret = q6v5_wcss_init_mmio(wcss, pdev);
545 if (ret)
546 goto free_rproc;
547
548 ret = q6v5_alloc_memory_region(wcss);
549 if (ret)
550 goto free_rproc;
551
552 ret = q6v5_wcss_init_reset(wcss);
553 if (ret)
554 goto free_rproc;
555
556 ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, WCSS_CRASH_REASON, NULL);
557 if (ret)
558 goto free_rproc;
559
560 ret = rproc_add(rproc);
561 if (ret)
562 goto free_rproc;
563
564 platform_set_drvdata(pdev, rproc);
565
566 return 0;
567
568free_rproc:
569 rproc_free(rproc);
570
571 return ret;
572}
573
574static int q6v5_wcss_remove(struct platform_device *pdev)
575{
576 struct rproc *rproc = platform_get_drvdata(pdev);
577
578 rproc_del(rproc);
579 rproc_free(rproc);
580
581 return 0;
582}
583
584static const struct of_device_id q6v5_wcss_of_match[] = {
585 { .compatible = "qcom,ipq8074-wcss-pil" },
586 { },
587};
588MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match);
589
590static struct platform_driver q6v5_wcss_driver = {
591 .probe = q6v5_wcss_probe,
592 .remove = q6v5_wcss_remove,
593 .driver = {
594 .name = "qcom-q6v5-wcss-pil",
595 .of_match_table = q6v5_wcss_of_match,
596 },
597};
598module_platform_driver(q6v5_wcss_driver);
599
600MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
601MODULE_LICENSE("GPL v2");