Files
linux-nv-oot/drivers/platform/tegra/nvadsp/acast.c
Viswanath L 119c4f87e2 nvadsp: Update license and remove kernel ver check
- 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>
2023-09-26 12:09:52 -07:00

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