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:
Adeel Raza
2020-06-23 10:50:36 -07:00
committed by mobile promotions
commit 70941decf9
10 changed files with 4636 additions and 0 deletions

11
Makefile Normal file
View 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
View 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
View 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
View File

File diff suppressed because it is too large Load Diff

136
tegra-soc-hwpm-io.h Normal file
View 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
View File

File diff suppressed because it is too large Load Diff

53
tegra-soc-hwpm-log.c Normal file
View 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
View 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
View 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
View 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 */