Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Mikko Perttunen and committed by
Thierry Reding
b7dc179e 95ffcb4c

+138 -1
+2 -1
drivers/gpu/drm/tegra/Makefile
··· 24 24 gr3d.o \ 25 25 falcon.o \ 26 26 vic.o \ 27 - nvdec.o 27 + nvdec.o \ 28 + riscv.o 28 29 29 30 tegra-drm-y += trace.o 30 31
+106
drivers/gpu/drm/tegra/riscv.c
··· 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 + }
+30
drivers/gpu/drm/tegra/riscv.h
··· 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