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:
Dave Airlie 2022-11-30 13:08:53 +10:00
commit 02339a83dc
18 changed files with 362 additions and 76 deletions

View File

@ -24,7 +24,8 @@ tegra-drm-y := \
gr3d.o \
falcon.o \
vic.o \
nvdec.o
nvdec.o \
riscv.o
tegra-drm-y += trace.o

View File

@ -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);

View File

@ -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 */ }
};

View File

@ -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

View File

@ -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);

View File

@ -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);

View 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;
}

View 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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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)
{

View File

@ -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 = {

View File

@ -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,

View File

@ -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)
{

View File

@ -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,
};

View File

@ -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;

View File

@ -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__ */