mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-22 09:12:05 +03:00
tegra: hwpm: add SOC HWPM driver
Add a driver for programming the Tegra SOC HWPM path. SOC HWPM allows performance monitoring of various Tegra IPs. The profiling tests cases are configured through IOCTLs sent by a userspace profiling app. The IOCTLs provide the following features: - IP discovery and reservation - Buffer management - Whitelist query - Register read/write ops Bug 200702306 Bug 3305495 Change-Id: I65003b126e01bd03d856767c55aa2424bcfd11fb Signed-off-by: Adeel Raza <araza@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-t23x/+/2515148 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
11
Makefile
Normal file
11
Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Tegra SOC HWPM
|
||||
#
|
||||
|
||||
GCOV_PROFILE := y
|
||||
|
||||
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-$(CONFIG_DEBUG_FS) += tegra-soc-hwpm-debugfs.o
|
||||
52
tegra-soc-hwpm-debugfs.c
Normal file
52
tegra-soc-hwpm-debugfs.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* tegra-soc-hwpm-debugfs.c:
|
||||
* This file adds debugfs nodes for the Tegra SOC HWPM driver.
|
||||
*
|
||||
* 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"
|
||||
|
||||
/* FIXME: This is a placeholder for now. We can add debugfs nodes as needed. */
|
||||
void tegra_soc_hwpm_debugfs_init(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
if (!hwpm) {
|
||||
tegra_soc_hwpm_err("Invalid hwpm struct");
|
||||
return;
|
||||
}
|
||||
|
||||
hwpm->debugfs_root = debugfs_create_dir(TEGRA_SOC_HWPM_MODULE_NAME, NULL);
|
||||
if (!hwpm->debugfs_root) {
|
||||
tegra_soc_hwpm_err("Failed to create debugfs root directory");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
debugfs_remove_recursive(hwpm->debugfs_root);
|
||||
hwpm->debugfs_root = NULL;
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_debugfs_deinit(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
if (!hwpm) {
|
||||
tegra_soc_hwpm_err("Invalid hwpm struct");
|
||||
return;
|
||||
}
|
||||
|
||||
debugfs_remove_recursive(hwpm->debugfs_root);
|
||||
hwpm->debugfs_root = NULL;
|
||||
}
|
||||
377
tegra-soc-hwpm-hw.h
Normal file
377
tegra-soc-hwpm-hw.h
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* tegra-soc-hwpm-hw.h:
|
||||
* This header contains HW aperture and register info for the Tegra SOC HWPM
|
||||
* driver.
|
||||
*
|
||||
* 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_HW_H
|
||||
#define TEGRA_SOC_HWPM_HW_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* FIXME: Move enum to DT include file? */
|
||||
enum tegra_soc_hwpm_dt_aperture {
|
||||
TEGRA_SOC_HWPM_INVALID_DT = -1,
|
||||
|
||||
/* PERFMONs */
|
||||
TEGRA_SOC_HWPM_VI0_PERFMON_DT = 0,
|
||||
TEGRA_SOC_HWPM_FIRST_PERFMON_DT = TEGRA_SOC_HWPM_VI0_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 */
|
||||
/* FIXME: Use __SIZE_1 for handling per PERFMON registers? */
|
||||
#define NV_ADDRESS_MAP_RPG_PM_BASE 0x0f100000
|
||||
#define NV_ADDRESS_MAP_RPG_PM_LIMIT 0x0f149fff
|
||||
#define NV_PERF_PMMSYS_PERDOMAIN_OFFSET 0x1000
|
||||
#define PERFMON_BASE(ip_idx) (NV_ADDRESS_MAP_RPG_PM_BASE + \
|
||||
((u32)(ip_idx)) * NV_PERF_PMMSYS_PERDOMAIN_OFFSET)
|
||||
#define PERFMON_LIMIT(ip_idx) (PERFMON_BASE((ip_idx) + 1) - 1)
|
||||
#define NV_PERF_PMMSYS_CONTROL 0x9C
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_SHIFT 0
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_MASK 0x00000007
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_DISABLE 0x00000000
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_A 0x00000001
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_B 0x00000002
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_C 0x00000003
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_E 0x00000005
|
||||
#define NV_PERF_PMMSYS_CONTROL_MODE_NULL 0x00000007
|
||||
#define NV_PERF_PMMSYS_SYS0_ENGINESTATUS 0xC8
|
||||
#define NV_PERF_PMMSYS_SYS0_ENGINESTATUS_ENABLE_SHIFT 8
|
||||
#define NV_PERF_PMMSYS_SYS0_ENGINESTATUS_ENABLE_MASK 0x00000100
|
||||
#define NV_PERF_PMMSYS_SYS0_ENGINESTATUS_ENABLE_MASKED 0x0
|
||||
#define NV_PERF_PMMSYS_SYS0_ENGINESTATUS_ENABLE_OUT 0x1
|
||||
|
||||
/* PMA Aperture */
|
||||
/* FIXME: Add __SIZE_1 logic for channels? */
|
||||
#define NV_ADDRESS_MAP_PMA_BASE 0x0f14a000
|
||||
#define NV_ADDRESS_MAP_PMA_LIMIT 0x0f14bfff
|
||||
#define NV_PERF_PMASYS_CG2 0x44
|
||||
#define NV_PERF_PMASYS_CG2_SLCG_SHIFT 0
|
||||
/* FIXME: Use standard format for masks */
|
||||
#define NV_PERF_PMASYS_CG2_SLCG_MASK 0x1
|
||||
#define NV_PERF_PMASYS_CG2_SLCG_ENABLED 0x00000000
|
||||
#define NV_PERF_PMASYS_CG2_SLCG_DISABLED 0x00000001
|
||||
#define NV_PERF_PMASYS_CONTROLB 0x70
|
||||
#define NV_PERF_PMASYS_CONTROLB_COALESCE_TIMEOUT_CYCLES_SHIFT 4
|
||||
#define NV_PERF_PMASYS_CONTROLB_COALESCE_TIMEOUT_CYCLES_MASK 0x00000070
|
||||
#define NV_PERF_PMASYS_CONTROLB_COALESCE_TIMEOUT_CYCLES__PROD 0x00000004
|
||||
#define NV_PERF_PMASYS_CHANNEL_STATUS_SECURE(i) (0x610+(i)*0x180)
|
||||
#define NV_PERF_PMASYS_CHANNEL_STATUS_SECURE_CH0 NV_PERF_PMASYS_CHANNEL_STATUS_SECURE(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_STATUS_SECURE_MEMBUF_STATUS_SHIFT 0
|
||||
#define NV_PERF_PMASYS_CHANNEL_STATUS_SECURE_MEMBUF_STATUS_MASK 0x00000001
|
||||
#define NV_PERF_PMASYS_CHANNEL_STATUS_SECURE_MEMBUF_STATUS_INIT 0x00000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_STATUS_SECURE_MEMBUF_STATUS_OVERFLOWED 0x00000001
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER(i) (0x620+(i)*0x180)
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_CH0 NV_PERF_PMASYS_CHANNEL_CONTROL_USER(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_STREAM_SHIFT 0
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_STREAM_MASK 0x00000001
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_STREAM_DISABLE 0x00000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_STREAM_ENABLE 0x00000001
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_UPDATE_BYTES_SHIFT 31
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_UPDATE_BYTES_MASK 0x80000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONTROL_USER_UPDATE_BYTES_DOIT 0x00000001
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BUMP(i) (0x624+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BUMP_CH0 NV_PERF_PMASYS_CHANNEL_MEM_BUMP(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK(i) (0x638+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_CH0 NV_PERF_PMASYS_CHANNEL_MEM_BLOCK(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_PTR_SHIFT 0
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_PTR_MASK 0x3fffffff
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_BASE_SHIFT 0
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_BASE_MASK 0xfffffff
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_TARGET_SHIFT 28
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_TARGET_MASK 0x30000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_TARGET_LFB 0x00000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_TARGET_SYS_COH 0x00000002
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_TARGET_SYS_NCOH 0x00000003
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_VALID_SHIFT 31
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_VALID_MASK 0x80000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_VALID_FALSE 0x00000000
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BLOCK_VALID_TRUE 0x00000001
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONFIG_USER(i) (0x640+(i)*0x180)
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONFIG_USER_CH0 NV_PERF_PMASYS_CHANNEL_CONFIG_USER(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONFIG_USER_COALESCE_TIMEOUT_CYCLES_SHIFT 4
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONFIG_USER_COALESCE_TIMEOUT_CYCLES_MASK 0x00000070
|
||||
#define NV_PERF_PMASYS_CHANNEL_CONFIG_USER_COALESCE_TIMEOUT_CYCLES__PROD 0x00000004
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASE(i) (0x644+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASE_CH0 NV_PERF_PMASYS_CHANNEL_OUTBASE(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASE_PTR_SHIFT 5
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASE_PTR_MASK 0xffffffe0
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASEUPPER(i) (0x648+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASEUPPER_CH0 NV_PERF_PMASYS_CHANNEL_OUTBASEUPPER(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASEUPPER_PTR_SHIFT 0
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTBASEUPPER_PTR_MASK 0x000000ff
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTSIZE(i) (0x64C+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTSIZE_CH0 NV_PERF_PMASYS_CHANNEL_OUTSIZE(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTSIZE_NUMBYTES_SHIFT 5
|
||||
#define NV_PERF_PMASYS_CHANNEL_OUTSIZE_NUMBYTES_MASK 0xffffffe0
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_HEAD(i) (0x650+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_HEAD_CH0 NV_PERF_PMASYS_CHANNEL_MEM_HEAD(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BYTES_ADDR(i) (0x658+(i)*4)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BYTES_ADDR_CH0 NV_PERF_PMASYS_CHANNEL_MEM_BYTES_ADDR(0)
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BYTES_ADDR_PTR_SHIFT 2
|
||||
#define NV_PERF_PMASYS_CHANNEL_MEM_BYTES_ADDR_PTR_MASK 0xfffffffc
|
||||
#define NV_PERF_PMASYS_SYS_TRIGGER_START_MASK 0x66C
|
||||
#define NV_PERF_PMASYS_SYS_TRIGGER_START_MASKB 0x670
|
||||
#define NV_PERF_PMASYS_SYS_TRIGGER_STOP_MASK 0x684
|
||||
#define NV_PERF_PMASYS_SYS_TRIGGER_STOP_MASKB 0x688
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER(i) (0x694+(i)*0x180)
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_CH0 NV_PERF_PMASYS_TRIGGER_CONFIG_USER(0)
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_PMA_PULSE_SHIFT 0
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_PMA_PULSE_MASK 0x00000001
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_PMA_PULSE_DISABLE 0x00000000
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_PMA_PULSE_ENABLE 0x00000001
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_RECORD_STREAM_SHIFT 6
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_RECORD_STREAM_MASK 0x00000040
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_RECORD_STREAM_DISABLE 0x00000000
|
||||
#define NV_PERF_PMASYS_TRIGGER_CONFIG_USER_RECORD_STREAM_ENABLE 0x00000001
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS 0x75C
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_SHIFT 0
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_MASK 0x00000007
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_EMPTY 0x00000000
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_ACTIVE 0x00000001
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_PAUSED 0x00000002
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_QUIESCENT 0x00000003
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_STALLED 0x00000005
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_FAULTED 0x00000006
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_STATUS_HALTED 0x00000007
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_SHIFT 4
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_MASK 0x00000010
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_EMPTY 0x00000001
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_MBU_STATUS_SHIFT 5
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_MBU_STATUS_MASK 0x00000060
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_MBU_STATUS_IDLE 0x00000000
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_MBU_STATUS_BUSY 0x00000001
|
||||
#define NV_PERF_PMASYS_ENGINESTATUS_MBU_STATUS_PENDING 0x00000002
|
||||
|
||||
/* RTR Aperture */
|
||||
#define NV_ADDRESS_MAP_RTR_BASE 0x0f14d000
|
||||
#define NV_ADDRESS_MAP_RTR_LIMIT 0x0f14dfff
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS 0x10
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_SHIFT 0
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_MASK 0x00000007
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_EMPTY 0x00000000
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_ACTIVE 0x00000001
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_PAUSED 0x00000002
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_QUIESCENT 0x00000003
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_STALLED 0x00000005
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_FAULTED 0x00000006
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_HALTED 0x00000007
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_ENABLE_SHIFT 8
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_ENABLE_MASK 0x00000100
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_ENABLE_MASKED 0x0
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_ENABLE_OUT 0x1
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_PERFMONSTATUS 0x14
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_PERFMONSTATUS_MERGED_SHIFT 0
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_PERFMONSTATUS_MERGED_MASK 0x00000007
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_PERFMONSTATUS_MERGED_EMPTY 0x00000000
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_CG2 0x18
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_CG2_SLCG_SHIFT 0
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_CG2_SLCG_MASK 0x3
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_CG2_SLCG_ENABLED 0x00000000
|
||||
#define NV_PERF_PMMSYS_SYS0ROUTER_CG2_SLCG_DISABLED 0x00000003
|
||||
|
||||
/* Display Aperture */
|
||||
#define NV_ADDRESS_MAP_DISP_BASE 0x13800000
|
||||
#define NV_ADDRESS_MAP_DISP_LIMIT 0x138effff
|
||||
|
||||
/* VI Apertures */
|
||||
#define NV_ADDRESS_MAP_VI_THI_BASE 0x15f00000
|
||||
#define NV_ADDRESS_MAP_VI_THI_LIMIT 0x15ffffff
|
||||
#define NV_ADDRESS_MAP_VI2_THI_BASE 0x14f00000
|
||||
#define NV_ADDRESS_MAP_VI2_THI_LIMIT 0x14ffffff
|
||||
|
||||
/* VIC Aperture */
|
||||
#define NV_ADDRESS_MAP_VIC_BASE 0x15340000
|
||||
#define NV_ADDRESS_MAP_VIC_LIMIT 0x1537ffff
|
||||
|
||||
/* NVDEC Aperture */
|
||||
#define NV_ADDRESS_MAP_NVDEC_BASE 0x15480000
|
||||
#define NV_ADDRESS_MAP_NVDEC_LIMIT 0x154bffff
|
||||
|
||||
/* NVENC Aperture */
|
||||
#define NV_ADDRESS_MAP_NVENC_BASE 0x154c0000
|
||||
#define NV_ADDRESS_MAP_NVENC_LIMIT 0x154fffff
|
||||
|
||||
/* OFA Aperture */
|
||||
#define NV_ADDRESS_MAP_OFA_BASE 0x15a50000
|
||||
#define NV_ADDRESS_MAP_OFA_LIMIT 0x15a5ffff
|
||||
|
||||
/* ISP Aperture */
|
||||
#define NV_ADDRESS_MAP_ISP_THI_BASE 0x14b00000
|
||||
#define NV_ADDRESS_MAP_ISP_THI_LIMIT 0x14bfffff
|
||||
|
||||
/* PCIE Apertures */
|
||||
#define NV_ADDRESS_MAP_PCIE_C0_CTL_BASE 0x14180000
|
||||
#define NV_ADDRESS_MAP_PCIE_C0_CTL_LIMIT 0x1419ffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C1_CTL_BASE 0x14100000
|
||||
#define NV_ADDRESS_MAP_PCIE_C1_CTL_LIMIT 0x1411ffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C2_CTL_BASE 0x14120000
|
||||
#define NV_ADDRESS_MAP_PCIE_C2_CTL_LIMIT 0x1413ffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C3_CTL_BASE 0x14140000
|
||||
#define NV_ADDRESS_MAP_PCIE_C3_CTL_LIMIT 0x1415ffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C4_CTL_BASE 0x14160000
|
||||
#define NV_ADDRESS_MAP_PCIE_C4_CTL_LIMIT 0x1417ffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C5_CTL_BASE 0x141a0000
|
||||
#define NV_ADDRESS_MAP_PCIE_C5_CTL_LIMIT 0x141bffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C6_CTL_BASE 0x141c0000
|
||||
#define NV_ADDRESS_MAP_PCIE_C6_CTL_LIMIT 0x141dffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C7_CTL_BASE 0x141e0000
|
||||
#define NV_ADDRESS_MAP_PCIE_C7_CTL_LIMIT 0x141fffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C8_CTL_BASE 0x140a0000
|
||||
#define NV_ADDRESS_MAP_PCIE_C8_CTL_LIMIT 0x140bffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C9_CTL_BASE 0x140c0000
|
||||
#define NV_ADDRESS_MAP_PCIE_C9_CTL_LIMIT 0x140dffff
|
||||
#define NV_ADDRESS_MAP_PCIE_C10_CTL_BASE 0x140e0000
|
||||
#define NV_ADDRESS_MAP_PCIE_C10_CTL_LIMIT 0x140fffff
|
||||
|
||||
/* PVA Aperture */
|
||||
#define NV_ADDRESS_MAP_PVA0_PM_BASE 0x16200000
|
||||
#define NV_ADDRESS_MAP_PVA0_PM_LIMIT 0x1620ffff
|
||||
|
||||
/* NVDLA Apertures */
|
||||
#define NV_ADDRESS_MAP_NVDLA0_BASE 0x15880000
|
||||
#define NV_ADDRESS_MAP_NVDLA0_LIMIT 0x158bffff
|
||||
#define NV_ADDRESS_MAP_NVDLA1_BASE 0x158c0000
|
||||
#define NV_ADDRESS_MAP_NVDLA1_LIMIT 0x158fffff
|
||||
|
||||
/* MGBE Apertures */
|
||||
#define NV_ADDRESS_MAP_MGBE0_BASE 0x06800000
|
||||
#define NV_ADDRESS_MAP_MGBE0_LIMIT 0x068fffff
|
||||
#define NV_ADDRESS_MAP_MGBE1_BASE 0x06900000
|
||||
#define NV_ADDRESS_MAP_MGBE1_LIMIT 0x069fffff
|
||||
#define NV_ADDRESS_MAP_MGBE2_BASE 0x06a00000
|
||||
#define NV_ADDRESS_MAP_MGBE2_LIMIT 0x06afffff
|
||||
#define NV_ADDRESS_MAP_MGBE3_BASE 0x06b00000
|
||||
#define NV_ADDRESS_MAP_MGBE3_LIMIT 0x06bfffff
|
||||
|
||||
/* MC Apertures */
|
||||
#define NV_ADDRESS_MAP_MCB_BASE 0x02c10000
|
||||
#define NV_ADDRESS_MAP_MCB_LIMIT 0x02c1ffff
|
||||
#define NV_ADDRESS_MAP_MC0_BASE 0x02c20000
|
||||
#define NV_ADDRESS_MAP_MC0_LIMIT 0x02c2ffff
|
||||
#define NV_ADDRESS_MAP_MC1_BASE 0x02c30000
|
||||
#define NV_ADDRESS_MAP_MC1_LIMIT 0x02c3ffff
|
||||
#define NV_ADDRESS_MAP_MC2_BASE 0x02c40000
|
||||
#define NV_ADDRESS_MAP_MC2_LIMIT 0x02c4ffff
|
||||
#define NV_ADDRESS_MAP_MC3_BASE 0x02c50000
|
||||
#define NV_ADDRESS_MAP_MC3_LIMIT 0x02c5ffff
|
||||
#define NV_ADDRESS_MAP_MC4_BASE 0x02b80000
|
||||
#define NV_ADDRESS_MAP_MC4_LIMIT 0x02b8ffff
|
||||
#define NV_ADDRESS_MAP_MC5_BASE 0x02b90000
|
||||
#define NV_ADDRESS_MAP_MC5_LIMIT 0x02b9ffff
|
||||
#define NV_ADDRESS_MAP_MC6_BASE 0x02ba0000
|
||||
#define NV_ADDRESS_MAP_MC6_LIMIT 0x02baffff
|
||||
#define NV_ADDRESS_MAP_MC7_BASE 0x02bb0000
|
||||
#define NV_ADDRESS_MAP_MC7_LIMIT 0x02bbffff
|
||||
#define NV_ADDRESS_MAP_MC8_BASE 0x01700000
|
||||
#define NV_ADDRESS_MAP_MC8_LIMIT 0x0170ffff
|
||||
#define NV_ADDRESS_MAP_MC9_BASE 0x01710000
|
||||
#define NV_ADDRESS_MAP_MC9_LIMIT 0x0171ffff
|
||||
#define NV_ADDRESS_MAP_MC10_BASE 0x01720000
|
||||
#define NV_ADDRESS_MAP_MC10_LIMIT 0x0172ffff
|
||||
#define NV_ADDRESS_MAP_MC11_BASE 0x01730000
|
||||
#define NV_ADDRESS_MAP_MC11_LIMIT 0x0173ffff
|
||||
#define NV_ADDRESS_MAP_MC12_BASE 0x01740000
|
||||
#define NV_ADDRESS_MAP_MC12_LIMIT 0x0174ffff
|
||||
#define NV_ADDRESS_MAP_MC13_BASE 0x01750000
|
||||
#define NV_ADDRESS_MAP_MC13_LIMIT 0x0175ffff
|
||||
#define NV_ADDRESS_MAP_MC14_BASE 0x01760000
|
||||
#define NV_ADDRESS_MAP_MC14_LIMIT 0x0176ffff
|
||||
#define NV_ADDRESS_MAP_MC15_BASE 0x01770000
|
||||
#define NV_ADDRESS_MAP_MC15_LIMIT 0x0177ffff
|
||||
|
||||
/* MSSNVLINK Apertures */
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_1_BASE 0x01f20000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_1_LIMIT 0x01f3ffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_2_BASE 0x01f40000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_2_LIMIT 0x01f5ffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_3_BASE 0x01f60000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_3_LIMIT 0x01f7ffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_4_BASE 0x01f80000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_4_LIMIT 0x01f9ffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_5_BASE 0x01fa0000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_5_LIMIT 0x01fbffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_6_BASE 0x01fc0000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_6_LIMIT 0x01fdffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_7_BASE 0x01fe0000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_7_LIMIT 0x01ffffff
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_8_BASE 0x01e00000
|
||||
#define NV_ADDRESS_MAP_MSS_NVLINK_8_LIMIT 0x01e1ffff
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_HW_H */
|
||||
1950
tegra-soc-hwpm-io.c
Normal file
1950
tegra-soc-hwpm-io.c
Normal file
File diff suppressed because it is too large
Load Diff
136
tegra-soc-hwpm-io.h
Normal file
136
tegra-soc-hwpm-io.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* tegra-soc-hwpm-io.h:
|
||||
* This header defines register read/write APIs for the Tegra SOC HWPM driver.
|
||||
*
|
||||
* 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_IO_H
|
||||
#define TEGRA_SOC_HWPM_IO_H
|
||||
|
||||
#include "tegra-soc-hwpm.h"
|
||||
|
||||
/* Mask and shift field_val so it can be written to a register */
|
||||
#define HWPM_REG_F(field, field_val) \
|
||||
(((field_val) << field##_SHIFT) & field##_MASK)
|
||||
|
||||
/* Extract a field's value from a register */
|
||||
#define HWPM_REG_V(field, reg_val) \
|
||||
(((reg_val) & field##_MASK) >> field##_SHIFT)
|
||||
|
||||
/*
|
||||
* Check if field_val is set in reg_val. field_val is already masked and
|
||||
* shifted to the correct location.
|
||||
*/
|
||||
#define HWPM_REG_CHECK(reg_val, field_mask, field_val) \
|
||||
(((reg_val) & (field_mask)) == ((field_val) & (field_mask)))
|
||||
|
||||
/* Mask and shift field_val. Then check if field_val is set in reg_val. */
|
||||
#define HWPM_REG_CHECK_F(reg_val, field, field_val) \
|
||||
(((reg_val) & field##_MASK) == HWPM_REG_F(field, (field_val)))
|
||||
|
||||
struct whitelist {
|
||||
u64 reg;
|
||||
bool zero_in_init;
|
||||
};
|
||||
|
||||
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_pa;
|
||||
u64 end_pa;
|
||||
|
||||
/* Whitelist */
|
||||
struct whitelist *wlist;
|
||||
u64 wlist_size;
|
||||
|
||||
/* 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 *pma_fake_regs;
|
||||
extern u32 *mc_fake_regs[16];
|
||||
extern struct hwpm_resource_aperture mss_channel_map[];
|
||||
extern struct hwpm_resource_aperture mss_iso_niso_hub_map[];
|
||||
extern struct hwpm_resource_aperture mss_mcf_map[];
|
||||
extern struct hwpm_resource_aperture pma_map[];
|
||||
extern struct hwpm_resource_aperture cmd_slice_rtr_map[];
|
||||
|
||||
struct hwpm_resource_aperture *find_hwpm_aperture(struct tegra_soc_hwpm *hwpm,
|
||||
u64 phys_addr,
|
||||
bool check_reservation);
|
||||
u32 hwpm_readl(struct tegra_soc_hwpm *hwpm,
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture,
|
||||
u32 reg);
|
||||
void hwpm_writel(struct tegra_soc_hwpm *hwpm,
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture,
|
||||
u32 reg,
|
||||
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);
|
||||
u32 ioctl_readl(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
u64 addr);
|
||||
void ioctl_writel(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
u64 addr,
|
||||
u32 val);
|
||||
int reg_rmw(struct tegra_soc_hwpm *hwpm,
|
||||
struct hwpm_resource_aperture *aperture,
|
||||
enum tegra_soc_hwpm_dt_aperture dt_aperture,
|
||||
u64 addr,
|
||||
u32 field_mask,
|
||||
u32 field_val,
|
||||
bool is_ioctl,
|
||||
bool is_ip);
|
||||
#define DRIVER_REG_RMW(hwpm, dt_aperture, reg, field, field_val, is_ip) \
|
||||
reg_rmw(hwpm, \
|
||||
NULL, \
|
||||
dt_aperture, \
|
||||
reg, \
|
||||
field##_MASK, \
|
||||
HWPM_REG_F(field, field_val), \
|
||||
false, \
|
||||
is_ip)
|
||||
#define IOCTL_REG_RMW(hwpm, aperture, addr, field_mask, field_val) \
|
||||
reg_rmw(hwpm, \
|
||||
aperture, \
|
||||
aperture->dt_aperture, \
|
||||
addr, \
|
||||
field_mask, \
|
||||
field_val, \
|
||||
true, \
|
||||
aperture->is_ip)
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_IO_H */
|
||||
1679
tegra-soc-hwpm-ioctl.c
Normal file
1679
tegra-soc-hwpm-ioctl.c
Normal file
File diff suppressed because it is too large
Load Diff
53
tegra-soc-hwpm-log.c
Normal file
53
tegra-soc-hwpm-log.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* tegra-soc-hwpm-log.c:
|
||||
* This file adds logging APIs for the Tegra SOC HWPM driver.
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
|
||||
#include "tegra-soc-hwpm.h"
|
||||
|
||||
#define LOG_BUF_SIZE 160
|
||||
|
||||
static void tegra_soc_hwpm_print(const char *func,
|
||||
int line,
|
||||
int type,
|
||||
const char *log)
|
||||
{
|
||||
switch (type) {
|
||||
case tegra_soc_hwpm_log_err:
|
||||
pr_err(TEGRA_SOC_HWPM_MODULE_NAME ": %s: %d: ERROR: %s\n",
|
||||
func, line, log);
|
||||
break;
|
||||
case tegra_soc_hwpm_log_dbg:
|
||||
pr_info(TEGRA_SOC_HWPM_MODULE_NAME ": %s: %d: DEBUG: %s\n",
|
||||
func, line, log);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void tegra_soc_hwpm_log(const char *func, int line, int type, const char *fmt, ...)
|
||||
{
|
||||
char log[LOG_BUF_SIZE];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
(void) vsnprintf(log, LOG_BUF_SIZE, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
tegra_soc_hwpm_print(func, line, type, log);
|
||||
}
|
||||
39
tegra-soc-hwpm-log.h
Normal file
39
tegra-soc-hwpm-log.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* tegra-soc-hwpm-log.h:
|
||||
* This is the logging API header for the Tegra SOC HWPM driver.
|
||||
*
|
||||
* 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_LOG_H
|
||||
#define TEGRA_SOC_HWPM_LOG_H
|
||||
|
||||
#define TEGRA_SOC_HWPM_MODULE_NAME "tegra-soc-hwpm"
|
||||
|
||||
enum tegra_soc_hwpm_log_type {
|
||||
tegra_soc_hwpm_log_err, /* Error prints */
|
||||
tegra_soc_hwpm_log_dbg, /* Debug prints */
|
||||
};
|
||||
|
||||
#define tegra_soc_hwpm_err(fmt, arg...) \
|
||||
tegra_soc_hwpm_log(__func__, __LINE__, tegra_soc_hwpm_log_err, \
|
||||
fmt, ##arg)
|
||||
#define tegra_soc_hwpm_dbg(fmt, arg...) \
|
||||
tegra_soc_hwpm_log(__func__, __LINE__, tegra_soc_hwpm_log_dbg, \
|
||||
fmt, ##arg)
|
||||
|
||||
void tegra_soc_hwpm_log(const char *func, int line, int type, const char *fmt, ...);
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_LOG_H */
|
||||
230
tegra-soc-hwpm.c
Normal file
230
tegra-soc-hwpm.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* tegra-soc-hwpm.c:
|
||||
* This is Tegra's driver for programming the SOC HWPM path.
|
||||
*
|
||||
* 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 <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
#include "tegra-soc-hwpm.h"
|
||||
|
||||
static const struct of_device_id tegra_soc_hwpm_of_match[] = {
|
||||
{
|
||||
.compatible = "nvidia,t23x-soc-hwpm",
|
||||
}, {
|
||||
},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_soc_hwpm_of_match);
|
||||
|
||||
static int tegra_soc_hwpm_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = NULL;
|
||||
struct tegra_soc_hwpm *hwpm = NULL;
|
||||
|
||||
if (!pdev) {
|
||||
tegra_soc_hwpm_err("Invalid platform device");
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hwpm = kzalloc(sizeof(struct tegra_soc_hwpm), GFP_KERNEL);
|
||||
if (!hwpm) {
|
||||
tegra_soc_hwpm_err("Couldn't allocate memory for hwpm struct");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
hwpm->pdev = pdev;
|
||||
hwpm->dev = &pdev->dev;
|
||||
hwpm->np = pdev->dev.of_node;
|
||||
hwpm->class.owner = THIS_MODULE;
|
||||
hwpm->class.name = TEGRA_SOC_HWPM_MODULE_NAME;
|
||||
|
||||
/* Create device node */
|
||||
ret = class_register(&hwpm->class);
|
||||
if (ret) {
|
||||
tegra_soc_hwpm_err("Failed to register class");
|
||||
goto class_register;
|
||||
}
|
||||
|
||||
ret = alloc_chrdev_region(&hwpm->dev_t, 0, 1, dev_name(hwpm->dev));
|
||||
if (ret) {
|
||||
tegra_soc_hwpm_err("Failed to allocate device region");
|
||||
goto alloc_chrdev_region;
|
||||
}
|
||||
|
||||
cdev_init(&hwpm->cdev, &tegra_soc_hwpm_ops);
|
||||
hwpm->cdev.owner = THIS_MODULE;
|
||||
|
||||
ret = cdev_add(&hwpm->cdev, hwpm->dev_t, 1);
|
||||
if (ret) {
|
||||
tegra_soc_hwpm_err("Failed to add cdev");
|
||||
goto cdev_add;
|
||||
}
|
||||
|
||||
dev = device_create(&hwpm->class,
|
||||
NULL,
|
||||
hwpm->dev_t,
|
||||
NULL,
|
||||
TEGRA_SOC_HWPM_MODULE_NAME);
|
||||
if (IS_ERR(dev)) {
|
||||
tegra_soc_hwpm_err("Failed to create device");
|
||||
ret = PTR_ERR(dev);
|
||||
goto device_create;
|
||||
}
|
||||
|
||||
/* FIXME: Enable clock and reset programming */
|
||||
#if 0
|
||||
hwpm->la_clk = devm_clk_get(hwpm->dev, "la");
|
||||
if (IS_ERR(hwpm->la_clk)) {
|
||||
tegra_soc_hwpm_err("Missing la clock");
|
||||
ret = PTR_ERR(hwpm->la_clk);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hwpm->la_rst = devm_reset_control_get(hwpm->dev, "la");
|
||||
if (IS_ERR(hwpm->la_rst)) {
|
||||
tegra_soc_hwpm_err("Missing la reset");
|
||||
ret = PTR_ERR(hwpm->la_rst);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hwpm->hwpm_rst = devm_reset_control_get(hwpm->dev, "hwpm");
|
||||
if (IS_ERR(hwpm->hwpm_rst)) {
|
||||
tegra_soc_hwpm_err("Missing hwpm reset");
|
||||
ret = PTR_ERR(hwpm->hwpm_rst);
|
||||
goto fail;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
tegra_soc_hwpm_debugfs_init(hwpm);
|
||||
|
||||
/*
|
||||
* Currently VDK doesn't have a fmodel for SOC HWPM. Therefore, we
|
||||
* enable fake registers on VDK for minimal testing.
|
||||
*/
|
||||
if (tegra_platform_is_vdk())
|
||||
hwpm->fake_registers_enabled = true;
|
||||
else
|
||||
hwpm->fake_registers_enabled = false;
|
||||
|
||||
platform_set_drvdata(pdev, hwpm);
|
||||
|
||||
tegra_soc_hwpm_dbg("Probe successful!");
|
||||
goto success;
|
||||
|
||||
|
||||
device_create:
|
||||
cdev_del(&hwpm->cdev);
|
||||
cdev_add:
|
||||
unregister_chrdev_region(hwpm->dev_t, 1);
|
||||
alloc_chrdev_region:
|
||||
class_unregister(&hwpm->class);
|
||||
class_register:
|
||||
kfree(hwpm);
|
||||
/* FIXME: Enable clock and reset programming */
|
||||
#if 0
|
||||
if (hwpm->la_clk)
|
||||
devm_clk_put(hwpm->dev, hwpm->la_clk);
|
||||
if (hwpm->la_rst)
|
||||
reset_control_assert(hwpm->la_rst);
|
||||
if (hwpm->hwpm_rst)
|
||||
reset_control_assert(hwpm->hwpm_rst);
|
||||
*/
|
||||
#endif
|
||||
fail:
|
||||
tegra_soc_hwpm_err("Probe failed!");
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tegra_soc_hwpm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_soc_hwpm *hwpm = NULL;
|
||||
|
||||
if (!pdev) {
|
||||
tegra_soc_hwpm_err("Invalid platform device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hwpm = platform_get_drvdata(pdev);
|
||||
if (!hwpm) {
|
||||
tegra_soc_hwpm_err("Invalid hwpm struct");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
tegra_soc_hwpm_debugfs_deinit(hwpm);
|
||||
|
||||
/* FIXME: Enable clock and reset programming */
|
||||
#if 0
|
||||
if (hwpm->la_clk)
|
||||
devm_clk_put(hwpm->dev, hwpm->la_clk);
|
||||
if (hwpm->la_rst)
|
||||
reset_control_assert(hwpm->la_rst);
|
||||
if (hwpm->hwpm_rst)
|
||||
reset_control_assert(hwpm->hwpm_rst);
|
||||
*/
|
||||
#endif
|
||||
|
||||
device_destroy(&hwpm->class, hwpm->dev_t);
|
||||
cdev_del(&hwpm->cdev);
|
||||
unregister_chrdev_region(hwpm->dev_t, 1);
|
||||
class_unregister(&hwpm->class);
|
||||
|
||||
kfree(hwpm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver tegra_soc_hwpm_pdrv = {
|
||||
.probe = tegra_soc_hwpm_probe,
|
||||
.remove = tegra_soc_hwpm_remove,
|
||||
.driver = {
|
||||
.name = TEGRA_SOC_HWPM_MODULE_NAME,
|
||||
.of_match_table = of_match_ptr(tegra_soc_hwpm_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tegra_soc_hwpm_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = platform_driver_register(&tegra_soc_hwpm_pdrv);
|
||||
if (ret < 0)
|
||||
tegra_soc_hwpm_err("Platform driver register failed");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tegra_soc_hwpm_exit(void)
|
||||
{
|
||||
tegra_soc_hwpm_dbg("Unloading the Tegra SOC HWPM driver");
|
||||
platform_driver_unregister(&tegra_soc_hwpm_pdrv);
|
||||
}
|
||||
|
||||
module_init(tegra_soc_hwpm_init);
|
||||
module_exit(tegra_soc_hwpm_exit);
|
||||
|
||||
MODULE_ALIAS(TEGRA_SOC_HWPM_MODULE_NAME);
|
||||
MODULE_DESCRIPTION("Tegra SOC HWPM Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
109
tegra-soc-hwpm.h
Normal file
109
tegra-soc-hwpm.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* tegra-soc-hwpm.h:
|
||||
* This is the header for the Tegra SOC HWPM driver.
|
||||
*
|
||||
* 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_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 "tegra-soc-hwpm-log.h"
|
||||
#include "tegra-soc-hwpm-hw.h"
|
||||
#include <uapi/linux/tegra-soc-hwpm-uapi.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;
|
||||
|
||||
/* MMIO apertures in device tree */
|
||||
void __iomem *dt_apertures[TEGRA_SOC_HWPM_NUM_DT_APERTURES];
|
||||
|
||||
/* Clocks and resets */
|
||||
/* FIXME: Enable clock and reset programming */
|
||||
#if 0
|
||||
struct clk *la_clk;
|
||||
struct reset_control *la_rst;
|
||||
struct reset_control *hwpm_rst;
|
||||
#endif
|
||||
|
||||
/* 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_wlist_size;
|
||||
|
||||
/* Debugging */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
#endif
|
||||
bool fake_registers_enabled;
|
||||
};
|
||||
|
||||
extern const struct file_operations tegra_soc_hwpm_ops;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void tegra_soc_hwpm_debugfs_init(struct tegra_soc_hwpm *hwpm);
|
||||
void tegra_soc_hwpm_debugfs_deinit(struct tegra_soc_hwpm *hwpm);
|
||||
#else
|
||||
static inline void tegra_soc_hwpm_debugfs_init(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
hwpm->debugfs_root = NULL;
|
||||
}
|
||||
static inline void tegra_soc_hwpm_debugfs_deinit(struct tegra_soc_hwpm *hwpm) {}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
#endif /* TEGRA_SOC_HWPM_H */
|
||||
Reference in New Issue
Block a user