mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
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:
@@ -1457,6 +1457,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
|
||||
{ .compatible = "nvidia,tegra234-nvjpg", },
|
||||
{ .compatible = "nvidia,tegra234-ofa", },
|
||||
{ .compatible = "nvidia,tegra234-host1x-virtual-engine", },
|
||||
{ .compatible = "nvidia,tegra264-vic", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ struct tegra_drm_client_ops {
|
||||
int (*get_streamid_offset)(struct tegra_drm_client *client, u32 *offset);
|
||||
int (*can_use_memory_ctx)(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,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "riscv.h"
|
||||
#include "falcon.h"
|
||||
|
||||
#define RISCV_CPUCTL 0x4388
|
||||
#define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
|
||||
@@ -31,6 +32,13 @@
|
||||
#define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684
|
||||
#define RISCV_BCR_DMACFG_SEC 0x4694
|
||||
#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)
|
||||
{
|
||||
@@ -100,3 +108,141 @@ int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t imag
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -14,11 +14,23 @@ struct tegra_drm_riscv_descriptor {
|
||||
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 {
|
||||
/* User initializes */
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
|
||||
struct tegra_drm_riscv_firmware firmware;
|
||||
struct tegra_drm_riscv_descriptor bl_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_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
|
||||
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
|
||||
|
||||
@@ -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 */
|
||||
dma_addr_t iova = buf->reloc.target_offset;
|
||||
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)
|
||||
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;
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/host1x-next.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -30,18 +31,35 @@
|
||||
|
||||
#include "drm.h"
|
||||
#include "falcon.h"
|
||||
#include "riscv.h"
|
||||
#include "util.h"
|
||||
#include "vic.h"
|
||||
#include "hwpm.h"
|
||||
|
||||
#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 {
|
||||
const char *firmware;
|
||||
unsigned int version;
|
||||
bool supports_sid;
|
||||
bool supports_timestamping;
|
||||
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 {
|
||||
@@ -63,6 +81,9 @@ struct vic {
|
||||
|
||||
/* Platform configuration */
|
||||
const struct vic_config *config;
|
||||
|
||||
/* RISC-V specific data */
|
||||
struct tegra_drm_riscv riscv;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int vic_boot(struct vic *vic)
|
||||
static int vic_falcon_boot(struct vic *vic)
|
||||
{
|
||||
u32 fce_ucode_size, fce_bin_data_offset;
|
||||
void *hdr;
|
||||
int err = 0;
|
||||
|
||||
if (vic->config->supports_sid)
|
||||
tegra_drm_program_iommu_regs(vic->dev, vic->regs, VIC_TFBIF_TRANSCFG);
|
||||
|
||||
/* setup clockgating registers */
|
||||
vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) |
|
||||
CG_IDLE_CG_EN |
|
||||
@@ -139,6 +157,46 @@ static int vic_boot(struct vic *vic)
|
||||
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)
|
||||
{
|
||||
unsigned long dev_rate;
|
||||
@@ -231,10 +289,14 @@ static int vic_devfreq_init(struct vic *vic)
|
||||
struct devfreq_dev_profile *devfreq_profile;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
while (rate <= max_rate) {
|
||||
margin = max(margin, 9000000UL);
|
||||
do {
|
||||
dev_pm_opp_add(vic->dev, rate, 0);
|
||||
/* Overflow check */
|
||||
if (margin > ULONG_MAX - rate)
|
||||
break;
|
||||
rate += margin;
|
||||
}
|
||||
} while (rate <= max_rate);
|
||||
|
||||
data = devm_kzalloc(vic->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
@@ -346,6 +408,11 @@ static int vic_exit(struct host1x_client *client)
|
||||
|
||||
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) {
|
||||
dma_unmap_single(vic->dev, vic->falcon.firmware.phys,
|
||||
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.iova);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -411,7 +479,7 @@ static const struct host1x_client_ops vic_client_ops = {
|
||||
.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 tegra_drm *tegra = vic->client.drm;
|
||||
@@ -506,29 +574,71 @@ cleanup:
|
||||
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)
|
||||
{
|
||||
if (vic->config->actmon_active_mask)
|
||||
vic_writel(vic,
|
||||
VIC_TFBIF_ACTMON_ACTIVE_MASK_STARVED |
|
||||
VIC_TFBIF_ACTMON_ACTIVE_MASK_STALLED |
|
||||
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_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)
|
||||
{
|
||||
const struct vic_config *config = vic->config;
|
||||
struct host1x_client *client = &vic->client.base;
|
||||
u32 weight = 0;
|
||||
|
||||
host1x_actmon_update_client_rate(client, rate, &weight);
|
||||
|
||||
if (weight)
|
||||
vic_writel(vic, weight, NV_PVIC_TFBIF_ACTMON_ACTIVE_WEIGHT);
|
||||
if (config->actmon_active_weight && weight)
|
||||
vic_writel(vic, weight, config->actmon_active_weight);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
goto assert;
|
||||
|
||||
err = vic_boot(vic);
|
||||
err = vic_riscv_boot(vic);
|
||||
if (err < 0)
|
||||
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 */
|
||||
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);
|
||||
int err;
|
||||
|
||||
if (vic->config->has_riscv) {
|
||||
*supported = true;
|
||||
} else {
|
||||
/* 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)
|
||||
return err;
|
||||
|
||||
*supported = vic->can_use_context;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -657,6 +784,15 @@ static int vic_has_job_timestamping(struct tegra_drm_client *client, bool *suppo
|
||||
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 = {
|
||||
.open_channel = vic_open_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,
|
||||
.can_use_memory_ctx = vic_can_use_memory_ctx,
|
||||
.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"
|
||||
@@ -688,6 +825,10 @@ static const struct vic_config vic_t186_config = {
|
||||
.firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE,
|
||||
.version = 0x18,
|
||||
.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"
|
||||
@@ -697,6 +838,10 @@ static const struct vic_config vic_t194_config = {
|
||||
.version = 0x19,
|
||||
.supports_sid = 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"
|
||||
@@ -707,6 +852,25 @@ static const struct vic_config vic_t234_config = {
|
||||
.supports_sid = true,
|
||||
.supports_timestamping = 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[] = {
|
||||
@@ -715,6 +879,7 @@ static const struct of_device_id tegra_vic_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config },
|
||||
{ .compatible = "nvidia,tegra194-vic", .data = &vic_t194_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);
|
||||
@@ -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.regs = vic->regs;
|
||||
|
||||
err = falcon_init(&vic->falcon);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, vic);
|
||||
|
||||
@@ -790,7 +969,7 @@ static int vic_probe(struct platform_device *pdev)
|
||||
err = host1x_client_register(&vic->client.base);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to register host1x client: %d\n", err);
|
||||
goto exit_falcon;
|
||||
goto exit_probe;
|
||||
}
|
||||
|
||||
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);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to set clock rate: %d\n", err);
|
||||
goto exit_actmon;
|
||||
goto exit_probe;
|
||||
}
|
||||
|
||||
err = vic_devfreq_init(vic);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
|
||||
goto exit_actmon;
|
||||
goto exit_probe;
|
||||
}
|
||||
|
||||
if (vic->config->has_crc_enable) {
|
||||
@@ -827,11 +1006,10 @@ static int vic_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_actmon:
|
||||
host1x_actmon_unregister(&vic->client.base);
|
||||
host1x_client_unregister(&vic->client.base);
|
||||
|
||||
exit_falcon:
|
||||
exit_probe:
|
||||
if (vic->config->has_riscv)
|
||||
tegra_drm_riscv_exit(&vic->riscv);
|
||||
else
|
||||
falcon_exit(&vic->falcon);
|
||||
|
||||
return err;
|
||||
@@ -852,6 +1030,9 @@ static int vic_remove(struct platform_device *pdev)
|
||||
|
||||
host1x_client_unregister(&vic->client.base);
|
||||
|
||||
if (vic->config->has_riscv)
|
||||
tegra_drm_riscv_exit(&vic->riscv);
|
||||
else
|
||||
falcon_exit(&vic->falcon);
|
||||
|
||||
return 0;
|
||||
@@ -905,3 +1086,6 @@ MODULE_FIRMWARE(NVIDIA_TEGRA_194_VIC_FIRMWARE);
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_234_VIC_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_264_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_264_VIC_FIRMWARE);
|
||||
#endif
|
||||
|
||||
@@ -18,17 +18,11 @@
|
||||
#define CG_IDLE_CG_EN (1 << 6)
|
||||
#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_STALLED BIT(1)
|
||||
#define VIC_TFBIF_ACTMON_ACTIVE_MASK_DELAYED BIT(2)
|
||||
#define VIC_TFBIF_ACTMON_ACTIVE_BORPS_ACTIVE BIT(7)
|
||||
|
||||
#define VIC_TFBIF_TRANSCFG 0x00002044
|
||||
|
||||
/* Firmware offsets */
|
||||
|
||||
#define VIC_UCODE_FCE_HEADER_OFFSET (6*4)
|
||||
|
||||
@@ -138,6 +138,14 @@ static int virt_engine_has_job_timestamping(struct tegra_drm_client *client, boo
|
||||
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 = {
|
||||
.open_channel = virt_engine_open_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,
|
||||
.can_use_memory_ctx = virt_engine_can_use_memory_ctx,
|
||||
.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)
|
||||
|
||||
Reference in New Issue
Block a user