Skip to content

Commit b7dc179

Browse files
cyndisthierryreding
authored andcommitted
drm/tegra: Add code for booting RISC-V based engines
Add helper code for booting RISC-V based engines where firmware is located in a carveout. Signed-off-by: Mikko Perttunen <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent 95ffcb4 commit b7dc179

File tree

3 files changed

+138
-1
lines changed

3 files changed

+138
-1
lines changed

drivers/gpu/drm/tegra/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ tegra-drm-y := \
2424
gr3d.o \
2525
falcon.o \
2626
vic.o \
27-
nvdec.o
27+
nvdec.o \
28+
riscv.o
2829

2930
tegra-drm-y += trace.o
3031

drivers/gpu/drm/tegra/riscv.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2022, NVIDIA Corporation.
4+
*/
5+
6+
#include <linux/dev_printk.h>
7+
#include <linux/device.h>
8+
#include <linux/iopoll.h>
9+
#include <linux/of.h>
10+
11+
#include "riscv.h"
12+
13+
#define RISCV_CPUCTL 0x4388
14+
#define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
15+
#define RISCV_BR_RETCODE 0x465c
16+
#define RISCV_BR_RETCODE_RESULT_V(x) ((x) & 0x3)
17+
#define RISCV_BR_RETCODE_RESULT_PASS_V 3
18+
#define RISCV_BCR_CTRL 0x4668
19+
#define RISCV_BCR_CTRL_CORE_SELECT_RISCV (1 << 4)
20+
#define RISCV_BCR_DMACFG 0x466c
21+
#define RISCV_BCR_DMACFG_TARGET_LOCAL_FB (0 << 0)
22+
#define RISCV_BCR_DMACFG_LOCK_LOCKED (1 << 31)
23+
#define RISCV_BCR_DMAADDR_PKCPARAM_LO 0x4670
24+
#define RISCV_BCR_DMAADDR_PKCPARAM_HI 0x4674
25+
#define RISCV_BCR_DMAADDR_FMCCODE_LO 0x4678
26+
#define RISCV_BCR_DMAADDR_FMCCODE_HI 0x467c
27+
#define RISCV_BCR_DMAADDR_FMCDATA_LO 0x4680
28+
#define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684
29+
#define RISCV_BCR_DMACFG_SEC 0x4694
30+
#define RISCV_BCR_DMACFG_SEC_GSCID(v) ((v) << 16)
31+
32+
static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset)
33+
{
34+
writel(value, riscv->regs + offset);
35+
}
36+
37+
int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv)
38+
{
39+
struct tegra_drm_riscv_descriptor *bl = &riscv->bl_desc;
40+
struct tegra_drm_riscv_descriptor *os = &riscv->os_desc;
41+
const struct device_node *np = riscv->dev->of_node;
42+
int err;
43+
44+
#define READ_PROP(name, location) \
45+
err = of_property_read_u32(np, name, location); \
46+
if (err) { \
47+
dev_err(riscv->dev, "failed to read " name ": %d\n", err); \
48+
return err; \
49+
}
50+
51+
READ_PROP("nvidia,bl-manifest-offset", &bl->manifest_offset);
52+
READ_PROP("nvidia,bl-code-offset", &bl->code_offset);
53+
READ_PROP("nvidia,bl-data-offset", &bl->data_offset);
54+
READ_PROP("nvidia,os-manifest-offset", &os->manifest_offset);
55+
READ_PROP("nvidia,os-code-offset", &os->code_offset);
56+
READ_PROP("nvidia,os-data-offset", &os->data_offset);
57+
#undef READ_PROP
58+
59+
if (bl->manifest_offset == 0 && bl->code_offset == 0 &&
60+
bl->data_offset == 0 && os->manifest_offset == 0 &&
61+
os->code_offset == 0 && os->data_offset == 0) {
62+
dev_err(riscv->dev, "descriptors not available\n");
63+
return -EINVAL;
64+
}
65+
66+
return 0;
67+
}
68+
69+
int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
70+
u32 gscid, const struct tegra_drm_riscv_descriptor *desc)
71+
{
72+
phys_addr_t addr;
73+
int err;
74+
u32 val;
75+
76+
riscv_writel(riscv, RISCV_BCR_CTRL_CORE_SELECT_RISCV, RISCV_BCR_CTRL);
77+
78+
addr = image_address + desc->manifest_offset;
79+
riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_LO);
80+
riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_HI);
81+
82+
addr = image_address + desc->code_offset;
83+
riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_LO);
84+
riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_HI);
85+
86+
addr = image_address + desc->data_offset;
87+
riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_LO);
88+
riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_HI);
89+
90+
riscv_writel(riscv, RISCV_BCR_DMACFG_SEC_GSCID(gscid), RISCV_BCR_DMACFG_SEC);
91+
riscv_writel(riscv,
92+
RISCV_BCR_DMACFG_TARGET_LOCAL_FB | RISCV_BCR_DMACFG_LOCK_LOCKED, RISCV_BCR_DMACFG);
93+
94+
riscv_writel(riscv, RISCV_CPUCTL_STARTCPU_TRUE, RISCV_CPUCTL);
95+
96+
err = readl_poll_timeout(
97+
riscv->regs + RISCV_BR_RETCODE, val,
98+
RISCV_BR_RETCODE_RESULT_V(val) == RISCV_BR_RETCODE_RESULT_PASS_V,
99+
10, 100000);
100+
if (err) {
101+
dev_err(riscv->dev, "error during bootrom execution. BR_RETCODE=%d\n", val);
102+
return err;
103+
}
104+
105+
return 0;
106+
}

drivers/gpu/drm/tegra/riscv.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (c) 2022, NVIDIA Corporation.
4+
*/
5+
6+
#ifndef DRM_TEGRA_RISCV_H
7+
#define DRM_TEGRA_RISCV_H
8+
9+
struct tegra_drm_riscv_descriptor {
10+
u32 manifest_offset;
11+
u32 code_offset;
12+
u32 code_size;
13+
u32 data_offset;
14+
u32 data_size;
15+
};
16+
17+
struct tegra_drm_riscv {
18+
/* User initializes */
19+
struct device *dev;
20+
void __iomem *regs;
21+
22+
struct tegra_drm_riscv_descriptor bl_desc;
23+
struct tegra_drm_riscv_descriptor os_desc;
24+
};
25+
26+
int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv);
27+
int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
28+
u32 gscid, const struct tegra_drm_riscv_descriptor *desc);
29+
30+
#endif

0 commit comments

Comments
 (0)