8
8
#include <linux/dma-mapping.h>
9
9
#include <linux/host1x.h>
10
10
#include <linux/iommu.h>
11
+ #include <linux/iopoll.h>
11
12
#include <linux/module.h>
12
13
#include <linux/of.h>
13
14
#include <linux/of_device.h>
16
17
#include <linux/pm_runtime.h>
17
18
#include <linux/reset.h>
18
19
19
- #include <soc/tegra/pmc .h>
20
+ #include <soc/tegra/mc .h>
20
21
21
22
#include "drm.h"
22
23
#include "falcon.h"
24
+ #include "riscv.h"
23
25
#include "vic.h"
24
26
27
+ #define NVDEC_FALCON_DEBUGINFO 0x1094
25
28
#define NVDEC_TFBIF_TRANSCFG 0x2c44
26
29
27
30
struct nvdec_config {
28
31
const char * firmware ;
29
32
unsigned int version ;
30
33
bool supports_sid ;
34
+ bool has_riscv ;
31
35
bool has_extra_clocks ;
32
36
};
33
37
@@ -40,9 +44,14 @@ struct nvdec {
40
44
struct device * dev ;
41
45
struct clk_bulk_data clks [3 ];
42
46
unsigned int num_clks ;
47
+ struct reset_control * reset ;
43
48
44
49
/* Platform configuration */
45
50
const struct nvdec_config * config ;
51
+
52
+ /* RISC-V specific data */
53
+ struct tegra_drm_riscv riscv ;
54
+ phys_addr_t carveout_base ;
46
55
};
47
56
48
57
static inline struct nvdec * to_nvdec (struct tegra_drm_client * client )
@@ -56,7 +65,7 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
56
65
writel (value , nvdec -> regs + offset );
57
66
}
58
67
59
- static int nvdec_boot (struct nvdec * nvdec )
68
+ static int nvdec_boot_falcon (struct nvdec * nvdec )
60
69
{
61
70
#ifdef CONFIG_IOMMU_API
62
71
struct iommu_fwspec * spec = dev_iommu_fwspec_get (nvdec -> dev );
@@ -92,6 +101,64 @@ static int nvdec_boot(struct nvdec *nvdec)
92
101
return 0 ;
93
102
}
94
103
104
+ static int nvdec_wait_debuginfo (struct nvdec * nvdec , const char * phase )
105
+ {
106
+ int err ;
107
+ u32 val ;
108
+
109
+ err = readl_poll_timeout (nvdec -> regs + NVDEC_FALCON_DEBUGINFO , val , val == 0x0 , 10 , 100000 );
110
+ if (err ) {
111
+ dev_err (nvdec -> dev , "failed to boot %s, debuginfo=0x%x\n" , phase , val );
112
+ return err ;
113
+ }
114
+
115
+ return 0 ;
116
+ }
117
+
118
+ static int nvdec_boot_riscv (struct nvdec * nvdec )
119
+ {
120
+ int err ;
121
+
122
+ err = reset_control_acquire (nvdec -> reset );
123
+ if (err )
124
+ return err ;
125
+
126
+ nvdec_writel (nvdec , 0xabcd1234 , NVDEC_FALCON_DEBUGINFO );
127
+
128
+ err = tegra_drm_riscv_boot_bootrom (& nvdec -> riscv , nvdec -> carveout_base , 1 ,
129
+ & nvdec -> riscv .bl_desc );
130
+ if (err ) {
131
+ dev_err (nvdec -> dev , "failed to execute bootloader\n" );
132
+ goto release_reset ;
133
+ }
134
+
135
+ err = nvdec_wait_debuginfo (nvdec , "bootloader" );
136
+ if (err )
137
+ goto release_reset ;
138
+
139
+ err = reset_control_reset (nvdec -> reset );
140
+ if (err )
141
+ goto release_reset ;
142
+
143
+ nvdec_writel (nvdec , 0xabcd1234 , NVDEC_FALCON_DEBUGINFO );
144
+
145
+ err = tegra_drm_riscv_boot_bootrom (& nvdec -> riscv , nvdec -> carveout_base , 1 ,
146
+ & nvdec -> riscv .os_desc );
147
+ if (err ) {
148
+ dev_err (nvdec -> dev , "failed to execute firmware\n" );
149
+ goto release_reset ;
150
+ }
151
+
152
+ err = nvdec_wait_debuginfo (nvdec , "firmware" );
153
+ if (err )
154
+ goto release_reset ;
155
+
156
+ release_reset :
157
+ reset_control_release (nvdec -> reset );
158
+
159
+ return err ;
160
+ }
161
+
95
162
static int nvdec_init (struct host1x_client * client )
96
163
{
97
164
struct tegra_drm_client * drm = host1x_to_drm_client (client );
@@ -191,7 +258,7 @@ static const struct host1x_client_ops nvdec_client_ops = {
191
258
.exit = nvdec_exit ,
192
259
};
193
260
194
- static int nvdec_load_firmware (struct nvdec * nvdec )
261
+ static int nvdec_load_falcon_firmware (struct nvdec * nvdec )
195
262
{
196
263
struct host1x_client * client = & nvdec -> client .base ;
197
264
struct tegra_drm * tegra = nvdec -> client .drm ;
@@ -254,7 +321,6 @@ static int nvdec_load_firmware(struct nvdec *nvdec)
254
321
return err ;
255
322
}
256
323
257
-
258
324
static __maybe_unused int nvdec_runtime_resume (struct device * dev )
259
325
{
260
326
struct nvdec * nvdec = dev_get_drvdata (dev );
@@ -266,13 +332,19 @@ static __maybe_unused int nvdec_runtime_resume(struct device *dev)
266
332
267
333
usleep_range (10 , 20 );
268
334
269
- err = nvdec_load_firmware (nvdec );
270
- if (err < 0 )
271
- goto disable ;
335
+ if (nvdec -> config -> has_riscv ) {
336
+ err = nvdec_boot_riscv (nvdec );
337
+ if (err < 0 )
338
+ goto disable ;
339
+ } else {
340
+ err = nvdec_load_falcon_firmware (nvdec );
341
+ if (err < 0 )
342
+ goto disable ;
272
343
273
- err = nvdec_boot (nvdec );
274
- if (err < 0 )
275
- goto disable ;
344
+ err = nvdec_boot_falcon (nvdec );
345
+ if (err < 0 )
346
+ goto disable ;
347
+ }
276
348
277
349
return 0 ;
278
350
@@ -348,10 +420,18 @@ static const struct nvdec_config nvdec_t194_config = {
348
420
.supports_sid = true,
349
421
};
350
422
423
+ static const struct nvdec_config nvdec_t234_config = {
424
+ .version = 0x23 ,
425
+ .supports_sid = true,
426
+ .has_riscv = true,
427
+ .has_extra_clocks = true,
428
+ };
429
+
351
430
static const struct of_device_id tegra_nvdec_of_match [] = {
352
431
{ .compatible = "nvidia,tegra210-nvdec" , .data = & nvdec_t210_config },
353
432
{ .compatible = "nvidia,tegra186-nvdec" , .data = & nvdec_t186_config },
354
433
{ .compatible = "nvidia,tegra194-nvdec" , .data = & nvdec_t194_config },
434
+ { .compatible = "nvidia,tegra234-nvdec" , .data = & nvdec_t234_config },
355
435
{ },
356
436
};
357
437
MODULE_DEVICE_TABLE (of , tegra_nvdec_of_match );
@@ -410,12 +490,42 @@ static int nvdec_probe(struct platform_device *pdev)
410
490
if (err < 0 )
411
491
host_class = HOST1X_CLASS_NVDEC ;
412
492
413
- nvdec -> falcon . dev = dev ;
414
- nvdec -> falcon . regs = nvdec -> regs ;
493
+ if ( nvdec -> config -> has_riscv ) {
494
+ struct tegra_mc * mc ;
415
495
416
- err = falcon_init (& nvdec -> falcon );
417
- if (err < 0 )
418
- return err ;
496
+ mc = devm_tegra_memory_controller_get (dev );
497
+ if (IS_ERR (mc )) {
498
+ dev_err_probe (dev , PTR_ERR (mc ),
499
+ "failed to get memory controller handle\n" );
500
+ return PTR_ERR (mc );
501
+ }
502
+
503
+ err = tegra_mc_get_carveout_info (mc , 1 , & nvdec -> carveout_base , NULL );
504
+ if (err ) {
505
+ dev_err (dev , "failed to get carveout info: %d\n" , err );
506
+ return err ;
507
+ }
508
+
509
+ nvdec -> reset = devm_reset_control_get_exclusive_released (dev , "nvdec" );
510
+ if (IS_ERR (nvdec -> reset )) {
511
+ dev_err_probe (dev , PTR_ERR (nvdec -> reset ), "failed to get reset\n" );
512
+ return PTR_ERR (nvdec -> reset );
513
+ }
514
+
515
+ nvdec -> riscv .dev = dev ;
516
+ nvdec -> riscv .regs = nvdec -> regs ;
517
+
518
+ err = tegra_drm_riscv_read_descriptors (& nvdec -> riscv );
519
+ if (err < 0 )
520
+ return err ;
521
+ } else {
522
+ nvdec -> falcon .dev = dev ;
523
+ nvdec -> falcon .regs = nvdec -> regs ;
524
+
525
+ err = falcon_init (& nvdec -> falcon );
526
+ if (err < 0 )
527
+ return err ;
528
+ }
419
529
420
530
platform_set_drvdata (pdev , nvdec );
421
531
0 commit comments