mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-22 17:30:40 +03:00
tegra: hwpm: read MC config fuse
On production board, MC config details are available through fuses. Add function to read MC config fuse. Use the floorsweep fuse info to find available elements. Bug 3936487 Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com> Change-Id: I9e1549e3dfb9c06d8013ca2e1d43eb21bf0289f4 (cherry picked from commit f38e98a94ab8d478af3ebe1c922da606df9b67dc) Reviewed-on: https://git-master.nvidia.com/r/c/linux-hwpm/+/2888554 Reviewed-by: Adeel Raza <araza@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
4ecc672c3e
commit
9a9f2f3635
@@ -301,11 +301,23 @@ static int tegra_hwpm_func_single_element(struct tegra_soc_hwpm *hwpm,
|
||||
e_info->element_arr[idx] = element;
|
||||
break;
|
||||
case TEGRA_HWPM_UPDATE_IP_INST_MASK:
|
||||
/* HWPM perfmuxes can be assumed to be available */
|
||||
/* HWPM perfmuxes (PMA,RTR) can be assumed to be available */
|
||||
if (element->element_type == HWPM_ELEMENT_PERFMUX) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle IPs with some value of fuse_fs_mask */
|
||||
if (ip_inst->fuse_fs_mask != 0U) {
|
||||
if ((element->element_index_mask &
|
||||
ip_inst->fuse_fs_mask) == 0U) {
|
||||
/* This element is floorswept */
|
||||
tegra_hwpm_dbg(hwpm, hwpm_dbg_floorsweep_info,
|
||||
"skip floorswept element 0x%llx",
|
||||
element->start_abs_pa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate perfmux availability by reading 1st alist offset */
|
||||
ret = tegra_hwpm_regops_readl(hwpm, ip_inst, element,
|
||||
tegra_hwpm_safe_add_u64(element->start_abs_pa,
|
||||
|
||||
@@ -198,6 +198,96 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int t234_hwpm_validate_emc_config(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
||||
# if defined(CONFIG_T234_HWPM_IP_MSS_CHANNEL) || \
|
||||
defined(CONFIG_T234_HWPM_IP_MSS_ISO_NISO_HUBS) || \
|
||||
defined(CONFIG_T234_HWPM_IP_MSS_MCF)
|
||||
struct hwpm_ip *chip_ip = NULL;
|
||||
struct hwpm_ip_inst *ip_inst = NULL;
|
||||
u32 inst_idx = 0U;
|
||||
u32 element_mask_max = 0U;
|
||||
#endif
|
||||
u32 emc_disable_fuse_val = 0U;
|
||||
u32 emc_disable_fuse_val_mask = 0xFU;
|
||||
u32 emc_element_floorsweep_mask = 0U;
|
||||
u32 idx = 0U;
|
||||
int err;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
#define TEGRA_FUSE_EMC_DISABLE 0x8c0U
|
||||
err = tegra_hwpm_fuse_readl(hwpm,
|
||||
TEGRA_FUSE_EMC_DISABLE, &emc_disable_fuse_val);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "emc_disable fuse read failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* In floorsweep fuse value,
|
||||
* each bit corresponds to 4 elements.
|
||||
* Bit value 0 indicates those elements are
|
||||
* available and bit value 1 indicates
|
||||
* corresponding elements are floorswept.
|
||||
*
|
||||
* Convert floorsweep fuse value to available EMC elements.
|
||||
*/
|
||||
do {
|
||||
if (emc_disable_fuse_val & 0x1U) {
|
||||
emc_element_floorsweep_mask =
|
||||
(emc_element_floorsweep_mask << 4U) | 0xFU;
|
||||
}
|
||||
emc_disable_fuse_val = (emc_disable_fuse_val >> 1U);
|
||||
emc_disable_fuse_val_mask = (emc_disable_fuse_val_mask >> 1U);
|
||||
} while (emc_disable_fuse_val_mask != 0U);
|
||||
|
||||
/* Set fuse value in MSS IP instances */
|
||||
for (idx = 0U; idx < active_chip->get_ip_max_idx(hwpm); idx++) {
|
||||
switch (idx) {
|
||||
#if defined(CONFIG_T234_HWPM_IP_MSS_CHANNEL)
|
||||
case T234_HWPM_IP_MSS_CHANNEL:
|
||||
#endif
|
||||
#if defined(CONFIG_T234_HWPM_IP_MSS_ISO_NISO_HUBS)
|
||||
case T234_HWPM_IP_MSS_ISO_NISO_HUBS:
|
||||
#endif
|
||||
#if defined(CONFIG_T234_HWPM_IP_MSS_MCF)
|
||||
case T234_HWPM_IP_MSS_MCF:
|
||||
#endif
|
||||
# if defined(CONFIG_T234_HWPM_IP_MSS_CHANNEL) || \
|
||||
defined(CONFIG_T234_HWPM_IP_MSS_ISO_NISO_HUBS) || \
|
||||
defined(CONFIG_T234_HWPM_IP_MSS_MCF)
|
||||
chip_ip = active_chip->chip_ips[idx];
|
||||
for (inst_idx = 0U; inst_idx < chip_ip->num_instances;
|
||||
inst_idx++) {
|
||||
ip_inst = &chip_ip->ip_inst_static_array[
|
||||
inst_idx];
|
||||
|
||||
/*
|
||||
* Hence use max element mask to get correct
|
||||
* fs info to use in HWPM driver.
|
||||
*/
|
||||
element_mask_max = tegra_hwpm_safe_sub_u32(
|
||||
tegra_hwpm_safe_cast_u64_to_u32(BIT(
|
||||
ip_inst->num_core_elements_per_inst)),
|
||||
1U);
|
||||
ip_inst->fuse_fs_mask =
|
||||
(emc_element_floorsweep_mask &
|
||||
element_mask_max);
|
||||
tegra_hwpm_dbg(hwpm, hwpm_info,
|
||||
"ip %d, fuse_mask 0x%x",
|
||||
idx, ip_inst->fuse_fs_mask);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t234_hwpm_validate_current_config(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
u32 production_mode = 0U;
|
||||
@@ -215,6 +305,12 @@ int t234_hwpm_validate_current_config(struct tegra_soc_hwpm *hwpm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = t234_hwpm_validate_emc_config(hwpm);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "failed to validate emc config");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Read production mode fuse */
|
||||
err = tegra_hwpm_fuse_readl_prod_mode(hwpm, &production_mode);
|
||||
if (err != 0) {
|
||||
|
||||
@@ -335,6 +335,12 @@ struct hwpm_ip_inst {
|
||||
*/
|
||||
struct tegra_hwpm_ip_ops ip_ops;
|
||||
|
||||
/*
|
||||
* Some IPs set fuses to indicate floorsweeping info on platforms.
|
||||
* This mask will contain fuse fs info if any.
|
||||
*/
|
||||
u32 fuse_fs_mask;
|
||||
|
||||
/*
|
||||
* An IP contains perfmux-perfmon groups that correspond to each other.
|
||||
* If a perfmux is present, it indicates that the corresponding
|
||||
|
||||
Reference in New Issue
Block a user