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
89 enum {
90 WCSS_IPQ8074,
91 WCSS_QCS404,
92 };
93
94 struct 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
107 struct 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_pdm pdm_subdev;
152 struct qcom_rproc_ssr ssr_subdev;
153 };
154
q6v5_wcss_reset(struct q6v5_wcss * wcss)155 static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
156 {
157 int ret;
158 u32 val;
159 int i;
160
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);
165
166 /* BHS require xo cbcr to be enabled */
167 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
168 val |= 0x1;
169 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
170
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);
175 if (ret) {
176 dev_err(wcss->dev,
177 "xo cbcr enabling timed out (rc:%d)\n", ret);
178 return ret;
179 }
180 /* Enable power block headswitch and wait for it to stabilize */
181 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
182 val |= Q6SS_BHS_ON;
183 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
184 udelay(1);
185
186 /* Put LDO in bypass mode */
187 val |= Q6SS_LDO_BYP;
188 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
189
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);
194
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);
198
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--) {
202 val |= BIT(i);
203 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
204 /*
205 * Read back value to ensure the write is done then
206 * wait for 1us for both memory peripheral and data
207 * array to turn on.
208 */
209 val |= readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
210 udelay(1);
211 }
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);
216
217 /* Remove IO clamp */
218 val &= ~Q6SS_CLAMP_IO;
219 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
220
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);
225
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);
230
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);
235
236 return 0;
237 }
238
q6v5_wcss_start(struct rproc * rproc)239 static int q6v5_wcss_start(struct rproc *rproc)
240 {
241 struct q6v5_wcss *wcss = rproc->priv;
242 int ret;
243
244 qcom_q6v5_prepare(&wcss->q6v5);
245
246 /* Release Q6 and WCSS reset */
247 ret = reset_control_deassert(wcss->wcss_reset);
248 if (ret) {
249 dev_err(wcss->dev, "wcss_reset failed\n");
250 return ret;
251 }
252
253 ret = reset_control_deassert(wcss->wcss_q6_reset);
254 if (ret) {
255 dev_err(wcss->dev, "wcss_q6_reset failed\n");
256 goto wcss_reset;
257 }
258
259 /* Lithium configuration - clock gating and bus arbitration */
260 ret = regmap_update_bits(wcss->halt_map,
261 wcss->halt_nc + TCSR_GLOBAL_CFG0,
262 TCSR_WCSS_CLK_MASK,
263 TCSR_WCSS_CLK_ENABLE);
264 if (ret)
265 goto wcss_q6_reset;
266
267 ret = regmap_update_bits(wcss->halt_map,
268 wcss->halt_nc + TCSR_GLOBAL_CFG1,
269 1, 0);
270 if (ret)
271 goto wcss_q6_reset;
272
273 /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
274 writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB);
275
276 ret = q6v5_wcss_reset(wcss);
277 if (ret)
278 goto wcss_q6_reset;
279
280 ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ);
281 if (ret == -ETIMEDOUT)
282 dev_err(wcss->dev, "start timed out\n");
283
284 return ret;
285
286 wcss_q6_reset:
287 reset_control_assert(wcss->wcss_q6_reset);
288
289 wcss_reset:
290 reset_control_assert(wcss->wcss_reset);
291
292 return ret;
293 }
294
q6v5_wcss_qcs404_power_on(struct q6v5_wcss * wcss)295 static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss)
296 {
297 unsigned long val;
298 int ret, idx;
299
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);
305
306 /* Enable GCC_WDSP_Q6SS_AHBS_CBCR clock */
307 ret = clk_prepare_enable(wcss->gcc_abhs_cbcr);
308 if (ret)
309 return ret;
310
311 /* Remove reset to the WCNSS QDSP6SS */
312 reset_control_deassert(wcss->wcss_q6_bcr_reset);
313
314 /* Enable Q6SSTOP_AHBFABRIC_CBCR clock */
315 ret = clk_prepare_enable(wcss->ahbfabric_cbcr_clk);
316 if (ret)
317 goto disable_gcc_abhs_cbcr_clk;
318
319 /* Enable the LCCCSR CBC clock, Q6SSTOP_Q6SSTOP_LCC_CSR_CBCR clock */
320 ret = clk_prepare_enable(wcss->lcc_csr_cbcr);
321 if (ret)
322 goto disable_ahbfabric_cbcr_clk;
323
324 /* Enable the Q6AHBS CBC, Q6SSTOP_Q6SS_AHBS_CBCR clock */
325 ret = clk_prepare_enable(wcss->ahbs_cbcr);
326 if (ret)
327 goto disable_csr_cbcr_clk;
328
329 /* Enable the TCM slave CBC, Q6SSTOP_Q6SS_TCM_SLAVE_CBCR clock */
330 ret = clk_prepare_enable(wcss->tcm_slave_cbcr);
331 if (ret)
332 goto disable_ahbs_cbcr_clk;
333
334 /* Enable the Q6SS AHB master CBC, Q6SSTOP_Q6SS_AHBM_CBCR clock */
335 ret = clk_prepare_enable(wcss->qdsp6ss_abhm_cbcr);
336 if (ret)
337 goto disable_tcm_slave_cbcr_clk;
338
339 /* Enable the Q6SS AXI master CBC, Q6SSTOP_Q6SS_AXIM_CBCR clock */
340 ret = clk_prepare_enable(wcss->qdsp6ss_axim_cbcr);
341 if (ret)
342 goto disable_abhm_cbcr_clk;
343
344 /* Enable the Q6SS XO CBC */
345 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
346 val |= BIT(0);
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);
352 if (ret) {
353 dev_err(wcss->dev,
354 "xo cbcr enabling timed out (rc:%d)\n", ret);
355 goto disable_xo_cbcr_clk;
356 }
357
358 writel(0, wcss->reg_base + Q6SS_CGC_OVERRIDE);
359
360 /* Enable QDSP6 sleep clock clock */
361 val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR);
362 val |= BIT(0);
363 writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR);
364
365 /* Enable the Enable the Q6 AXI clock, GCC_WDSP_Q6SS_AXIM_CBCR*/
366 ret = clk_prepare_enable(wcss->gcc_axim_cbcr);
367 if (ret)
368 goto disable_sleep_cbcr_clk;
369
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);
374
375 /* Program the QDSP6SS PWR_CTL register */
376 writel(0x01700000, wcss->reg_base + Q6SS_PWR_CTL_REG);
377
378 writel(0x03700000, wcss->reg_base + Q6SS_PWR_CTL_REG);
379
380 writel(0x03300000, wcss->reg_base + Q6SS_PWR_CTL_REG);
381
382 writel(0x033C0000, wcss->reg_base + Q6SS_PWR_CTL_REG);
383
384 /*
385 * Enable memories by turning on the QDSP6 memory foot/head switch, one
386 * bank at a time to avoid in-rush current
387 */
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);
391 }
392
393 writel(0x031C0000, wcss->reg_base + Q6SS_PWR_CTL_REG);
394 writel(0x030C0000, wcss->reg_base + Q6SS_PWR_CTL_REG);
395
396 val = readl(wcss->reg_base + Q6SS_RESET_REG);
397 val &= ~Q6SS_CORE_ARES;
398 writel(val, wcss->reg_base + Q6SS_RESET_REG);
399
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);
404
405 /* Enable sleep clock branch needed for BCR circuit */
406 ret = clk_prepare_enable(wcss->lcc_bcr_sleep);
407 if (ret)
408 goto disable_core_gfmux_clk;
409
410 return 0;
411
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);
421 disable_xo_cbcr_clk:
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);
438
439 return ret;
440 }
441
q6v5_wcss_qcs404_reset(struct q6v5_wcss * wcss)442 static inline int q6v5_wcss_qcs404_reset(struct q6v5_wcss *wcss)
443 {
444 unsigned long val;
445
446 writel(0x80800000, wcss->reg_base + Q6SS_STRAP_ACC);
447
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);
452
453 return 0;
454 }
455
q6v5_qcs404_wcss_start(struct rproc * rproc)456 static int q6v5_qcs404_wcss_start(struct rproc *rproc)
457 {
458 struct q6v5_wcss *wcss = rproc->priv;
459 int ret;
460
461 ret = clk_prepare_enable(wcss->xo);
462 if (ret)
463 return ret;
464
465 ret = regulator_enable(wcss->cx_supply);
466 if (ret)
467 goto disable_xo_clk;
468
469 qcom_q6v5_prepare(&wcss->q6v5);
470
471 ret = q6v5_wcss_qcs404_power_on(wcss);
472 if (ret) {
473 dev_err(wcss->dev, "wcss clk_enable failed\n");
474 goto disable_cx_supply;
475 }
476
477 writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB);
478
479 q6v5_wcss_qcs404_reset(wcss);
480
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;
485 }
486
487 return 0;
488
489 disable_cx_supply:
490 regulator_disable(wcss->cx_supply);
491 disable_xo_clk:
492 clk_disable_unprepare(wcss->xo);
493
494 return ret;
495 }
496
q6v5_wcss_halt_axi_port(struct q6v5_wcss * wcss,struct regmap * halt_map,u32 offset)497 static void q6v5_wcss_halt_axi_port(struct q6v5_wcss *wcss,
498 struct regmap *halt_map,
499 u32 offset)
500 {
501 unsigned long timeout;
502 unsigned int val;
503 int ret;
504
505 /* Check if we're already idle */
506 ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
507 if (!ret && val)
508 return;
509
510 /* Assert halt request */
511 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
512
513 /* Wait for halt */
514 timeout = jiffies + msecs_to_jiffies(HALT_ACK_TIMEOUT_MS);
515 for (;;) {
516 ret = regmap_read(halt_map, offset + AXI_HALTACK_REG, &val);
517 if (ret || val || time_after(jiffies, timeout))
518 break;
519
520 msleep(1);
521 }
522
523 ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
524 if (ret || !val)
525 dev_err(wcss->dev, "port failed halt\n");
526
527 /* Clear halt request (port will remain halted until reset) */
528 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
529 }
530
q6v5_qcs404_wcss_shutdown(struct q6v5_wcss * wcss)531 static int q6v5_qcs404_wcss_shutdown(struct q6v5_wcss *wcss)
532 {
533 unsigned long val;
534 int ret;
535
536 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss);
537
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);
542
543 /* Disable memories by turning off memory foot/headswitch */
544 writel((readl(wcss->reg_base + Q6SS_MEM_PWR_CTL) &
545 ~QDSS_Q6_MEMORIES),
546 wcss->reg_base + Q6SS_MEM_PWR_CTL);
547
548 /* Clear the BHS_ON bit */
549 val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
550 val &= ~Q6SS_BHS_ON;
551 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
552
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);
558
559 val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR);
560 val &= ~BIT(0);
561 writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR);
562
563 val = readl(wcss->reg_base + Q6SS_XO_CBCR);
564 val &= ~BIT(0);
565 writel(val, wcss->reg_base + Q6SS_XO_CBCR);
566
567 clk_disable_unprepare(wcss->ahbs_cbcr);
568 clk_disable_unprepare(wcss->lcc_bcr_sleep);
569
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);
573
574 clk_disable_unprepare(wcss->gcc_abhs_cbcr);
575
576 ret = reset_control_assert(wcss->wcss_reset);
577 if (ret) {
578 dev_err(wcss->dev, "wcss_reset failed\n");
579 return ret;
580 }
581 usleep_range(200, 300);
582
583 ret = reset_control_deassert(wcss->wcss_reset);
584 if (ret) {
585 dev_err(wcss->dev, "wcss_reset failed\n");
586 return ret;
587 }
588 usleep_range(200, 300);
589
590 clk_disable_unprepare(wcss->gcc_axim_cbcr);
591
592 return 0;
593 }
594
q6v5_wcss_powerdown(struct q6v5_wcss * wcss)595 static int q6v5_wcss_powerdown(struct q6v5_wcss *wcss)
596 {
597 int ret;
598 u32 val;
599
600 /* 1 - Assert WCSS/Q6 HALTREQ */
601 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss);
602
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);
607
608 /* 3 - Set SSCAON_CONFIG */
609 val |= SSCAON_BUS_EN;
610 val &= ~SSCAON_BUS_MUX_MASK;
611 writel(val, wcss->rmb_base + SSCAON_CONFIG);
612
613 /* 4 - SSCAON_CONFIG 1 */
614 val |= BIT(1);
615 writel(val, wcss->rmb_base + SSCAON_CONFIG);
616
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);
621 if (ret) {
622 dev_err(wcss->dev,
623 "can't get SSCAON_STATUS rc:%d)\n", ret);
624 return ret;
625 }
626
627 /* 6 - De-assert WCSS_AON reset */
628 reset_control_assert(wcss->wcss_aon_reset);
629
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);
634
635 /* 8 - De-assert WCSS/Q6 HALTREQ */
636 reset_control_assert(wcss->wcss_reset);
637
638 return 0;
639 }
640
q6v5_q6_powerdown(struct q6v5_wcss * wcss)641 static int q6v5_q6_powerdown(struct q6v5_wcss *wcss)
642 {
643 int ret;
644 u32 val;
645 int i;
646
647 /* 1 - Halt Q6 bus interface */
648 q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_q6);
649
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);
654
655 /* 3 - Clamp I/O */
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);
659
660 /* 4 - Clamp WL */
661 val |= QDSS_BHS_ON;
662 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
663
664 /* 5 - Clear Erase standby */
665 val &= ~Q6SS_L2DATA_STBY_N;
666 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
667
668 /* 6 - Clear Sleep RTN */
669 val &= ~Q6SS_SLP_RET_N;
670 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
671
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);
675 val &= ~BIT(i);
676 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
677 mdelay(1);
678 }
679
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);
684
685 /* 9 - Turn off BHS */
686 val &= ~Q6SS_BHS_ON;
687 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
688 udelay(1);
689
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);
694 if (ret) {
695 dev_err(wcss->dev, "BHS_STATUS not OFF (rc:%d)\n", ret);
696 return ret;
697 }
698
699 /* 11 - Assert WCSS reset */
700 reset_control_assert(wcss->wcss_reset);
701
702 /* 12 - Assert Q6 reset */
703 reset_control_assert(wcss->wcss_q6_reset);
704
705 return 0;
706 }
707
q6v5_wcss_stop(struct rproc * rproc)708 static int q6v5_wcss_stop(struct rproc *rproc)
709 {
710 struct q6v5_wcss *wcss = rproc->priv;
711 int ret;
712
713 /* WCSS powerdown */
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");
718 return ret;
719 }
720 }
721
722 if (wcss->version == WCSS_QCS404) {
723 ret = q6v5_qcs404_wcss_shutdown(wcss);
724 if (ret)
725 return ret;
726 } else {
727 ret = q6v5_wcss_powerdown(wcss);
728 if (ret)
729 return ret;
730
731 /* Q6 Power down */
732 ret = q6v5_q6_powerdown(wcss);
733 if (ret)
734 return ret;
735 }
736
737 qcom_q6v5_unprepare(&wcss->q6v5);
738
739 return 0;
740 }
741
q6v5_wcss_da_to_va(struct rproc * rproc,u64 da,size_t len,bool * is_iomem)742 static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
743 {
744 struct q6v5_wcss *wcss = rproc->priv;
745 int offset;
746
747 offset = da - wcss->mem_reloc;
748 if (offset < 0 || offset + len > wcss->mem_size)
749 return NULL;
750
751 return wcss->mem_region + offset;
752 }
753
q6v5_wcss_load(struct rproc * rproc,const struct firmware * fw)754 static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
755 {
756 struct q6v5_wcss *wcss = rproc->priv;
757 int ret;
758
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);
762 if (ret)
763 return ret;
764
765 qcom_pil_info_store("wcnss", wcss->mem_phys, wcss->mem_size);
766
767 return ret;
768 }
769
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,
776 };
777
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,
785 };
786
q6v5_wcss_init_reset(struct q6v5_wcss * wcss,const struct wcss_data * desc)787 static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss,
788 const struct wcss_data *desc)
789 {
790 struct device *dev = wcss->dev;
791
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);
797 }
798 }
799
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);
804 }
805
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);
811 }
812 }
813
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);
818 }
819
820 return 0;
821 }
822
q6v5_wcss_init_mmio(struct q6v5_wcss * wcss,struct platform_device * pdev)823 static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,
824 struct platform_device *pdev)
825 {
826 unsigned int halt_reg[MAX_HALT_REG] = {0};
827 struct device_node *syscon;
828 struct resource *res;
829 int ret;
830
831 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6");
832 if (!res)
833 return -EINVAL;
834
835 wcss->reg_base = devm_ioremap(&pdev->dev, res->start,
836 resource_size(res));
837 if (!wcss->reg_base)
838 return -ENOMEM;
839
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);
844 }
845
846 syscon = of_parse_phandle(pdev->dev.of_node,
847 "qcom,halt-regs", 0);
848 if (!syscon) {
849 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
850 return -EINVAL;
851 }
852
853 wcss->halt_map = syscon_node_to_regmap(syscon);
854 of_node_put(syscon);
855 if (IS_ERR(wcss->halt_map))
856 return PTR_ERR(wcss->halt_map);
857
858 ret = of_property_read_variable_u32_array(pdev->dev.of_node,
859 "qcom,halt-regs",
860 halt_reg, 0,
861 MAX_HALT_REG);
862 if (ret < 0) {
863 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
864 return -EINVAL;
865 }
866
867 wcss->halt_q6 = halt_reg[0];
868 wcss->halt_wcss = halt_reg[1];
869 wcss->halt_nc = halt_reg[2];
870
871 return 0;
872 }
873
q6v5_alloc_memory_region(struct q6v5_wcss * wcss)874 static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss)
875 {
876 struct reserved_mem *rmem = NULL;
877 struct device_node *node;
878 struct device *dev = wcss->dev;
879
880 node = of_parse_phandle(dev->of_node, "memory-region", 0);
881 if (node)
882 rmem = of_reserved_mem_lookup(node);
883 of_node_put(node);
884
885 if (!rmem) {
886 dev_err(dev, "unable to acquire memory-region\n");
887 return -EINVAL;
888 }
889
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);
897 return -EBUSY;
898 }
899
900 return 0;
901 }
902
q6v5_wcss_init_clock(struct q6v5_wcss * wcss)903 static int q6v5_wcss_init_clock(struct q6v5_wcss *wcss)
904 {
905 int ret;
906
907 wcss->xo = devm_clk_get(wcss->dev, "xo");
908 if (IS_ERR(wcss->xo)) {
909 ret = PTR_ERR(wcss->xo);
910 if (ret != -EPROBE_DEFER)
911 dev_err(wcss->dev, "failed to get xo clock");
912 return ret;
913 }
914
915 wcss->gcc_abhs_cbcr = devm_clk_get(wcss->dev, "gcc_abhs_cbcr");
916 if (IS_ERR(wcss->gcc_abhs_cbcr)) {
917 ret = PTR_ERR(wcss->gcc_abhs_cbcr);
918 if (ret != -EPROBE_DEFER)
919 dev_err(wcss->dev, "failed to get gcc abhs clock");
920 return ret;
921 }
922
923 wcss->gcc_axim_cbcr = devm_clk_get(wcss->dev, "gcc_axim_cbcr");
924 if (IS_ERR(wcss->gcc_axim_cbcr)) {
925 ret = PTR_ERR(wcss->gcc_axim_cbcr);
926 if (ret != -EPROBE_DEFER)
927 dev_err(wcss->dev, "failed to get gcc axim clock\n");
928 return ret;
929 }
930
931 wcss->ahbfabric_cbcr_clk = devm_clk_get(wcss->dev,
932 "lcc_ahbfabric_cbc");
933 if (IS_ERR(wcss->ahbfabric_cbcr_clk)) {
934 ret = PTR_ERR(wcss->ahbfabric_cbcr_clk);
935 if (ret != -EPROBE_DEFER)
936 dev_err(wcss->dev, "failed to get ahbfabric clock\n");
937 return ret;
938 }
939
940 wcss->lcc_csr_cbcr = devm_clk_get(wcss->dev, "tcsr_lcc_cbc");
941 if (IS_ERR(wcss->lcc_csr_cbcr)) {
942 ret = PTR_ERR(wcss->lcc_csr_cbcr);
943 if (ret != -EPROBE_DEFER)
944 dev_err(wcss->dev, "failed to get csr cbcr clk\n");
945 return ret;
946 }
947
948 wcss->ahbs_cbcr = devm_clk_get(wcss->dev,
949 "lcc_abhs_cbc");
950 if (IS_ERR(wcss->ahbs_cbcr)) {
951 ret = PTR_ERR(wcss->ahbs_cbcr);
952 if (ret != -EPROBE_DEFER)
953 dev_err(wcss->dev, "failed to get ahbs_cbcr clk\n");
954 return ret;
955 }
956
957 wcss->tcm_slave_cbcr = devm_clk_get(wcss->dev,
958 "lcc_tcm_slave_cbc");
959 if (IS_ERR(wcss->tcm_slave_cbcr)) {
960 ret = PTR_ERR(wcss->tcm_slave_cbcr);
961 if (ret != -EPROBE_DEFER)
962 dev_err(wcss->dev, "failed to get tcm cbcr clk\n");
963 return ret;
964 }
965
966 wcss->qdsp6ss_abhm_cbcr = devm_clk_get(wcss->dev, "lcc_abhm_cbc");
967 if (IS_ERR(wcss->qdsp6ss_abhm_cbcr)) {
968 ret = PTR_ERR(wcss->qdsp6ss_abhm_cbcr);
969 if (ret != -EPROBE_DEFER)
970 dev_err(wcss->dev, "failed to get abhm cbcr clk\n");
971 return ret;
972 }
973
974 wcss->qdsp6ss_axim_cbcr = devm_clk_get(wcss->dev, "lcc_axim_cbc");
975 if (IS_ERR(wcss->qdsp6ss_axim_cbcr)) {
976 ret = PTR_ERR(wcss->qdsp6ss_axim_cbcr);
977 if (ret != -EPROBE_DEFER)
978 dev_err(wcss->dev, "failed to get axim cbcr clk\n");
979 return ret;
980 }
981
982 wcss->lcc_bcr_sleep = devm_clk_get(wcss->dev, "lcc_bcr_sleep");
983 if (IS_ERR(wcss->lcc_bcr_sleep)) {
984 ret = PTR_ERR(wcss->lcc_bcr_sleep);
985 if (ret != -EPROBE_DEFER)
986 dev_err(wcss->dev, "failed to get bcr cbcr clk\n");
987 return ret;
988 }
989
990 return 0;
991 }
992
q6v5_wcss_init_regulator(struct q6v5_wcss * wcss)993 static int q6v5_wcss_init_regulator(struct q6v5_wcss *wcss)
994 {
995 wcss->cx_supply = devm_regulator_get(wcss->dev, "cx");
996 if (IS_ERR(wcss->cx_supply))
997 return PTR_ERR(wcss->cx_supply);
998
999 regulator_set_load(wcss->cx_supply, 100000);
1000
1001 return 0;
1002 }
1003
q6v5_wcss_probe(struct platform_device * pdev)1004 static int q6v5_wcss_probe(struct platform_device *pdev)
1005 {
1006 const struct wcss_data *desc;
1007 struct q6v5_wcss *wcss;
1008 struct rproc *rproc;
1009 int ret;
1010
1011 desc = device_get_match_data(&pdev->dev);
1012 if (!desc)
1013 return -EINVAL;
1014
1015 rproc = devm_rproc_alloc(&pdev->dev, pdev->name, desc->ops,
1016 desc->firmware_name, sizeof(*wcss));
1017 if (!rproc) {
1018 dev_err(&pdev->dev, "failed to allocate rproc\n");
1019 return -ENOMEM;
1020 }
1021
1022 wcss = rproc->priv;
1023 wcss->dev = &pdev->dev;
1024 wcss->version = desc->version;
1025
1026 wcss->version = desc->version;
1027 wcss->requires_force_stop = desc->requires_force_stop;
1028
1029 ret = q6v5_wcss_init_mmio(wcss, pdev);
1030 if (ret)
1031 return ret;
1032
1033 ret = q6v5_alloc_memory_region(wcss);
1034 if (ret)
1035 return ret;
1036
1037 if (wcss->version == WCSS_QCS404) {
1038 ret = q6v5_wcss_init_clock(wcss);
1039 if (ret)
1040 return ret;
1041
1042 ret = q6v5_wcss_init_regulator(wcss);
1043 if (ret)
1044 return ret;
1045 }
1046
1047 ret = q6v5_wcss_init_reset(wcss, desc);
1048 if (ret)
1049 return ret;
1050
1051 ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, NULL, NULL);
1052 if (ret)
1053 return ret;
1054
1055 qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
1056 qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
1057 qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
1058
1059 if (desc->ssctl_id)
1060 wcss->sysmon = qcom_add_sysmon_subdev(rproc,
1061 desc->sysmon_name,
1062 desc->ssctl_id);
1063
1064 ret = rproc_add(rproc);
1065 if (ret)
1066 return ret;
1067
1068 platform_set_drvdata(pdev, rproc);
1069
1070 return 0;
1071 }
1072
q6v5_wcss_remove(struct platform_device * pdev)1073 static void q6v5_wcss_remove(struct platform_device *pdev)
1074 {
1075 struct rproc *rproc = platform_get_drvdata(pdev);
1076 struct q6v5_wcss *wcss = rproc->priv;
1077
1078 qcom_q6v5_deinit(&wcss->q6v5);
1079 qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
1080 rproc_del(rproc);
1081 }
1082
1083 static const struct wcss_data wcss_ipq8074_res_init = {
1084 .firmware_name = "IPQ8074/q6_fw.mdt",
1085 .crash_reason_smem = WCSS_CRASH_REASON,
1086 .aon_reset_required = true,
1087 .wcss_q6_reset_required = true,
1088 .ops = &q6v5_wcss_ipq8074_ops,
1089 .requires_force_stop = true,
1090 };
1091
1092 static const struct wcss_data wcss_qcs404_res_init = {
1093 .crash_reason_smem = WCSS_CRASH_REASON,
1094 .firmware_name = "wcnss.mdt",
1095 .version = WCSS_QCS404,
1096 .aon_reset_required = false,
1097 .wcss_q6_reset_required = false,
1098 .ssr_name = "mpss",
1099 .sysmon_name = "wcnss",
1100 .ssctl_id = 0x12,
1101 .ops = &q6v5_wcss_qcs404_ops,
1102 .requires_force_stop = false,
1103 };
1104
1105 static const struct of_device_id q6v5_wcss_of_match[] = {
1106 { .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init },
1107 { .compatible = "qcom,qcs404-wcss-pil", .data = &wcss_qcs404_res_init },
1108 { },
1109 };
1110 MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match);
1111
1112 static struct platform_driver q6v5_wcss_driver = {
1113 .probe = q6v5_wcss_probe,
1114 .remove_new = q6v5_wcss_remove,
1115 .driver = {
1116 .name = "qcom-q6v5-wcss-pil",
1117 .of_match_table = q6v5_wcss_of_match,
1118 },
1119 };
1120 module_platform_driver(q6v5_wcss_driver);
1121
1122 MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
1123 MODULE_LICENSE("GPL v2");
1124