mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-24 10:13:00 +03:00
Currently, read/write functions validate aperture and mmio address pointers. However, the error cannot be returned to the parent resulting into undetected errors. Modify all read write functions to return error on failure. This will also allow HWPM driver to know about unavailable IP perfmuxes. Jira THWPM-41 Change-Id: I6cc4ba7a831d5058657d4f2536b1ce3ab20b30c6 Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2707446 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Vasuki Shankar <vasukis@nvidia.com> Reviewed-by: Seema Khowala <seemaj@nvidia.com> GVS: Gerrit_Virtual_Submit
296 lines
9.2 KiB
C
296 lines
9.2 KiB
C
/*
|
|
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. 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.
|
|
*/
|
|
|
|
#include <soc/tegra/fuse.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/dma-buf.h>
|
|
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
|
|
|
#include <tegra_hwpm_log.h>
|
|
#include <tegra_hwpm_io.h>
|
|
#include <tegra_hwpm.h>
|
|
#include <hal/t234/t234_hwpm_internal.h>
|
|
|
|
#include <hal/t234/hw/t234_pmasys_soc_hwpm.h>
|
|
#include <hal/t234/hw/t234_pmmsys_soc_hwpm.h>
|
|
|
|
int t234_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm)
|
|
{
|
|
int err = 0;
|
|
bool timeout = false;
|
|
u32 reg_val = 0U;
|
|
u32 field_mask = 0U;
|
|
u32 field_val = 0U;
|
|
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
|
struct hwpm_ip *chip_ip = active_chip->chip_ips[
|
|
active_chip->get_rtr_int_idx(hwpm)];
|
|
struct hwpm_ip_inst *ip_inst_rtr = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_RTR_INST];
|
|
struct hwpm_ip_inst *ip_inst_pma = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_PMA_INST];
|
|
struct hwpm_ip_aperture *rtr_perfmux = &ip_inst_rtr->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
struct hwpm_ip_aperture *pma_perfmux = &ip_inst_pma->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
|
|
tegra_hwpm_fn(hwpm, " ");
|
|
|
|
/* Disable PMA triggers */
|
|
err = tegra_hwpm_readl(hwpm, pma_perfmux,
|
|
pmasys_trigger_config_user_r(0), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
reg_val = set_field(reg_val, pmasys_trigger_config_user_pma_pulse_m(),
|
|
pmasys_trigger_config_user_pma_pulse_disable_f());
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux,
|
|
pmasys_trigger_config_user_r(0), reg_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux,
|
|
pmasys_sys_trigger_start_mask_r(), 0);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux,
|
|
pmasys_sys_trigger_start_maskb_r(), 0);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux,
|
|
pmasys_sys_trigger_stop_mask_r(), 0);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux,
|
|
pmasys_sys_trigger_stop_maskb_r(), 0);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
/* Wait for PERFMONs, ROUTER, and PMA to idle */
|
|
err = tegra_hwpm_readl(hwpm, rtr_perfmux,
|
|
pmmsys_sys0router_perfmonstatus_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
timeout = HWPM_TIMEOUT(
|
|
pmmsys_sys0router_perfmonstatus_merged_v(reg_val) == 0U,
|
|
"NV_PERF_PMMSYS_SYS0ROUTER_PERFMONSTATUS_MERGED_EMPTY");
|
|
if (timeout) {
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
err = tegra_hwpm_readl(hwpm, rtr_perfmux,
|
|
pmmsys_sys0router_enginestatus_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
timeout = HWPM_TIMEOUT(
|
|
pmmsys_sys0router_enginestatus_status_v(reg_val) ==
|
|
pmmsys_sys0router_enginestatus_status_empty_v(),
|
|
"NV_PERF_PMMSYS_SYS0ROUTER_ENGINESTATUS_STATUS_EMPTY");
|
|
if (timeout) {
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
field_mask = pmasys_enginestatus_status_m() |
|
|
pmasys_enginestatus_rbufempty_m();
|
|
field_val = pmasys_enginestatus_status_empty_f() |
|
|
pmasys_enginestatus_rbufempty_empty_f();
|
|
err = tegra_hwpm_readl(hwpm, pma_perfmux,
|
|
pmasys_enginestatus_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
timeout = HWPM_TIMEOUT((reg_val & field_mask) == field_val,
|
|
"NV_PERF_PMASYS_ENGINESTATUS");
|
|
if (timeout) {
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int t234_hwpm_init_prod_values(struct tegra_soc_hwpm *hwpm)
|
|
{
|
|
int err = 0;
|
|
u32 val = 0U;
|
|
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
|
struct hwpm_ip *chip_ip = active_chip->chip_ips[
|
|
active_chip->get_rtr_int_idx(hwpm)];
|
|
struct hwpm_ip_inst *ip_inst_pma = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_PMA_INST];
|
|
struct hwpm_ip_aperture *pma_perfmux = &ip_inst_pma->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
|
|
tegra_hwpm_fn(hwpm, " ");
|
|
|
|
err = tegra_hwpm_readl(hwpm, pma_perfmux, pmasys_controlb_r(), &val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
val = set_field(val, pmasys_controlb_coalesce_timeout_cycles_m(),
|
|
pmasys_controlb_coalesce_timeout_cycles__prod_f());
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux, pmasys_controlb_r(), val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
err = tegra_hwpm_readl(hwpm, pma_perfmux,
|
|
pmasys_channel_config_user_r(0), &val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
val = set_field(val,
|
|
pmasys_channel_config_user_coalesce_timeout_cycles_m(),
|
|
pmasys_channel_config_user_coalesce_timeout_cycles__prod_f());
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux,
|
|
pmasys_channel_config_user_r(0), val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int t234_hwpm_disable_slcg(struct tegra_soc_hwpm *hwpm)
|
|
{
|
|
int err = 0;
|
|
u32 field_mask = 0U;
|
|
u32 field_val = 0U;
|
|
u32 reg_val = 0U;
|
|
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
|
struct hwpm_ip *chip_ip = active_chip->chip_ips[
|
|
active_chip->get_rtr_int_idx(hwpm)];
|
|
struct hwpm_ip_inst *ip_inst_rtr = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_RTR_INST];
|
|
struct hwpm_ip_inst *ip_inst_pma = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_PMA_INST];
|
|
struct hwpm_ip_aperture *rtr_perfmux = &ip_inst_rtr->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
struct hwpm_ip_aperture *pma_perfmux = &ip_inst_pma->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
|
|
err = tegra_hwpm_readl(hwpm, pma_perfmux, pmasys_cg2_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
reg_val = set_field(reg_val, pmasys_cg2_slcg_m(),
|
|
pmasys_cg2_slcg_disabled_f());
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux, pmasys_cg2_r(), reg_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
field_mask = pmmsys_sys0router_cg2_slcg_perfmon_m() |
|
|
pmmsys_sys0router_cg2_slcg_router_m() |
|
|
pmmsys_sys0router_cg2_slcg_m();
|
|
field_val = pmmsys_sys0router_cg2_slcg_perfmon_disabled_f() |
|
|
pmmsys_sys0router_cg2_slcg_router_disabled_f() |
|
|
pmmsys_sys0router_cg2_slcg_disabled_f();
|
|
err = tegra_hwpm_readl(hwpm, rtr_perfmux,
|
|
pmmsys_sys0router_cg2_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
reg_val = set_field(reg_val, field_mask, field_val);
|
|
err = tegra_hwpm_writel(hwpm, rtr_perfmux,
|
|
pmmsys_sys0router_cg2_r(), reg_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int t234_hwpm_enable_slcg(struct tegra_soc_hwpm *hwpm)
|
|
{
|
|
int err = 0;
|
|
u32 reg_val = 0U;
|
|
u32 field_mask = 0U;
|
|
u32 field_val = 0U;
|
|
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
|
struct hwpm_ip *chip_ip = active_chip->chip_ips[
|
|
active_chip->get_rtr_int_idx(hwpm)];
|
|
struct hwpm_ip_inst *ip_inst_rtr = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_RTR_INST];
|
|
struct hwpm_ip_inst *ip_inst_pma = &chip_ip->ip_inst_static_array[
|
|
T234_HWPM_IP_RTR_STATIC_PMA_INST];
|
|
struct hwpm_ip_aperture *rtr_perfmux = &ip_inst_rtr->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
struct hwpm_ip_aperture *pma_perfmux = &ip_inst_pma->element_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_PERFMUX].element_static_array[
|
|
T234_HWPM_IP_RTR_PERMUX_INDEX];
|
|
|
|
err = tegra_hwpm_readl(hwpm, pma_perfmux, pmasys_cg2_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
reg_val = set_field(reg_val, pmasys_cg2_slcg_m(),
|
|
pmasys_cg2_slcg_enabled_f());
|
|
err = tegra_hwpm_writel(hwpm, pma_perfmux, pmasys_cg2_r(), reg_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
field_mask = pmmsys_sys0router_cg2_slcg_perfmon_m() |
|
|
pmmsys_sys0router_cg2_slcg_router_m() |
|
|
pmmsys_sys0router_cg2_slcg_m();
|
|
field_val = pmmsys_sys0router_cg2_slcg_perfmon__prod_f() |
|
|
pmmsys_sys0router_cg2_slcg_router__prod_f() |
|
|
pmmsys_sys0router_cg2_slcg__prod_f();
|
|
err = tegra_hwpm_readl(hwpm, rtr_perfmux,
|
|
pmmsys_sys0router_cg2_r(), ®_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm read failed");
|
|
return err;
|
|
}
|
|
reg_val = set_field(reg_val, field_mask, field_val);
|
|
err = tegra_hwpm_writel(hwpm, rtr_perfmux,
|
|
pmmsys_sys0router_cg2_r(), reg_val);
|
|
if (err != 0) {
|
|
tegra_hwpm_err(hwpm, "hwpm write failed");
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|