mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-22 17:30:40 +03:00
tegra: soc_hwpm: t234: move chip specific files
Move chip specific code to chip specific folder. This will allow multiple chip support in the future. Create new specific functions - Initialize hwpm structures - Reserve and release PMA and RTR apertures - Zero, update and check allowlists - Set and get fake registers for MC aperture on simulation - perfmon dt aperture enums Jira THWPM-41 Change-Id: Ib80f324283c8d29b5c6f7bb6345a6df2410954e6 Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2620234 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Seema Khowala <seemaj@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
mobile promotions
parent
1dd2527129
commit
3edf3f6034
7
Makefile
7
Makefile
@@ -4,13 +4,16 @@
|
||||
|
||||
GCOV_PROFILE := y
|
||||
|
||||
ccflags-y += -I$(srctree.nvidia)/drivers/platform/tegra/hwpm/include/regops/t234
|
||||
ccflags-y += -I$(srctree.nvidia)/drivers/platform/tegra/hwpm/include/hw/t234
|
||||
ccflags-y += -I$(srctree.nvidia)/drivers/platform/tegra/hwpm
|
||||
ccflags-y += -I$(srctree.nvidia)/include
|
||||
|
||||
obj-y += tegra-soc-hwpm.o
|
||||
obj-y += tegra-soc-hwpm-io.o
|
||||
obj-y += tegra-soc-hwpm-ioctl.o
|
||||
obj-y += tegra-soc-hwpm-log.o
|
||||
obj-y += tegra-soc-hwpm-ip.o
|
||||
obj-y += hal/tegra_soc_hwpm_init.o
|
||||
obj-y += hal/t234/t234_soc_hwpm_init.o
|
||||
obj-y += hal/t234/t234_soc_hwpm_mem_buf_utils.o
|
||||
obj-y += hal/t234/t234_soc_hwpm_resource_utils.o
|
||||
obj-$(CONFIG_DEBUG_FS) += tegra-soc-hwpm-debugfs.o
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
* comparison with unshifted values appropriate for use in field <y>
|
||||
* of register <x>.
|
||||
*/
|
||||
#ifndef TEGRA_HW_ADDR_MAP_SOC_HWPM_H
|
||||
#define TEGRA_HW_ADDR_MAP_SOC_HWPM_H
|
||||
#ifndef T234_ADDR_MAP_SOC_HWPM_H
|
||||
#define T234_ADDR_MAP_SOC_HWPM_H
|
||||
|
||||
#define addr_map_rpg_pm_base_r() (0x0f100000U)
|
||||
#define addr_map_rpg_pm_limit_r() (0x0f149fffU)
|
||||
@@ -53,8 +53,8 @@
|
||||
* comparison with unshifted values appropriate for use in field <y>
|
||||
* of register <x>.
|
||||
*/
|
||||
#ifndef TEGRA_HW_PMASYS_SOC_HWPM_H
|
||||
#define TEGRA_HW_PMASYS_SOC_HWPM_H
|
||||
#ifndef T234_PMASYS_SOC_HWPM_H
|
||||
#define T234_PMASYS_SOC_HWPM_H
|
||||
|
||||
#define pmasys_cg2_r() (0x0f14a044U)
|
||||
#define pmasys_cg2_slcg_f(v) (((v) & 0x1U) << 0U)
|
||||
@@ -53,8 +53,8 @@
|
||||
* comparison with unshifted values appropriate for use in field <y>
|
||||
* of register <x>.
|
||||
*/
|
||||
#ifndef TEGRA_HW_PMMSYS_SOC_HWPM_H
|
||||
#define TEGRA_HW_PMMSYS_SOC_HWPM_H
|
||||
#ifndef T234_PMMSYS_SOC_HWPM_H
|
||||
#define T234_PMMSYS_SOC_HWPM_H
|
||||
|
||||
#define pmmsys_perdomain_offset_v() (0x00001000U)
|
||||
#define pmmsys_control_r(i)\
|
||||
1008
hal/t234/t234_soc_hwpm_init.c
Normal file
1008
hal/t234/t234_soc_hwpm_init.c
Normal file
File diff suppressed because it is too large
Load Diff
68
hal/t234/t234_soc_hwpm_init.h
Normal file
68
hal/t234/t234_soc_hwpm_init.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef T234_SOC_HWPM_INIT_H
|
||||
#define T234_SOC_HWPM_INIT_H
|
||||
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
|
||||
void __iomem **t234_soc_hwpm_init_dt_apertures(void);
|
||||
struct tegra_soc_hwpm_ip_ops *t234_soc_hwpm_init_ip_ops_info(void);
|
||||
bool t234_soc_hwpm_is_perfmon(u32 dt_aperture);
|
||||
u64 t234_soc_hwpm_get_perfmon_base(u32 dt_aperture);
|
||||
bool t234_soc_hwpm_is_dt_aperture(u32 dt_aperture);
|
||||
u32 t234_soc_hwpm_get_ip_aperture(struct tegra_soc_hwpm *hwpm,
|
||||
u64 phys_address, u64 *ip_base_addr);
|
||||
int t234_soc_hwpm_fs_info_init(struct tegra_soc_hwpm *hwpm);
|
||||
int t234_soc_hwpm_disable_pma_triggers(struct tegra_soc_hwpm *hwpm);
|
||||
u32 **t234_soc_hwpm_get_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture);
|
||||
void t234_soc_hwpm_set_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
bool set_null);
|
||||
int t234_soc_hwpm_pma_rtr_map(struct tegra_soc_hwpm *hwpm);
|
||||
int t234_soc_hwpm_pma_rtr_unmap(struct tegra_soc_hwpm *hwpm);
|
||||
int t234_soc_hwpm_disable_slcg(struct tegra_soc_hwpm *hwpm);
|
||||
int t234_soc_hwpm_enable_slcg(struct tegra_soc_hwpm *hwpm);
|
||||
struct hwpm_resource_aperture *t234_soc_hwpm_find_aperture(
|
||||
struct tegra_soc_hwpm *hwpm, u64 phys_addr,
|
||||
bool use_absolute_base, bool check_reservation,
|
||||
u64 *updated_pa);
|
||||
|
||||
void t234_soc_hwpm_zero_alist_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture);
|
||||
int t234_soc_hwpm_update_allowlist(struct tegra_soc_hwpm *hwpm,
|
||||
void *ioctl_struct);
|
||||
bool t234_soc_hwpm_allowlist_check(struct hwpm_resource_aperture *aperture,
|
||||
u64 phys_addr, bool use_absolute_base,
|
||||
u64 *updated_pa);
|
||||
void t234_soc_hwpm_get_full_allowlist(struct tegra_soc_hwpm *hwpm);
|
||||
|
||||
int t234_soc_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_update_get_put *update_get_put);
|
||||
int t234_soc_hwpm_clear_pipeline(struct tegra_soc_hwpm *hwpm);
|
||||
int t234_soc_hwpm_stream_buf_map(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream);
|
||||
|
||||
bool t234_soc_hwpm_is_dt_aperture_reserved(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture, u32 rsrc_id);
|
||||
int t234_soc_hwpm_reserve_given_resource(
|
||||
struct tegra_soc_hwpm *hwpm, u32 resource);
|
||||
void t234_soc_hwpm_reset_resources(struct tegra_soc_hwpm *hwpm);
|
||||
void t234_soc_hwpm_disable_perfmons(struct tegra_soc_hwpm *hwpm);
|
||||
int t234_soc_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm);
|
||||
|
||||
#endif /* T234_SOC_HWPM_INIT_H */
|
||||
1562
hal/t234/t234_soc_hwpm_ip_map.h
Normal file
1562
hal/t234/t234_soc_hwpm_ip_map.h
Normal file
File diff suppressed because it is too large
Load Diff
343
hal/t234/t234_soc_hwpm_mem_buf_utils.c
Normal file
343
hal/t234/t234_soc_hwpm_mem_buf_utils.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <tegra-soc-hwpm-log.h>
|
||||
#include <tegra-soc-hwpm-io.h>
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
||||
#include <hal/t234/t234_soc_hwpm_perfmon_dt.h>
|
||||
#include <hal/t234/t234_soc_hwpm_init.h>
|
||||
#include <hal/t234/hw/t234_addr_map_soc_hwpm.h>
|
||||
|
||||
int t234_soc_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_update_get_put *update_get_put)
|
||||
{
|
||||
u32 *mem_bytes_kernel_u32 = NULL;
|
||||
u32 reg_val = 0U;
|
||||
u32 field_val = 0U;
|
||||
int ret;
|
||||
|
||||
|
||||
/* Update SW get pointer */
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_bump_r(0) - addr_map_pma_base_r(),
|
||||
update_get_put->mem_bump);
|
||||
|
||||
/* Stream MEM_BYTES value to MEM_BYTES buffer */
|
||||
if (update_get_put->b_stream_mem_bytes) {
|
||||
mem_bytes_kernel_u32 = (u32 *)(hwpm->mem_bytes_kernel);
|
||||
*mem_bytes_kernel_u32 = TEGRA_SOC_HWPM_MEM_BYTES_INVALID;
|
||||
ret = reg_rmw(hwpm, NULL, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_control_user_r(0) - addr_map_pma_base_r(),
|
||||
pmasys_channel_control_user_update_bytes_m(),
|
||||
pmasys_channel_control_user_update_bytes_doit_f(),
|
||||
false, false);
|
||||
if (ret < 0) {
|
||||
tegra_soc_hwpm_err("Failed to stream mem_bytes to buffer");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read HW put pointer */
|
||||
if (update_get_put->b_read_mem_head) {
|
||||
update_get_put->mem_head = hwpm_readl(hwpm,
|
||||
T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_head_r(0) - addr_map_pma_base_r());
|
||||
tegra_soc_hwpm_dbg("MEM_HEAD = 0x%llx",
|
||||
update_get_put->mem_head);
|
||||
}
|
||||
|
||||
/* Check overflow error status */
|
||||
if (update_get_put->b_check_overflow) {
|
||||
reg_val = hwpm_readl(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_status_secure_r(0) -
|
||||
addr_map_pma_base_r());
|
||||
field_val = pmasys_channel_status_secure_membuf_status_v(
|
||||
reg_val);
|
||||
update_get_put->b_overflowed = (field_val ==
|
||||
pmasys_channel_status_secure_membuf_status_overflowed_v());
|
||||
tegra_soc_hwpm_dbg("OVERFLOWED = %u",
|
||||
update_get_put->b_overflowed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t234_soc_hwpm_clear_pipeline(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int err = 0;
|
||||
int ret = 0;
|
||||
bool timeout = false;
|
||||
u32 *mem_bytes_kernel_u32 = NULL;
|
||||
|
||||
/* Stream MEM_BYTES to clear pipeline */
|
||||
if (hwpm->mem_bytes_kernel) {
|
||||
mem_bytes_kernel_u32 = (u32 *)(hwpm->mem_bytes_kernel);
|
||||
*mem_bytes_kernel_u32 = TEGRA_SOC_HWPM_MEM_BYTES_INVALID;
|
||||
err = reg_rmw(hwpm, NULL, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_control_user_r(0) - addr_map_pma_base_r(),
|
||||
pmasys_channel_control_user_update_bytes_m(),
|
||||
pmasys_channel_control_user_update_bytes_doit_f(),
|
||||
false, false);
|
||||
RELEASE_FAIL("Unable to stream MEM_BYTES");
|
||||
timeout = HWPM_TIMEOUT(*mem_bytes_kernel_u32 !=
|
||||
TEGRA_SOC_HWPM_MEM_BYTES_INVALID,
|
||||
"MEM_BYTES streaming");
|
||||
if (timeout && ret == 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
/* Disable PMA streaming */
|
||||
err = reg_rmw(hwpm, NULL, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_trigger_config_user_r(0) - addr_map_pma_base_r(),
|
||||
pmasys_trigger_config_user_record_stream_m(),
|
||||
pmasys_trigger_config_user_record_stream_disable_f(),
|
||||
false, false);
|
||||
RELEASE_FAIL("Unable to disable PMA streaming");
|
||||
|
||||
err = reg_rmw(hwpm, NULL, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_control_user_r(0) - addr_map_pma_base_r(),
|
||||
pmasys_channel_control_user_stream_m(),
|
||||
pmasys_channel_control_user_stream_disable_f(),
|
||||
false, false);
|
||||
RELEASE_FAIL("Unable to disable PMA streaming");
|
||||
|
||||
/* Memory Management */
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outbase_r(0) - addr_map_pma_base_r(), 0);
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outbaseupper_r(0) - addr_map_pma_base_r(), 0);
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outsize_r(0) - addr_map_pma_base_r(), 0);
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_bytes_addr_r(0) - addr_map_pma_base_r(), 0);
|
||||
|
||||
if (hwpm->stream_sgt && (!IS_ERR(hwpm->stream_sgt))) {
|
||||
dma_buf_unmap_attachment(hwpm->stream_attach,
|
||||
hwpm->stream_sgt,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
hwpm->stream_sgt = NULL;
|
||||
|
||||
if (hwpm->stream_attach && (!IS_ERR(hwpm->stream_attach))) {
|
||||
dma_buf_detach(hwpm->stream_dma_buf, hwpm->stream_attach);
|
||||
}
|
||||
hwpm->stream_attach = NULL;
|
||||
|
||||
if (hwpm->stream_dma_buf && (!IS_ERR(hwpm->stream_dma_buf))) {
|
||||
dma_buf_put(hwpm->stream_dma_buf);
|
||||
}
|
||||
hwpm->stream_dma_buf = NULL;
|
||||
|
||||
if (hwpm->mem_bytes_kernel) {
|
||||
dma_buf_vunmap(hwpm->mem_bytes_dma_buf,
|
||||
hwpm->mem_bytes_kernel);
|
||||
hwpm->mem_bytes_kernel = NULL;
|
||||
}
|
||||
|
||||
if (hwpm->mem_bytes_sgt && (!IS_ERR(hwpm->mem_bytes_sgt))) {
|
||||
dma_buf_unmap_attachment(hwpm->mem_bytes_attach,
|
||||
hwpm->mem_bytes_sgt,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
hwpm->mem_bytes_sgt = NULL;
|
||||
|
||||
if (hwpm->mem_bytes_attach && (!IS_ERR(hwpm->mem_bytes_attach))) {
|
||||
dma_buf_detach(hwpm->mem_bytes_dma_buf, hwpm->mem_bytes_attach);
|
||||
}
|
||||
hwpm->mem_bytes_attach = NULL;
|
||||
|
||||
if (hwpm->mem_bytes_dma_buf && (!IS_ERR(hwpm->mem_bytes_dma_buf))) {
|
||||
dma_buf_put(hwpm->mem_bytes_dma_buf);
|
||||
}
|
||||
hwpm->mem_bytes_dma_buf = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int t234_soc_hwpm_stream_buf_map(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 reg_val = 0;
|
||||
u32 outbase_lo = 0;
|
||||
u32 outbase_hi = 0;
|
||||
u32 outsize = 0;
|
||||
u32 mem_bytes_addr = 0;
|
||||
|
||||
/* Memory map stream buffer */
|
||||
hwpm->stream_dma_buf = dma_buf_get(alloc_pma_stream->stream_buf_fd);
|
||||
if (IS_ERR(hwpm->stream_dma_buf)) {
|
||||
tegra_soc_hwpm_err("Unable to get stream dma_buf");
|
||||
ret = PTR_ERR(hwpm->stream_dma_buf);
|
||||
goto fail;
|
||||
}
|
||||
hwpm->stream_attach = dma_buf_attach(hwpm->stream_dma_buf, hwpm->dev);
|
||||
if (IS_ERR(hwpm->stream_attach)) {
|
||||
tegra_soc_hwpm_err("Unable to attach stream dma_buf");
|
||||
ret = PTR_ERR(hwpm->stream_attach);
|
||||
goto fail;
|
||||
}
|
||||
hwpm->stream_sgt = dma_buf_map_attachment(hwpm->stream_attach,
|
||||
DMA_FROM_DEVICE);
|
||||
if (IS_ERR(hwpm->stream_sgt)) {
|
||||
tegra_soc_hwpm_err("Unable to map stream attachment");
|
||||
ret = PTR_ERR(hwpm->stream_sgt);
|
||||
goto fail;
|
||||
}
|
||||
alloc_pma_stream->stream_buf_pma_va =
|
||||
sg_dma_address(hwpm->stream_sgt->sgl);
|
||||
if (alloc_pma_stream->stream_buf_pma_va == 0) {
|
||||
tegra_soc_hwpm_err("Invalid stream buffer SMMU IOVA");
|
||||
ret = -ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
tegra_soc_hwpm_dbg("stream_buf_pma_va = 0x%llx",
|
||||
alloc_pma_stream->stream_buf_pma_va);
|
||||
|
||||
/* Memory map mem bytes buffer */
|
||||
hwpm->mem_bytes_dma_buf =
|
||||
dma_buf_get(alloc_pma_stream->mem_bytes_buf_fd);
|
||||
if (IS_ERR(hwpm->mem_bytes_dma_buf)) {
|
||||
tegra_soc_hwpm_err("Unable to get mem bytes dma_buf");
|
||||
ret = PTR_ERR(hwpm->mem_bytes_dma_buf);
|
||||
goto fail;
|
||||
}
|
||||
hwpm->mem_bytes_attach = dma_buf_attach(hwpm->mem_bytes_dma_buf,
|
||||
hwpm->dev);
|
||||
if (IS_ERR(hwpm->mem_bytes_attach)) {
|
||||
tegra_soc_hwpm_err("Unable to attach mem bytes dma_buf");
|
||||
ret = PTR_ERR(hwpm->mem_bytes_attach);
|
||||
goto fail;
|
||||
}
|
||||
hwpm->mem_bytes_sgt = dma_buf_map_attachment(hwpm->mem_bytes_attach,
|
||||
DMA_FROM_DEVICE);
|
||||
if (IS_ERR(hwpm->mem_bytes_sgt)) {
|
||||
tegra_soc_hwpm_err("Unable to map mem bytes attachment");
|
||||
ret = PTR_ERR(hwpm->mem_bytes_sgt);
|
||||
goto fail;
|
||||
}
|
||||
hwpm->mem_bytes_kernel = dma_buf_vmap(hwpm->mem_bytes_dma_buf);
|
||||
if (!hwpm->mem_bytes_kernel) {
|
||||
tegra_soc_hwpm_err(
|
||||
"Unable to map mem_bytes buffer into kernel VA space");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(hwpm->mem_bytes_kernel, 0, 32);
|
||||
|
||||
outbase_lo = alloc_pma_stream->stream_buf_pma_va &
|
||||
pmasys_channel_outbase_ptr_m();
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outbase_r(0) - addr_map_pma_base_r(),
|
||||
outbase_lo);
|
||||
tegra_soc_hwpm_dbg("OUTBASE = 0x%x", reg_val);
|
||||
|
||||
outbase_hi = (alloc_pma_stream->stream_buf_pma_va >> 32) &
|
||||
pmasys_channel_outbaseupper_ptr_m();
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outbaseupper_r(0) - addr_map_pma_base_r(),
|
||||
outbase_hi);
|
||||
tegra_soc_hwpm_dbg("OUTBASEUPPER = 0x%x", reg_val);
|
||||
|
||||
outsize = alloc_pma_stream->stream_buf_size &
|
||||
pmasys_channel_outsize_numbytes_m();
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outsize_r(0) - addr_map_pma_base_r(),
|
||||
outsize);
|
||||
tegra_soc_hwpm_dbg("OUTSIZE = 0x%x", reg_val);
|
||||
|
||||
mem_bytes_addr = sg_dma_address(hwpm->mem_bytes_sgt->sgl) &
|
||||
pmasys_channel_mem_bytes_addr_ptr_m();
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_bytes_addr_r(0) - addr_map_pma_base_r(),
|
||||
mem_bytes_addr);
|
||||
tegra_soc_hwpm_dbg("MEM_BYTES_ADDR = 0x%x", reg_val);
|
||||
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_block_r(0) - addr_map_pma_base_r(),
|
||||
pmasys_channel_mem_block_valid_f(
|
||||
pmasys_channel_mem_block_valid_true_v()));
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_block_r(0) - addr_map_pma_base_r(),
|
||||
pmasys_channel_mem_block_valid_f(
|
||||
pmasys_channel_mem_block_valid_false_v()));
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outbase_r(0) - addr_map_pma_base_r(), 0);
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outbaseupper_r(0) - addr_map_pma_base_r(), 0);
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_outsize_r(0) - addr_map_pma_base_r(), 0);
|
||||
hwpm_writel(hwpm, T234_SOC_HWPM_PMA_DT,
|
||||
pmasys_channel_mem_bytes_addr_r(0) - addr_map_pma_base_r(), 0);
|
||||
|
||||
alloc_pma_stream->stream_buf_pma_va = 0;
|
||||
|
||||
if (hwpm->stream_sgt && (!IS_ERR(hwpm->stream_sgt))) {
|
||||
dma_buf_unmap_attachment(hwpm->stream_attach,
|
||||
hwpm->stream_sgt,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
hwpm->stream_sgt = NULL;
|
||||
|
||||
if (hwpm->stream_attach && (!IS_ERR(hwpm->stream_attach))) {
|
||||
dma_buf_detach(hwpm->stream_dma_buf, hwpm->stream_attach);
|
||||
}
|
||||
hwpm->stream_attach = NULL;
|
||||
|
||||
if (hwpm->stream_dma_buf && (!IS_ERR(hwpm->stream_dma_buf))) {
|
||||
dma_buf_put(hwpm->stream_dma_buf);
|
||||
}
|
||||
hwpm->stream_dma_buf = NULL;
|
||||
|
||||
if (hwpm->mem_bytes_kernel) {
|
||||
dma_buf_vunmap(hwpm->mem_bytes_dma_buf,
|
||||
hwpm->mem_bytes_kernel);
|
||||
hwpm->mem_bytes_kernel = NULL;
|
||||
}
|
||||
if (hwpm->mem_bytes_sgt && (!IS_ERR(hwpm->mem_bytes_sgt))) {
|
||||
dma_buf_unmap_attachment(hwpm->mem_bytes_attach,
|
||||
hwpm->mem_bytes_sgt,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
hwpm->mem_bytes_sgt = NULL;
|
||||
|
||||
if (hwpm->mem_bytes_attach && (!IS_ERR(hwpm->mem_bytes_attach))) {
|
||||
dma_buf_detach(hwpm->mem_bytes_dma_buf, hwpm->mem_bytes_attach);
|
||||
}
|
||||
hwpm->mem_bytes_attach = NULL;
|
||||
|
||||
if (hwpm->mem_bytes_dma_buf && (!IS_ERR(hwpm->mem_bytes_dma_buf))) {
|
||||
dma_buf_put(hwpm->mem_bytes_dma_buf);
|
||||
}
|
||||
hwpm->mem_bytes_dma_buf = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
99
hal/t234/t234_soc_hwpm_perfmon_dt.h
Normal file
99
hal/t234/t234_soc_hwpm_perfmon_dt.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This header contains HW aperture and register info for the Tegra SOC HWPM
|
||||
* driver.
|
||||
*/
|
||||
|
||||
#ifndef T234_SOC_HWPM_PERFMON_DT_H
|
||||
#define T234_SOC_HWPM_PERFMON_DT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <hal/t234/hw/t234_pmasys_soc_hwpm.h>
|
||||
#include <hal/t234/hw/t234_pmmsys_soc_hwpm.h>
|
||||
#include <hal/t234/hw/t234_addr_map_soc_hwpm.h>
|
||||
|
||||
enum t234_soc_hwpm_dt_aperture {
|
||||
T234_SOC_HWPM_INVALID_DT = -1,
|
||||
|
||||
/* PERFMONs */
|
||||
T234_SOC_HWPM_FIRST_PERFMON_DT = 0,
|
||||
T234_SOC_HWPM_VI0_PERFMON_DT = T234_SOC_HWPM_FIRST_PERFMON_DT,
|
||||
T234_SOC_HWPM_VI1_PERFMON_DT = T234_SOC_HWPM_FIRST_PERFMON_DT + 1,
|
||||
T234_SOC_HWPM_ISP0_PERFMON_DT,
|
||||
T234_SOC_HWPM_VICA0_PERFMON_DT,
|
||||
T234_SOC_HWPM_OFAA0_PERFMON_DT,
|
||||
T234_SOC_HWPM_PVAV0_PERFMON_DT,
|
||||
T234_SOC_HWPM_PVAV1_PERFMON_DT,
|
||||
T234_SOC_HWPM_PVAC0_PERFMON_DT,
|
||||
T234_SOC_HWPM_NVDLAB0_PERFMON_DT,
|
||||
T234_SOC_HWPM_NVDLAB1_PERFMON_DT,
|
||||
T234_SOC_HWPM_NVDISPLAY0_PERFMON_DT,
|
||||
T234_SOC_HWPM_SYS0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MGBE0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MGBE1_PERFMON_DT,
|
||||
T234_SOC_HWPM_MGBE2_PERFMON_DT,
|
||||
T234_SOC_HWPM_MGBE3_PERFMON_DT,
|
||||
T234_SOC_HWPM_SCF0_PERFMON_DT,
|
||||
T234_SOC_HWPM_NVDECA0_PERFMON_DT,
|
||||
T234_SOC_HWPM_NVENCA0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSNVLHSH0_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE0_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE1_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE2_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE3_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE4_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE5_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE6_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE7_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE8_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE9_PERFMON_DT,
|
||||
T234_SOC_HWPM_PCIE10_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTA0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTA1_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTA2_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTA3_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTB0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTB1_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTB2_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTB3_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTC0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTC1_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTC2_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTC3_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTD0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTD1_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTD2_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSCHANNELPARTD3_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSHUB0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSHUB1_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSMCFCLIENT0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSMCFMEM0_PERFMON_DT,
|
||||
T234_SOC_HWPM_MSSMCFMEM1_PERFMON_DT,
|
||||
T234_SOC_HWPM_LAST_PERFMON_DT = T234_SOC_HWPM_MSSMCFMEM1_PERFMON_DT,
|
||||
T234_SOC_HWPM_PMA_DT = T234_SOC_HWPM_LAST_PERFMON_DT + 1,
|
||||
T234_SOC_HWPM_RTR_DT,
|
||||
T234_SOC_HWPM_NUM_DT_APERTURES
|
||||
};
|
||||
#define IS_PERFMON(idx) (((idx) >= T234_SOC_HWPM_FIRST_PERFMON_DT) && \
|
||||
((idx) <= T234_SOC_HWPM_LAST_PERFMON_DT))
|
||||
|
||||
/* RPG_PM Aperture */
|
||||
#define PERFMON_BASE(ip_idx) (addr_map_rpg_pm_base_r() + \
|
||||
((u32)(ip_idx)) * pmmsys_perdomain_offset_v())
|
||||
#define PERFMON_LIMIT(ip_idx) (PERFMON_BASE((ip_idx) + 1) - 1)
|
||||
|
||||
#endif /* T234_SOC_HWPM_PERFMON_DT_H */
|
||||
@@ -22,15 +22,15 @@
|
||||
* This file is autogenerated. Do not edit.
|
||||
*/
|
||||
|
||||
#ifndef SOC_HWPM_REGOPS_ALLOWLIST_H
|
||||
#define SOC_HWPM_REGOPS_ALLOWLIST_H
|
||||
#ifndef T234_SOC_HWPM_REGOPS_ALLOWLIST_H
|
||||
#define T234_SOC_HWPM_REGOPS_ALLOWLIST_H
|
||||
|
||||
struct allowlist {
|
||||
u64 reg_offset;
|
||||
bool zero_at_init;
|
||||
};
|
||||
|
||||
struct allowlist perfmon_alist[] = {
|
||||
struct allowlist t234_perfmon_alist[] = {
|
||||
{0x00000000, true},
|
||||
{0x00000004, true},
|
||||
{0x00000008, true},
|
||||
@@ -100,7 +100,7 @@ struct allowlist perfmon_alist[] = {
|
||||
{0x00000130, true},
|
||||
};
|
||||
|
||||
struct allowlist pma_res_cmd_slice_rtr_alist[] = {
|
||||
struct allowlist t234_pma_res_cmd_slice_rtr_alist[] = {
|
||||
{0x00000000, false},
|
||||
{0x00000008, false},
|
||||
{0x0000000c, false},
|
||||
@@ -189,11 +189,11 @@ struct allowlist pma_res_cmd_slice_rtr_alist[] = {
|
||||
{0x0000075c, false},
|
||||
};
|
||||
|
||||
struct allowlist pma_res_pma_alist[] = {
|
||||
struct allowlist t234_pma_res_pma_alist[] = {
|
||||
{0x00000628, true},
|
||||
};
|
||||
|
||||
struct allowlist rtr_alist[] = {
|
||||
struct allowlist t234_rtr_alist[] = {
|
||||
{0x00000000, false},
|
||||
{0x00000008, false},
|
||||
{0x0000000c, false},
|
||||
@@ -204,7 +204,7 @@ struct allowlist rtr_alist[] = {
|
||||
{0x00000154, false},
|
||||
};
|
||||
|
||||
struct allowlist vi_thi_alist[] = {
|
||||
struct allowlist t234_vi_thi_alist[] = {
|
||||
{0x0000e800, false},
|
||||
{0x0000e804, false},
|
||||
{0x0000e808, true},
|
||||
@@ -214,7 +214,7 @@ struct allowlist vi_thi_alist[] = {
|
||||
{0x0000e818, true},
|
||||
};
|
||||
|
||||
struct allowlist isp_thi_alist[] = {
|
||||
struct allowlist t234_isp_thi_alist[] = {
|
||||
{0x000091c0, false},
|
||||
{0x000091c4, false},
|
||||
{0x000091c8, true},
|
||||
@@ -224,7 +224,7 @@ struct allowlist isp_thi_alist[] = {
|
||||
{0x000091d8, true},
|
||||
};
|
||||
|
||||
struct allowlist vic_alist[] = {
|
||||
struct allowlist t234_vic_alist[] = {
|
||||
{0x00001088, false},
|
||||
{0x000010a8, false},
|
||||
{0x00001c00, true},
|
||||
@@ -236,7 +236,7 @@ struct allowlist vic_alist[] = {
|
||||
{0x00001c18, false},
|
||||
};
|
||||
|
||||
struct allowlist ofa_alist[] = {
|
||||
struct allowlist t234_ofa_alist[] = {
|
||||
{0x00001088, false},
|
||||
{0x000010a8, false},
|
||||
{0x00003308, true},
|
||||
@@ -247,7 +247,7 @@ struct allowlist ofa_alist[] = {
|
||||
{0x0000331c, false},
|
||||
};
|
||||
|
||||
struct allowlist pva0_pm_alist[] = {
|
||||
struct allowlist t234_pva0_pm_alist[] = {
|
||||
{0x00008000, false},
|
||||
{0x00008004, false},
|
||||
{0x00008008, false},
|
||||
@@ -259,7 +259,7 @@ struct allowlist pva0_pm_alist[] = {
|
||||
{0x00008020, true},
|
||||
};
|
||||
|
||||
struct allowlist nvdla_alist[] = {
|
||||
struct allowlist t234_nvdla_alist[] = {
|
||||
{0x00001088, false},
|
||||
{0x000010a8, false},
|
||||
{0x0001a000, false},
|
||||
@@ -296,12 +296,12 @@ struct allowlist nvdla_alist[] = {
|
||||
{0x0001a07c, true},
|
||||
};
|
||||
|
||||
struct allowlist mgbe_alist[] = {
|
||||
struct allowlist t234_mgbe_alist[] = {
|
||||
{0x00008020, true},
|
||||
{0x00008024, false},
|
||||
};
|
||||
|
||||
struct allowlist nvdec_alist[] = {
|
||||
struct allowlist t234_nvdec_alist[] = {
|
||||
{0x00001088, false},
|
||||
{0x000010a8, false},
|
||||
{0x00001b48, false},
|
||||
@@ -312,7 +312,7 @@ struct allowlist nvdec_alist[] = {
|
||||
{0x00001b5c, true},
|
||||
};
|
||||
|
||||
struct allowlist nvenc_alist[] = {
|
||||
struct allowlist t234_nvenc_alist[] = {
|
||||
{0x00001088, false},
|
||||
{0x000010a8, false},
|
||||
{0x00002134, true},
|
||||
@@ -324,50 +324,50 @@ struct allowlist nvenc_alist[] = {
|
||||
{0x00002130, false},
|
||||
};
|
||||
|
||||
struct allowlist pcie_ctl_alist[] = {
|
||||
struct allowlist t234_pcie_ctl_alist[] = {
|
||||
{0x00000174, true},
|
||||
{0x00000178, false},
|
||||
};
|
||||
|
||||
struct allowlist disp_alist[] = {
|
||||
struct allowlist t234_disp_alist[] = {
|
||||
{0x0001e118, true},
|
||||
{0x0001e120, true},
|
||||
{0x0001e124, false},
|
||||
};
|
||||
|
||||
struct allowlist mss_channel_alist[] = {
|
||||
struct allowlist t234_mss_channel_alist[] = {
|
||||
{0x00000814, true},
|
||||
{0x0000082c, true},
|
||||
};
|
||||
|
||||
struct allowlist mss_nvlink_alist[] = {
|
||||
struct allowlist t234_mss_nvlink_alist[] = {
|
||||
{0x00000a30, true},
|
||||
};
|
||||
|
||||
struct allowlist mc0to7_res_mss_iso_niso_hub_alist[] = {
|
||||
struct allowlist t234_mc0to7_res_mss_iso_niso_hub_alist[] = {
|
||||
{0x00000818, true},
|
||||
{0x0000081c, true},
|
||||
};
|
||||
|
||||
struct allowlist mc8_res_mss_iso_niso_hub_alist[] = {
|
||||
struct allowlist t234_mc8_res_mss_iso_niso_hub_alist[] = {
|
||||
{0x00000828, true},
|
||||
};
|
||||
|
||||
struct allowlist mcb_mss_mcf_alist[] = {
|
||||
struct allowlist t234_mcb_mss_mcf_alist[] = {
|
||||
{0x00000800, true},
|
||||
{0x00000820, true},
|
||||
{0x0000080c, true},
|
||||
{0x00000824, true},
|
||||
};
|
||||
|
||||
struct allowlist mc0to1_mss_mcf_alist[] = {
|
||||
struct allowlist t234_mc0to1_mss_mcf_alist[] = {
|
||||
{0x00000808, true},
|
||||
{0x00000804, true},
|
||||
{0x00000810, true},
|
||||
};
|
||||
|
||||
struct allowlist mc2to7_mss_mcf_alist[] = {
|
||||
struct allowlist t234_mc2to7_mss_mcf_alist[] = {
|
||||
{0x00000810, true},
|
||||
};
|
||||
|
||||
#endif /* SOC_HWPM_REGOPS_ALLOWLIST_H */
|
||||
#endif /* T234_SOC_HWPM_REGOPS_ALLOWLIST_H */
|
||||
531
hal/t234/t234_soc_hwpm_resource_utils.c
Normal file
531
hal/t234/t234_soc_hwpm_resource_utils.c
Normal file
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
||||
|
||||
#include <tegra-soc-hwpm-log.h>
|
||||
#include <tegra-soc-hwpm-io.h>
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
#include <hal/t234/t234_soc_hwpm_perfmon_dt.h>
|
||||
#include <hal/t234/t234_soc_hwpm_init.h>
|
||||
#include <hal/t234/hw/t234_addr_map_soc_hwpm.h>
|
||||
|
||||
/*
|
||||
* Normally there is a 1-to-1 mapping between an MMIO aperture and a
|
||||
* hwpm_resource_aperture struct. But MC MMIO apertures are used in multiple
|
||||
* hwpm_resource_aperture structs. Therefore, we have to share the fake register
|
||||
* arrays between these hwpm_resource_aperture structs. This is why we have to
|
||||
* define the fake register arrays globally. For all other 1-to-1 mapping
|
||||
* apertures the fake register arrays are directly embedded inside the
|
||||
* hwpm_resource_aperture structs.
|
||||
*/
|
||||
u32 *t234_mc_fake_regs[16] = {NULL};
|
||||
|
||||
bool t234_soc_hwpm_is_dt_aperture_reserved(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture, u32 rsrc_id)
|
||||
{
|
||||
return ((aperture->dt_aperture == T234_SOC_HWPM_PMA_DT) ||
|
||||
(aperture->dt_aperture == T234_SOC_HWPM_RTR_DT) ||
|
||||
(aperture->dt_aperture == T234_SOC_HWPM_SYS0_PERFMON_DT) ||
|
||||
((aperture->index_mask & hwpm->ip_fs_info[rsrc_id]) != 0));
|
||||
}
|
||||
|
||||
u32 **t234_soc_hwpm_get_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture)
|
||||
{
|
||||
if (!hwpm->fake_registers_enabled)
|
||||
return NULL;
|
||||
if (!aperture) {
|
||||
tegra_soc_hwpm_err("aperture is NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (aperture->start_pa) {
|
||||
case addr_map_mc0_base_r():
|
||||
return &t234_mc_fake_regs[0];
|
||||
case addr_map_mc1_base_r():
|
||||
return &t234_mc_fake_regs[1];
|
||||
case addr_map_mc2_base_r():
|
||||
return &t234_mc_fake_regs[2];
|
||||
case addr_map_mc3_base_r():
|
||||
return &t234_mc_fake_regs[3];
|
||||
case addr_map_mc4_base_r():
|
||||
return &t234_mc_fake_regs[4];
|
||||
case addr_map_mc5_base_r():
|
||||
return &t234_mc_fake_regs[5];
|
||||
case addr_map_mc6_base_r():
|
||||
return &t234_mc_fake_regs[6];
|
||||
case addr_map_mc7_base_r():
|
||||
return &t234_mc_fake_regs[7];
|
||||
case addr_map_mc8_base_r():
|
||||
return &t234_mc_fake_regs[8];
|
||||
case addr_map_mc9_base_r():
|
||||
return &t234_mc_fake_regs[9];
|
||||
case addr_map_mc10_base_r():
|
||||
return &t234_mc_fake_regs[10];
|
||||
case addr_map_mc11_base_r():
|
||||
return &t234_mc_fake_regs[11];
|
||||
case addr_map_mc12_base_r():
|
||||
return &t234_mc_fake_regs[12];
|
||||
case addr_map_mc13_base_r():
|
||||
return &t234_mc_fake_regs[13];
|
||||
case addr_map_mc14_base_r():
|
||||
return &t234_mc_fake_regs[14];
|
||||
case addr_map_mc15_base_r():
|
||||
return &t234_mc_fake_regs[15];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void t234_soc_hwpm_set_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
bool set_null)
|
||||
{
|
||||
u32 *fake_regs = NULL;
|
||||
|
||||
/* Get pointer to array of MSS channel apertures */
|
||||
struct hwpm_resource_aperture *l_mss_channel_map =
|
||||
hwpm->hwpm_resources[TEGRA_SOC_HWPM_RESOURCE_MSS_CHANNEL].map;
|
||||
/* Get pointer to array of MSS ISO/NISO hub apertures */
|
||||
struct hwpm_resource_aperture *l_mss_iso_niso_map =
|
||||
hwpm->hwpm_resources[TEGRA_SOC_HWPM_RESOURCE_MSS_ISO_NISO_HUBS].map;
|
||||
/* Get pointer to array of MSS MCF apertures */
|
||||
struct hwpm_resource_aperture *l_mss_mcf_map =
|
||||
hwpm->hwpm_resources[TEGRA_SOC_HWPM_RESOURCE_MSS_MCF].map;
|
||||
|
||||
if (!aperture) {
|
||||
tegra_soc_hwpm_err("aperture is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aperture->start_pa) {
|
||||
case addr_map_mc0_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[0];
|
||||
l_mss_channel_map[0].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[0].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[0].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc1_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[1];
|
||||
l_mss_channel_map[1].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[1].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[1].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc2_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[2];
|
||||
l_mss_channel_map[2].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[2].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[2].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc3_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[3];
|
||||
l_mss_channel_map[3].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[3].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[3].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc4_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[4];
|
||||
l_mss_channel_map[4].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[4].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[4].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc5_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[5];
|
||||
l_mss_channel_map[5].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[5].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[5].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc6_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[6];
|
||||
l_mss_channel_map[6].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[6].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[6].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc7_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[7];
|
||||
l_mss_channel_map[7].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[7].fake_registers = fake_regs;
|
||||
l_mss_mcf_map[7].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc8_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[8];
|
||||
l_mss_channel_map[8].fake_registers = fake_regs;
|
||||
l_mss_iso_niso_map[8].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc9_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[9];
|
||||
l_mss_channel_map[9].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc10_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[10];
|
||||
l_mss_channel_map[10].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc11_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[11];
|
||||
l_mss_channel_map[11].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc12_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[12];
|
||||
l_mss_channel_map[12].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc13_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[13];
|
||||
l_mss_channel_map[13].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc14_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[14];
|
||||
l_mss_channel_map[14].fake_registers = fake_regs;
|
||||
break;
|
||||
case addr_map_mc15_base_r():
|
||||
fake_regs = (!hwpm->fake_registers_enabled || set_null) ?
|
||||
NULL : t234_mc_fake_regs[15];
|
||||
l_mss_channel_map[15].fake_registers = fake_regs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int t234_soc_hwpm_reserve_given_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
|
||||
{
|
||||
struct hwpm_resource_aperture *aperture = NULL;
|
||||
int aprt_idx = 0;
|
||||
int ret = 0, err;
|
||||
struct tegra_soc_hwpm_ip_ops *ip_ops;
|
||||
|
||||
/* Map reserved apertures and allocate fake register arrays if needed */
|
||||
for (aprt_idx = 0;
|
||||
aprt_idx < hwpm->hwpm_resources[resource].map_size;
|
||||
aprt_idx++) {
|
||||
aperture = &(hwpm->hwpm_resources[resource].map[aprt_idx]);
|
||||
if ((aperture->dt_aperture == T234_SOC_HWPM_PMA_DT) ||
|
||||
(aperture->dt_aperture == T234_SOC_HWPM_RTR_DT)) {
|
||||
/* PMA and RTR apertures are handled in open(fd) */
|
||||
continue;
|
||||
} else if (t234_soc_hwpm_is_dt_aperture_reserved(hwpm,
|
||||
aperture, resource)) {
|
||||
if (t234_soc_hwpm_is_perfmon(aperture->dt_aperture)) {
|
||||
struct resource *res = NULL;
|
||||
u64 num_regs = 0;
|
||||
|
||||
tegra_soc_hwpm_dbg("Found PERFMON(0x%llx - 0x%llx)",
|
||||
aperture->start_pa, aperture->end_pa);
|
||||
ip_ops = &hwpm->ip_info[aperture->dt_aperture];
|
||||
if (ip_ops && (*ip_ops->hwpm_ip_pm)) {
|
||||
err = (*ip_ops->hwpm_ip_pm)
|
||||
(ip_ops->ip_dev, true);
|
||||
if (err) {
|
||||
tegra_soc_hwpm_err(
|
||||
"Disable Runtime PM(%d) Failed",
|
||||
aperture->dt_aperture);
|
||||
}
|
||||
} else {
|
||||
tegra_soc_hwpm_dbg(
|
||||
"No Runtime PM(%d) for IP",
|
||||
aperture->dt_aperture);
|
||||
}
|
||||
hwpm->dt_apertures[aperture->dt_aperture] =
|
||||
of_iomap(hwpm->np, aperture->dt_aperture);
|
||||
if (!hwpm->dt_apertures[aperture->dt_aperture]) {
|
||||
tegra_soc_hwpm_err("Couldn't map PERFMON(%d)",
|
||||
aperture->dt_aperture);
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = platform_get_resource(hwpm->pdev,
|
||||
IORESOURCE_MEM,
|
||||
aperture->dt_aperture);
|
||||
if ((!res) || (res->start == 0) || (res->end == 0)) {
|
||||
tegra_soc_hwpm_err("Invalid resource for PERFMON(%d)",
|
||||
aperture->dt_aperture);
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
aperture->start_pa = res->start;
|
||||
aperture->end_pa = res->end;
|
||||
|
||||
if (hwpm->fake_registers_enabled) {
|
||||
num_regs = (aperture->end_pa + 1 - aperture->start_pa) /
|
||||
sizeof(*aperture->fake_registers);
|
||||
aperture->fake_registers =
|
||||
(u32 *)kzalloc(sizeof(*aperture->fake_registers) *
|
||||
num_regs,
|
||||
GFP_KERNEL);
|
||||
if (!aperture->fake_registers) {
|
||||
tegra_soc_hwpm_err("Aperture(0x%llx - 0x%llx):"
|
||||
" Couldn't allocate memory for fake"
|
||||
" registers",
|
||||
aperture->start_pa,
|
||||
aperture->end_pa);
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
} else { /* IP apertures */
|
||||
if (hwpm->fake_registers_enabled) {
|
||||
u64 num_regs = 0;
|
||||
u32 **fake_regs =
|
||||
t234_soc_hwpm_get_mc_fake_regs(hwpm, aperture);
|
||||
|
||||
if (!fake_regs)
|
||||
fake_regs = &aperture->fake_registers;
|
||||
|
||||
num_regs = (aperture->end_pa + 1 - aperture->start_pa) /
|
||||
sizeof(*(*fake_regs));
|
||||
*fake_regs =
|
||||
(u32 *)kzalloc(sizeof(*(*fake_regs)) * num_regs,
|
||||
GFP_KERNEL);
|
||||
if (!(*fake_regs)) {
|
||||
tegra_soc_hwpm_err("Aperture(0x%llx - 0x%llx):"
|
||||
" Couldn't allocate memory for fake"
|
||||
" registers",
|
||||
aperture->start_pa,
|
||||
aperture->end_pa);
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
t234_soc_hwpm_set_mc_fake_regs(hwpm, aperture, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tegra_soc_hwpm_dbg("resource %d index_mask %d not available",
|
||||
resource, aperture->index_mask);
|
||||
}
|
||||
}
|
||||
|
||||
hwpm->hwpm_resources[resource].reserved = true;
|
||||
goto success;
|
||||
|
||||
fail:
|
||||
for (aprt_idx = 0;
|
||||
aprt_idx < hwpm->hwpm_resources[resource].map_size;
|
||||
aprt_idx++) {
|
||||
aperture = &(hwpm->hwpm_resources[resource].map[aprt_idx]);
|
||||
if ((aperture->dt_aperture == T234_SOC_HWPM_PMA_DT) ||
|
||||
(aperture->dt_aperture == T234_SOC_HWPM_RTR_DT)) {
|
||||
/* PMA and RTR apertures are handled in open(fd) */
|
||||
continue;
|
||||
} else if (t234_soc_hwpm_is_dt_aperture_reserved(hwpm,
|
||||
aperture, resource)) {
|
||||
if (t234_soc_hwpm_is_perfmon(aperture->dt_aperture)) {
|
||||
if (hwpm->dt_apertures[aperture->dt_aperture]) {
|
||||
iounmap(hwpm->dt_apertures[aperture->dt_aperture]);
|
||||
hwpm->dt_apertures[aperture->dt_aperture] = NULL;
|
||||
}
|
||||
|
||||
aperture->start_pa = 0;
|
||||
aperture->end_pa = 0;
|
||||
|
||||
if (aperture->fake_registers) {
|
||||
kfree(aperture->fake_registers);
|
||||
aperture->fake_registers = NULL;
|
||||
}
|
||||
} else { /* IP apertures */
|
||||
if (aperture->fake_registers) {
|
||||
kfree(aperture->fake_registers);
|
||||
aperture->fake_registers = NULL;
|
||||
t234_soc_hwpm_set_mc_fake_regs(hwpm, aperture, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hwpm->hwpm_resources[resource].reserved = false;
|
||||
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void t234_soc_hwpm_reset_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int res_idx = 0;
|
||||
int aprt_idx = 0;
|
||||
struct hwpm_resource_aperture *aperture = NULL;
|
||||
|
||||
/* Reset resource and aperture state */
|
||||
for (res_idx = 0; res_idx < TERGA_SOC_HWPM_NUM_RESOURCES; res_idx++) {
|
||||
if (!hwpm->hwpm_resources[res_idx].reserved)
|
||||
continue;
|
||||
hwpm->hwpm_resources[res_idx].reserved = false;
|
||||
|
||||
for (aprt_idx = 0;
|
||||
aprt_idx < hwpm->hwpm_resources[res_idx].map_size;
|
||||
aprt_idx++) {
|
||||
aperture = &(hwpm->hwpm_resources[res_idx].map[aprt_idx]);
|
||||
if ((aperture->dt_aperture == T234_SOC_HWPM_PMA_DT) ||
|
||||
(aperture->dt_aperture == T234_SOC_HWPM_RTR_DT)) {
|
||||
/* PMA and RTR apertures are handled separately */
|
||||
continue;
|
||||
} else if (t234_soc_hwpm_is_perfmon(aperture->dt_aperture)) {
|
||||
if (hwpm->dt_apertures[aperture->dt_aperture]) {
|
||||
iounmap(hwpm->dt_apertures[aperture->dt_aperture]);
|
||||
hwpm->dt_apertures[aperture->dt_aperture] = NULL;
|
||||
}
|
||||
|
||||
aperture->start_pa = 0;
|
||||
aperture->end_pa = 0;
|
||||
|
||||
if (aperture->fake_registers) {
|
||||
kfree(aperture->fake_registers);
|
||||
aperture->fake_registers = NULL;
|
||||
}
|
||||
} else { /* IP apertures */
|
||||
if (aperture->fake_registers) {
|
||||
kfree(aperture->fake_registers);
|
||||
aperture->fake_registers = NULL;
|
||||
t234_soc_hwpm_set_mc_fake_regs(hwpm, aperture, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void t234_soc_hwpm_disable_perfmons(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int res_idx = 0;
|
||||
int aprt_idx = 0;
|
||||
struct hwpm_resource_aperture *aperture = NULL;
|
||||
struct tegra_soc_hwpm_ip_ops *ip_ops;
|
||||
int err, ret = 0;
|
||||
|
||||
for (res_idx = 0; res_idx < TERGA_SOC_HWPM_NUM_RESOURCES; res_idx++) {
|
||||
if (!hwpm->hwpm_resources[res_idx].reserved)
|
||||
continue;
|
||||
tegra_soc_hwpm_dbg("Found reserved IP(%d)", res_idx);
|
||||
|
||||
for (aprt_idx = 0;
|
||||
aprt_idx < hwpm->hwpm_resources[res_idx].map_size;
|
||||
aprt_idx++) {
|
||||
aperture = &(hwpm->hwpm_resources[res_idx].map[aprt_idx]);
|
||||
if (t234_soc_hwpm_is_perfmon(aperture->dt_aperture)) {
|
||||
if (t234_soc_hwpm_is_dt_aperture_reserved(hwpm,
|
||||
aperture, res_idx)) {
|
||||
tegra_soc_hwpm_dbg("Found PERFMON(0x%llx - 0x%llx)",
|
||||
aperture->start_pa,
|
||||
aperture->end_pa);
|
||||
err = reg_rmw(hwpm, NULL, aperture->dt_aperture,
|
||||
pmmsys_control_r(0) - addr_map_rpg_pm_base_r(),
|
||||
pmmsys_control_mode_m(),
|
||||
pmmsys_control_mode_disable_f(),
|
||||
false, false);
|
||||
RELEASE_FAIL("Unable to disable PERFMON(0x%llx - 0x%llx)",
|
||||
aperture->start_pa,
|
||||
aperture->end_pa);
|
||||
ip_ops = &hwpm->ip_info[aperture->dt_aperture];
|
||||
if (ip_ops && (*ip_ops->hwpm_ip_pm)) {
|
||||
err = (*ip_ops->hwpm_ip_pm)
|
||||
(ip_ops->ip_dev, false);
|
||||
if (err) {
|
||||
tegra_soc_hwpm_err(
|
||||
"Enable Runtime PM(%d) Failed",
|
||||
aperture->dt_aperture);
|
||||
}
|
||||
} else {
|
||||
tegra_soc_hwpm_dbg(
|
||||
"No Runtime PM(%d) for IP",
|
||||
aperture->dt_aperture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int t234_soc_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int ret = 0;
|
||||
int res_idx = 0;
|
||||
int aprt_idx = 0;
|
||||
struct hwpm_resource_aperture *aperture = NULL;
|
||||
|
||||
for (res_idx = 0; res_idx < TERGA_SOC_HWPM_NUM_RESOURCES; res_idx++) {
|
||||
if (!hwpm->hwpm_resources[res_idx].reserved)
|
||||
continue;
|
||||
tegra_soc_hwpm_dbg("Found reserved IP(%d)", res_idx);
|
||||
|
||||
for (aprt_idx = 0;
|
||||
aprt_idx < hwpm->hwpm_resources[res_idx].map_size;
|
||||
aprt_idx++) {
|
||||
aperture = &(hwpm->hwpm_resources[res_idx].map[aprt_idx]);
|
||||
|
||||
if (t234_soc_hwpm_is_dt_aperture_reserved(hwpm,
|
||||
aperture, res_idx)) {
|
||||
|
||||
/* Zero out necessary registers */
|
||||
if (aperture->alist) {
|
||||
t234_soc_hwpm_zero_alist_regs(hwpm, aperture);
|
||||
} else {
|
||||
tegra_soc_hwpm_err(
|
||||
"NULL allowlist in aperture(0x%llx - 0x%llx)",
|
||||
aperture->start_pa, aperture->end_pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable reporting of PERFMON status to
|
||||
* NV_PERF_PMMSYS_SYS0ROUTER_PERFMONSTATUS_MERGED
|
||||
*/
|
||||
if (t234_soc_hwpm_is_perfmon(aperture->dt_aperture)) {
|
||||
tegra_soc_hwpm_dbg("Found PERFMON(0x%llx - 0x%llx)",
|
||||
aperture->start_pa,
|
||||
aperture->end_pa);
|
||||
ret = reg_rmw(hwpm, NULL, aperture->dt_aperture,
|
||||
pmmsys_sys0_enginestatus_r(0) -
|
||||
addr_map_rpg_pm_base_r(),
|
||||
pmmsys_sys0_enginestatus_enable_m(),
|
||||
pmmsys_sys0_enginestatus_enable_out_f(),
|
||||
false, false);
|
||||
if (ret < 0) {
|
||||
tegra_soc_hwpm_err(
|
||||
"Unable to set PMM ENGINESTATUS_ENABLE"
|
||||
" for PERFMON(0x%llx - 0x%llx)",
|
||||
aperture->start_pa,
|
||||
aperture->end_pa);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
149
hal/tegra-soc-hwpm-structures.h
Normal file
149
hal/tegra-soc-hwpm-structures.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TEGRA_SOC_HWPM_STRUCTURES_H
|
||||
#define TEGRA_SOC_HWPM_STRUCTURES_H
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
||||
|
||||
#define TEGRA_SOC_HWPM_DT_APERTURE_INVALID 100U
|
||||
|
||||
#define RELEASE_FAIL(msg, ...) \
|
||||
do { \
|
||||
if (err < 0) { \
|
||||
tegra_soc_hwpm_err(msg, ##__VA_ARGS__); \
|
||||
if (ret == 0) \
|
||||
ret = err; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* FIXME: Default timeout is 1 sec. Is this sufficient for pre-si? */
|
||||
#define HWPM_TIMEOUT(timeout_check, expiry_msg) ({ \
|
||||
bool timeout_expired = false; \
|
||||
s32 timeout_msecs = 1000; \
|
||||
u32 sleep_msecs = 100; \
|
||||
while (!(timeout_check)) { \
|
||||
msleep(sleep_msecs); \
|
||||
timeout_msecs -= sleep_msecs; \
|
||||
if (timeout_msecs <= 0) { \
|
||||
tegra_soc_hwpm_err("Timeout expired for %s!", \
|
||||
expiry_msg); \
|
||||
timeout_expired = true; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
timeout_expired; \
|
||||
})
|
||||
|
||||
struct allowlist;
|
||||
extern struct platform_device *tegra_soc_hwpm_pdev;
|
||||
extern const struct file_operations tegra_soc_hwpm_ops;
|
||||
|
||||
/* Driver struct */
|
||||
struct tegra_soc_hwpm {
|
||||
/* Device */
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
struct class class;
|
||||
dev_t dev_t;
|
||||
struct cdev cdev;
|
||||
|
||||
struct hwpm_resource *hwpm_resources;
|
||||
|
||||
/* IP floorsweep info */
|
||||
u64 ip_fs_info[TERGA_SOC_HWPM_NUM_IPS];
|
||||
|
||||
/* MMIO apertures in device tree */
|
||||
void __iomem **dt_apertures;
|
||||
|
||||
/* Clocks and resets */
|
||||
struct clk *la_clk;
|
||||
struct clk *la_parent_clk;
|
||||
struct reset_control *la_rst;
|
||||
struct reset_control *hwpm_rst;
|
||||
|
||||
struct tegra_soc_hwpm_ip_ops *ip_info;
|
||||
|
||||
/* Memory Management */
|
||||
struct dma_buf *stream_dma_buf;
|
||||
struct dma_buf_attachment *stream_attach;
|
||||
struct sg_table *stream_sgt;
|
||||
struct dma_buf *mem_bytes_dma_buf;
|
||||
struct dma_buf_attachment *mem_bytes_attach;
|
||||
struct sg_table *mem_bytes_sgt;
|
||||
void *mem_bytes_kernel;
|
||||
|
||||
/* SW State */
|
||||
bool bind_completed;
|
||||
s32 full_alist_size;
|
||||
|
||||
/* Debugging */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
bool fake_registers_enabled;
|
||||
};
|
||||
|
||||
struct hwpm_resource_aperture {
|
||||
/*
|
||||
* If false, this is a HWPM aperture (PERFRMON, PMA or RTR). Else this
|
||||
* is a non-HWPM aperture (ex: VIC).
|
||||
*/
|
||||
bool is_ip;
|
||||
|
||||
/*
|
||||
* If is_ip == false, specify dt_aperture for readl/writel operations.
|
||||
* If is_ip == true, dt_aperture == TEGRA_SOC_HWPM_INVALID_DT.
|
||||
*/
|
||||
u32 dt_aperture;
|
||||
|
||||
/* Physical aperture */
|
||||
u64 start_abs_pa;
|
||||
u64 end_abs_pa;
|
||||
u64 start_pa;
|
||||
u64 end_pa;
|
||||
|
||||
/* Allowlist */
|
||||
struct allowlist *alist;
|
||||
u64 alist_size;
|
||||
|
||||
/*
|
||||
* Currently, perfmons and perfmuxes for all instances of an IP
|
||||
* are listed in a single aperture mask. It is possible that
|
||||
* some instances are disable. In this case, accessing corresponding
|
||||
* registers will result in kernel panic.
|
||||
* Bit set in the index_mask value will indicate the instance index
|
||||
* within that IP (or resource).
|
||||
*/
|
||||
u32 index_mask;
|
||||
|
||||
/* Fake registers for VDK which doesn't have a SOC HWPM fmodel */
|
||||
u32 *fake_registers;
|
||||
};
|
||||
|
||||
struct hwpm_resource {
|
||||
bool reserved;
|
||||
u32 map_size;
|
||||
struct hwpm_resource_aperture *map;
|
||||
};
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_STRUCTURES_H */
|
||||
171
hal/tegra_soc_hwpm_init.c
Normal file
171
hal/tegra_soc_hwpm_init.c
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <tegra-soc-hwpm.h>
|
||||
#include <hal/tegra_soc_hwpm_init.h>
|
||||
|
||||
#include <hal/t234/t234_soc_hwpm_init.h>
|
||||
|
||||
void __iomem **tegra_soc_hwpm_init_dt_apertures(void)
|
||||
{
|
||||
return t234_soc_hwpm_init_dt_apertures();
|
||||
}
|
||||
|
||||
struct tegra_soc_hwpm_ip_ops *tegra_soc_hwpm_init_ip_ops_info(void)
|
||||
{
|
||||
return t234_soc_hwpm_init_ip_ops_info();
|
||||
}
|
||||
|
||||
bool tegra_soc_hwpm_is_perfmon(u32 dt_aperture)
|
||||
{
|
||||
return t234_soc_hwpm_is_perfmon(dt_aperture);
|
||||
}
|
||||
|
||||
u64 tegra_soc_hwpm_get_perfmon_base(u32 dt_aperture)
|
||||
{
|
||||
return t234_soc_hwpm_get_perfmon_base(dt_aperture);
|
||||
}
|
||||
|
||||
bool tegra_soc_hwpm_is_dt_aperture(u32 dt_aperture)
|
||||
{
|
||||
return t234_soc_hwpm_is_dt_aperture(dt_aperture);
|
||||
}
|
||||
|
||||
bool tegra_soc_hwpm_is_dt_aperture_reserved(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture, u32 rsrc_id)
|
||||
{
|
||||
return t234_soc_hwpm_is_dt_aperture_reserved(hwpm, aperture, rsrc_id);
|
||||
}
|
||||
|
||||
u32 tegra_soc_hwpm_get_ip_aperture(struct tegra_soc_hwpm *hwpm,
|
||||
u64 phys_address, u64 *ip_base_addr)
|
||||
{
|
||||
return t234_soc_hwpm_get_ip_aperture(hwpm, phys_address, ip_base_addr);
|
||||
}
|
||||
|
||||
struct hwpm_resource_aperture *tegra_soc_hwpm_find_aperture(
|
||||
struct tegra_soc_hwpm *hwpm, u64 phys_addr,
|
||||
bool use_absolute_base, bool check_reservation,
|
||||
u64 *updated_pa)
|
||||
{
|
||||
return t234_soc_hwpm_find_aperture(hwpm, phys_addr,
|
||||
use_absolute_base, check_reservation, updated_pa);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_fs_info_init(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_fs_info_init(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_disable_pma_triggers(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_disable_pma_triggers(hwpm);
|
||||
}
|
||||
|
||||
u32 **tegra_soc_hwpm_get_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture)
|
||||
{
|
||||
return t234_soc_hwpm_get_mc_fake_regs(hwpm, aperture);
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_set_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
bool set_null)
|
||||
{
|
||||
t234_soc_hwpm_set_mc_fake_regs(hwpm, aperture, set_null);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_disable_slcg(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_disable_slcg(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_enable_slcg(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_enable_slcg(hwpm);
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_zero_alist_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture)
|
||||
{
|
||||
t234_soc_hwpm_zero_alist_regs(hwpm, aperture);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_update_allowlist(struct tegra_soc_hwpm *hwpm,
|
||||
void *ioctl_struct)
|
||||
{
|
||||
return t234_soc_hwpm_update_allowlist(hwpm, ioctl_struct);
|
||||
}
|
||||
|
||||
bool tegra_soc_hwpm_allowlist_check(struct hwpm_resource_aperture *aperture,
|
||||
u64 phys_addr, bool use_absolute_base,
|
||||
u64 *updated_pa)
|
||||
{
|
||||
return t234_soc_hwpm_allowlist_check(aperture, phys_addr,
|
||||
use_absolute_base, updated_pa);
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_get_full_allowlist(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
t234_soc_hwpm_get_full_allowlist(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_update_get_put *update_get_put)
|
||||
{
|
||||
return t234_soc_hwpm_update_mem_bytes(hwpm, update_get_put);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_clear_pipeline(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_clear_pipeline(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_stream_buf_map(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream)
|
||||
{
|
||||
return t234_soc_hwpm_stream_buf_map(hwpm, alloc_pma_stream);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_pma_rtr_map(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_pma_rtr_map(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_pma_rtr_unmap(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_pma_rtr_unmap(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_reserve_given_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
|
||||
{
|
||||
return t234_soc_hwpm_reserve_given_resource(hwpm, resource);
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_reset_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
t234_soc_hwpm_reset_resources(hwpm);
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_disable_perfmons(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
t234_soc_hwpm_disable_perfmons(hwpm);
|
||||
}
|
||||
|
||||
int tegra_soc_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
return t234_soc_hwpm_bind_resources(hwpm);
|
||||
}
|
||||
68
hal/tegra_soc_hwpm_init.h
Normal file
68
hal/tegra_soc_hwpm_init.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This header contains interfaces to soc specific functions.
|
||||
*/
|
||||
|
||||
#ifndef TEGRA_SOC_HWPM_INIT_H
|
||||
#define TEGRA_SOC_HWPM_INIT_H
|
||||
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
||||
|
||||
void __iomem **tegra_soc_hwpm_init_dt_apertures(void);
|
||||
struct tegra_soc_hwpm_ip_ops *tegra_soc_hwpm_init_ip_ops_info(void);
|
||||
bool tegra_soc_hwpm_is_perfmon(u32 dt_aperture);
|
||||
u64 tegra_soc_hwpm_get_perfmon_base(u32 dt_aperture);
|
||||
bool tegra_soc_hwpm_is_dt_aperture(u32 dt_aperture);
|
||||
bool tegra_soc_hwpm_is_dt_aperture_reserved(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture, u32 rsrc_id);
|
||||
u32 tegra_soc_hwpm_get_ip_aperture(struct tegra_soc_hwpm *hwpm,
|
||||
u64 phys_address, u64 *ip_base_addr);
|
||||
struct hwpm_resource_aperture *tegra_soc_hwpm_find_aperture(
|
||||
struct tegra_soc_hwpm *hwpm, u64 phys_addr,
|
||||
bool use_absolute_base, bool check_reservation,
|
||||
u64 *updated_pa);
|
||||
int tegra_soc_hwpm_fs_info_init(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_disable_pma_triggers(struct tegra_soc_hwpm *hwpm);
|
||||
u32 **tegra_soc_hwpm_get_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture);
|
||||
void tegra_soc_hwpm_set_mc_fake_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
bool set_null);
|
||||
int tegra_soc_hwpm_disable_slcg(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_enable_slcg(struct tegra_soc_hwpm *hwpm);
|
||||
void tegra_soc_hwpm_zero_alist_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture);
|
||||
int tegra_soc_hwpm_update_allowlist(struct tegra_soc_hwpm *hwpm,
|
||||
void *ioctl_struct);
|
||||
bool tegra_soc_hwpm_allowlist_check(struct hwpm_resource_aperture *aperture,
|
||||
u64 phys_addr, bool use_absolute_base,
|
||||
u64 *updated_pa);
|
||||
void tegra_soc_hwpm_get_full_allowlist(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_update_get_put *update_get_put);
|
||||
int tegra_soc_hwpm_clear_pipeline(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_stream_buf_map(struct tegra_soc_hwpm *hwpm,
|
||||
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream);
|
||||
int tegra_soc_hwpm_pma_rtr_map(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_pma_rtr_unmap(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_reserve_given_resource(
|
||||
struct tegra_soc_hwpm *hwpm, u32 resource);
|
||||
void tegra_soc_hwpm_reset_resources(struct tegra_soc_hwpm *hwpm);
|
||||
void tegra_soc_hwpm_disable_perfmons(struct tegra_soc_hwpm *hwpm);
|
||||
int tegra_soc_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm);
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_INIT_H */
|
||||
@@ -17,6 +17,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
#include "tegra-soc-hwpm-log.h"
|
||||
#include "tegra-soc-hwpm.h"
|
||||
|
||||
/* FIXME: This is a placeholder for now. We can add debugfs nodes as needed. */
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* tegra-soc-hwpm-hw.h:
|
||||
* This header contains HW aperture and register info for the Tegra SOC HWPM
|
||||
* driver.
|
||||
*/
|
||||
|
||||
#ifndef TEGRA_SOC_HWPM_HW_H
|
||||
#define TEGRA_SOC_HWPM_HW_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "include/hw/t234/hw_addr_map_soc_hwpm.h"
|
||||
#include "include/hw/t234/hw_pmasys_soc_hwpm.h"
|
||||
#include "include/hw/t234/hw_pmmsys_soc_hwpm.h"
|
||||
|
||||
/* FIXME: Move enum to DT include file? */
|
||||
enum tegra_soc_hwpm_dt_aperture {
|
||||
TEGRA_SOC_HWPM_INVALID_DT = -1,
|
||||
|
||||
/* PERFMONs */
|
||||
TEGRA_SOC_HWPM_FIRST_PERFMON_DT = 0,
|
||||
TEGRA_SOC_HWPM_VI0_PERFMON_DT = TEGRA_SOC_HWPM_FIRST_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_VI1_PERFMON_DT = TEGRA_SOC_HWPM_FIRST_PERFMON_DT + 1,
|
||||
TEGRA_SOC_HWPM_ISP0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_VICA0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_OFAA0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PVAV0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PVAV1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PVAC0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_NVDLAB0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_NVDLAB1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_NVDISPLAY0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_SYS0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MGBE0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MGBE1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MGBE2_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MGBE3_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_SCF0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_NVDECA0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_NVENCA0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSNVLHSH0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE2_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE3_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE4_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE5_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE6_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE7_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE8_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE9_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_PCIE10_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTA0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTA1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTA2_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTA3_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTB0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTB1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTB2_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTB3_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTC0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTC1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTC2_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTC3_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTD0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTD1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTD2_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSCHANNELPARTD3_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSHUB0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSHUB1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSMCFCLIENT0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSMCFMEM0_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_MSSMCFMEM1_PERFMON_DT,
|
||||
TEGRA_SOC_HWPM_LAST_PERFMON_DT = TEGRA_SOC_HWPM_MSSMCFMEM1_PERFMON_DT,
|
||||
|
||||
/* PMA */
|
||||
TEGRA_SOC_HWPM_PMA_DT = TEGRA_SOC_HWPM_LAST_PERFMON_DT + 1,
|
||||
|
||||
/* RTR */
|
||||
TEGRA_SOC_HWPM_RTR_DT,
|
||||
|
||||
TEGRA_SOC_HWPM_NUM_DT_APERTURES
|
||||
};
|
||||
#define IS_PERFMON(idx) (((idx) >= TEGRA_SOC_HWPM_FIRST_PERFMON_DT) && \
|
||||
((idx) <= TEGRA_SOC_HWPM_LAST_PERFMON_DT))
|
||||
|
||||
/* RPG_PM Aperture */
|
||||
#define PERFMON_BASE(ip_idx) (addr_map_rpg_pm_base_r() + \
|
||||
((u32)(ip_idx)) * pmmsys_perdomain_offset_v())
|
||||
#define PERFMON_LIMIT(ip_idx) (PERFMON_BASE((ip_idx) + 1) - 1)
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_HW_H */
|
||||
1896
tegra-soc-hwpm-io.c
1896
tegra-soc-hwpm-io.c
File diff suppressed because it is too large
Load Diff
@@ -20,77 +20,19 @@
|
||||
#ifndef TEGRA_SOC_HWPM_IO_H
|
||||
#define TEGRA_SOC_HWPM_IO_H
|
||||
|
||||
#include "tegra-soc-hwpm.h"
|
||||
struct tegra_soc_hwpm;
|
||||
struct hwpm_resource_aperture;
|
||||
|
||||
struct allowlist;
|
||||
|
||||
struct hwpm_resource_aperture {
|
||||
/*
|
||||
* If false, this is a HWPM aperture (PERFRMON, PMA or RTR). Else this
|
||||
* is a non-HWPM aperture (ex: VIC).
|
||||
*/
|
||||
bool is_ip;
|
||||
|
||||
/*
|
||||
* If is_ip == false, specify dt_aperture for readl/writel operations.
|
||||
* If is_ip == true, dt_aperture == TEGRA_SOC_HWPM_INVALID_DT.
|
||||
*/
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture;
|
||||
|
||||
/* Physical aperture */
|
||||
u64 start_abs_pa;
|
||||
u64 end_abs_pa;
|
||||
u64 start_pa;
|
||||
u64 end_pa;
|
||||
|
||||
/* Allowlist */
|
||||
struct allowlist *alist;
|
||||
u64 alist_size;
|
||||
|
||||
/*
|
||||
* Currently, perfmons and perfmuxes for all instances of an IP
|
||||
* are listed in a single aperture mask. It is possible that
|
||||
* some instances are disable. In this case, accessing corresponding
|
||||
* registers will result in kernel panic.
|
||||
* Bit set in the index_mask value will indicate the instance index
|
||||
* within that IP (or resource).
|
||||
*/
|
||||
u32 index_mask;
|
||||
|
||||
/* Fake registers for VDK which doesn't have a SOC HWPM fmodel */
|
||||
u32 *fake_registers;
|
||||
};
|
||||
|
||||
struct hwpm_resource {
|
||||
bool reserved;
|
||||
u32 map_size;
|
||||
struct hwpm_resource_aperture *map;
|
||||
};
|
||||
|
||||
/* Externs */
|
||||
extern struct hwpm_resource hwpm_resources[TERGA_SOC_HWPM_NUM_RESOURCES];
|
||||
extern u32 *mc_fake_regs[16];
|
||||
extern struct hwpm_resource_aperture t234_mss_channel_map[];
|
||||
extern struct hwpm_resource_aperture t234_mss_gpu_hub_map[];
|
||||
extern struct hwpm_resource_aperture t234_mss_iso_niso_hub_map[];
|
||||
extern struct hwpm_resource_aperture t234_mss_mcf_map[];
|
||||
extern struct hwpm_resource_aperture t234_pma_map[];
|
||||
extern struct hwpm_resource_aperture t234_cmd_slice_rtr_map[];
|
||||
|
||||
void tegra_soc_hwpm_zero_alist_regs(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture);
|
||||
int tegra_soc_hwpm_update_allowlist(struct tegra_soc_hwpm *hwpm,
|
||||
void *ioctl_struct);
|
||||
struct hwpm_resource_aperture *find_hwpm_aperture(struct tegra_soc_hwpm *hwpm,
|
||||
u64 phys_addr,
|
||||
bool use_absolute_base,
|
||||
bool check_reservation,
|
||||
u64 *updated_pa);
|
||||
u32 hwpm_readl(struct tegra_soc_hwpm *hwpm,
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture,
|
||||
u32 dt_aperture,
|
||||
u32 reg_offset);
|
||||
void hwpm_writel(struct tegra_soc_hwpm *hwpm,
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture,
|
||||
u32 dt_aperture,
|
||||
u32 reg_offset, u32 val);
|
||||
u32 ip_readl(struct tegra_soc_hwpm *hwpm, u64 phys_addr);
|
||||
void ip_writel(struct tegra_soc_hwpm *hwpm, u64 phys_addr, u32 val);
|
||||
@@ -103,7 +45,7 @@ void ioctl_writel(struct tegra_soc_hwpm *hwpm,
|
||||
u32 val);
|
||||
int reg_rmw(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture,
|
||||
u32 dt_aperture,
|
||||
u64 addr,
|
||||
u32 field_mask,
|
||||
u32 field_val,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,34 +17,18 @@
|
||||
* This file contains functions for SOC HWPM <-> IPC communication.
|
||||
*/
|
||||
|
||||
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
#include <hal/tegra_soc_hwpm_init.h>
|
||||
#include "tegra-soc-hwpm-log.h"
|
||||
#include "tegra-soc-hwpm.h"
|
||||
|
||||
struct platform_device *tegra_soc_hwpm_pdev;
|
||||
|
||||
static enum tegra_soc_hwpm_dt_aperture tegra_soc_hwpm_get_apeture(
|
||||
struct tegra_soc_hwpm *hwpm, u64 ip_base_address)
|
||||
{
|
||||
enum tegra_soc_hwpm_dt_aperture aperture =
|
||||
TEGRA_SOC_HWPM_NUM_DT_APERTURES;
|
||||
|
||||
/* TODO chip speciifc implementation for finding aperture */
|
||||
if (ip_base_address == addr_map_vic_base_r()) {
|
||||
aperture = TEGRA_SOC_HWPM_VICA0_PERFMON_DT;
|
||||
} else if (ip_base_address == addr_map_nvenc_base_r()) {
|
||||
aperture = TEGRA_SOC_HWPM_NVENCA0_PERFMON_DT;
|
||||
} else if (ip_base_address == addr_map_ofa_base_r()) {
|
||||
aperture = TEGRA_SOC_HWPM_OFAA0_PERFMON_DT;
|
||||
}
|
||||
|
||||
return aperture;
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_ip_register(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
|
||||
{
|
||||
struct tegra_soc_hwpm *hwpm = NULL;
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture;
|
||||
u32 dt_aperture;
|
||||
|
||||
tegra_soc_hwpm_dbg("HWPM Registered IP 0x%llx",
|
||||
hwpm_ip_ops->ip_base_address);
|
||||
@@ -59,9 +43,9 @@ void tegra_soc_hwpm_ip_register(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
|
||||
return;
|
||||
}
|
||||
hwpm = platform_get_drvdata(tegra_soc_hwpm_pdev);
|
||||
dt_aperture = tegra_soc_hwpm_get_apeture(hwpm,
|
||||
hwpm_ip_ops->ip_base_address);
|
||||
if (dt_aperture != TEGRA_SOC_HWPM_NUM_DT_APERTURES) {
|
||||
dt_aperture = tegra_soc_hwpm_get_ip_aperture(hwpm,
|
||||
hwpm_ip_ops->ip_base_address, NULL);
|
||||
if (dt_aperture != TEGRA_SOC_HWPM_DT_APERTURE_INVALID) {
|
||||
memcpy(&hwpm->ip_info[dt_aperture], hwpm_ip_ops,
|
||||
sizeof(struct tegra_soc_hwpm_ip_ops));
|
||||
} else {
|
||||
@@ -76,7 +60,7 @@ void tegra_soc_hwpm_ip_register(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
|
||||
void tegra_soc_hwpm_ip_unregister(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
|
||||
{
|
||||
struct tegra_soc_hwpm *hwpm = NULL;
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture;
|
||||
u32 dt_aperture;
|
||||
|
||||
if (tegra_soc_hwpm_pdev == NULL) {
|
||||
tegra_soc_hwpm_dbg("IP unregister before SOC HWPM 0x%llx",
|
||||
@@ -87,9 +71,9 @@ void tegra_soc_hwpm_ip_unregister(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
|
||||
return;
|
||||
}
|
||||
hwpm = platform_get_drvdata(tegra_soc_hwpm_pdev);
|
||||
dt_aperture = tegra_soc_hwpm_get_apeture(hwpm,
|
||||
hwpm_ip_ops->ip_base_address);
|
||||
if (dt_aperture != TEGRA_SOC_HWPM_NUM_DT_APERTURES) {
|
||||
dt_aperture = tegra_soc_hwpm_get_ip_aperture(hwpm,
|
||||
hwpm_ip_ops->ip_base_address, NULL);
|
||||
if (dt_aperture != TEGRA_SOC_HWPM_DT_APERTURE_INVALID) {
|
||||
memset(&hwpm->ip_info[dt_aperture], 0,
|
||||
sizeof(struct tegra_soc_hwpm_ip_ops));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "tegra-soc-hwpm.h"
|
||||
#include "tegra-soc-hwpm-log.h"
|
||||
|
||||
#define LOG_BUF_SIZE 160
|
||||
|
||||
|
||||
@@ -22,10 +22,17 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
#include "tegra-soc-hwpm.h"
|
||||
#include "tegra-soc-hwpm-log.h"
|
||||
#include <hal/tegra_soc_hwpm_init.h>
|
||||
#include <hal/tegra-soc-hwpm-structures.h>
|
||||
|
||||
static const struct of_device_id tegra_soc_hwpm_of_match[] = {
|
||||
{
|
||||
@@ -125,6 +132,8 @@ static int tegra_soc_hwpm_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
tegra_soc_hwpm_debugfs_init(hwpm);
|
||||
hwpm->dt_apertures = tegra_soc_hwpm_init_dt_apertures();
|
||||
hwpm->ip_info = tegra_soc_hwpm_init_ip_ops_info();
|
||||
|
||||
/*
|
||||
* Currently VDK doesn't have a fmodel for SOC HWPM. Therefore, we
|
||||
|
||||
@@ -20,84 +20,15 @@
|
||||
#ifndef TEGRA_SOC_HWPM_H
|
||||
#define TEGRA_SOC_HWPM_H
|
||||
|
||||
#include <linux/reset.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/delay.h>
|
||||
//
|
||||
//
|
||||
// #include <linux/scatterlist.h>
|
||||
//
|
||||
|
||||
#include "tegra-soc-hwpm-log.h"
|
||||
#include "tegra-soc-hwpm-hw.h"
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
||||
// #include "tegra-soc-hwpm-log.h"
|
||||
//
|
||||
|
||||
/* FIXME: Default timeout is 1 sec. Is this sufficient for pre-si? */
|
||||
#define HWPM_TIMEOUT(timeout_check, expiry_msg) ({ \
|
||||
bool timeout_expired = false; \
|
||||
s32 timeout_msecs = 1000; \
|
||||
u32 sleep_msecs = 100; \
|
||||
while(!(timeout_check)) { \
|
||||
msleep(sleep_msecs); \
|
||||
timeout_msecs -= sleep_msecs; \
|
||||
if (timeout_msecs <= 0) { \
|
||||
tegra_soc_hwpm_err("Timeout expired for %s!", \
|
||||
expiry_msg); \
|
||||
timeout_expired = true; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
timeout_expired; \
|
||||
})
|
||||
|
||||
/* Driver struct */
|
||||
struct tegra_soc_hwpm {
|
||||
/* Device */
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
struct class class;
|
||||
dev_t dev_t;
|
||||
struct cdev cdev;
|
||||
|
||||
/* IP floorsweep info */
|
||||
u64 ip_fs_info[TERGA_SOC_HWPM_NUM_IPS];
|
||||
|
||||
/* MMIO apertures in device tree */
|
||||
void __iomem *dt_apertures[TEGRA_SOC_HWPM_NUM_DT_APERTURES];
|
||||
|
||||
/* Clocks and resets */
|
||||
struct clk *la_clk;
|
||||
struct clk *la_parent_clk;
|
||||
struct reset_control *la_rst;
|
||||
struct reset_control *hwpm_rst;
|
||||
|
||||
struct tegra_soc_hwpm_ip_ops ip_info[TEGRA_SOC_HWPM_NUM_DT_APERTURES];
|
||||
|
||||
/* Memory Management */
|
||||
struct dma_buf *stream_dma_buf;
|
||||
struct dma_buf_attachment *stream_attach;
|
||||
struct sg_table *stream_sgt;
|
||||
struct dma_buf *mem_bytes_dma_buf;
|
||||
struct dma_buf_attachment *mem_bytes_attach;
|
||||
struct sg_table *mem_bytes_sgt;
|
||||
void *mem_bytes_kernel;
|
||||
|
||||
/* SW State */
|
||||
bool bind_completed;
|
||||
s32 full_alist_size;
|
||||
|
||||
/* Debugging */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
bool fake_registers_enabled;
|
||||
};
|
||||
|
||||
extern struct platform_device *tegra_soc_hwpm_pdev;
|
||||
extern const struct file_operations tegra_soc_hwpm_ops;
|
||||
struct tegra_soc_hwpm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void tegra_soc_hwpm_debugfs_init(struct tegra_soc_hwpm *hwpm);
|
||||
|
||||
Reference in New Issue
Block a user