drm/tegra: nvhost support for t264

- VIC RISC-V EB boot support
- Programming sequence modification needed for Thor
- Reloc block linear addressing not needed for t264

Bug 4132685

Signed-off-by: Santosh BS <santoshb@nvidia.com>
Change-Id: I8ad47cce31cfd06020e33d3457a0d674a11e4d49
This commit is contained in:
Santosh BS
2023-08-08 15:17:56 +00:00
committed by Jon Hunter
parent 340bd4418f
commit 26b1cb4a82
8 changed files with 416 additions and 59 deletions

View File

@@ -1457,6 +1457,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra234-nvjpg", }, { .compatible = "nvidia,tegra234-nvjpg", },
{ .compatible = "nvidia,tegra234-ofa", }, { .compatible = "nvidia,tegra234-ofa", },
{ .compatible = "nvidia,tegra234-host1x-virtual-engine", }, { .compatible = "nvidia,tegra234-host1x-virtual-engine", },
{ .compatible = "nvidia,tegra264-vic", },
{ /* sentinel */ } { /* sentinel */ }
}; };

View File

@@ -95,6 +95,7 @@ struct tegra_drm_client_ops {
int (*get_streamid_offset)(struct tegra_drm_client *client, u32 *offset); int (*get_streamid_offset)(struct tegra_drm_client *client, u32 *offset);
int (*can_use_memory_ctx)(struct tegra_drm_client *client, bool *supported); int (*can_use_memory_ctx)(struct tegra_drm_client *client, bool *supported);
int (*has_job_timestamping)(struct tegra_drm_client *client, bool *supported); int (*has_job_timestamping)(struct tegra_drm_client *client, bool *supported);
int (*skip_bl_swizzling)(struct tegra_drm_client *client, bool *skip);
}; };
int tegra_drm_submit(struct tegra_drm_context *context, int tegra_drm_submit(struct tegra_drm_context *context,

View File

@@ -12,6 +12,7 @@
#include <linux/of.h> #include <linux/of.h>
#include "riscv.h" #include "riscv.h"
#include "falcon.h"
#define RISCV_CPUCTL 0x4388 #define RISCV_CPUCTL 0x4388
#define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0) #define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
@@ -31,6 +32,13 @@
#define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684 #define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684
#define RISCV_BCR_DMACFG_SEC 0x4694 #define RISCV_BCR_DMACFG_SEC 0x4694
#define RISCV_BCR_DMACFG_SEC_GSCID(v) ((v) << 16) #define RISCV_BCR_DMACFG_SEC_GSCID(v) ((v) << 16)
#define RISCV_BOOT_VECTOR_LO 0x1780
#define RISCV_BOOT_VECTOR_HI 0x1784
enum riscv_memory {
RISCV_MEMORY_IMEM,
RISCV_MEMORY_DATA,
};
static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset) static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset)
{ {
@@ -100,3 +108,141 @@ int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t imag
return 0; return 0;
} }
int tegra_drm_riscv_read_firmware(struct tegra_drm_riscv *riscv, const char *name)
{
int err;
/* request_firmware prints error if it fails */
err = request_firmware(&riscv->firmware.firmware, name, riscv->dev);
if (err < 0)
return err;
riscv->firmware.size = riscv->firmware.firmware->size;
return 0;
}
int tegra_drm_riscv_load_firmware(struct tegra_drm_riscv *riscv)
{
const struct firmware *firmware = riscv->firmware.firmware;
u32 *virt = riscv->firmware.virt;
size_t i;
/* Copy firmware image into local area taking into account endianness */
for (i = 0; i < firmware->size / sizeof(u32); i++)
virt[i] = le32_to_cpu(((__le32 *)firmware->data)[i]);
release_firmware(firmware);
riscv->firmware.firmware = NULL;
return 0;
}
int tegra_drm_riscv_init(struct tegra_drm_riscv *riscv)
{
riscv->firmware.virt = NULL;
return 0;
}
void tegra_drm_riscv_exit(struct tegra_drm_riscv *riscv)
{
if (riscv->firmware.firmware)
release_firmware(riscv->firmware.firmware);
}
static int tegra_drm_riscv_dma_wait_idle(struct tegra_drm_riscv *riscv)
{
u32 value;
return readl_poll_timeout(riscv->regs + FALCON_DMATRFCMD, value,
(value & FALCON_DMATRFCMD_IDLE), 10, 100000);
}
static int tegra_drm_riscv_copy_chunk(struct tegra_drm_riscv *riscv,
phys_addr_t base,
unsigned long offset,
enum riscv_memory target)
{
u32 cmd = FALCON_DMATRFCMD_SIZE_256B;
if (target == RISCV_MEMORY_IMEM)
cmd |= FALCON_DMATRFCMD_IMEM;
/*
* Use second DMA context (i.e. the one for firmware). Strictly
* speaking, at this point both DMA contexts point to the firmware
* stream ID, but this register's value will be reused by the firmware
* for later DMA transactions, so we need to use the correct value.
*/
cmd |= FALCON_DMATRFCMD_DMACTX(1);
riscv_writel(riscv, offset, FALCON_DMATRFMOFFS);
riscv_writel(riscv, base, FALCON_DMATRFFBOFFS);
riscv_writel(riscv, cmd, FALCON_DMATRFCMD);
return tegra_drm_riscv_dma_wait_idle(riscv);
}
int tegra_drm_riscv_boot_external(struct tegra_drm_riscv *riscv)
{
unsigned long offset;
u32 value;
int err;
if (!riscv->firmware.virt)
return -EINVAL;
err = readl_poll_timeout(riscv->regs + FALCON_DMACTL, value,
(value & (FALCON_DMACTL_IMEM_SCRUBBING |
FALCON_DMACTL_DMEM_SCRUBBING)) == 0,
10, 10000);
if (err < 0)
return err;
riscv_writel(riscv, 0, FALCON_DMACTL);
/* setup the address of the binary data so Falcon can access it later */
riscv_writel(riscv, riscv->firmware.iova >> 8, FALCON_DMATRFBASE);
/* copy the data segment into riscv internal memory */
for (offset = 0; offset < riscv->os_desc.data_size; offset += 256) {
err = tegra_drm_riscv_copy_chunk(riscv,
riscv->os_desc.data_offset + offset,
offset, RISCV_MEMORY_DATA);
}
/* copy the code segment into riscv internal memory */
for (offset = 0; offset < riscv->os_desc.code_size; offset += 256) {
err = tegra_drm_riscv_copy_chunk(riscv,
riscv->os_desc.code_offset + offset,
offset, RISCV_MEMORY_IMEM);
}
/* setup riscv interrupts */
riscv_writel(riscv, FALCON_IRQMSET_EXT(0xff) |
FALCON_IRQMSET_SWGEN1 |
FALCON_IRQMSET_SWGEN0 |
FALCON_IRQMSET_EXTERR |
FALCON_IRQMSET_HALT |
FALCON_IRQMSET_WDTMR,
FALCON_IRQMSET);
riscv_writel(riscv, FALCON_IRQDEST_EXT(0xff) |
FALCON_IRQDEST_SWGEN1 |
FALCON_IRQDEST_SWGEN0 |
FALCON_IRQDEST_EXTERR |
FALCON_IRQDEST_HALT,
FALCON_IRQDEST);
/* enable interface */
riscv_writel(riscv, FALCON_ITFEN_MTHDEN |
FALCON_ITFEN_CTXEN,
FALCON_ITFEN);
/* boot riscv */
riscv_writel(riscv, 0x00000000, RISCV_BOOT_VECTOR_HI);
riscv_writel(riscv, 0x00100000, RISCV_BOOT_VECTOR_LO);
return 0;
}

View File

@@ -14,11 +14,23 @@ struct tegra_drm_riscv_descriptor {
u32 data_size; u32 data_size;
}; };
struct tegra_drm_riscv_firmware {
/* Firmware after it is read but not loaded */
const struct firmware *firmware;
/* Raw firmware data */
dma_addr_t iova;
dma_addr_t phys;
void *virt;
size_t size;
};
struct tegra_drm_riscv { struct tegra_drm_riscv {
/* User initializes */ /* User initializes */
struct device *dev; struct device *dev;
void __iomem *regs; void __iomem *regs;
struct tegra_drm_riscv_firmware firmware;
struct tegra_drm_riscv_descriptor bl_desc; struct tegra_drm_riscv_descriptor bl_desc;
struct tegra_drm_riscv_descriptor os_desc; struct tegra_drm_riscv_descriptor os_desc;
}; };
@@ -26,5 +38,10 @@ struct tegra_drm_riscv {
int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv); int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv);
int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address, int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
u32 gscid, const struct tegra_drm_riscv_descriptor *desc); u32 gscid, const struct tegra_drm_riscv_descriptor *desc);
int tegra_drm_riscv_init(struct tegra_drm_riscv *riscv);
void tegra_drm_riscv_exit(struct tegra_drm_riscv *riscv);
int tegra_drm_riscv_read_firmware(struct tegra_drm_riscv *riscv, const char *firmware_name);
int tegra_drm_riscv_load_firmware(struct tegra_drm_riscv *riscv);
int tegra_drm_riscv_boot_external(struct tegra_drm_riscv *riscv);
#endif #endif

View File

@@ -242,6 +242,11 @@ static int submit_write_reloc(struct tegra_drm_context *context, struct gather_b
/* TODO check that target_offset is within bounds */ /* TODO check that target_offset is within bounds */
dma_addr_t iova = buf->reloc.target_offset; dma_addr_t iova = buf->reloc.target_offset;
u32 written_ptr; u32 written_ptr;
bool skip_bl_swizzling = false;
if (context->client->ops->skip_bl_swizzling &&
context->client->ops->skip_bl_swizzling(context->client, &skip_bl_swizzling))
skip_bl_swizzling = false;
if (mapping->bo_map) if (mapping->bo_map)
iova += mapping->iova; iova += mapping->iova;
@@ -249,7 +254,7 @@ static int submit_write_reloc(struct tegra_drm_context *context, struct gather_b
iova += mapping->ctx_map->mapping->phys; iova += mapping->ctx_map->mapping->phys;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
if (buf->flags & DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT) if ((buf->flags & DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT) && !skip_bl_swizzling)
iova |= BIT_ULL(39); iova |= BIT_ULL(39);
#endif #endif

View File

@@ -12,6 +12,7 @@
#include <linux/host1x-next.h> #include <linux/host1x-next.h>
#include <linux/interconnect.h> #include <linux/interconnect.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
@@ -30,18 +31,35 @@
#include "drm.h" #include "drm.h"
#include "falcon.h" #include "falcon.h"
#include "riscv.h"
#include "util.h" #include "util.h"
#include "vic.h" #include "vic.h"
#include "hwpm.h" #include "hwpm.h"
#define VIC_SEC_INTF_CRC_CTRL 0xe000 #define VIC_SEC_INTF_CRC_CTRL 0xe000
#define VIC_RISCV_BCR_CTRL 0x1a68
#define VIC_RISCV_BCR_CTRL_CORE_SELECT_RISCV (1 << 4)
#define VIC_FALCON_DEBUGINFO 0x1094
#define VIC_DEBUGINFO_DUMMY 0xabcd1234
#define VIC_DEBUGINFO_CLEAR 0x0
#define VIC_RISCV_CPUCTL 0x1788
#define VIC_RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
#define VIC_RISCV_CPUCTL_ACTIVE_STATE_V(x) ((x >> 7) & 0x1)
#define VIC_RISCV_CPUCTL_ACTIVE_STATE_ACTIVE_V 0x1
struct vic_config { struct vic_config {
const char *firmware; const char *firmware;
unsigned int version; unsigned int version;
bool supports_sid; bool supports_sid;
bool supports_timestamping; bool supports_timestamping;
bool has_crc_enable; bool has_crc_enable;
bool has_riscv;
u32 transcfg_addr;
u32 actmon_active_mask;
u32 actmon_active_borps;
u32 actmon_active_weight;
bool skip_bl_swizzling;
}; };
struct vic { struct vic {
@@ -63,6 +81,9 @@ struct vic {
/* Platform configuration */ /* Platform configuration */
const struct vic_config *config; const struct vic_config *config;
/* RISC-V specific data */
struct tegra_drm_riscv riscv;
}; };
static bool blf_write_allowed(u32 offset) static bool blf_write_allowed(u32 offset)
@@ -94,15 +115,12 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
writel(value, vic->regs + offset); writel(value, vic->regs + offset);
} }
static int vic_boot(struct vic *vic) static int vic_falcon_boot(struct vic *vic)
{ {
u32 fce_ucode_size, fce_bin_data_offset; u32 fce_ucode_size, fce_bin_data_offset;
void *hdr; void *hdr;
int err = 0; int err = 0;
if (vic->config->supports_sid)
tegra_drm_program_iommu_regs(vic->dev, vic->regs, VIC_TFBIF_TRANSCFG);
/* setup clockgating registers */ /* setup clockgating registers */
vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) | vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) |
CG_IDLE_CG_EN | CG_IDLE_CG_EN |
@@ -139,6 +157,46 @@ static int vic_boot(struct vic *vic)
return 0; return 0;
} }
static int vic_riscv_boot(struct vic *vic)
{
int err;
u32 val;
vic_writel(vic, VIC_RISCV_BCR_CTRL_CORE_SELECT_RISCV, VIC_RISCV_BCR_CTRL);
/* Write a known pattern into DEBUGINFO register */
vic_writel(vic, VIC_DEBUGINFO_DUMMY, VIC_FALCON_DEBUGINFO);
err = tegra_drm_riscv_boot_external(&vic->riscv);
if (err < 0)
return err;
/* Kick start RISC-V */
vic_writel(vic, VIC_RISCV_CPUCTL_STARTCPU_TRUE, VIC_RISCV_CPUCTL);
err = readl_poll_timeout(
vic->regs + VIC_RISCV_CPUCTL, val,
VIC_RISCV_CPUCTL_ACTIVE_STATE_V(val) == VIC_RISCV_CPUCTL_ACTIVE_STATE_ACTIVE_V,
10, 100000);
if (err) {
dev_err(vic->dev, "cpuctl active state timeout! val=0x%x", val);
return err;
}
/* Check vic has reached a proper initialized state */
err = readl_poll_timeout(
vic->regs + VIC_FALCON_DEBUGINFO, val,
(val == VIC_DEBUGINFO_CLEAR),
1000, 2000000);
if (err) {
dev_err(vic->dev, "not reached initialized state, timeout! val=0x%x", val);
return err;
}
return 0;
}
static int vic_set_rate(struct vic *vic, unsigned long rate) static int vic_set_rate(struct vic *vic, unsigned long rate)
{ {
unsigned long dev_rate; unsigned long dev_rate;
@@ -231,10 +289,14 @@ static int vic_devfreq_init(struct vic *vic)
struct devfreq_dev_profile *devfreq_profile; struct devfreq_dev_profile *devfreq_profile;
struct devfreq *devfreq; struct devfreq *devfreq;
while (rate <= max_rate) { margin = max(margin, 9000000UL);
do {
dev_pm_opp_add(vic->dev, rate, 0); dev_pm_opp_add(vic->dev, rate, 0);
/* Overflow check */
if (margin > ULONG_MAX - rate)
break;
rate += margin; rate += margin;
} } while (rate <= max_rate);
data = devm_kzalloc(vic->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(vic->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
@@ -346,6 +408,11 @@ static int vic_exit(struct host1x_client *client)
vic->channel = NULL; vic->channel = NULL;
if (vic->config->has_riscv) {
dma_free_coherent(vic->dev, vic->riscv.firmware.size,
vic->riscv.firmware.virt,
vic->riscv.firmware.iova);
} else {
if (client->group) { if (client->group) {
dma_unmap_single(vic->dev, vic->falcon.firmware.phys, dma_unmap_single(vic->dev, vic->falcon.firmware.phys,
vic->falcon.firmware.size, DMA_TO_DEVICE); vic->falcon.firmware.size, DMA_TO_DEVICE);
@@ -357,6 +424,7 @@ static int vic_exit(struct host1x_client *client)
vic->falcon.firmware.virt, vic->falcon.firmware.virt,
vic->falcon.firmware.iova); vic->falcon.firmware.iova);
} }
}
return 0; return 0;
} }
@@ -411,7 +479,7 @@ static const struct host1x_client_ops vic_client_ops = {
.actmon_event = vic_actmon_event, .actmon_event = vic_actmon_event,
}; };
static int vic_load_firmware(struct vic *vic) static int vic_load_falcon_firmware(struct vic *vic)
{ {
struct host1x_client *client = &vic->client.base; struct host1x_client *client = &vic->client.base;
struct tegra_drm *tegra = vic->client.drm; struct tegra_drm *tegra = vic->client.drm;
@@ -506,29 +574,71 @@ cleanup:
return err; return err;
} }
static int vic_load_riscv_firmware(struct vic *vic)
{
dma_addr_t iova;
size_t size;
void *virt;
int err;
if (vic->riscv.firmware.virt)
return 0;
err = tegra_drm_riscv_read_firmware(&vic->riscv, vic->config->firmware);
if (err < 0)
return err;
size = vic->riscv.firmware.size;
virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL);
err = dma_mapping_error(vic->dev, iova);
if (err < 0)
return err;
vic->riscv.firmware.virt = virt;
vic->riscv.firmware.iova = iova;
err = tegra_drm_riscv_load_firmware(&vic->riscv);
if (err < 0)
goto cleanup;
vic->can_use_context = true;
return 0;
cleanup:
dma_free_coherent(vic->dev, size, virt, iova);
return err;
}
static void vic_actmon_reg_init(struct vic *vic) static void vic_actmon_reg_init(struct vic *vic)
{ {
if (vic->config->actmon_active_mask)
vic_writel(vic, vic_writel(vic,
VIC_TFBIF_ACTMON_ACTIVE_MASK_STARVED | VIC_TFBIF_ACTMON_ACTIVE_MASK_STARVED |
VIC_TFBIF_ACTMON_ACTIVE_MASK_STALLED | VIC_TFBIF_ACTMON_ACTIVE_MASK_STALLED |
VIC_TFBIF_ACTMON_ACTIVE_MASK_DELAYED, VIC_TFBIF_ACTMON_ACTIVE_MASK_DELAYED,
NV_PVIC_TFBIF_ACTMON_ACTIVE_MASK); vic->config->actmon_active_mask);
if (vic->config->actmon_active_borps)
vic_writel(vic, vic_writel(vic,
VIC_TFBIF_ACTMON_ACTIVE_BORPS_ACTIVE, VIC_TFBIF_ACTMON_ACTIVE_BORPS_ACTIVE,
NV_PVIC_TFBIF_ACTMON_ACTIVE_BORPS); vic->config->actmon_active_borps);
} }
static void vic_count_weight_init(struct vic *vic, unsigned long rate) static void vic_count_weight_init(struct vic *vic, unsigned long rate)
{ {
const struct vic_config *config = vic->config;
struct host1x_client *client = &vic->client.base; struct host1x_client *client = &vic->client.base;
u32 weight = 0; u32 weight = 0;
host1x_actmon_update_client_rate(client, rate, &weight); host1x_actmon_update_client_rate(client, rate, &weight);
if (weight) if (config->actmon_active_weight && weight)
vic_writel(vic, weight, NV_PVIC_TFBIF_ACTMON_ACTIVE_WEIGHT); vic_writel(vic, weight, config->actmon_active_weight);
} }
static int __maybe_unused vic_runtime_resume(struct device *dev) static int __maybe_unused vic_runtime_resume(struct device *dev)
@@ -548,13 +658,26 @@ static int __maybe_unused vic_runtime_resume(struct device *dev)
usleep_range(10, 20); usleep_range(10, 20);
err = vic_load_firmware(vic); if (vic->config->supports_sid)
tegra_drm_program_iommu_regs(vic->dev, vic->regs, vic->config->transcfg_addr);
if (vic->config->has_riscv) {
err = vic_load_riscv_firmware(vic);
if (err < 0) if (err < 0)
goto assert; goto assert;
err = vic_boot(vic); err = vic_riscv_boot(vic);
if (err < 0) if (err < 0)
goto assert; goto assert;
} else {
err = vic_load_falcon_firmware(vic);
if (err < 0)
goto assert;
err = vic_falcon_boot(vic);
if (err < 0)
goto assert;
}
/* Forcely set frequency as Fmax when device is resumed back */ /* Forcely set frequency as Fmax when device is resumed back */
vic->devfreq->resume_freq = vic->devfreq->scaling_max_freq; vic->devfreq->resume_freq = vic->devfreq->scaling_max_freq;
@@ -638,12 +761,16 @@ static int vic_can_use_memory_ctx(struct tegra_drm_client *client, bool *support
struct vic *vic = to_vic(client); struct vic *vic = to_vic(client);
int err; int err;
if (vic->config->has_riscv) {
*supported = true;
} else {
/* This doesn't access HW so it's safe to call without powering up. */ /* This doesn't access HW so it's safe to call without powering up. */
err = vic_load_firmware(vic); err = vic_load_falcon_firmware(vic);
if (err < 0) if (err < 0)
return err; return err;
*supported = vic->can_use_context; *supported = vic->can_use_context;
}
return 0; return 0;
} }
@@ -657,6 +784,15 @@ static int vic_has_job_timestamping(struct tegra_drm_client *client, bool *suppo
return 0; return 0;
} }
static int vic_skip_bl_swizzling(struct tegra_drm_client *client, bool *skip)
{
struct vic *vic = to_vic(client);
*skip = vic->config->skip_bl_swizzling;
return 0;
}
static const struct tegra_drm_client_ops vic_ops = { static const struct tegra_drm_client_ops vic_ops = {
.open_channel = vic_open_channel, .open_channel = vic_open_channel,
.close_channel = vic_close_channel, .close_channel = vic_close_channel,
@@ -664,6 +800,7 @@ static const struct tegra_drm_client_ops vic_ops = {
.get_streamid_offset = tegra_drm_get_streamid_offset_thi, .get_streamid_offset = tegra_drm_get_streamid_offset_thi,
.can_use_memory_ctx = vic_can_use_memory_ctx, .can_use_memory_ctx = vic_can_use_memory_ctx,
.has_job_timestamping = vic_has_job_timestamping, .has_job_timestamping = vic_has_job_timestamping,
.skip_bl_swizzling = vic_skip_bl_swizzling,
}; };
#define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin" #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
@@ -688,6 +825,10 @@ static const struct vic_config vic_t186_config = {
.firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE, .firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE,
.version = 0x18, .version = 0x18,
.supports_sid = true, .supports_sid = true,
.transcfg_addr = 0x2044,
.actmon_active_mask = 0x204c,
.actmon_active_borps = 0x2050,
.actmon_active_weight = 0x2054,
}; };
#define NVIDIA_TEGRA_194_VIC_FIRMWARE "nvidia/tegra194/vic.bin" #define NVIDIA_TEGRA_194_VIC_FIRMWARE "nvidia/tegra194/vic.bin"
@@ -697,6 +838,10 @@ static const struct vic_config vic_t194_config = {
.version = 0x19, .version = 0x19,
.supports_sid = true, .supports_sid = true,
.supports_timestamping = true, .supports_timestamping = true,
.transcfg_addr = 0x2044,
.actmon_active_mask = 0x204c,
.actmon_active_borps = 0x2050,
.actmon_active_weight = 0x2054,
}; };
#define NVIDIA_TEGRA_234_VIC_FIRMWARE "nvidia/tegra234/vic.bin" #define NVIDIA_TEGRA_234_VIC_FIRMWARE "nvidia/tegra234/vic.bin"
@@ -707,6 +852,25 @@ static const struct vic_config vic_t234_config = {
.supports_sid = true, .supports_sid = true,
.supports_timestamping = true, .supports_timestamping = true,
.has_crc_enable = true, .has_crc_enable = true,
.transcfg_addr = 0x2044,
.actmon_active_mask = 0x204c,
.actmon_active_borps = 0x2050,
.actmon_active_weight = 0x2054,
};
#define NVIDIA_TEGRA_264_VIC_FIRMWARE "nvidia/tegra264/vic.bin"
static const struct vic_config vic_t264_config = {
.firmware = NVIDIA_TEGRA_264_VIC_FIRMWARE,
.version = 0x26,
.supports_sid = true,
.supports_timestamping = true,
.has_riscv = true,
.transcfg_addr = 0x2244,
.actmon_active_mask = 0x224c,
.actmon_active_borps = 0x2250,
.actmon_active_weight = 0x2254,
.skip_bl_swizzling = true,
}; };
static const struct of_device_id tegra_vic_of_match[] = { static const struct of_device_id tegra_vic_of_match[] = {
@@ -715,6 +879,7 @@ static const struct of_device_id tegra_vic_of_match[] = {
{ .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config }, { .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config },
{ .compatible = "nvidia,tegra194-vic", .data = &vic_t194_config }, { .compatible = "nvidia,tegra194-vic", .data = &vic_t194_config },
{ .compatible = "nvidia,tegra234-vic", .data = &vic_t234_config }, { .compatible = "nvidia,tegra234-vic", .data = &vic_t234_config },
{ .compatible = "nvidia,tegra264-vic", .data = &vic_t264_config },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, tegra_vic_of_match); MODULE_DEVICE_TABLE(of, tegra_vic_of_match);
@@ -766,12 +931,26 @@ static int vic_probe(struct platform_device *pdev)
} }
} }
if (vic->config->has_riscv) {
vic->riscv.dev = dev;
vic->riscv.regs = vic->regs;
vic->riscv.os_desc.code_offset = 0x0;
vic->riscv.os_desc.code_size = 0x1200;
vic->riscv.os_desc.data_offset = 0x1200;
vic->riscv.os_desc.data_size = 0xa00;
err = tegra_drm_riscv_init(&vic->riscv);
if (err < 0)
return err;
} else {
vic->falcon.dev = dev; vic->falcon.dev = dev;
vic->falcon.regs = vic->regs; vic->falcon.regs = vic->regs;
err = falcon_init(&vic->falcon); err = falcon_init(&vic->falcon);
if (err < 0) if (err < 0)
return err; return err;
}
platform_set_drvdata(pdev, vic); platform_set_drvdata(pdev, vic);
@@ -790,7 +969,7 @@ static int vic_probe(struct platform_device *pdev)
err = host1x_client_register(&vic->client.base); err = host1x_client_register(&vic->client.base);
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to register host1x client: %d\n", err); dev_err(dev, "failed to register host1x client: %d\n", err);
goto exit_falcon; goto exit_probe;
} }
err = host1x_actmon_register(&vic->client.base); err = host1x_actmon_register(&vic->client.base);
@@ -801,13 +980,13 @@ static int vic_probe(struct platform_device *pdev)
err = clk_set_rate(vic->clk, ULONG_MAX); err = clk_set_rate(vic->clk, ULONG_MAX);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to set clock rate: %d\n", err); dev_err(&pdev->dev, "failed to set clock rate: %d\n", err);
goto exit_actmon; goto exit_probe;
} }
err = vic_devfreq_init(vic); err = vic_devfreq_init(vic);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err); dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
goto exit_actmon; goto exit_probe;
} }
if (vic->config->has_crc_enable) { if (vic->config->has_crc_enable) {
@@ -827,11 +1006,10 @@ static int vic_probe(struct platform_device *pdev)
return 0; return 0;
exit_actmon: exit_probe:
host1x_actmon_unregister(&vic->client.base); if (vic->config->has_riscv)
host1x_client_unregister(&vic->client.base); tegra_drm_riscv_exit(&vic->riscv);
else
exit_falcon:
falcon_exit(&vic->falcon); falcon_exit(&vic->falcon);
return err; return err;
@@ -852,6 +1030,9 @@ static int vic_remove(struct platform_device *pdev)
host1x_client_unregister(&vic->client.base); host1x_client_unregister(&vic->client.base);
if (vic->config->has_riscv)
tegra_drm_riscv_exit(&vic->riscv);
else
falcon_exit(&vic->falcon); falcon_exit(&vic->falcon);
return 0; return 0;
@@ -905,3 +1086,6 @@ MODULE_FIRMWARE(NVIDIA_TEGRA_194_VIC_FIRMWARE);
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) #if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_234_VIC_FIRMWARE); MODULE_FIRMWARE(NVIDIA_TEGRA_234_VIC_FIRMWARE);
#endif #endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_264_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_264_VIC_FIRMWARE);
#endif

View File

@@ -18,17 +18,11 @@
#define CG_IDLE_CG_EN (1 << 6) #define CG_IDLE_CG_EN (1 << 6)
#define CG_WAKEUP_DLY_CNT(val) ((val & 0xf) << 16) #define CG_WAKEUP_DLY_CNT(val) ((val & 0xf) << 16)
#define NV_PVIC_TFBIF_ACTMON_ACTIVE_MASK 0x0000204c
#define NV_PVIC_TFBIF_ACTMON_ACTIVE_BORPS 0x00002050
#define NV_PVIC_TFBIF_ACTMON_ACTIVE_WEIGHT 0x00002054
#define VIC_TFBIF_ACTMON_ACTIVE_MASK_STARVED BIT(0) #define VIC_TFBIF_ACTMON_ACTIVE_MASK_STARVED BIT(0)
#define VIC_TFBIF_ACTMON_ACTIVE_MASK_STALLED BIT(1) #define VIC_TFBIF_ACTMON_ACTIVE_MASK_STALLED BIT(1)
#define VIC_TFBIF_ACTMON_ACTIVE_MASK_DELAYED BIT(2) #define VIC_TFBIF_ACTMON_ACTIVE_MASK_DELAYED BIT(2)
#define VIC_TFBIF_ACTMON_ACTIVE_BORPS_ACTIVE BIT(7) #define VIC_TFBIF_ACTMON_ACTIVE_BORPS_ACTIVE BIT(7)
#define VIC_TFBIF_TRANSCFG 0x00002044
/* Firmware offsets */ /* Firmware offsets */
#define VIC_UCODE_FCE_HEADER_OFFSET (6*4) #define VIC_UCODE_FCE_HEADER_OFFSET (6*4)

View File

@@ -138,6 +138,14 @@ static int virt_engine_has_job_timestamping(struct tegra_drm_client *client, boo
return 0; return 0;
} }
static int virt_skip_bl_swizzling(struct tegra_drm_client *client, bool *skip)
{
if (of_machine_is_compatible("nvidia,tegra264"))
*skip = true;
return 0;
}
static const struct tegra_drm_client_ops virt_engine_ops = { static const struct tegra_drm_client_ops virt_engine_ops = {
.open_channel = virt_engine_open_channel, .open_channel = virt_engine_open_channel,
.close_channel = virt_engine_close_channel, .close_channel = virt_engine_close_channel,
@@ -145,6 +153,7 @@ static const struct tegra_drm_client_ops virt_engine_ops = {
.get_streamid_offset = tegra_drm_get_streamid_offset_thi, .get_streamid_offset = tegra_drm_get_streamid_offset_thi,
.can_use_memory_ctx = virt_engine_can_use_memory_ctx, .can_use_memory_ctx = virt_engine_can_use_memory_ctx,
.has_job_timestamping = virt_engine_has_job_timestamping, .has_job_timestamping = virt_engine_has_job_timestamping,
.skip_bl_swizzling = virt_skip_bl_swizzling,
}; };
static int virt_engine_setup_ivc(struct virt_engine *virt) static int virt_engine_setup_ivc(struct virt_engine *virt)