diff --git a/common/tegra_hwpm_init.c b/common/tegra_hwpm_init.c index b210163..30f7d5c 100644 --- a/common/tegra_hwpm_init.c +++ b/common/tegra_hwpm_init.c @@ -135,8 +135,15 @@ void tegra_hwpm_release_sw_components(struct tegra_soc_hwpm *hwpm) int tegra_hwpm_setup_sw(struct tegra_soc_hwpm *hwpm) { + int ret = 0; tegra_hwpm_fn(hwpm, " "); + ret = hwpm->active_chip->validate_current_config(hwpm); + if (ret != 0) { + tegra_hwpm_err(hwpm, "Failed to validate current conifg"); + return ret; + } + /* Initialize SW state */ hwpm->bind_completed = false; hwpm->full_alist_size = 0; diff --git a/common/tegra_hwpm_ip_utils.c b/common/tegra_hwpm_ip_utils.c index 0a04c72..b5c4f3e 100644 --- a/common/tegra_hwpm_ip_utils.c +++ b/common/tegra_hwpm_ip_utils.c @@ -297,10 +297,11 @@ int tegra_hwpm_finalize_chip_info(struct tegra_soc_hwpm *hwpm) ret = hwpm->active_chip->force_enable_ips(hwpm); if (ret != 0) { tegra_hwpm_err(hwpm, "Failed to force enable IPs"); - return ret; + /* Do not fail because of force enable failure */ + return 0; } - return ret; + return 0; } static bool tegra_hwpm_addr_in_single_element(struct tegra_soc_hwpm *hwpm, diff --git a/hal/t234/hw/t234_addr_map_soc_hwpm.h b/hal/t234/hw/t234_addr_map_soc_hwpm.h index 949d571..f5f6c98 100644 --- a/hal/t234/hw/t234_addr_map_soc_hwpm.h +++ b/hal/t234/hw/t234_addr_map_soc_hwpm.h @@ -262,4 +262,5 @@ #define addr_map_mss_nvlink_8_limit_r() (0x01e1ffffU) #define addr_map_rpg_pm_scf_base_r() (0x0f110000U) #define addr_map_rpg_pm_scf_limit_r() (0x0f110fffU) +#define addr_map_pmc_misc_base_r() (0x0c3a0000U) #endif diff --git a/hal/t234/ip/display/t234_hwpm_ip_display.c b/hal/t234/ip/display/t234_hwpm_ip_display.c index 4800cb9..f122f16 100644 --- a/hal/t234/ip/display/t234_hwpm_ip_display.c +++ b/hal/t234/ip/display/t234_hwpm_ip_display.c @@ -166,6 +166,8 @@ struct hwpm_ip t234_hwpm_ip_display = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/isp/t234_hwpm_ip_isp.c b/hal/t234/ip/isp/t234_hwpm_ip_isp.c index a71cf91..82dc04f 100644 --- a/hal/t234/ip/isp/t234_hwpm_ip_isp.c +++ b/hal/t234/ip/isp/t234_hwpm_ip_isp.c @@ -163,6 +163,8 @@ struct hwpm_ip t234_hwpm_ip_isp = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/mgbe/t234_hwpm_ip_mgbe.c b/hal/t234/ip/mgbe/t234_hwpm_ip_mgbe.c index 042c1bd..eb7e26c 100644 --- a/hal/t234/ip/mgbe/t234_hwpm_ip_mgbe.c +++ b/hal/t234/ip/mgbe/t234_hwpm_ip_mgbe.c @@ -461,6 +461,8 @@ struct hwpm_ip t234_hwpm_ip_mgbe = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/mss_channel/t234_hwpm_ip_mss_channel.c b/hal/t234/ip/mss_channel/t234_hwpm_ip_mss_channel.c index 63fae2f..4970ecc 100644 --- a/hal/t234/ip/mss_channel/t234_hwpm_ip_mss_channel.c +++ b/hal/t234/ip/mss_channel/t234_hwpm_ip_mss_channel.c @@ -637,6 +637,7 @@ struct hwpm_ip t234_hwpm_ip_mss_channel = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .reserved = false, diff --git a/hal/t234/ip/mss_gpu_hub/t234_hwpm_ip_mss_gpu_hub.c b/hal/t234/ip/mss_gpu_hub/t234_hwpm_ip_mss_gpu_hub.c index b1d47fd..95f068b 100644 --- a/hal/t234/ip/mss_gpu_hub/t234_hwpm_ip_mss_gpu_hub.c +++ b/hal/t234/ip/mss_gpu_hub/t234_hwpm_ip_mss_gpu_hub.c @@ -269,6 +269,7 @@ struct hwpm_ip t234_hwpm_ip_mss_gpu_hub = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/mss_iso_niso_hubs/t234_hwpm_ip_mss_iso_niso_hubs.c b/hal/t234/ip/mss_iso_niso_hubs/t234_hwpm_ip_mss_iso_niso_hubs.c index 2ac5ab9..faf3121 100644 --- a/hal/t234/ip/mss_iso_niso_hubs/t234_hwpm_ip_mss_iso_niso_hubs.c +++ b/hal/t234/ip/mss_iso_niso_hubs/t234_hwpm_ip_mss_iso_niso_hubs.c @@ -331,6 +331,7 @@ struct hwpm_ip t234_hwpm_ip_mss_iso_niso_hubs = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/mss_mcf/t234_hwpm_ip_mss_mcf.c b/hal/t234/ip/mss_mcf/t234_hwpm_ip_mss_mcf.c index 016207c..7e97bdd 100644 --- a/hal/t234/ip/mss_mcf/t234_hwpm_ip_mss_mcf.c +++ b/hal/t234/ip/mss_mcf/t234_hwpm_ip_mss_mcf.c @@ -323,6 +323,7 @@ struct hwpm_ip t234_hwpm_ip_mss_mcf = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/nvdec/t234_hwpm_ip_nvdec.c b/hal/t234/ip/nvdec/t234_hwpm_ip_nvdec.c index 8c0e07a..cf5fae6 100644 --- a/hal/t234/ip/nvdec/t234_hwpm_ip_nvdec.c +++ b/hal/t234/ip/nvdec/t234_hwpm_ip_nvdec.c @@ -164,6 +164,8 @@ struct hwpm_ip t234_hwpm_ip_nvdec = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/nvdla/t234_hwpm_ip_nvdla.c b/hal/t234/ip/nvdla/t234_hwpm_ip_nvdla.c index 6b7a001..cc1bcae 100644 --- a/hal/t234/ip/nvdla/t234_hwpm_ip_nvdla.c +++ b/hal/t234/ip/nvdla/t234_hwpm_ip_nvdla.c @@ -263,6 +263,8 @@ struct hwpm_ip t234_hwpm_ip_nvdla = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/nvenc/t234_hwpm_ip_nvenc.c b/hal/t234/ip/nvenc/t234_hwpm_ip_nvenc.c index 40edb64..ee30893 100644 --- a/hal/t234/ip/nvenc/t234_hwpm_ip_nvenc.c +++ b/hal/t234/ip/nvenc/t234_hwpm_ip_nvenc.c @@ -164,6 +164,8 @@ struct hwpm_ip t234_hwpm_ip_nvenc = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/ofa/t234_hwpm_ip_ofa.c b/hal/t234/ip/ofa/t234_hwpm_ip_ofa.c index e5a9158..05234de 100644 --- a/hal/t234/ip/ofa/t234_hwpm_ip_ofa.c +++ b/hal/t234/ip/ofa/t234_hwpm_ip_ofa.c @@ -164,6 +164,8 @@ struct hwpm_ip t234_hwpm_ip_ofa = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/pcie/t234_hwpm_ip_pcie.c b/hal/t234/ip/pcie/t234_hwpm_ip_pcie.c index 24e4b4e..4f83875 100644 --- a/hal/t234/ip/pcie/t234_hwpm_ip_pcie.c +++ b/hal/t234/ip/pcie/t234_hwpm_ip_pcie.c @@ -1155,6 +1155,8 @@ struct hwpm_ip t234_hwpm_ip_pcie = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/pma/t234_hwpm_ip_pma.c b/hal/t234/ip/pma/t234_hwpm_ip_pma.c index 5c8e55f..b426830 100644 --- a/hal/t234/ip/pma/t234_hwpm_ip_pma.c +++ b/hal/t234/ip/pma/t234_hwpm_ip_pma.c @@ -164,6 +164,8 @@ struct hwpm_ip t234_hwpm_ip_pma = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0x1U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_VALID, diff --git a/hal/t234/ip/pva/t234_hwpm_ip_pva.c b/hal/t234/ip/pva/t234_hwpm_ip_pva.c index d9c0566..8177f8b 100644 --- a/hal/t234/ip/pva/t234_hwpm_ip_pva.c +++ b/hal/t234/ip/pva/t234_hwpm_ip_pva.c @@ -194,6 +194,8 @@ struct hwpm_ip t234_hwpm_ip_pva = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/rtr/t234_hwpm_ip_rtr.c b/hal/t234/ip/rtr/t234_hwpm_ip_rtr.c index 6cd53d8..f100480 100644 --- a/hal/t234/ip/rtr/t234_hwpm_ip_rtr.c +++ b/hal/t234/ip/rtr/t234_hwpm_ip_rtr.c @@ -225,6 +225,7 @@ struct hwpm_ip t234_hwpm_ip_rtr = { }, }, + .dependent_fuse_mask = 0U, .override_enable = false, /* RTR is defined as 2 instance IP corresponding to router and pma */ /* Set this mask to indicate that instances are available */ diff --git a/hal/t234/ip/scf/t234_hwpm_ip_scf.c b/hal/t234/ip/scf/t234_hwpm_ip_scf.c index 0d601cd..62a9271 100644 --- a/hal/t234/ip/scf/t234_hwpm_ip_scf.c +++ b/hal/t234/ip/scf/t234_hwpm_ip_scf.c @@ -142,6 +142,8 @@ struct hwpm_ip t234_hwpm_ip_scf = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0x1U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_VALID, diff --git a/hal/t234/ip/vi/t234_hwpm_ip_vi.c b/hal/t234/ip/vi/t234_hwpm_ip_vi.c index f734546..02f850b 100644 --- a/hal/t234/ip/vi/t234_hwpm_ip_vi.c +++ b/hal/t234/ip/vi/t234_hwpm_ip_vi.c @@ -265,6 +265,8 @@ struct hwpm_ip t234_hwpm_ip_vi = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/ip/vic/t234_hwpm_ip_vic.c b/hal/t234/ip/vic/t234_hwpm_ip_vic.c index 154fcd6..c62328f 100644 --- a/hal/t234/ip/vic/t234_hwpm_ip_vic.c +++ b/hal/t234/ip/vic/t234_hwpm_ip_vic.c @@ -164,6 +164,8 @@ struct hwpm_ip t234_hwpm_ip_vic = { }, }, + .dependent_fuse_mask = TEGRA_HWPM_FUSE_SECURITY_MODE_MASK | + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK, .override_enable = false, .inst_fs_mask = 0U, .resource_status = TEGRA_HWPM_RESOURCE_STATUS_INVALID, diff --git a/hal/t234/t234_hwpm_interface_utils.c b/hal/t234/t234_hwpm_interface_utils.c index d505625..31e55b8 100644 --- a/hal/t234/t234_hwpm_interface_utils.c +++ b/hal/t234/t234_hwpm_interface_utils.c @@ -33,6 +33,7 @@ struct tegra_soc_hwpm_chip t234_chip_info = { .extract_ip_ops = t234_hwpm_extract_ip_ops, .force_enable_ips = t234_hwpm_force_enable_ips, + .validate_current_config = t234_hwpm_validate_current_config, .get_fs_info = t234_hwpm_get_fs_info, .get_resource_info = t234_hwpm_get_resource_info, @@ -97,6 +98,11 @@ static bool t234_hwpm_validate_hals(struct tegra_soc_hwpm *hwpm) return false; } + if (hwpm->active_chip->validate_current_config == NULL) { + tegra_hwpm_err(hwpm, "validate_current_config uninitialized"); + return false; + } + if (hwpm->active_chip->get_fs_info == NULL) { tegra_hwpm_err(hwpm, "get_fs_info uninitialized"); return false; diff --git a/hal/t234/t234_hwpm_internal.h b/hal/t234/t234_hwpm_internal.h index 20713ab..5851e65 100644 --- a/hal/t234/t234_hwpm_internal.h +++ b/hal/t234/t234_hwpm_internal.h @@ -79,6 +79,7 @@ u32 t234_get_ip_max_idx(struct tegra_soc_hwpm *hwpm); int t234_hwpm_extract_ip_ops(struct tegra_soc_hwpm *hwpm, struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops, bool available); int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm); +int t234_hwpm_validate_current_config(struct tegra_soc_hwpm *hwpm); int t234_hwpm_get_fs_info(struct tegra_soc_hwpm *hwpm, u32 ip_enum, u64 *fs_mask, u8 *ip_status); int t234_hwpm_get_resource_info(struct tegra_soc_hwpm *hwpm, diff --git a/hal/t234/t234_hwpm_ip_utils.c b/hal/t234/t234_hwpm_ip_utils.c index 0cda670..00086f8 100644 --- a/hal/t234/t234_hwpm_ip_utils.c +++ b/hal/t234/t234_hwpm_ip_utils.c @@ -14,9 +14,10 @@ #include #include +#include +#include #include #include -#include #include #include #include @@ -186,9 +187,86 @@ fail: return ret; } +int t234_hwpm_validate_current_config(struct tegra_soc_hwpm *hwpm) +{ + u32 production_mode = 0U; + u32 security_mode = 0U; + u32 hwpm_global_disable = 0U; + u32 idx = 0U; + int err; + struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip; + struct hwpm_ip *chip_ip = NULL; + + tegra_hwpm_fn(hwpm, " "); + + if (!tegra_platform_is_silicon()) { + return 0; + } + + /* Read production mode fuse */ + err = tegra_fuse_readl(TEGRA_FUSE_PRODUCTION_MODE, &production_mode); + if (err != 0) { + tegra_hwpm_err(hwpm, "prod mode fuse read failed"); + return err; + } + +#define TEGRA_FUSE_SECURITY_MODE 0xA0U + err = tegra_fuse_readl(TEGRA_FUSE_SECURITY_MODE, &security_mode); + if (err != 0) { + tegra_hwpm_err(hwpm, "security mode fuse read failed"); + return err; + } + +#define TEGRA_HWPM_GLOBAL_DISABLE_OFFSET 0x3CU +#define TEGRA_HWPM_GLOBAL_DISABLE_DISABLED 0x1U + err = tegra_hwpm_read_sticky_bits(hwpm, addr_map_pmc_misc_base_r(), + TEGRA_HWPM_GLOBAL_DISABLE_OFFSET, &hwpm_global_disable); + if (err != 0) { + tegra_hwpm_err(hwpm, "hwpm global disable read failed"); + return err; + } + + /* Override enable depends on security mode and global hwpm disable */ + if ((security_mode == 0U) && + (hwpm_global_disable == TEGRA_HWPM_GLOBAL_DISABLE_DISABLED)) { + tegra_hwpm_dbg(hwpm, hwpm_info, "PROD_MODE fuse = 0x%x " + "SECURITY_MODE fuse = 0x%x HWPM_GLOBAL_DISABLE = 0x%x," + " no override required", + production_mode, security_mode, hwpm_global_disable); + return 0; + } + + for (idx = 0U; idx < active_chip->get_ip_max_idx(hwpm); idx++) { + chip_ip = active_chip->chip_ips[idx]; + + if ((hwpm_global_disable != + TEGRA_HWPM_GLOBAL_DISABLE_DISABLED) && + ((chip_ip->dependent_fuse_mask & + TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK) != 0U)) { + /* HWPM disable is true */ + /* IP depends on HWPM global disable */ + chip_ip->override_enable = true; + } else { + /* HWPM disable is false */ + if ((security_mode != 0U) && + ((chip_ip->dependent_fuse_mask & + TEGRA_HWPM_FUSE_SECURITY_MODE_MASK) != 0U)) { + /* Security mode fuse is set */ + /* IP depends on security mode fuse */ + chip_ip->override_enable = true; + } else { + tegra_hwpm_err(hwpm, + "Execution shouldn't reach here"); + } + } + } + + return 0; +} + int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) { - int ret = 0; + int ret = 0, err = 0; tegra_hwpm_fn(hwpm, " "); @@ -200,7 +278,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_mc0_base_r(), T234_HWPM_IP_MSS_CHANNEL, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_MSS_CHANNEL force enable failed"); + err = ret; } #endif #if defined(CONFIG_SOC_HWPM_IP_MSS_GPU_HUB) @@ -210,7 +290,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_mss_nvlink_1_base_r(), T234_HWPM_IP_MSS_GPU_HUB, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_MSS_GPU_HUB force enable failed"); + err = ret; } #endif } @@ -223,13 +305,17 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_vi_thi_base_r(), T234_HWPM_IP_VI, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_VI force enable failed"); + err = ret; } ret = tegra_hwpm_set_fs_info_ip_ops(hwpm, NULL, addr_map_vi2_thi_base_r(), T234_HWPM_IP_VI, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_VI force enable failed"); + err = ret; } #endif */ @@ -239,7 +325,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_isp_thi_base_r(), T234_HWPM_IP_ISP, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_ISP force enable failed"); + err = ret; } #endif @@ -264,7 +352,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_mgbe0_mac_rm_base_r(), T234_HWPM_IP_MGBE, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_MGBE force enable failed"); + err = ret; } #endif */ @@ -275,7 +365,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_rpg_pm_scf_base_r(), T234_HWPM_IP_SCF, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_SCF force enable failed"); + err = ret; } #endif #if defined(CONFIG_SOC_HWPM_IP_NVDEC) @@ -285,7 +377,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_nvdec_base_r(), T234_HWPM_IP_NVDEC, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_NVDEC force enable failed"); + err = ret; } #endif @@ -296,19 +390,25 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_pcie_c1_ctl_base_r(), T234_HWPM_IP_PCIE, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_PCIE force enable failed"); + err = ret; } ret = tegra_hwpm_set_fs_info_ip_ops(hwpm, NULL, addr_map_pcie_c4_ctl_base_r(), T234_HWPM_IP_PCIE, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_PCIE force enable failed"); + err = ret; } ret = tegra_hwpm_set_fs_info_ip_ops(hwpm, NULL, addr_map_pcie_c5_ctl_base_r(), T234_HWPM_IP_PCIE, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_PCIE force enable failed"); + err = ret; } #endif */ @@ -320,7 +420,9 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_disp_base_r(), T234_HWPM_IP_DISPLAY, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_DISPLAY force enable failed"); + err = ret; } #endif */ @@ -331,12 +433,14 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) addr_map_mss_nvlink_1_base_r(), T234_HWPM_IP_MSS_GPU_HUB, true); if (ret != 0) { - return ret; + tegra_hwpm_err(hwpm, + "T234_HWPM_IP_MSS_GPU_HUB force enable failed"); + err = ret; } #endif } - return 0; + return err; } int t234_hwpm_get_fs_info(struct tegra_soc_hwpm *hwpm, @@ -351,31 +455,39 @@ int t234_hwpm_get_fs_info(struct tegra_soc_hwpm *hwpm, tegra_hwpm_fn(hwpm, " "); /* Convert tegra_soc_hwpm_ip enum to internal ip index */ - if (!(t234_hwpm_is_ip_active(hwpm, ip_enum, &ip_idx))) { - tegra_hwpm_dbg(hwpm, hwpm_info, - "SOC hwpm IP %d is unavailable", ip_enum); + if (t234_hwpm_is_ip_active(hwpm, ip_enum, &ip_idx)) { + active_chip = hwpm->active_chip; + chip_ip = active_chip->chip_ips[ip_idx]; - *ip_status = TEGRA_SOC_HWPM_IP_STATUS_INVALID; - *fs_mask = 0ULL; - return 0; - } + if (!(chip_ip->override_enable)) { + for (inst_idx = 0U; inst_idx < chip_ip->num_instances; + inst_idx++) { + ip_inst = &chip_ip->ip_inst_static_array[ + inst_idx]; + element_mask_shift = (inst_idx == 0U ? 0U : + ip_inst->num_core_elements_per_inst); - active_chip = hwpm->active_chip; - chip_ip = active_chip->chip_ips[ip_idx]; + if (ip_inst->hw_inst_mask & + chip_ip->inst_fs_mask) { + floorsweep = (floorsweep << + element_mask_shift); + floorsweep |= + ((u64)ip_inst->element_fs_mask); + } + } - for (inst_idx = 0U; inst_idx < chip_ip->num_instances; inst_idx++) { - ip_inst = &chip_ip->ip_inst_static_array[inst_idx]; - element_mask_shift = (inst_idx == 0U ? - 0U : ip_inst->num_core_elements_per_inst); + *fs_mask = floorsweep; + *ip_status = TEGRA_SOC_HWPM_IP_STATUS_VALID; - if (ip_inst->hw_inst_mask & chip_ip->inst_fs_mask) { - floorsweep = (floorsweep << element_mask_shift); - floorsweep |= ((u64)ip_inst->element_fs_mask); + return 0; } } - *fs_mask = floorsweep; - *ip_status = TEGRA_SOC_HWPM_IP_STATUS_VALID; + tegra_hwpm_dbg(hwpm, hwpm_info, + "SOC hwpm IP %d is unavailable", ip_enum); + + *ip_status = TEGRA_SOC_HWPM_IP_STATUS_INVALID; + *fs_mask = 0ULL; return 0; } @@ -390,14 +502,18 @@ int t234_hwpm_get_resource_info(struct tegra_soc_hwpm *hwpm, tegra_hwpm_fn(hwpm, " "); /* Convert tegra_soc_hwpm_resource to internal enum */ - if (!(t234_hwpm_is_resource_active(hwpm, resource_enum, &ip_idx))) { - *status = tegra_hwpm_safe_cast_u32_to_u8( - TEGRA_HWPM_RESOURCE_STATUS_INVALID); - } else { + if (t234_hwpm_is_resource_active(hwpm, resource_enum, &ip_idx)) { chip_ip = active_chip->chip_ips[ip_idx]; - *status = tegra_hwpm_safe_cast_u32_to_u8( + + if (!(chip_ip->override_enable)) { + *status = tegra_hwpm_safe_cast_u32_to_u8( chip_ip->resource_status); + return 0; + } } + *status = tegra_hwpm_safe_cast_u32_to_u8( + TEGRA_HWPM_RESOURCE_STATUS_INVALID); + return 0; } diff --git a/include/tegra_hwpm.h b/include/tegra_hwpm.h index 5b4f23a..abb5270 100644 --- a/include/tegra_hwpm.h +++ b/include/tegra_hwpm.h @@ -94,6 +94,10 @@ struct tegra_hwpm_ip_ops { #define TEGRA_HWPM_RESOURCE_STATUS_VALID \ TEGRA_SOC_HWPM_RESOURCE_STATUS_VALID +#define TEGRA_HWPM_FUSE_PRODUCTION_MODE_MASK BIT(0) +#define TEGRA_HWPM_FUSE_SECURITY_MODE_MASK BIT(1) +#define TEGRA_HWPM_FUSE_HWPM_GLOBAL_DISABLE_MASK BIT(2) + /* * Devices handled by HWPM driver can be divided into 2 categories * - HWPM : Components in HWPM device address space @@ -287,6 +291,13 @@ struct hwpm_ip { struct hwpm_ip_inst_per_aperture_info inst_aperture_info[ TEGRA_HWPM_APERTURE_TYPE_MAX]; + /* + * Indicates fuses this IP depends on + * If fuse corresponding to the mask is blown, + * set override_enable = true + */ + u32 dependent_fuse_mask; + /* Override IP config based on fuse value */ bool override_enable; @@ -327,6 +338,7 @@ struct tegra_soc_hwpm_chip { int (*extract_ip_ops)(struct tegra_soc_hwpm *hwpm, struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops, bool available); int (*force_enable_ips)(struct tegra_soc_hwpm *hwpm); + int (*validate_current_config)(struct tegra_soc_hwpm *hwpm); int (*get_fs_info)(struct tegra_soc_hwpm *hwpm, u32 ip_enum, u64 *fs_mask, u8 *ip_status); int (*get_resource_info)(struct tegra_soc_hwpm *hwpm, diff --git a/include/tegra_hwpm_io.h b/include/tegra_hwpm_io.h index 1720f4f..b8b0f5b 100644 --- a/include/tegra_hwpm_io.h +++ b/include/tegra_hwpm_io.h @@ -54,6 +54,8 @@ struct tegra_soc_hwpm; struct hwpm_ip_inst; struct hwpm_ip_aperture; +int tegra_hwpm_read_sticky_bits(struct tegra_soc_hwpm *hwpm, + u64 reg_base, u64 reg_offset, u32 *val); int tegra_hwpm_readl(struct tegra_soc_hwpm *hwpm, struct hwpm_ip_aperture *aperture, u64 addr, u32 *val); int tegra_hwpm_writel(struct tegra_soc_hwpm *hwpm, diff --git a/os/linux/tegra_hwpm_io.c b/os/linux/tegra_hwpm_io.c index 2cbe8b4..6b69796 100644 --- a/os/linux/tegra_hwpm_io.c +++ b/os/linux/tegra_hwpm_io.c @@ -23,6 +23,24 @@ #include #include +int tegra_hwpm_read_sticky_bits(struct tegra_soc_hwpm *hwpm, + u64 reg_base, u64 reg_offset, u32 *val) +{ + void __iomem *ptr = NULL; + u64 reg_addr = tegra_hwpm_safe_add_u64(reg_base, reg_offset); + + ptr = ioremap(reg_addr, 0x4); + if (!ptr) { + tegra_hwpm_err(hwpm, "Failed to map register(0x%llx)", + reg_addr); + return -ENODEV; + } + *val = __raw_readl(ptr); + iounmap(ptr); + + return 0; +} + static int fake_readl(struct tegra_soc_hwpm *hwpm, struct hwpm_ip_aperture *aperture, u64 offset, u32 *val) {