1
1
// SPDX-License-Identifier: GPL-2.0-only
2
2
/*
3
- * Copyright (c) 2015-2021 , NVIDIA Corporation.
3
+ * Copyright (c) 2015-2022 , NVIDIA Corporation.
4
4
*/
5
5
6
6
#include <linux/clk.h>
7
7
#include <linux/delay.h>
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 ;
35
+ bool has_extra_clocks ;
31
36
};
32
37
33
38
struct nvdec {
@@ -37,10 +42,16 @@ struct nvdec {
37
42
struct tegra_drm_client client ;
38
43
struct host1x_channel * channel ;
39
44
struct device * dev ;
40
- struct clk * clk ;
45
+ struct clk_bulk_data clks [3 ];
46
+ unsigned int num_clks ;
47
+ struct reset_control * reset ;
41
48
42
49
/* Platform configuration */
43
50
const struct nvdec_config * config ;
51
+
52
+ /* RISC-V specific data */
53
+ struct tegra_drm_riscv riscv ;
54
+ phys_addr_t carveout_base ;
44
55
};
45
56
46
57
static inline struct nvdec * to_nvdec (struct tegra_drm_client * client )
@@ -54,7 +65,7 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
54
65
writel (value , nvdec -> regs + offset );
55
66
}
56
67
57
- static int nvdec_boot (struct nvdec * nvdec )
68
+ static int nvdec_boot_falcon (struct nvdec * nvdec )
58
69
{
59
70
#ifdef CONFIG_IOMMU_API
60
71
struct iommu_fwspec * spec = dev_iommu_fwspec_get (nvdec -> dev );
@@ -90,6 +101,64 @@ static int nvdec_boot(struct nvdec *nvdec)
90
101
return 0 ;
91
102
}
92
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
+
93
162
static int nvdec_init (struct host1x_client * client )
94
163
{
95
164
struct tegra_drm_client * drm = host1x_to_drm_client (client );
@@ -189,7 +258,7 @@ static const struct host1x_client_ops nvdec_client_ops = {
189
258
.exit = nvdec_exit ,
190
259
};
191
260
192
- static int nvdec_load_firmware (struct nvdec * nvdec )
261
+ static int nvdec_load_falcon_firmware (struct nvdec * nvdec )
193
262
{
194
263
struct host1x_client * client = & nvdec -> client .base ;
195
264
struct tegra_drm * tegra = nvdec -> client .drm ;
@@ -252,30 +321,35 @@ static int nvdec_load_firmware(struct nvdec *nvdec)
252
321
return err ;
253
322
}
254
323
255
-
256
324
static __maybe_unused int nvdec_runtime_resume (struct device * dev )
257
325
{
258
326
struct nvdec * nvdec = dev_get_drvdata (dev );
259
327
int err ;
260
328
261
- err = clk_prepare_enable (nvdec -> clk );
329
+ err = clk_bulk_prepare_enable (nvdec -> num_clks , nvdec -> clks );
262
330
if (err < 0 )
263
331
return err ;
264
332
265
333
usleep_range (10 , 20 );
266
334
267
- err = nvdec_load_firmware (nvdec );
268
- if (err < 0 )
269
- 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 ;
270
343
271
- err = nvdec_boot (nvdec );
272
- if (err < 0 )
273
- goto disable ;
344
+ err = nvdec_boot_falcon (nvdec );
345
+ if (err < 0 )
346
+ goto disable ;
347
+ }
274
348
275
349
return 0 ;
276
350
277
351
disable :
278
- clk_disable_unprepare (nvdec -> clk );
352
+ clk_bulk_disable_unprepare (nvdec -> num_clks , nvdec -> clks );
279
353
return err ;
280
354
}
281
355
@@ -285,7 +359,7 @@ static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
285
359
286
360
host1x_channel_stop (nvdec -> channel );
287
361
288
- clk_disable_unprepare (nvdec -> clk );
362
+ clk_bulk_disable_unprepare (nvdec -> num_clks , nvdec -> clks );
289
363
290
364
return 0 ;
291
365
}
@@ -346,10 +420,18 @@ static const struct nvdec_config nvdec_t194_config = {
346
420
.supports_sid = true,
347
421
};
348
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
+
349
430
static const struct of_device_id tegra_nvdec_of_match [] = {
350
431
{ .compatible = "nvidia,tegra210-nvdec" , .data = & nvdec_t210_config },
351
432
{ .compatible = "nvidia,tegra186-nvdec" , .data = & nvdec_t186_config },
352
433
{ .compatible = "nvidia,tegra194-nvdec" , .data = & nvdec_t194_config },
434
+ { .compatible = "nvidia,tegra234-nvdec" , .data = & nvdec_t234_config },
353
435
{ },
354
436
};
355
437
MODULE_DEVICE_TABLE (of , tegra_nvdec_of_match );
@@ -383,13 +465,22 @@ static int nvdec_probe(struct platform_device *pdev)
383
465
if (IS_ERR (nvdec -> regs ))
384
466
return PTR_ERR (nvdec -> regs );
385
467
386
- nvdec -> clk = devm_clk_get (dev , NULL );
387
- if (IS_ERR (nvdec -> clk )) {
388
- dev_err (& pdev -> dev , "failed to get clock\n" );
389
- return PTR_ERR (nvdec -> clk );
468
+ nvdec -> clks [0 ].id = "nvdec" ;
469
+ nvdec -> num_clks = 1 ;
470
+
471
+ if (nvdec -> config -> has_extra_clocks ) {
472
+ nvdec -> num_clks = 3 ;
473
+ nvdec -> clks [1 ].id = "fuse" ;
474
+ nvdec -> clks [2 ].id = "tsec_pka" ;
390
475
}
391
476
392
- err = clk_set_rate (nvdec -> clk , ULONG_MAX );
477
+ err = devm_clk_bulk_get (dev , nvdec -> num_clks , nvdec -> clks );
478
+ if (err ) {
479
+ dev_err (& pdev -> dev , "failed to get clock(s)\n" );
480
+ return err ;
481
+ }
482
+
483
+ err = clk_set_rate (nvdec -> clks [0 ].clk , ULONG_MAX );
393
484
if (err < 0 ) {
394
485
dev_err (& pdev -> dev , "failed to set clock rate\n" );
395
486
return err ;
@@ -399,12 +490,42 @@ static int nvdec_probe(struct platform_device *pdev)
399
490
if (err < 0 )
400
491
host_class = HOST1X_CLASS_NVDEC ;
401
492
402
- nvdec -> falcon . dev = dev ;
403
- nvdec -> falcon . regs = nvdec -> regs ;
493
+ if ( nvdec -> config -> has_riscv ) {
494
+ struct tegra_mc * mc ;
404
495
405
- err = falcon_init (& nvdec -> falcon );
406
- if (err < 0 )
407
- 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
+ }
408
529
409
530
platform_set_drvdata (pdev , nvdec );
410
531
0 commit comments