Merge tag 'xfs-6.9-merge-9' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux-2.6-microblaze.git] / drivers / remoteproc / qcom_q6v5_wcss.c
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_ssr ssr_subdev;
152 };
153
154 static 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
238 static 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
285 wcss_q6_reset:
286         reset_control_assert(wcss->wcss_q6_reset);
287
288 wcss_reset:
289         reset_control_assert(wcss->wcss_reset);
290
291         return ret;
292 }
293
294 static 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
411 disable_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);
416 disable_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);
420 disable_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);
425 disable_abhm_cbcr_clk:
426         clk_disable_unprepare(wcss->qdsp6ss_abhm_cbcr);
427 disable_tcm_slave_cbcr_clk:
428         clk_disable_unprepare(wcss->tcm_slave_cbcr);
429 disable_ahbs_cbcr_clk:
430         clk_disable_unprepare(wcss->ahbs_cbcr);
431 disable_csr_cbcr_clk:
432         clk_disable_unprepare(wcss->lcc_csr_cbcr);
433 disable_ahbfabric_cbcr_clk:
434         clk_disable_unprepare(wcss->ahbfabric_cbcr_clk);
435 disable_gcc_abhs_cbcr_clk:
436         clk_disable_unprepare(wcss->gcc_abhs_cbcr);
437
438         return ret;
439 }
440
441 static 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
455 static 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
488 disable_cx_supply:
489         regulator_disable(wcss->cx_supply);
490 disable_xo_clk:
491         clk_disable_unprepare(wcss->xo);
492
493         return ret;
494 }
495
496 static 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
530 static 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
594 static 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
640 static 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
707 static 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
741 static 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
753 static 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
769 static 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
777 static 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
786 static 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
822 static 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
873 static 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
902 static 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
992 static 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
1003 static 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 = devm_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                 return ret;
1031
1032         ret = q6v5_alloc_memory_region(wcss);
1033         if (ret)
1034                 return ret;
1035
1036         if (wcss->version == WCSS_QCS404) {
1037                 ret = q6v5_wcss_init_clock(wcss);
1038                 if (ret)
1039                         return ret;
1040
1041                 ret = q6v5_wcss_init_regulator(wcss);
1042                 if (ret)
1043                         return ret;
1044         }
1045
1046         ret = q6v5_wcss_init_reset(wcss, desc);
1047         if (ret)
1048                 return ret;
1049
1050         ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, NULL, NULL);
1051         if (ret)
1052                 return ret;
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                 return ret;
1065
1066         platform_set_drvdata(pdev, rproc);
1067
1068         return 0;
1069 }
1070
1071 static void q6v5_wcss_remove(struct platform_device *pdev)
1072 {
1073         struct rproc *rproc = platform_get_drvdata(pdev);
1074         struct q6v5_wcss *wcss = rproc->priv;
1075
1076         qcom_q6v5_deinit(&wcss->q6v5);
1077         rproc_del(rproc);
1078 }
1079
1080 static const struct wcss_data wcss_ipq8074_res_init = {
1081         .firmware_name = "IPQ8074/q6_fw.mdt",
1082         .crash_reason_smem = WCSS_CRASH_REASON,
1083         .aon_reset_required = true,
1084         .wcss_q6_reset_required = true,
1085         .ops = &q6v5_wcss_ipq8074_ops,
1086         .requires_force_stop = true,
1087 };
1088
1089 static const struct wcss_data wcss_qcs404_res_init = {
1090         .crash_reason_smem = WCSS_CRASH_REASON,
1091         .firmware_name = "wcnss.mdt",
1092         .version = WCSS_QCS404,
1093         .aon_reset_required = false,
1094         .wcss_q6_reset_required = false,
1095         .ssr_name = "mpss",
1096         .sysmon_name = "wcnss",
1097         .ssctl_id = 0x12,
1098         .ops = &q6v5_wcss_qcs404_ops,
1099         .requires_force_stop = false,
1100 };
1101
1102 static const struct of_device_id q6v5_wcss_of_match[] = {
1103         { .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init },
1104         { .compatible = "qcom,qcs404-wcss-pil", .data = &wcss_qcs404_res_init },
1105         { },
1106 };
1107 MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match);
1108
1109 static struct platform_driver q6v5_wcss_driver = {
1110         .probe = q6v5_wcss_probe,
1111         .remove_new = q6v5_wcss_remove,
1112         .driver = {
1113                 .name = "qcom-q6v5-wcss-pil",
1114                 .of_match_table = q6v5_wcss_of_match,
1115         },
1116 };
1117 module_platform_driver(q6v5_wcss_driver);
1118
1119 MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
1120 MODULE_LICENSE("GPL v2");