mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
- Update license of all files in nvadsp that will be used - Remove kernel version checks in the code Bug 4164138 Bug 3682950 Change-Id: Ie1f9ba95c1d46c3dd9bc5614e502b1b444484df6 Signed-off-by: Viswanath L <viswanathl@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2980528 Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
221 lines
6.1 KiB
C
221 lines
6.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/**
|
|
* Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/platform_device.h>
|
|
#include <linux/of.h>
|
|
#include <linux/io.h>
|
|
#include "dev.h"
|
|
#include "dev-t18x.h"
|
|
|
|
#define AST_CONTROL 0x000
|
|
#define AST_STREAMID_CTL_0 0x020
|
|
#define AST_STREAMID_CTL_1 0x024
|
|
#define AST_RGN_SLAVE_BASE_LO 0x100
|
|
#define AST_RGN_SLAVE_BASE_HI 0x104
|
|
#define AST_RGN_MASK_BASE_LO 0x108
|
|
#define AST_RGN_MASK_BASE_HI 0x10c
|
|
#define AST_RGN_MASTER_BASE_LO 0x110
|
|
#define AST_RGN_MASTER_BASE_HI 0x114
|
|
#define AST_RGN_CONTROL 0x118
|
|
|
|
#define AST_PAGE_MASK (~0xFFF)
|
|
#define AST_LO_SHIFT 32
|
|
#define AST_LO_MASK 0xFFFFFFFF
|
|
#define AST_PHY_SID_IDX 0
|
|
#define AST_APE_SID_IDX 1
|
|
#define AST_NS (1 << 3)
|
|
#define AST_CARVEOUTID(ID) (ID << 5)
|
|
#define AST_VMINDEX(IDX) (IDX << 15)
|
|
#define AST_PHSICAL(PHY) (PHY << 19)
|
|
#define AST_STREAMID(ID) (ID << 8)
|
|
#define AST_VMINDEX_ENABLE (1 << 0)
|
|
#define AST_RGN_ENABLE (1 << 0)
|
|
#define AST_RGN_OFFSET 0x20
|
|
|
|
struct acast_region {
|
|
u32 rgn;
|
|
u32 rgn_ctrl;
|
|
u32 strmid_reg;
|
|
u32 strmid_ctrl;
|
|
u64 slave;
|
|
u64 size;
|
|
u64 master;
|
|
};
|
|
|
|
#define NUM_MAX_ACAST 2
|
|
|
|
#define ACAST_RGN_PHY 0x0
|
|
#define ACAST_RGN_CTL_PHY (AST_PHSICAL(1) | AST_CARVEOUTID(0x7))
|
|
|
|
#define ACAST_RGN_VM 0x2
|
|
#define ACAST_VMINDEX 1
|
|
#define ACAST_RGN_CTL_VM(IDX) AST_VMINDEX(IDX)
|
|
#define ACAST_SID_REG_EVAL(IDX) AST_STREAMID_CTL_##IDX
|
|
#define ACAST_STRMID_REG(IDX) ACAST_SID_REG_EVAL(IDX)
|
|
|
|
static inline void acast_write(void __iomem *acast, u32 reg, u32 val)
|
|
{
|
|
writel(val, acast + reg);
|
|
}
|
|
|
|
static inline u32 acast_read(void __iomem *acast, u32 reg)
|
|
{
|
|
return readl(acast + reg);
|
|
}
|
|
|
|
static inline u32 acast_rgn_reg(u32 rgn, u32 reg)
|
|
{
|
|
return rgn * AST_RGN_OFFSET + reg;
|
|
}
|
|
|
|
static void tegra18x_acast_map(struct device *dev,
|
|
void __iomem *acast, u32 rgn, u32 rgn_ctrl,
|
|
u32 strmid_reg, u32 strmid_ctrl,
|
|
u64 slave, u64 size, u64 master)
|
|
{
|
|
u32 val;
|
|
|
|
val = acast_read(acast, acast_rgn_reg(rgn, AST_RGN_SLAVE_BASE_LO));
|
|
if (val & AST_RGN_ENABLE) {
|
|
dev_warn(dev, "ACAST rgn %u already mapped...skipping\n", rgn);
|
|
return;
|
|
}
|
|
|
|
val = master & AST_LO_MASK;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_MASTER_BASE_LO), val);
|
|
val = master >> AST_LO_SHIFT;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_MASTER_BASE_HI), val);
|
|
|
|
val = ((size - 1) & AST_PAGE_MASK) & AST_LO_MASK;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_MASK_BASE_LO), val);
|
|
val = (size - 1) >> AST_LO_SHIFT;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_MASK_BASE_HI), val);
|
|
|
|
val = acast_read(acast, acast_rgn_reg(rgn, AST_RGN_CONTROL));
|
|
val |= rgn_ctrl;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_CONTROL), val);
|
|
|
|
if (strmid_reg)
|
|
acast_write(acast, strmid_reg, strmid_ctrl);
|
|
|
|
val = slave >> AST_LO_SHIFT;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_SLAVE_BASE_HI), val);
|
|
val = (slave & AST_LO_MASK) | AST_RGN_ENABLE;
|
|
acast_write(acast,
|
|
acast_rgn_reg(rgn, AST_RGN_SLAVE_BASE_LO), val);
|
|
}
|
|
|
|
static int tegra18x_acast_init(struct device *dev,
|
|
uint32_t acast_addr, uint32_t acast_size,
|
|
struct acast_region *acast_regions, uint32_t num_regions)
|
|
{
|
|
void __iomem *acast_base;
|
|
int i;
|
|
|
|
acast_base = devm_ioremap(dev, acast_addr, acast_size);
|
|
if (IS_ERR_OR_NULL(acast_base)) {
|
|
dev_err(dev, "failed to map ACAST 0x%x\n", acast_addr);
|
|
return PTR_ERR(acast_base);
|
|
}
|
|
|
|
for (i = 0; i < num_regions; i++) {
|
|
tegra18x_acast_map(dev, acast_base,
|
|
acast_regions[i].rgn,
|
|
acast_regions[i].rgn_ctrl,
|
|
acast_regions[i].strmid_reg,
|
|
acast_regions[i].strmid_ctrl,
|
|
acast_regions[i].slave,
|
|
acast_regions[i].size,
|
|
acast_regions[i].master);
|
|
|
|
dev_dbg(dev, "i:%d rgn:0x%x rgn_ctrl:0x%x ",
|
|
i, acast_regions[i].rgn, acast_regions[i].rgn_ctrl);
|
|
dev_dbg(dev, "strmid_reg:0x%x strmid_ctrl:0x%x ",
|
|
acast_regions[i].strmid_reg,
|
|
acast_regions[i].strmid_ctrl);
|
|
dev_dbg(dev, "slave:0x%llx size:0x%llx master:0x%llx\n",
|
|
acast_regions[i].slave, acast_regions[i].size,
|
|
acast_regions[i].master);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int nvadsp_acast_t18x_init(struct platform_device *pdev)
|
|
{
|
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
|
struct device *dev = &pdev->dev;
|
|
struct resource *co_mem = &drv_data->co_mem;
|
|
uint32_t acast_addr, acast_size;
|
|
int iter, num_acast = 0, ret = 0;
|
|
struct acast_region acast_config;
|
|
|
|
if (co_mem->start) {
|
|
acast_config.rgn = ACAST_RGN_PHY;
|
|
acast_config.rgn_ctrl = ACAST_RGN_CTL_PHY;
|
|
acast_config.strmid_reg = 0;
|
|
acast_config.strmid_ctrl = 0;
|
|
acast_config.slave = drv_data->adsp_mem[ADSP_OS_ADDR];
|
|
acast_config.size = drv_data->adsp_mem[ADSP_OS_SIZE];
|
|
acast_config.master = co_mem->start;
|
|
} else {
|
|
uint32_t stream_id;
|
|
uint64_t iommu_addr_start, iommu_addr_end;
|
|
|
|
if (of_property_read_u32_index(dev->of_node,
|
|
"iommus", 1, &stream_id)) {
|
|
dev_warn(dev, "no SMMU stream ID found\n");
|
|
goto exit;
|
|
}
|
|
if (of_property_read_u64_index(dev->of_node,
|
|
"iommu-resv-regions", 1, &iommu_addr_start)) {
|
|
dev_warn(dev, "no IOMMU reserved region\n");
|
|
goto exit;
|
|
}
|
|
if (of_property_read_u64_index(dev->of_node,
|
|
"iommu-resv-regions", 2, &iommu_addr_end)) {
|
|
dev_warn(dev, "no IOMMU reserved region\n");
|
|
goto exit;
|
|
}
|
|
|
|
acast_config.rgn = ACAST_RGN_VM;
|
|
acast_config.rgn_ctrl = ACAST_RGN_CTL_VM(ACAST_VMINDEX);
|
|
acast_config.strmid_reg = ACAST_STRMID_REG(ACAST_VMINDEX);
|
|
acast_config.strmid_ctrl = AST_STREAMID(stream_id) |
|
|
AST_VMINDEX_ENABLE;
|
|
acast_config.slave = iommu_addr_start;
|
|
acast_config.size = (iommu_addr_end - acast_config.slave);
|
|
acast_config.master = iommu_addr_start;
|
|
}
|
|
|
|
for (iter = 0; iter < (NUM_MAX_ACAST * 2); iter += 2) {
|
|
if (of_property_read_u32_index(dev->of_node,
|
|
"nvidia,acast_config", iter, &acast_addr))
|
|
continue;
|
|
if (of_property_read_u32_index(dev->of_node,
|
|
"nvidia,acast_config", (iter + 1), &acast_size))
|
|
continue;
|
|
|
|
ret = tegra18x_acast_init(dev, acast_addr, acast_size,
|
|
&acast_config, 1);
|
|
if (ret)
|
|
goto exit;
|
|
|
|
num_acast++;
|
|
}
|
|
|
|
if (num_acast == 0)
|
|
dev_warn(dev, "no ACAST configurations found\n");
|
|
|
|
exit:
|
|
return ret;
|
|
}
|