tegra: hwpm: update basic structure layout

Introduced macros to define HWPM aperture types perfmon, perfmux and
broadcast.
Added new enum to define element type.
IP perfmux and IP broadcast are handled in similar way. Whereas, HWPM
perfmux should use HWPM perfmon functions.

Updated hwpm structures are as below
Parent HWPM structure
  -> Active chip structure
     -> Array of IPs
     -> HALs

IP structure
  -> Array of instances
  -> Array of instance info with respect to perfmon, perfmux, broadcast
  -> Instance mask : indicates available instances
  -> reserved status

Instance structure
  -> Array of element info with respect to perfmon, perfmux, broadcast
      -> Array of corresponding element structures
  -> Element mask : indicates available elements in the instance

Element structure
  -> Aperture address details
  -> DT node / MMIO details

Update all functions to use new HWPM structures.

Update hwpm_probe to include force IP enable step.

Jira THWPM-41

Change-Id: I9461063d2136b34e841322c4ddd77a20486424c6
Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2706489
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
This commit is contained in:
Vedashree Vidwans
2022-05-02 23:50:58 -07:00
committed by mobile promotions
parent 7dd5b5c956
commit 3b6a1b35b7
56 changed files with 5479 additions and 3217 deletions

View File

@@ -15,17 +15,136 @@
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
#include <tegra_hwpm_log.h>
#include <tegra_hwpm.h>
#include <tegra_hwpm_io.h>
#include <tegra_hwpm_log.h>
#include <tegra_hwpm_common.h>
#include <tegra_hwpm_static_analysis.h>
static int tegra_hwpm_exec_reg_ops(struct tegra_soc_hwpm *hwpm,
struct tegra_soc_hwpm_reg_op *reg_op)
{
bool found = false;
u32 ip_idx = TEGRA_SOC_HWPM_IP_INACTIVE;
u32 inst_idx = 0U, element_idx = 0U;
u32 a_type = 0U;
u32 reg_val = 0U;
u64 addr_hi = 0ULL;
enum tegra_hwpm_element_type element_type = HWPM_ELEMENT_INVALID;
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
struct hwpm_ip *chip_ip = NULL;
struct hwpm_ip_inst_per_aperture_info *inst_a_info = NULL;
struct hwpm_ip_inst *ip_inst = NULL;
struct hwpm_ip_element_info *e_info = NULL;
struct hwpm_ip_aperture *element = NULL;
tegra_hwpm_fn(hwpm, " ");
/* Find IP aperture containing phys_addr in allowlist */
found = tegra_hwpm_aperture_for_address(hwpm,
TEGRA_HWPM_FIND_GIVEN_ADDRESS, reg_op->phys_addr,
&ip_idx, &inst_idx, &element_idx, &element_type);
if (!found) {
/* Silent failure as regops can continue on error */
tegra_hwpm_dbg(hwpm, hwpm_verbose,
"Phys addr 0x%llx not available in any IP",
reg_op->phys_addr);
reg_op->status = TEGRA_SOC_HWPM_REG_OP_STATUS_INVALID_ADDR;
return -EINVAL;
}
tegra_hwpm_dbg(hwpm, hwpm_verbose,
"Found addr 0x%llx IP %d inst_idx %d element_idx %d e_type %d",
reg_op->phys_addr, ip_idx, inst_idx, element_idx, element_type);
switch (element_type) {
case HWPM_ELEMENT_PERFMON:
a_type = TEGRA_HWPM_APERTURE_TYPE_PERFMON;
break;
case HWPM_ELEMENT_PERFMUX:
case IP_ELEMENT_PERFMUX:
a_type = TEGRA_HWPM_APERTURE_TYPE_PERFMUX;
break;
case IP_ELEMENT_BROADCAST:
a_type = TEGRA_HWPM_APERTURE_TYPE_BROADCAST;
break;
case HWPM_ELEMENT_INVALID:
default:
tegra_hwpm_err(hwpm, "Invalid element type %d", element_type);
return -EINVAL;
}
chip_ip = active_chip->chip_ips[ip_idx];
inst_a_info = &chip_ip->inst_aperture_info[a_type];
ip_inst = inst_a_info->inst_arr[inst_idx];
e_info = &ip_inst->element_info[a_type];
element = e_info->element_arr[element_idx];
switch (reg_op->cmd) {
case TEGRA_SOC_HWPM_REG_OP_CMD_RD32:
reg_op->reg_val_lo = tegra_hwpm_regops_readl(hwpm,
reg_op->phys_addr, ip_inst, element);
reg_op->status = TEGRA_SOC_HWPM_REG_OP_STATUS_SUCCESS;
break;
case TEGRA_SOC_HWPM_REG_OP_CMD_RD64:
addr_hi = tegra_hwpm_safe_add_u64(reg_op->phys_addr, 4ULL);
reg_op->reg_val_lo = tegra_hwpm_regops_readl(hwpm,
reg_op->phys_addr, ip_inst, element);
reg_op->reg_val_hi = tegra_hwpm_regops_readl(hwpm,
addr_hi, ip_inst, element);
reg_op->status = TEGRA_SOC_HWPM_REG_OP_STATUS_SUCCESS;
break;
/* Read Modify Write operation */
case TEGRA_SOC_HWPM_REG_OP_CMD_WR32:
reg_val = tegra_hwpm_regops_readl(hwpm,
reg_op->phys_addr, ip_inst, element);
reg_val = set_field(reg_val, reg_op->mask_lo,
reg_op->reg_val_lo);
tegra_hwpm_regops_writel(hwpm,
reg_op->phys_addr, reg_val, ip_inst, element);
reg_op->status = TEGRA_SOC_HWPM_REG_OP_STATUS_SUCCESS;
break;
/* Read Modify Write operation */
case TEGRA_SOC_HWPM_REG_OP_CMD_WR64:
addr_hi = tegra_hwpm_safe_add_u64(reg_op->phys_addr, 4ULL);
/* Lower 32 bits */
reg_val = tegra_hwpm_regops_readl(hwpm,
reg_op->phys_addr, ip_inst, element);
reg_val = set_field(reg_val, reg_op->mask_lo,
reg_op->reg_val_lo);
tegra_hwpm_regops_writel(hwpm,
reg_op->phys_addr, reg_val, ip_inst, element);
/* Upper 32 bits */
reg_val = tegra_hwpm_regops_readl(hwpm,
addr_hi, ip_inst, element);
reg_val = set_field(reg_val, reg_op->mask_hi,
reg_op->reg_val_hi);
tegra_hwpm_regops_writel(hwpm,
reg_op->phys_addr, reg_val, ip_inst, element);
reg_op->status = TEGRA_SOC_HWPM_REG_OP_STATUS_SUCCESS;
break;
default:
tegra_hwpm_err(hwpm, "Invalid reg op command(%u)", reg_op->cmd);
reg_op->status = TEGRA_SOC_HWPM_REG_OP_STATUS_INVALID_CMD;
return -EINVAL;
break;
}
return 0;
}
int tegra_hwpm_exec_regops(struct tegra_soc_hwpm *hwpm,
struct tegra_soc_hwpm_exec_reg_ops *exec_reg_ops)
{
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
int op_idx = 0;
struct tegra_soc_hwpm_reg_op *reg_op = NULL;
int ret = 0;
struct tegra_soc_hwpm_reg_op *reg_op = NULL;
tegra_hwpm_fn(hwpm, " ");
@@ -46,11 +165,6 @@ int tegra_hwpm_exec_regops(struct tegra_soc_hwpm *hwpm,
return -EINVAL;
}
if (active_chip->exec_reg_ops == NULL) {
tegra_hwpm_err(hwpm, "exec_reg_ops uninitialized");
return -ENODEV;
}
/*
* Initialize flag to true assuming all regops will pass
* If any regop fails, the flag will be reset to false.
@@ -63,7 +177,7 @@ int tegra_hwpm_exec_regops(struct tegra_soc_hwpm *hwpm,
"reg op: idx(%d), phys(0x%llx), cmd(%u)",
op_idx, reg_op->phys_addr, reg_op->cmd);
ret = active_chip->exec_reg_ops(hwpm, reg_op);
ret = tegra_hwpm_exec_reg_ops(hwpm, reg_op);
if (ret < 0) {
tegra_hwpm_err(hwpm, "exec_reg_ops %d failed", op_idx);
exec_reg_ops->b_all_reg_ops_passed = false;