Files
linux-hwpm/drivers/tegra/hwpm/os/linux/ip_utils.c
Besar Wicaksono 106bc61f86 tegra: hwpm: add cpu_ext_* enums
Add new CPU IP and resource enum in
kernel driver and userspace library.
This is to extend support for chips with
more than 32 CPU instances (up to 128).

JIRA MSST-893

Change-Id: I33142c7fc8f268f8c436cc3b7cd97385da31b558
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-hwpm/+/3328654
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Yifei Wan <ywan@nvidia.com>
Reviewed-by: Vasuki Shankar <vasukis@nvidia.com>
2025-04-25 05:31:02 -07:00

576 lines
15 KiB
C

/* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*
* 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.
*/
#include <linux/slab.h>
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
#include <tegra_hwpm_kmem.h>
#include <tegra_hwpm_log.h>
#include <tegra_hwpm_io.h>
#include <tegra_hwpm.h>
#include <os/linux/ip_utils.h>
#include <os/linux/driver.h>
struct platform_device *tegra_soc_hwpm_pdev;
struct hwpm_ip_register_list *ip_register_list_head;
#define REGISTER_IP true
#define UNREGISTER_IP false
static u32 tegra_hwpm_translate_soc_hwpm_ip(struct tegra_soc_hwpm *hwpm,
enum tegra_soc_hwpm_ip ip_enum)
{
u32 ip_enum_idx = TEGRA_HWPM_IP_INACTIVE;
switch (ip_enum) {
case TEGRA_SOC_HWPM_IP_VI:
ip_enum_idx = TEGRA_HWPM_IP_VI;
break;
case TEGRA_SOC_HWPM_IP_ISP:
ip_enum_idx = TEGRA_HWPM_IP_ISP;
break;
case TEGRA_SOC_HWPM_IP_VIC:
ip_enum_idx = TEGRA_HWPM_IP_VIC;
break;
case TEGRA_SOC_HWPM_IP_OFA:
ip_enum_idx = TEGRA_HWPM_IP_OFA;
break;
case TEGRA_SOC_HWPM_IP_PVA:
ip_enum_idx = TEGRA_HWPM_IP_PVA;
break;
case TEGRA_SOC_HWPM_IP_NVDLA:
ip_enum_idx = TEGRA_HWPM_IP_NVDLA;
break;
case TEGRA_SOC_HWPM_IP_MGBE:
ip_enum_idx = TEGRA_HWPM_IP_MGBE;
break;
case TEGRA_SOC_HWPM_IP_SCF:
ip_enum_idx = TEGRA_HWPM_IP_SCF;
break;
case TEGRA_SOC_HWPM_IP_NVDEC:
ip_enum_idx = TEGRA_HWPM_IP_NVDEC;
break;
case TEGRA_SOC_HWPM_IP_NVENC:
ip_enum_idx = TEGRA_HWPM_IP_NVENC;
break;
case TEGRA_SOC_HWPM_IP_PCIE:
ip_enum_idx = TEGRA_HWPM_IP_PCIE;
break;
case TEGRA_SOC_HWPM_IP_DISPLAY:
ip_enum_idx = TEGRA_HWPM_IP_DISPLAY;
break;
case TEGRA_SOC_HWPM_IP_MSS_CHANNEL:
ip_enum_idx = TEGRA_HWPM_IP_MSS_CHANNEL;
break;
case TEGRA_SOC_HWPM_IP_MSS_GPU_HUB:
ip_enum_idx = TEGRA_HWPM_IP_MSS_GPU_HUB;
break;
case TEGRA_SOC_HWPM_IP_MSS_ISO_NISO_HUBS:
ip_enum_idx = TEGRA_HWPM_IP_MSS_ISO_NISO_HUBS;
break;
case TEGRA_SOC_HWPM_IP_MSS_MCF:
ip_enum_idx = TEGRA_HWPM_IP_MSS_MCF;
break;
case TEGRA_SOC_HWPM_IP_APE:
ip_enum_idx = TEGRA_HWPM_IP_APE;
break;
case TEGRA_SOC_HWPM_IP_C2C:
ip_enum_idx = TEGRA_HWPM_IP_C2C;
break;
case TEGRA_SOC_HWPM_IP_SMMU:
ip_enum_idx = TEGRA_HWPM_IP_SMMU;
break;
case TEGRA_SOC_HWPM_IP_CL2:
ip_enum_idx = TEGRA_HWPM_IP_CL2;
break;
case TEGRA_SOC_HWPM_IP_NVLCTRL:
ip_enum_idx = TEGRA_HWPM_IP_NVLCTRL;
break;
case TEGRA_SOC_HWPM_IP_NVLRX:
ip_enum_idx = TEGRA_HWPM_IP_NVLRX;
break;
case TEGRA_SOC_HWPM_IP_NVLTX:
ip_enum_idx = TEGRA_HWPM_IP_NVLTX;
break;
case TEGRA_SOC_HWPM_IP_MSS_HUB:
ip_enum_idx = TEGRA_HWPM_IP_MSS_HUB;
break;
case TEGRA_SOC_HWPM_IP_MCF_SOC:
ip_enum_idx = TEGRA_HWPM_IP_MCF_SOC;
break;
case TEGRA_SOC_HWPM_IP_MCF_C2C:
ip_enum_idx = TEGRA_HWPM_IP_MCF_C2C;
break;
case TEGRA_SOC_HWPM_IP_MCF_CLINK:
ip_enum_idx = TEGRA_HWPM_IP_MCF_CLINK;
break;
case TEGRA_SOC_HWPM_IP_MCF_CORE:
ip_enum_idx = TEGRA_HWPM_IP_MCF_CORE;
break;
case TEGRA_SOC_HWPM_IP_MCF_OCU:
ip_enum_idx = TEGRA_HWPM_IP_MCF_OCU;
break;
case TEGRA_SOC_HWPM_IP_PCIE_XTLQ:
ip_enum_idx = TEGRA_HWPM_IP_PCIE_XTLQ;
break;
case TEGRA_SOC_HWPM_IP_PCIE_XTLRC:
ip_enum_idx = TEGRA_HWPM_IP_PCIE_XTLRC;
break;
case TEGRA_SOC_HWPM_IP_PCIE_XALRC:
ip_enum_idx = TEGRA_HWPM_IP_PCIE_XALRC;
break;
case TEGRA_SOC_HWPM_IP_UCF_MSW:
ip_enum_idx = TEGRA_HWPM_IP_UCF_MSW;
break;
case TEGRA_SOC_HWPM_IP_UCF_PSW:
ip_enum_idx = TEGRA_HWPM_IP_UCF_PSW;
break;
case TEGRA_SOC_HWPM_IP_UCF_CSW:
ip_enum_idx = TEGRA_HWPM_IP_UCF_CSW;
break;
case TEGRA_SOC_HWPM_IP_UCF_HUB:
ip_enum_idx = TEGRA_HWPM_IP_UCF_HUB;
break;
case TEGRA_SOC_HWPM_IP_UCF_SCB:
ip_enum_idx = TEGRA_HWPM_IP_UCF_SCB;
break;
case TEGRA_SOC_HWPM_IP_CPU:
ip_enum_idx = TEGRA_HWPM_IP_CPU;
break;
case TEGRA_SOC_HWPM_IP_CPU_EXT_0:
ip_enum_idx = TEGRA_HWPM_IP_CPU_EXT_0;
break;
case TEGRA_SOC_HWPM_IP_CPU_EXT_1:
ip_enum_idx = TEGRA_HWPM_IP_CPU_EXT_1;
break;
case TEGRA_SOC_HWPM_IP_CPU_EXT_2:
ip_enum_idx = TEGRA_HWPM_IP_CPU_EXT_2;
break;
case TEGRA_SOC_HWPM_IP_NVTHERM:
ip_enum_idx = TEGRA_HWPM_IP_NVTHERM;
break;
case TEGRA_SOC_HWPM_IP_CSN:
ip_enum_idx = TEGRA_HWPM_IP_CSN;
break;
case TEGRA_SOC_HWPM_IP_CSN_EXT_0:
ip_enum_idx = TEGRA_HWPM_IP_CSN_EXT_0;
break;
case TEGRA_SOC_HWPM_IP_CSNH:
ip_enum_idx = TEGRA_HWPM_IP_CSNH;
break;
default:
tegra_hwpm_err(hwpm,
"Queried enum tegra_soc_hwpm_ip %d is invalid",
ip_enum);
break;
}
return ip_enum_idx;
}
int tegra_hwpm_obtain_floorsweep_info(struct tegra_soc_hwpm *hwpm,
struct tegra_soc_hwpm_ip_floorsweep_info *fs_info)
{
int ret = 0;
u32 i = 0U;
tegra_hwpm_fn(hwpm, " ");
for (i = 0U; i < fs_info->num_queries; i++) {
ret = hwpm->active_chip->get_fs_info(hwpm,
tegra_hwpm_translate_soc_hwpm_ip(
hwpm, fs_info->ip_fsinfo[i].ip),
&fs_info->ip_fsinfo[i].ip_inst_mask,
&fs_info->ip_fsinfo[i].status);
if (ret != 0) {
tegra_hwpm_err(hwpm,
"Failed to get fs_info query %d", i);
}
tegra_hwpm_dbg(hwpm, hwpm_info | hwpm_dbg_floorsweep_info,
"Query %d: tegra_soc_hwpm_ip %d: ip_status: %d"
" inst_mask 0x%llx",
i, fs_info->ip_fsinfo[i].ip,
fs_info->ip_fsinfo[i].status,
fs_info->ip_fsinfo[i].ip_inst_mask);
}
return ret;
}
u32 tegra_hwpm_translate_soc_hwpm_resource(struct tegra_soc_hwpm *hwpm,
enum tegra_soc_hwpm_resource res_enum)
{
u32 res_enum_idx = TEGRA_HWPM_IP_INACTIVE;
switch (res_enum) {
case TEGRA_SOC_HWPM_RESOURCE_VI:
res_enum_idx = TEGRA_HWPM_RESOURCE_VI;
break;
case TEGRA_SOC_HWPM_RESOURCE_ISP:
res_enum_idx = TEGRA_HWPM_RESOURCE_ISP;
break;
case TEGRA_SOC_HWPM_RESOURCE_VIC:
res_enum_idx = TEGRA_HWPM_RESOURCE_VIC;
break;
case TEGRA_SOC_HWPM_RESOURCE_OFA:
res_enum_idx = TEGRA_HWPM_RESOURCE_OFA;
break;
case TEGRA_SOC_HWPM_RESOURCE_PVA:
res_enum_idx = TEGRA_HWPM_RESOURCE_PVA;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVDLA:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVDLA;
break;
case TEGRA_SOC_HWPM_RESOURCE_MGBE:
res_enum_idx = TEGRA_HWPM_RESOURCE_MGBE;
break;
case TEGRA_SOC_HWPM_RESOURCE_SCF:
res_enum_idx = TEGRA_HWPM_RESOURCE_SCF;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVDEC:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVDEC;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVENC:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVENC;
break;
case TEGRA_SOC_HWPM_RESOURCE_PCIE:
res_enum_idx = TEGRA_HWPM_RESOURCE_PCIE;
break;
case TEGRA_SOC_HWPM_RESOURCE_DISPLAY:
res_enum_idx = TEGRA_HWPM_RESOURCE_DISPLAY;
break;
case TEGRA_SOC_HWPM_RESOURCE_MSS_CHANNEL:
res_enum_idx = TEGRA_HWPM_RESOURCE_MSS_CHANNEL;
break;
case TEGRA_SOC_HWPM_RESOURCE_MSS_GPU_HUB:
res_enum_idx = TEGRA_HWPM_RESOURCE_MSS_GPU_HUB;
break;
case TEGRA_SOC_HWPM_RESOURCE_MSS_ISO_NISO_HUBS:
res_enum_idx = TEGRA_HWPM_RESOURCE_MSS_ISO_NISO_HUBS;
break;
case TEGRA_SOC_HWPM_RESOURCE_MSS_MCF:
res_enum_idx = TEGRA_HWPM_RESOURCE_MSS_MCF;
break;
case TEGRA_SOC_HWPM_RESOURCE_PMA:
res_enum_idx = TEGRA_HWPM_RESOURCE_PMA;
break;
case TEGRA_SOC_HWPM_RESOURCE_CMD_SLICE_RTR:
res_enum_idx = TEGRA_HWPM_RESOURCE_CMD_SLICE_RTR;
break;
case TEGRA_SOC_HWPM_RESOURCE_APE:
res_enum_idx = TEGRA_HWPM_RESOURCE_APE;
break;
case TEGRA_SOC_HWPM_RESOURCE_C2C:
res_enum_idx = TEGRA_HWPM_RESOURCE_C2C;
break;
case TEGRA_SOC_HWPM_RESOURCE_SMMU:
res_enum_idx = TEGRA_HWPM_RESOURCE_SMMU;
break;
case TEGRA_SOC_HWPM_RESOURCE_CL2:
res_enum_idx = TEGRA_HWPM_RESOURCE_CL2;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVLCTRL:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVLCTRL;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVLRX:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVLRX;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVLTX:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVLTX;
break;
case TEGRA_SOC_HWPM_RESOURCE_MSS_HUB:
res_enum_idx = TEGRA_HWPM_RESOURCE_MSS_HUB;
break;
case TEGRA_SOC_HWPM_RESOURCE_MCF_SOC:
res_enum_idx = TEGRA_HWPM_RESOURCE_MCF_SOC;
break;
case TEGRA_SOC_HWPM_RESOURCE_MCF_C2C:
res_enum_idx = TEGRA_HWPM_RESOURCE_MCF_C2C;
break;
case TEGRA_SOC_HWPM_RESOURCE_MCF_CLINK:
res_enum_idx = TEGRA_HWPM_RESOURCE_MCF_CLINK;
break;
case TEGRA_SOC_HWPM_RESOURCE_MCF_CORE:
res_enum_idx = TEGRA_HWPM_RESOURCE_MCF_CORE;
break;
case TEGRA_SOC_HWPM_RESOURCE_MCF_OCU:
res_enum_idx = TEGRA_HWPM_RESOURCE_MCF_OCU;
break;
case TEGRA_SOC_HWPM_RESOURCE_PCIE_XTLQ:
res_enum_idx = TEGRA_HWPM_RESOURCE_PCIE_XTLQ;
break;
case TEGRA_SOC_HWPM_RESOURCE_PCIE_XTLRC:
res_enum_idx = TEGRA_HWPM_RESOURCE_PCIE_XTLRC;
break;
case TEGRA_SOC_HWPM_RESOURCE_PCIE_XALRC:
res_enum_idx = TEGRA_HWPM_RESOURCE_PCIE_XALRC;
break;
case TEGRA_SOC_HWPM_RESOURCE_UCF_MSW:
res_enum_idx = TEGRA_HWPM_RESOURCE_UCF_MSW;
break;
case TEGRA_SOC_HWPM_RESOURCE_UCF_PSW:
res_enum_idx = TEGRA_HWPM_RESOURCE_UCF_PSW;
break;
case TEGRA_SOC_HWPM_RESOURCE_UCF_CSW:
res_enum_idx = TEGRA_HWPM_RESOURCE_UCF_CSW;
break;
case TEGRA_SOC_HWPM_RESOURCE_UCF_HUB:
res_enum_idx = TEGRA_HWPM_RESOURCE_UCF_HUB;
break;
case TEGRA_SOC_HWPM_RESOURCE_UCF_SCB:
res_enum_idx = TEGRA_HWPM_RESOURCE_UCF_SCB;
break;
case TEGRA_SOC_HWPM_RESOURCE_CPU:
res_enum_idx = TEGRA_HWPM_RESOURCE_CPU;
break;
case TEGRA_SOC_HWPM_RESOURCE_CPU_EXT_0:
res_enum_idx = TEGRA_HWPM_RESOURCE_CPU_EXT_0;
break;
case TEGRA_SOC_HWPM_RESOURCE_CPU_EXT_1:
res_enum_idx = TEGRA_HWPM_RESOURCE_CPU_EXT_1;
break;
case TEGRA_SOC_HWPM_RESOURCE_CPU_EXT_2:
res_enum_idx = TEGRA_HWPM_RESOURCE_CPU_EXT_2;
break;
case TEGRA_SOC_HWPM_RESOURCE_NVTHERM:
res_enum_idx = TEGRA_HWPM_RESOURCE_NVTHERM;
break;
case TEGRA_SOC_HWPM_RESOURCE_CSN:
res_enum_idx = TEGRA_HWPM_RESOURCE_CSN;
break;
case TEGRA_SOC_HWPM_RESOURCE_CSN_EXT_0:
res_enum_idx = TEGRA_HWPM_RESOURCE_CSN_EXT_0;
break;
case TEGRA_SOC_HWPM_RESOURCE_CSNH:
res_enum_idx = TEGRA_HWPM_RESOURCE_CSNH;
break;
default:
tegra_hwpm_err(hwpm,
"Queried enum tegra_soc_hwpm_resource %d is invalid",
res_enum);
break;
}
return res_enum_idx;
}
int tegra_hwpm_obtain_resource_info(struct tegra_soc_hwpm *hwpm,
struct tegra_soc_hwpm_resource_info *rsrc_info)
{
int ret = 0;
u32 i = 0U;
tegra_hwpm_fn(hwpm, " ");
for (i = 0U; i < rsrc_info->num_queries; i++) {
ret = hwpm->active_chip->get_resource_info(
hwpm, tegra_hwpm_translate_soc_hwpm_resource(
hwpm, rsrc_info->resource_info[i].resource),
&rsrc_info->resource_info[i].status);
if (ret < 0) {
/* Print error for debug purpose. */
tegra_hwpm_err(hwpm, "Failed to get rsrc_info");
}
tegra_hwpm_dbg(hwpm, hwpm_info | hwpm_dbg_resource_info,
"Query %d: resource %d: status: %d",
i, rsrc_info->resource_info[i].resource,
rsrc_info->resource_info[i].status);
}
return ret;
}
static int tegra_hwpm_record_ip_ops(struct tegra_soc_hwpm *hwpm,
struct tegra_soc_hwpm_ip_ops *soc_ip_ops, bool available)
{
struct tegra_hwpm_ip_ops ip_ops;
tegra_hwpm_fn(hwpm, " ");
ip_ops.ip_dev = soc_ip_ops->ip_dev;
ip_ops.hwpm_ip_pm = soc_ip_ops->hwpm_ip_pm;
ip_ops.hwpm_ip_reg_op = soc_ip_ops->hwpm_ip_reg_op;
if (soc_ip_ops->resource_enum >= TERGA_SOC_HWPM_NUM_RESOURCES) {
tegra_hwpm_err(hwpm, "resource enum %d out of scope",
soc_ip_ops->resource_enum);
return -EINVAL;
}
return hwpm->active_chip->extract_ip_ops(hwpm,
tegra_hwpm_translate_soc_hwpm_resource(hwpm,
(enum tegra_soc_hwpm_resource)soc_ip_ops->resource_enum),
soc_ip_ops->ip_base_address,
&ip_ops, available);
}
int tegra_hwpm_complete_ip_register_impl(struct tegra_soc_hwpm *hwpm)
{
int ret = 0;
struct hwpm_ip_register_list *node = ip_register_list_head;
tegra_hwpm_fn(hwpm, " ");
while (node != NULL) {
ret = tegra_hwpm_record_ip_ops(hwpm, &node->ip_ops, REGISTER_IP);
if (ret != 0) {
tegra_hwpm_err(hwpm,
"Resource enum %d extract IP ops failed",
node->ip_ops.resource_enum);
return ret;
}
node = node->next;
}
return ret;
}
static int tegra_hwpm_alloc_ip_register_list_node(
struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops,
struct hwpm_ip_register_list **node_ptr)
{
struct hwpm_ip_register_list *new_node = NULL;
new_node = tegra_hwpm_kzalloc(NULL,
sizeof(struct hwpm_ip_register_list));
if (new_node == NULL) {
tegra_hwpm_err(NULL,
"struct hwpm_ip_register_list node allocation failed");
return -ENOMEM;
}
new_node->next = NULL;
/* Copy given ip register details to node */
memcpy(&new_node->ip_ops, hwpm_ip_ops,
sizeof(struct tegra_soc_hwpm_ip_ops));
(*node_ptr) = new_node;
return 0;
}
static int tegra_hwpm_note_ip_register(
struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
{
int err = 0;
struct hwpm_ip_register_list *node;
if (ip_register_list_head == NULL) {
err = tegra_hwpm_alloc_ip_register_list_node(hwpm_ip_ops,
&ip_register_list_head);
if (err != 0) {
tegra_hwpm_err(NULL,
"failed to note ip registration");
return err;
}
} else {
node = ip_register_list_head;
while (node->next != NULL) {
node = node->next;
}
err = tegra_hwpm_alloc_ip_register_list_node(hwpm_ip_ops,
&node->next);
if (err != 0) {
tegra_hwpm_err(NULL,
"failed to note ip registration");
return err;
}
}
return err;
}
void tegra_soc_hwpm_ip_register(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
{
struct tegra_soc_hwpm *hwpm = NULL;
int ret = 0;
if (hwpm_ip_ops == NULL) {
tegra_hwpm_err(NULL, "IP details missing");
return;
}
if (tegra_soc_hwpm_pdev == NULL) {
tegra_hwpm_dbg(hwpm, hwpm_info | hwpm_dbg_ip_register,
"Noting IP 0x%llx register request",
hwpm_ip_ops->ip_base_address);
ret = tegra_hwpm_note_ip_register(hwpm_ip_ops);
if (ret != 0) {
tegra_hwpm_err(NULL,
"Couldn't save IP register details");
return;
}
} else {
if (hwpm_ip_ops->ip_dev == NULL) {
tegra_hwpm_err(hwpm, "IP dev to register is NULL");
return;
}
hwpm = platform_get_drvdata(tegra_soc_hwpm_pdev);
tegra_hwpm_dbg(hwpm, hwpm_info | hwpm_dbg_ip_register,
"Register IP 0x%llx", hwpm_ip_ops->ip_base_address);
ret = tegra_hwpm_record_ip_ops(hwpm, hwpm_ip_ops, REGISTER_IP);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to set IP ops for IP %d",
hwpm_ip_ops->resource_enum);
}
}
}
EXPORT_SYMBOL(tegra_soc_hwpm_ip_register);
void tegra_soc_hwpm_ip_unregister(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
{
struct tegra_soc_hwpm *hwpm = NULL;
int ret = 0;
if (hwpm_ip_ops == NULL) {
tegra_hwpm_err(NULL, "IP details missing");
return;
}
if (tegra_soc_hwpm_pdev == NULL) {
tegra_hwpm_dbg(hwpm, hwpm_info | hwpm_dbg_ip_register,
"HWPM device not available");
} else {
if (hwpm_ip_ops->ip_dev == NULL) {
tegra_hwpm_err(hwpm, "IP dev to unregister is NULL");
return;
}
hwpm = platform_get_drvdata(tegra_soc_hwpm_pdev);
tegra_hwpm_dbg(hwpm, hwpm_info | hwpm_dbg_ip_register,
"Unregister IP 0x%llx", hwpm_ip_ops->ip_base_address);
ret = tegra_hwpm_record_ip_ops(hwpm, hwpm_ip_ops, UNREGISTER_IP);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Failed to reset IP ops for IP %d",
hwpm_ip_ops->resource_enum);
}
}
}
EXPORT_SYMBOL(tegra_soc_hwpm_ip_unregister);
void tegra_hwpm_release_ip_register_node(struct tegra_soc_hwpm *hwpm)
{
struct hwpm_ip_register_list *node = ip_register_list_head;
struct hwpm_ip_register_list *tmp_node = NULL;
tegra_hwpm_fn(hwpm, " ");
while (node != NULL) {
tmp_node = node;
node = tmp_node->next;
tegra_hwpm_kfree(hwpm, tmp_node);
}
}