drm/nouveau/kms/nv50-: use NVIDIA's headers for core head_olut_set()
[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/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
73 struct 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         struct qcom_rproc_glink glink_subdev;
96         struct qcom_rproc_ssr ssr_subdev;
97 };
98
99 static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
100 {
101         int ret;
102         u32 val;
103         int i;
104
105         /* Assert resets, stop core */
106         val = readl(wcss->reg_base + Q6SS_RESET_REG);
107         val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
108         writel(val, wcss->reg_base + Q6SS_RESET_REG);
109
110         /* BHS require xo cbcr to be enabled */
111         val = readl(wcss->reg_base + Q6SS_XO_CBCR);
112         val |= 0x1;
113         writel(val, wcss->reg_base + Q6SS_XO_CBCR);
114
115         /* Read CLKOFF bit to go low indicating CLK is enabled */
116         ret = readl_poll_timeout(wcss->reg_base + Q6SS_XO_CBCR,
117                                  val, !(val & BIT(31)), 1,
118                                  HALT_CHECK_MAX_LOOPS);
119         if (ret) {
120                 dev_err(wcss->dev,
121                         "xo cbcr enabling timed out (rc:%d)\n", ret);
122                 return ret;
123         }
124         /* Enable power block headswitch and wait for it to stabilize */
125         val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
126         val |= Q6SS_BHS_ON;
127         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
128         udelay(1);
129
130         /* Put LDO in bypass mode */
131         val |= Q6SS_LDO_BYP;
132         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
133
134         /* Deassert Q6 compiler memory clamp */
135         val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
136         val &= ~Q6SS_CLAMP_QMC_MEM;
137         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
138
139         /* Deassert memory peripheral sleep and L2 memory standby */
140         val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N;
141         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
142
143         /* Turn on L1, L2, ETB and JU memories 1 at a time */
144         val = readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
145         for (i = MEM_BANKS; i >= 0; i--) {
146                 val |= BIT(i);
147                 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
148                 /*
149                  * Read back value to ensure the write is done then
150                  * wait for 1us for both memory peripheral and data
151                  * array to turn on.
152                  */
153                 val |= readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
154                 udelay(1);
155         }
156         /* Remove word line clamp */
157         val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
158         val &= ~Q6SS_CLAMP_WL;
159         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
160
161         /* Remove IO clamp */
162         val &= ~Q6SS_CLAMP_IO;
163         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
164
165         /* Bring core out of reset */
166         val = readl(wcss->reg_base + Q6SS_RESET_REG);
167         val &= ~Q6SS_CORE_ARES;
168         writel(val, wcss->reg_base + Q6SS_RESET_REG);
169
170         /* Turn on core clock */
171         val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
172         val |= Q6SS_CLK_ENABLE;
173         writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
174
175         /* Start core execution */
176         val = readl(wcss->reg_base + Q6SS_RESET_REG);
177         val &= ~Q6SS_STOP_CORE;
178         writel(val, wcss->reg_base + Q6SS_RESET_REG);
179
180         return 0;
181 }
182
183 static int q6v5_wcss_start(struct rproc *rproc)
184 {
185         struct q6v5_wcss *wcss = rproc->priv;
186         int ret;
187
188         qcom_q6v5_prepare(&wcss->q6v5);
189
190         /* Release Q6 and WCSS reset */
191         ret = reset_control_deassert(wcss->wcss_reset);
192         if (ret) {
193                 dev_err(wcss->dev, "wcss_reset failed\n");
194                 return ret;
195         }
196
197         ret = reset_control_deassert(wcss->wcss_q6_reset);
198         if (ret) {
199                 dev_err(wcss->dev, "wcss_q6_reset failed\n");
200                 goto wcss_reset;
201         }
202
203         /* Lithium configuration - clock gating and bus arbitration */
204         ret = regmap_update_bits(wcss->halt_map,
205                                  wcss->halt_nc + TCSR_GLOBAL_CFG0,
206                                  TCSR_WCSS_CLK_MASK,
207                                  TCSR_WCSS_CLK_ENABLE);
208         if (ret)
209                 goto wcss_q6_reset;
210
211         ret = regmap_update_bits(wcss->halt_map,
212                                  wcss->halt_nc + TCSR_GLOBAL_CFG1,
213                                  1, 0);
214         if (ret)
215                 goto wcss_q6_reset;
216
217         /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */
218         writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB);
219
220         ret = q6v5_wcss_reset(wcss);
221         if (ret)
222                 goto wcss_q6_reset;
223
224         ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ);
225         if (ret == -ETIMEDOUT)
226                 dev_err(wcss->dev, "start timed out\n");
227
228         return ret;
229
230 wcss_q6_reset:
231         reset_control_assert(wcss->wcss_q6_reset);
232
233 wcss_reset:
234         reset_control_assert(wcss->wcss_reset);
235
236         return ret;
237 }
238
239 static void q6v5_wcss_halt_axi_port(struct q6v5_wcss *wcss,
240                                     struct regmap *halt_map,
241                                     u32 offset)
242 {
243         unsigned long timeout;
244         unsigned int val;
245         int ret;
246
247         /* Check if we're already idle */
248         ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
249         if (!ret && val)
250                 return;
251
252         /* Assert halt request */
253         regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
254
255         /* Wait for halt */
256         timeout = jiffies + msecs_to_jiffies(HALT_ACK_TIMEOUT_MS);
257         for (;;) {
258                 ret = regmap_read(halt_map, offset + AXI_HALTACK_REG, &val);
259                 if (ret || val || time_after(jiffies, timeout))
260                         break;
261
262                 msleep(1);
263         }
264
265         ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
266         if (ret || !val)
267                 dev_err(wcss->dev, "port failed halt\n");
268
269         /* Clear halt request (port will remain halted until reset) */
270         regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
271 }
272
273 static int q6v5_wcss_powerdown(struct q6v5_wcss *wcss)
274 {
275         int ret;
276         u32 val;
277
278         /* 1 - Assert WCSS/Q6 HALTREQ */
279         q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss);
280
281         /* 2 - Enable WCSSAON_CONFIG */
282         val = readl(wcss->rmb_base + SSCAON_CONFIG);
283         val |= SSCAON_ENABLE;
284         writel(val, wcss->rmb_base + SSCAON_CONFIG);
285
286         /* 3 - Set SSCAON_CONFIG */
287         val |= SSCAON_BUS_EN;
288         val &= ~SSCAON_BUS_MUX_MASK;
289         writel(val, wcss->rmb_base + SSCAON_CONFIG);
290
291         /* 4 - SSCAON_CONFIG 1 */
292         val |= BIT(1);
293         writel(val, wcss->rmb_base + SSCAON_CONFIG);
294
295         /* 5 - wait for SSCAON_STATUS */
296         ret = readl_poll_timeout(wcss->rmb_base + SSCAON_STATUS,
297                                  val, (val & 0xffff) == 0x400, 1000,
298                                  HALT_CHECK_MAX_LOOPS);
299         if (ret) {
300                 dev_err(wcss->dev,
301                         "can't get SSCAON_STATUS rc:%d)\n", ret);
302                 return ret;
303         }
304
305         /* 6 - De-assert WCSS_AON reset */
306         reset_control_assert(wcss->wcss_aon_reset);
307
308         /* 7 - Disable WCSSAON_CONFIG 13 */
309         val = readl(wcss->rmb_base + SSCAON_CONFIG);
310         val &= ~SSCAON_ENABLE;
311         writel(val, wcss->rmb_base + SSCAON_CONFIG);
312
313         /* 8 - De-assert WCSS/Q6 HALTREQ */
314         reset_control_assert(wcss->wcss_reset);
315
316         return 0;
317 }
318
319 static int q6v5_q6_powerdown(struct q6v5_wcss *wcss)
320 {
321         int ret;
322         u32 val;
323         int i;
324
325         /* 1 - Halt Q6 bus interface */
326         q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_q6);
327
328         /* 2 - Disable Q6 Core clock */
329         val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG);
330         val &= ~Q6SS_CLK_ENABLE;
331         writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG);
332
333         /* 3 - Clamp I/O */
334         val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
335         val |= Q6SS_CLAMP_IO;
336         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
337
338         /* 4 - Clamp WL */
339         val |= QDSS_BHS_ON;
340         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
341
342         /* 5 - Clear Erase standby */
343         val &= ~Q6SS_L2DATA_STBY_N;
344         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
345
346         /* 6 - Clear Sleep RTN */
347         val &= ~Q6SS_SLP_RET_N;
348         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
349
350         /* 7 - turn off Q6 memory foot/head switch one bank at a time */
351         for (i = 0; i < 20; i++) {
352                 val = readl(wcss->reg_base + Q6SS_MEM_PWR_CTL);
353                 val &= ~BIT(i);
354                 writel(val, wcss->reg_base + Q6SS_MEM_PWR_CTL);
355                 mdelay(1);
356         }
357
358         /* 8 - Assert QMC memory RTN */
359         val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG);
360         val |= Q6SS_CLAMP_QMC_MEM;
361         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
362
363         /* 9 - Turn off BHS */
364         val &= ~Q6SS_BHS_ON;
365         writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG);
366         udelay(1);
367
368         /* 10 - Wait till BHS Reset is done */
369         ret = readl_poll_timeout(wcss->reg_base + Q6SS_BHS_STATUS,
370                                  val, !(val & BHS_EN_REST_ACK), 1000,
371                                  HALT_CHECK_MAX_LOOPS);
372         if (ret) {
373                 dev_err(wcss->dev, "BHS_STATUS not OFF (rc:%d)\n", ret);
374                 return ret;
375         }
376
377         /* 11 -  Assert WCSS reset */
378         reset_control_assert(wcss->wcss_reset);
379
380         /* 12 - Assert Q6 reset */
381         reset_control_assert(wcss->wcss_q6_reset);
382
383         return 0;
384 }
385
386 static int q6v5_wcss_stop(struct rproc *rproc)
387 {
388         struct q6v5_wcss *wcss = rproc->priv;
389         int ret;
390
391         /* WCSS powerdown */
392         ret = qcom_q6v5_request_stop(&wcss->q6v5);
393         if (ret == -ETIMEDOUT) {
394                 dev_err(wcss->dev, "timed out on wait\n");
395                 return ret;
396         }
397
398         ret = q6v5_wcss_powerdown(wcss);
399         if (ret)
400                 return ret;
401
402         /* Q6 Power down */
403         ret = q6v5_q6_powerdown(wcss);
404         if (ret)
405                 return ret;
406
407         qcom_q6v5_unprepare(&wcss->q6v5);
408
409         return 0;
410 }
411
412 static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len)
413 {
414         struct q6v5_wcss *wcss = rproc->priv;
415         int offset;
416
417         offset = da - wcss->mem_reloc;
418         if (offset < 0 || offset + len > wcss->mem_size)
419                 return NULL;
420
421         return wcss->mem_region + offset;
422 }
423
424 static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
425 {
426         struct q6v5_wcss *wcss = rproc->priv;
427
428         return qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware,
429                                      0, wcss->mem_region, wcss->mem_phys,
430                                      wcss->mem_size, &wcss->mem_reloc);
431 }
432
433 static const struct rproc_ops q6v5_wcss_ops = {
434         .start = q6v5_wcss_start,
435         .stop = q6v5_wcss_stop,
436         .da_to_va = q6v5_wcss_da_to_va,
437         .load = q6v5_wcss_load,
438         .get_boot_addr = rproc_elf_get_boot_addr,
439 };
440
441 static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss)
442 {
443         struct device *dev = wcss->dev;
444
445         wcss->wcss_aon_reset = devm_reset_control_get(dev, "wcss_aon_reset");
446         if (IS_ERR(wcss->wcss_aon_reset)) {
447                 dev_err(wcss->dev, "unable to acquire wcss_aon_reset\n");
448                 return PTR_ERR(wcss->wcss_aon_reset);
449         }
450
451         wcss->wcss_reset = devm_reset_control_get(dev, "wcss_reset");
452         if (IS_ERR(wcss->wcss_reset)) {
453                 dev_err(wcss->dev, "unable to acquire wcss_reset\n");
454                 return PTR_ERR(wcss->wcss_reset);
455         }
456
457         wcss->wcss_q6_reset = devm_reset_control_get(dev, "wcss_q6_reset");
458         if (IS_ERR(wcss->wcss_q6_reset)) {
459                 dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n");
460                 return PTR_ERR(wcss->wcss_q6_reset);
461         }
462
463         return 0;
464 }
465
466 static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,
467                                struct platform_device *pdev)
468 {
469         struct of_phandle_args args;
470         struct resource *res;
471         int ret;
472
473         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6");
474         wcss->reg_base = devm_ioremap_resource(&pdev->dev, res);
475         if (IS_ERR(wcss->reg_base))
476                 return PTR_ERR(wcss->reg_base);
477
478         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb");
479         wcss->rmb_base = devm_ioremap_resource(&pdev->dev, res);
480         if (IS_ERR(wcss->rmb_base))
481                 return PTR_ERR(wcss->rmb_base);
482
483         ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
484                                                "qcom,halt-regs", 3, 0, &args);
485         if (ret < 0) {
486                 dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
487                 return -EINVAL;
488         }
489
490         wcss->halt_map = syscon_node_to_regmap(args.np);
491         of_node_put(args.np);
492         if (IS_ERR(wcss->halt_map))
493                 return PTR_ERR(wcss->halt_map);
494
495         wcss->halt_q6 = args.args[0];
496         wcss->halt_wcss = args.args[1];
497         wcss->halt_nc = args.args[2];
498
499         return 0;
500 }
501
502 static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss)
503 {
504         struct reserved_mem *rmem = NULL;
505         struct device_node *node;
506         struct device *dev = wcss->dev;
507
508         node = of_parse_phandle(dev->of_node, "memory-region", 0);
509         if (node)
510                 rmem = of_reserved_mem_lookup(node);
511         of_node_put(node);
512
513         if (!rmem) {
514                 dev_err(dev, "unable to acquire memory-region\n");
515                 return -EINVAL;
516         }
517
518         wcss->mem_phys = rmem->base;
519         wcss->mem_reloc = rmem->base;
520         wcss->mem_size = rmem->size;
521         wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
522         if (!wcss->mem_region) {
523                 dev_err(dev, "unable to map memory region: %pa+%pa\n",
524                         &rmem->base, &rmem->size);
525                 return -EBUSY;
526         }
527
528         return 0;
529 }
530
531 static int q6v5_wcss_probe(struct platform_device *pdev)
532 {
533         struct q6v5_wcss *wcss;
534         struct rproc *rproc;
535         int ret;
536
537         rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_wcss_ops,
538                             "IPQ8074/q6_fw.mdt", sizeof(*wcss));
539         if (!rproc) {
540                 dev_err(&pdev->dev, "failed to allocate rproc\n");
541                 return -ENOMEM;
542         }
543
544         wcss = rproc->priv;
545         wcss->dev = &pdev->dev;
546
547         ret = q6v5_wcss_init_mmio(wcss, pdev);
548         if (ret)
549                 goto free_rproc;
550
551         ret = q6v5_alloc_memory_region(wcss);
552         if (ret)
553                 goto free_rproc;
554
555         ret = q6v5_wcss_init_reset(wcss);
556         if (ret)
557                 goto free_rproc;
558
559         ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, WCSS_CRASH_REASON, NULL);
560         if (ret)
561                 goto free_rproc;
562
563         qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
564         qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
565
566         ret = rproc_add(rproc);
567         if (ret)
568                 goto free_rproc;
569
570         platform_set_drvdata(pdev, rproc);
571
572         return 0;
573
574 free_rproc:
575         rproc_free(rproc);
576
577         return ret;
578 }
579
580 static int q6v5_wcss_remove(struct platform_device *pdev)
581 {
582         struct rproc *rproc = platform_get_drvdata(pdev);
583
584         rproc_del(rproc);
585         rproc_free(rproc);
586
587         return 0;
588 }
589
590 static const struct of_device_id q6v5_wcss_of_match[] = {
591         { .compatible = "qcom,ipq8074-wcss-pil" },
592         { },
593 };
594 MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match);
595
596 static struct platform_driver q6v5_wcss_driver = {
597         .probe = q6v5_wcss_probe,
598         .remove = q6v5_wcss_remove,
599         .driver = {
600                 .name = "qcom-q6v5-wcss-pil",
601                 .of_match_table = q6v5_wcss_of_match,
602         },
603 };
604 module_platform_driver(q6v5_wcss_driver);
605
606 MODULE_DESCRIPTION("Hexagon WCSS Peripheral Image Loader");
607 MODULE_LICENSE("GPL v2");