mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
drm/tegra: Changes for v6.2-rc1
This contains a bunch of cleanups across the board as well as support for the NVDEC hardware found on the Tegra234 SoC. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmOA3FITHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoVLeD/9iybaJ3/d3WO/946jUcEx+4h5kBKV7 F5TVdbEb8p5w3ttDl9FaU0ZPvZqF6rA1EnSEc//skygtIQwCf+s8UEOdgBOiFXvd SkKP8Vqfl2IDFHCFdnhUYgtZBXHPD8mIGuUCS8fmUTb8IMnEwjA7bGhVKUtezO+E xUR0vL6Gl2OunI+lBGWsX2DgxvDW7usHVLrxHhUWJJ1KjLlKno4w9ZUQWpoAbZK+ hLnQJFjq7Zqr4FvcAQ7hyrPYA/ZPIgrNj0PeYzfbTl5S8JnohmgsxGSWNvaYlvcf Sc9GukwzvROHVvJnfg1+1iNUCOVbxZMCi9H7lpJ/6clIcErTUoDnGjmnsddH4mJB jyxhBrmAKxU2hC/qtTuyMcCl//b8fALwvUGxjDfuhgv0UVO9AV4eaysD5azkfKms d8XfJKjvF4V22DZQH5EXG7s+0/7Fqfdvcc9e9oUrBtcl5Vz9ENpX7Y7Q68040jm9 8Wwia2zKaU96t8rFdyN5yb43uhYU/kg+kiVHvKb/yiAKn6t2Q0RdaKBfFlmssF8w KLAywS0+Yb8Z8vnrAfyhFKUoOkEOXyXI/LJ6YfynTFtAWisgafVUbVopSHqR6BrI hVshmTinC2r2akrz1JrEcYHDUxtfYt6+/CiQgzIhSNQd4dOy8jw4wJYI2iAL4GKv jkb1mkUQYMxJcQ== =7VMV -----END PGP SIGNATURE----- Merge tag 'drm/tegra/for-6.2-rc1' of https://gitlab.freedesktop.org/drm/tegra into drm-next drm/tegra: Changes for v6.2-rc1 This contains a bunch of cleanups across the board as well as support for the NVDEC hardware found on the Tegra234 SoC. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thierry Reding <thierry.reding@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221125155219.3352952-1-thierry.reding@gmail.com
This commit is contained in:
commit
02339a83dc
@ -24,7 +24,8 @@ tegra-drm-y := \
|
||||
gr3d.o \
|
||||
falcon.o \
|
||||
vic.o \
|
||||
nvdec.o
|
||||
nvdec.o \
|
||||
riscv.o
|
||||
|
||||
tegra-drm-y += trace.o
|
||||
|
||||
|
@ -3205,8 +3205,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
||||
usleep_range(2000, 4000);
|
||||
|
||||
err = reset_control_assert(dc->rst);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
clk_disable_unprepare(dc->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
usleep_range(2000, 4000);
|
||||
|
||||
|
@ -1386,6 +1386,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
|
||||
{ .compatible = "nvidia,tegra194-vic", },
|
||||
{ .compatible = "nvidia,tegra194-nvdec", },
|
||||
{ .compatible = "nvidia,tegra234-vic", },
|
||||
{ .compatible = "nvidia,tegra234-nvdec", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
@ -867,14 +867,7 @@ static int tegra_hdmi_reconfigure_audio(struct tegra_hdmi *hdmi)
|
||||
|
||||
static bool tegra_output_is_hdmi(struct tegra_output *output)
|
||||
{
|
||||
struct edid *edid;
|
||||
|
||||
if (!output->connector.edid_blob_ptr)
|
||||
return false;
|
||||
|
||||
edid = (struct edid *)output->connector.edid_blob_ptr->data;
|
||||
|
||||
return drm_detect_hdmi_monitor(edid);
|
||||
return output->connector.display_info.is_hdmi;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2021, NVIDIA Corporation.
|
||||
* Copyright (c) 2015-2022, NVIDIA Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@ -8,6 +8,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/host1x.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
@ -16,18 +17,22 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include <soc/tegra/pmc.h>
|
||||
#include <soc/tegra/mc.h>
|
||||
|
||||
#include "drm.h"
|
||||
#include "falcon.h"
|
||||
#include "riscv.h"
|
||||
#include "vic.h"
|
||||
|
||||
#define NVDEC_FALCON_DEBUGINFO 0x1094
|
||||
#define NVDEC_TFBIF_TRANSCFG 0x2c44
|
||||
|
||||
struct nvdec_config {
|
||||
const char *firmware;
|
||||
unsigned int version;
|
||||
bool supports_sid;
|
||||
bool has_riscv;
|
||||
bool has_extra_clocks;
|
||||
};
|
||||
|
||||
struct nvdec {
|
||||
@ -37,10 +42,16 @@ struct nvdec {
|
||||
struct tegra_drm_client client;
|
||||
struct host1x_channel *channel;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct clk_bulk_data clks[3];
|
||||
unsigned int num_clks;
|
||||
struct reset_control *reset;
|
||||
|
||||
/* Platform configuration */
|
||||
const struct nvdec_config *config;
|
||||
|
||||
/* RISC-V specific data */
|
||||
struct tegra_drm_riscv riscv;
|
||||
phys_addr_t carveout_base;
|
||||
};
|
||||
|
||||
static inline struct nvdec *to_nvdec(struct tegra_drm_client *client)
|
||||
@ -54,7 +65,7 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
|
||||
writel(value, nvdec->regs + offset);
|
||||
}
|
||||
|
||||
static int nvdec_boot(struct nvdec *nvdec)
|
||||
static int nvdec_boot_falcon(struct nvdec *nvdec)
|
||||
{
|
||||
#ifdef CONFIG_IOMMU_API
|
||||
struct iommu_fwspec *spec = dev_iommu_fwspec_get(nvdec->dev);
|
||||
@ -90,6 +101,64 @@ static int nvdec_boot(struct nvdec *nvdec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvdec_wait_debuginfo(struct nvdec *nvdec, const char *phase)
|
||||
{
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
err = readl_poll_timeout(nvdec->regs + NVDEC_FALCON_DEBUGINFO, val, val == 0x0, 10, 100000);
|
||||
if (err) {
|
||||
dev_err(nvdec->dev, "failed to boot %s, debuginfo=0x%x\n", phase, val);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvdec_boot_riscv(struct nvdec *nvdec)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = reset_control_acquire(nvdec->reset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
nvdec_writel(nvdec, 0xabcd1234, NVDEC_FALCON_DEBUGINFO);
|
||||
|
||||
err = tegra_drm_riscv_boot_bootrom(&nvdec->riscv, nvdec->carveout_base, 1,
|
||||
&nvdec->riscv.bl_desc);
|
||||
if (err) {
|
||||
dev_err(nvdec->dev, "failed to execute bootloader\n");
|
||||
goto release_reset;
|
||||
}
|
||||
|
||||
err = nvdec_wait_debuginfo(nvdec, "bootloader");
|
||||
if (err)
|
||||
goto release_reset;
|
||||
|
||||
err = reset_control_reset(nvdec->reset);
|
||||
if (err)
|
||||
goto release_reset;
|
||||
|
||||
nvdec_writel(nvdec, 0xabcd1234, NVDEC_FALCON_DEBUGINFO);
|
||||
|
||||
err = tegra_drm_riscv_boot_bootrom(&nvdec->riscv, nvdec->carveout_base, 1,
|
||||
&nvdec->riscv.os_desc);
|
||||
if (err) {
|
||||
dev_err(nvdec->dev, "failed to execute firmware\n");
|
||||
goto release_reset;
|
||||
}
|
||||
|
||||
err = nvdec_wait_debuginfo(nvdec, "firmware");
|
||||
if (err)
|
||||
goto release_reset;
|
||||
|
||||
release_reset:
|
||||
reset_control_release(nvdec->reset);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvdec_init(struct host1x_client *client)
|
||||
{
|
||||
struct tegra_drm_client *drm = host1x_to_drm_client(client);
|
||||
@ -189,7 +258,7 @@ static const struct host1x_client_ops nvdec_client_ops = {
|
||||
.exit = nvdec_exit,
|
||||
};
|
||||
|
||||
static int nvdec_load_firmware(struct nvdec *nvdec)
|
||||
static int nvdec_load_falcon_firmware(struct nvdec *nvdec)
|
||||
{
|
||||
struct host1x_client *client = &nvdec->client.base;
|
||||
struct tegra_drm *tegra = nvdec->client.drm;
|
||||
@ -252,30 +321,35 @@ cleanup:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static __maybe_unused int nvdec_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct nvdec *nvdec = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_prepare_enable(nvdec->clk);
|
||||
err = clk_bulk_prepare_enable(nvdec->num_clks, nvdec->clks);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
err = nvdec_load_firmware(nvdec);
|
||||
if (err < 0)
|
||||
goto disable;
|
||||
if (nvdec->config->has_riscv) {
|
||||
err = nvdec_boot_riscv(nvdec);
|
||||
if (err < 0)
|
||||
goto disable;
|
||||
} else {
|
||||
err = nvdec_load_falcon_firmware(nvdec);
|
||||
if (err < 0)
|
||||
goto disable;
|
||||
|
||||
err = nvdec_boot(nvdec);
|
||||
if (err < 0)
|
||||
goto disable;
|
||||
err = nvdec_boot_falcon(nvdec);
|
||||
if (err < 0)
|
||||
goto disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
disable:
|
||||
clk_disable_unprepare(nvdec->clk);
|
||||
clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -285,7 +359,7 @@ static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
|
||||
|
||||
host1x_channel_stop(nvdec->channel);
|
||||
|
||||
clk_disable_unprepare(nvdec->clk);
|
||||
clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -346,10 +420,18 @@ static const struct nvdec_config nvdec_t194_config = {
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
static const struct nvdec_config nvdec_t234_config = {
|
||||
.version = 0x23,
|
||||
.supports_sid = true,
|
||||
.has_riscv = true,
|
||||
.has_extra_clocks = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_nvdec_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-nvdec", .data = &nvdec_t210_config },
|
||||
{ .compatible = "nvidia,tegra186-nvdec", .data = &nvdec_t186_config },
|
||||
{ .compatible = "nvidia,tegra194-nvdec", .data = &nvdec_t194_config },
|
||||
{ .compatible = "nvidia,tegra234-nvdec", .data = &nvdec_t234_config },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_nvdec_of_match);
|
||||
@ -383,13 +465,22 @@ static int nvdec_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(nvdec->regs))
|
||||
return PTR_ERR(nvdec->regs);
|
||||
|
||||
nvdec->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(nvdec->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
return PTR_ERR(nvdec->clk);
|
||||
nvdec->clks[0].id = "nvdec";
|
||||
nvdec->num_clks = 1;
|
||||
|
||||
if (nvdec->config->has_extra_clocks) {
|
||||
nvdec->num_clks = 3;
|
||||
nvdec->clks[1].id = "fuse";
|
||||
nvdec->clks[2].id = "tsec_pka";
|
||||
}
|
||||
|
||||
err = clk_set_rate(nvdec->clk, ULONG_MAX);
|
||||
err = devm_clk_bulk_get(dev, nvdec->num_clks, nvdec->clks);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to get clock(s)\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_set_rate(nvdec->clks[0].clk, ULONG_MAX);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to set clock rate\n");
|
||||
return err;
|
||||
@ -399,12 +490,42 @@ static int nvdec_probe(struct platform_device *pdev)
|
||||
if (err < 0)
|
||||
host_class = HOST1X_CLASS_NVDEC;
|
||||
|
||||
nvdec->falcon.dev = dev;
|
||||
nvdec->falcon.regs = nvdec->regs;
|
||||
if (nvdec->config->has_riscv) {
|
||||
struct tegra_mc *mc;
|
||||
|
||||
err = falcon_init(&nvdec->falcon);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mc = devm_tegra_memory_controller_get(dev);
|
||||
if (IS_ERR(mc)) {
|
||||
dev_err_probe(dev, PTR_ERR(mc),
|
||||
"failed to get memory controller handle\n");
|
||||
return PTR_ERR(mc);
|
||||
}
|
||||
|
||||
err = tegra_mc_get_carveout_info(mc, 1, &nvdec->carveout_base, NULL);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to get carveout info: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
nvdec->reset = devm_reset_control_get_exclusive_released(dev, "nvdec");
|
||||
if (IS_ERR(nvdec->reset)) {
|
||||
dev_err_probe(dev, PTR_ERR(nvdec->reset), "failed to get reset\n");
|
||||
return PTR_ERR(nvdec->reset);
|
||||
}
|
||||
|
||||
nvdec->riscv.dev = dev;
|
||||
nvdec->riscv.regs = nvdec->regs;
|
||||
|
||||
err = tegra_drm_riscv_read_descriptors(&nvdec->riscv);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else {
|
||||
nvdec->falcon.dev = dev;
|
||||
nvdec->falcon.regs = nvdec->regs;
|
||||
|
||||
err = falcon_init(&nvdec->falcon);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, nvdec);
|
||||
|
||||
|
@ -133,11 +133,11 @@ int tegra_output_probe(struct tegra_output *output)
|
||||
}
|
||||
}
|
||||
|
||||
output->hpd_gpio = devm_gpiod_get_from_of_node(output->dev,
|
||||
output->of_node,
|
||||
"nvidia,hpd-gpio", 0,
|
||||
GPIOD_IN,
|
||||
"HDMI hotplug detect");
|
||||
output->hpd_gpio = devm_fwnode_gpiod_get(output->dev,
|
||||
of_fwnode_handle(output->of_node),
|
||||
"nvidia,hpd",
|
||||
GPIOD_IN,
|
||||
"HDMI hotplug detect");
|
||||
if (IS_ERR(output->hpd_gpio)) {
|
||||
if (PTR_ERR(output->hpd_gpio) != -ENOENT)
|
||||
return PTR_ERR(output->hpd_gpio);
|
||||
|
106
drivers/gpu/drm/tegra/riscv.c
Normal file
106
drivers/gpu/drm/tegra/riscv.c
Normal file
@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022, NVIDIA Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "riscv.h"
|
||||
|
||||
#define RISCV_CPUCTL 0x4388
|
||||
#define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
|
||||
#define RISCV_BR_RETCODE 0x465c
|
||||
#define RISCV_BR_RETCODE_RESULT_V(x) ((x) & 0x3)
|
||||
#define RISCV_BR_RETCODE_RESULT_PASS_V 3
|
||||
#define RISCV_BCR_CTRL 0x4668
|
||||
#define RISCV_BCR_CTRL_CORE_SELECT_RISCV (1 << 4)
|
||||
#define RISCV_BCR_DMACFG 0x466c
|
||||
#define RISCV_BCR_DMACFG_TARGET_LOCAL_FB (0 << 0)
|
||||
#define RISCV_BCR_DMACFG_LOCK_LOCKED (1 << 31)
|
||||
#define RISCV_BCR_DMAADDR_PKCPARAM_LO 0x4670
|
||||
#define RISCV_BCR_DMAADDR_PKCPARAM_HI 0x4674
|
||||
#define RISCV_BCR_DMAADDR_FMCCODE_LO 0x4678
|
||||
#define RISCV_BCR_DMAADDR_FMCCODE_HI 0x467c
|
||||
#define RISCV_BCR_DMAADDR_FMCDATA_LO 0x4680
|
||||
#define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684
|
||||
#define RISCV_BCR_DMACFG_SEC 0x4694
|
||||
#define RISCV_BCR_DMACFG_SEC_GSCID(v) ((v) << 16)
|
||||
|
||||
static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset)
|
||||
{
|
||||
writel(value, riscv->regs + offset);
|
||||
}
|
||||
|
||||
int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv)
|
||||
{
|
||||
struct tegra_drm_riscv_descriptor *bl = &riscv->bl_desc;
|
||||
struct tegra_drm_riscv_descriptor *os = &riscv->os_desc;
|
||||
const struct device_node *np = riscv->dev->of_node;
|
||||
int err;
|
||||
|
||||
#define READ_PROP(name, location) \
|
||||
err = of_property_read_u32(np, name, location); \
|
||||
if (err) { \
|
||||
dev_err(riscv->dev, "failed to read " name ": %d\n", err); \
|
||||
return err; \
|
||||
}
|
||||
|
||||
READ_PROP("nvidia,bl-manifest-offset", &bl->manifest_offset);
|
||||
READ_PROP("nvidia,bl-code-offset", &bl->code_offset);
|
||||
READ_PROP("nvidia,bl-data-offset", &bl->data_offset);
|
||||
READ_PROP("nvidia,os-manifest-offset", &os->manifest_offset);
|
||||
READ_PROP("nvidia,os-code-offset", &os->code_offset);
|
||||
READ_PROP("nvidia,os-data-offset", &os->data_offset);
|
||||
#undef READ_PROP
|
||||
|
||||
if (bl->manifest_offset == 0 && bl->code_offset == 0 &&
|
||||
bl->data_offset == 0 && os->manifest_offset == 0 &&
|
||||
os->code_offset == 0 && os->data_offset == 0) {
|
||||
dev_err(riscv->dev, "descriptors not available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
phys_addr_t addr;
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
riscv_writel(riscv, RISCV_BCR_CTRL_CORE_SELECT_RISCV, RISCV_BCR_CTRL);
|
||||
|
||||
addr = image_address + desc->manifest_offset;
|
||||
riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_LO);
|
||||
riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_HI);
|
||||
|
||||
addr = image_address + desc->code_offset;
|
||||
riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_LO);
|
||||
riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_HI);
|
||||
|
||||
addr = image_address + desc->data_offset;
|
||||
riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_LO);
|
||||
riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_HI);
|
||||
|
||||
riscv_writel(riscv, RISCV_BCR_DMACFG_SEC_GSCID(gscid), RISCV_BCR_DMACFG_SEC);
|
||||
riscv_writel(riscv,
|
||||
RISCV_BCR_DMACFG_TARGET_LOCAL_FB | RISCV_BCR_DMACFG_LOCK_LOCKED, RISCV_BCR_DMACFG);
|
||||
|
||||
riscv_writel(riscv, RISCV_CPUCTL_STARTCPU_TRUE, RISCV_CPUCTL);
|
||||
|
||||
err = readl_poll_timeout(
|
||||
riscv->regs + RISCV_BR_RETCODE, val,
|
||||
RISCV_BR_RETCODE_RESULT_V(val) == RISCV_BR_RETCODE_RESULT_PASS_V,
|
||||
10, 100000);
|
||||
if (err) {
|
||||
dev_err(riscv->dev, "error during bootrom execution. BR_RETCODE=%d\n", val);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
30
drivers/gpu/drm/tegra/riscv.h
Normal file
30
drivers/gpu/drm/tegra/riscv.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022, NVIDIA Corporation.
|
||||
*/
|
||||
|
||||
#ifndef DRM_TEGRA_RISCV_H
|
||||
#define DRM_TEGRA_RISCV_H
|
||||
|
||||
struct tegra_drm_riscv_descriptor {
|
||||
u32 manifest_offset;
|
||||
u32 code_offset;
|
||||
u32 code_size;
|
||||
u32 data_offset;
|
||||
u32 data_size;
|
||||
};
|
||||
|
||||
struct tegra_drm_riscv {
|
||||
/* User initializes */
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
|
||||
struct tegra_drm_riscv_descriptor bl_desc;
|
||||
struct tegra_drm_riscv_descriptor os_desc;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
@ -133,7 +133,7 @@ static void gather_bo_munmap(struct host1x_bo *host_bo, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
const struct host1x_bo_ops gather_bo_ops = {
|
||||
static const struct host1x_bo_ops gather_bo_ops = {
|
||||
.get = gather_bo_get,
|
||||
.put = gather_bo_put,
|
||||
.pin = gather_bo_pin,
|
||||
@ -169,14 +169,9 @@ static void *alloc_copy_user_array(void __user *from, size_t count, size_t size)
|
||||
if (copy_len > 0x4000)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
data = kvmalloc(copy_len, GFP_KERNEL);
|
||||
if (!data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (copy_from_user(data, from, copy_len)) {
|
||||
kvfree(data);
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
data = vmemdup_user(from, copy_len);
|
||||
if (IS_ERR(data))
|
||||
return ERR_CAST(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_
|
||||
|
||||
if (supported)
|
||||
context->memory_context = host1x_memory_context_alloc(
|
||||
host, get_task_pid(current, PIDTYPE_TGID));
|
||||
host, client->base.dev, get_task_pid(current, PIDTYPE_TGID));
|
||||
|
||||
if (IS_ERR(context->memory_context)) {
|
||||
if (PTR_ERR(context->memory_context) != -EOPNOTSUPP) {
|
||||
|
@ -104,6 +104,7 @@ void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl)
|
||||
}
|
||||
|
||||
struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
|
||||
struct device *dev,
|
||||
struct pid *pid)
|
||||
{
|
||||
struct host1x_memory_context_list *cdl = &host1x->context_list;
|
||||
@ -118,6 +119,9 @@ struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
|
||||
for (i = 0; i < cdl->len; i++) {
|
||||
struct host1x_memory_context *cd = &cdl->devs[i];
|
||||
|
||||
if (cd->dev.iommu->iommu_dev != dev->iommu->iommu_dev)
|
||||
continue;
|
||||
|
||||
if (cd->owner == pid) {
|
||||
refcount_inc(&cd->ref);
|
||||
mutex_unlock(&cdl->lock);
|
||||
|
@ -140,7 +140,7 @@ static void show_all(struct host1x *m, struct output *o, bool show_fifo)
|
||||
}
|
||||
}
|
||||
|
||||
static int host1x_debug_show_all(struct seq_file *s, void *unused)
|
||||
static int host1x_debug_all_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct output o = {
|
||||
.fn = write_to_seqfile,
|
||||
@ -151,6 +151,7 @@ static int host1x_debug_show_all(struct seq_file *s, void *unused)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(host1x_debug_all);
|
||||
|
||||
static int host1x_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
@ -163,30 +164,7 @@ static int host1x_debug_show(struct seq_file *s, void *unused)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int host1x_debug_open_all(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, host1x_debug_show_all, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations host1x_debug_all_fops = {
|
||||
.open = host1x_debug_open_all,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int host1x_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, host1x_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations host1x_debug_fops = {
|
||||
.open = host1x_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(host1x_debug);
|
||||
|
||||
static void host1x_debugfs_init(struct host1x *host1x)
|
||||
{
|
||||
|
@ -225,6 +225,18 @@ static const struct host1x_sid_entry tegra234_sid_table[] = {
|
||||
.offset = 0x34,
|
||||
.limit = 0x34
|
||||
},
|
||||
{
|
||||
/* NVDEC channel */
|
||||
.base = 0x17c8,
|
||||
.offset = 0x30,
|
||||
.limit = 0x30,
|
||||
},
|
||||
{
|
||||
/* NVDEC MMIO */
|
||||
.base = 0x1698,
|
||||
.offset = 0x34,
|
||||
.limit = 0x34,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct host1x_info host1x08_info = {
|
||||
|
@ -99,7 +99,7 @@ static void host1x_syncpt_fence_release(struct dma_fence *f)
|
||||
dma_fence_free(f);
|
||||
}
|
||||
|
||||
const struct dma_fence_ops host1x_syncpt_fence_ops = {
|
||||
static const struct dma_fence_ops host1x_syncpt_fence_ops = {
|
||||
.get_driver_name = host1x_syncpt_fence_get_driver_name,
|
||||
.get_timeline_name = host1x_syncpt_fence_get_timeline_name,
|
||||
.enable_signaling = host1x_syncpt_fence_enable_signaling,
|
||||
|
@ -107,6 +107,31 @@ int tegra_mc_probe_device(struct tegra_mc *mc, struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_mc_probe_device);
|
||||
|
||||
int tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id,
|
||||
phys_addr_t *base, u64 *size)
|
||||
{
|
||||
u32 offset;
|
||||
|
||||
if (id < 1 || id >= mc->soc->num_carveouts)
|
||||
return -EINVAL;
|
||||
|
||||
if (id < 6)
|
||||
offset = 0xc0c + 0x50 * (id - 1);
|
||||
else
|
||||
offset = 0x2004 + 0x50 * (id - 6);
|
||||
|
||||
*base = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, offset + 0x0);
|
||||
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
||||
*base |= (phys_addr_t)mc_ch_readl(mc, MC_BROADCAST_CHANNEL, offset + 0x4) << 32;
|
||||
#endif
|
||||
|
||||
if (size)
|
||||
*size = mc_ch_readl(mc, MC_BROADCAST_CHANNEL, offset + 0x8) << 17;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_mc_get_carveout_info);
|
||||
|
||||
static int tegra_mc_block_dma_common(struct tegra_mc *mc,
|
||||
const struct tegra_mc_reset *rst)
|
||||
{
|
||||
|
@ -187,4 +187,9 @@ const struct tegra_mc_soc tegra234_mc_soc = {
|
||||
.ops = &tegra186_mc_ops,
|
||||
.ch_intmask = 0x0000ff00,
|
||||
.global_intstatus_channel_shift = 8,
|
||||
/*
|
||||
* Additionally, there are lite carveouts but those are not currently
|
||||
* supported.
|
||||
*/
|
||||
.num_carveouts = 32,
|
||||
};
|
||||
|
@ -469,11 +469,13 @@ struct host1x_memory_context {
|
||||
|
||||
#ifdef CONFIG_IOMMU_API
|
||||
struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
|
||||
struct device *dev,
|
||||
struct pid *pid);
|
||||
void host1x_memory_context_get(struct host1x_memory_context *cd);
|
||||
void host1x_memory_context_put(struct host1x_memory_context *cd);
|
||||
#else
|
||||
static inline struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
|
||||
struct device *dev,
|
||||
struct pid *pid)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -193,6 +193,8 @@ struct tegra_mc_soc {
|
||||
unsigned int num_address_bits;
|
||||
unsigned int atom_size;
|
||||
|
||||
unsigned int num_carveouts;
|
||||
|
||||
u16 client_id_mask;
|
||||
u8 num_channels;
|
||||
|
||||
@ -244,6 +246,8 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
|
||||
#ifdef CONFIG_TEGRA_MC
|
||||
struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev);
|
||||
int tegra_mc_probe_device(struct tegra_mc *mc, struct device *dev);
|
||||
int tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id,
|
||||
phys_addr_t *base, u64 *size);
|
||||
#else
|
||||
static inline struct tegra_mc *
|
||||
devm_tegra_memory_controller_get(struct device *dev)
|
||||
@ -256,6 +260,13 @@ tegra_mc_probe_device(struct tegra_mc *mc, struct device *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int
|
||||
tegra_mc_get_carveout_info(struct tegra_mc *mc, unsigned int id,
|
||||
phys_addr_t *base, u64 *size)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SOC_TEGRA_MC_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user