Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 32static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset)
 33{
 34	writel(value, riscv->regs + offset);
 35}
 36
 37int 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
 69int 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}