mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-24 02:07:34 +03:00
tegra: hwpm: add HALs to support multiple chip
Add below HALs to make code chip agnostic. This will allow us to use t234 specific HALs for next chips. - get_pma_int_idx: get PMA's internal index corresponding to active chip - get_rtr_int_idx: get RTR's internal index corresponding to active chip - get_ip_max_idx: get MAX IP index corresponding to active chip Move chip agnostic code to common files. Jira THWPM-41 Change-Id: I5518469b1473fe7f66b6517cee729cf46520bbac Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2675515 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:
committed by
mobile promotions
parent
53f8d0799c
commit
ea5e4e406b
@@ -19,6 +19,154 @@
|
||||
#include <tegra_hwpm_common.h>
|
||||
#include <tegra_hwpm_static_analysis.h>
|
||||
|
||||
/* ip_idx indicates internal active ip index */
|
||||
static int tegra_hwpm_reserve_given_resource(struct tegra_soc_hwpm *hwpm,
|
||||
u32 ip_idx)
|
||||
{
|
||||
int err = 0, ret = 0;
|
||||
u32 perfmux_idx, perfmon_idx;
|
||||
unsigned long inst_idx = 0UL;
|
||||
unsigned long floorsweep_info = 0UL, reserved_insts = 0UL;
|
||||
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
||||
struct hwpm_ip *chip_ip = active_chip->chip_ips[ip_idx];
|
||||
hwpm_ip_perfmon *perfmon = NULL;
|
||||
hwpm_ip_perfmux *perfmux = NULL;
|
||||
|
||||
floorsweep_info = (unsigned long)chip_ip->fs_mask;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
tegra_hwpm_dbg(hwpm, hwpm_info, "Reserve IP %d, fs_mask 0x%x",
|
||||
ip_idx, chip_ip->fs_mask);
|
||||
|
||||
/* PMA and RTR are already reserved */
|
||||
if ((ip_idx == active_chip->get_pma_int_idx(hwpm)) ||
|
||||
(ip_idx == active_chip->get_rtr_int_idx(hwpm))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for_each_set_bit(inst_idx, &floorsweep_info, 32U) {
|
||||
/* Reserve all perfmon belonging to this instance */
|
||||
for (perfmon_idx = 0U; perfmon_idx < chip_ip->num_perfmon_slots;
|
||||
perfmon_idx++) {
|
||||
perfmon = chip_ip->ip_perfmon[perfmon_idx];
|
||||
|
||||
if (perfmon == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmon->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = tegra_hwpm_perfmon_reserve(hwpm, perfmon);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"IP %d perfmon %d reserve failed",
|
||||
ip_idx, perfmon_idx);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reserve all perfmux belonging to this instance */
|
||||
for (perfmux_idx = 0U; perfmux_idx < chip_ip->num_perfmux_slots;
|
||||
perfmux_idx++) {
|
||||
perfmux = chip_ip->ip_perfmux[perfmux_idx];
|
||||
|
||||
if (perfmux == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmux->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = tegra_hwpm_perfmux_reserve(hwpm, perfmux);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"IP %d perfmux %d reserve failed",
|
||||
ip_idx, perfmux_idx);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
reserved_insts |= BIT(inst_idx);
|
||||
}
|
||||
chip_ip->reserved = true;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
if (hwpm->active_chip->perfmon_disable == NULL) {
|
||||
tegra_hwpm_err(hwpm, "perfmon_disable HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (hwpm->active_chip->perfmux_disable == NULL) {
|
||||
tegra_hwpm_err(hwpm, "perfmux_disable HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* release reserved instances */
|
||||
for_each_set_bit(inst_idx, &reserved_insts, 32U) {
|
||||
/* Release all perfmon belonging to this instance */
|
||||
for (perfmon_idx = 0U; perfmon_idx < chip_ip->num_perfmon_slots;
|
||||
perfmon_idx++) {
|
||||
perfmon = chip_ip->ip_perfmon[perfmon_idx];
|
||||
|
||||
if (perfmon == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmon->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = hwpm->active_chip->perfmon_disable(hwpm, perfmon);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"IP %d perfmon %d disable failed",
|
||||
ip_idx, perfmon_idx);
|
||||
}
|
||||
|
||||
ret = tegra_hwpm_perfmon_release(hwpm, perfmon);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"IP %d perfmon %d release failed",
|
||||
ip_idx, perfmon_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release all perfmux belonging to this instance */
|
||||
for (perfmux_idx = 0U; perfmux_idx < chip_ip->num_perfmux_slots;
|
||||
perfmux_idx++) {
|
||||
perfmux = chip_ip->ip_perfmux[perfmux_idx];
|
||||
|
||||
if (perfmux == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmux->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = hwpm->active_chip->perfmux_disable(hwpm, perfmux);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"IP %d perfmux %d disable failed",
|
||||
ip_idx, perfmux_idx);
|
||||
}
|
||||
|
||||
ret = tegra_hwpm_perfmux_release(hwpm, perfmux);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"IP %d perfmux %d release failed",
|
||||
ip_idx, perfmux_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
|
||||
{
|
||||
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
||||
@@ -61,12 +209,7 @@ int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (active_chip->reserve_given_resource == NULL) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"reserve_given_resource HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = active_chip->reserve_given_resource(hwpm, ip_idx);
|
||||
ret = tegra_hwpm_reserve_given_resource(hwpm, ip_idx);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm, "Failed to reserve resource %d", resource);
|
||||
return ret;
|
||||
@@ -75,17 +218,250 @@ int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_hwpm_bind_reserved_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
||||
struct hwpm_ip *chip_ip = NULL;
|
||||
u32 ip_idx;
|
||||
u32 perfmux_idx, perfmon_idx;
|
||||
unsigned long inst_idx = 0UL;
|
||||
unsigned long floorsweep_info = 0UL;
|
||||
int err = 0;
|
||||
hwpm_ip_perfmon *perfmon = NULL;
|
||||
hwpm_ip_perfmux *perfmux = NULL;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
if (hwpm->active_chip->zero_alist_regs == NULL) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"zero_alist_regs HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (hwpm->active_chip->perfmon_enable == NULL) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"perfmon_enable HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (ip_idx = 0U; ip_idx < active_chip->get_ip_max_idx(hwpm);
|
||||
ip_idx++) {
|
||||
chip_ip = active_chip->chip_ips[ip_idx];
|
||||
|
||||
/* Skip unavailable IPs */
|
||||
if (!chip_ip->reserved) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chip_ip->fs_mask == 0U) {
|
||||
/* No IP instance is available */
|
||||
continue;
|
||||
}
|
||||
|
||||
floorsweep_info = (unsigned long)chip_ip->fs_mask;
|
||||
|
||||
for_each_set_bit(inst_idx, &floorsweep_info, 32U) {
|
||||
/* Zero out necessary perfmux registers */
|
||||
for (perfmux_idx = 0U;
|
||||
perfmux_idx < chip_ip->num_perfmux_slots;
|
||||
perfmux_idx++) {
|
||||
perfmux = chip_ip->ip_perfmux[perfmux_idx];
|
||||
|
||||
if (perfmux == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmux->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = hwpm->active_chip->zero_alist_regs(
|
||||
hwpm, perfmux);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmux %d zero regs failed",
|
||||
ip_idx, perfmux_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero out necessary perfmon registers */
|
||||
/* And enable reporting of PERFMON status */
|
||||
for (perfmon_idx = 0U;
|
||||
perfmon_idx < chip_ip->num_perfmon_slots;
|
||||
perfmon_idx++) {
|
||||
perfmon = chip_ip->ip_perfmon[perfmon_idx];
|
||||
|
||||
if (perfmon == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmon->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = hwpm->active_chip->zero_alist_regs(
|
||||
hwpm, perfmon);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmon %d zero regs failed",
|
||||
ip_idx, perfmon_idx);
|
||||
}
|
||||
|
||||
err = hwpm->active_chip->perfmon_enable(
|
||||
hwpm, perfmon);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmon %d enable failed",
|
||||
ip_idx, perfmon_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int tegra_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
ret = tegra_hwpm_bind_reserved_resources(hwpm);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm, "failed to bind resources");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_hwpm_release_all_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
|
||||
struct hwpm_ip *chip_ip = NULL;
|
||||
hwpm_ip_perfmon *perfmon = NULL;
|
||||
hwpm_ip_perfmux *perfmux = NULL;
|
||||
u32 ip_idx;
|
||||
u32 perfmux_idx, perfmon_idx;
|
||||
unsigned long floorsweep_info = 0UL;
|
||||
unsigned long inst_idx = 0UL;
|
||||
int err = 0;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
for (ip_idx = 0U; ip_idx < active_chip->get_ip_max_idx(hwpm);
|
||||
ip_idx++) {
|
||||
chip_ip = active_chip->chip_ips[ip_idx];
|
||||
|
||||
/* PMA and RTR will be released later */
|
||||
if ((ip_idx == active_chip->get_pma_int_idx(hwpm)) ||
|
||||
(ip_idx == active_chip->get_rtr_int_idx(hwpm))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Disable only available IPs */
|
||||
if (chip_ip->override_enable) {
|
||||
/* IP not available */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Disable and release only reserved IPs */
|
||||
if (!chip_ip->reserved) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chip_ip->fs_mask == 0U) {
|
||||
/* No IP instance is available */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hwpm->active_chip->perfmon_disable == NULL) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"perfmon_disable HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (hwpm->active_chip->perfmux_disable == NULL) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"perfmux_disable HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
floorsweep_info = (unsigned long)chip_ip->fs_mask;
|
||||
|
||||
for_each_set_bit(inst_idx, &floorsweep_info, 32U) {
|
||||
/* Release all perfmon associated with inst_idx */
|
||||
for (perfmon_idx = 0U;
|
||||
perfmon_idx < chip_ip->num_perfmon_slots;
|
||||
perfmon_idx++) {
|
||||
perfmon = chip_ip->ip_perfmon[perfmon_idx];
|
||||
|
||||
if (perfmon == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmon->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = hwpm->active_chip->perfmon_disable(
|
||||
hwpm, perfmon);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmon %d disable failed",
|
||||
ip_idx, perfmon_idx);
|
||||
}
|
||||
|
||||
err = tegra_hwpm_perfmon_release(hwpm, perfmon);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmon %d release failed",
|
||||
ip_idx, perfmon_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release all perfmux associated with inst_idx */
|
||||
for (perfmux_idx = 0U;
|
||||
perfmux_idx < chip_ip->num_perfmux_slots;
|
||||
perfmux_idx++) {
|
||||
perfmux = chip_ip->ip_perfmux[perfmux_idx];
|
||||
|
||||
if (perfmux == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (perfmux->hw_inst_mask != BIT(inst_idx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = hwpm->active_chip->perfmux_disable(
|
||||
hwpm, perfmux);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmux %d disable failed",
|
||||
ip_idx, perfmux_idx);
|
||||
}
|
||||
|
||||
err = tegra_hwpm_perfmux_release(hwpm, perfmux);
|
||||
if (err != 0) {
|
||||
tegra_hwpm_err(hwpm, "IP %d"
|
||||
" perfmux %d release failed",
|
||||
ip_idx, perfmux_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
chip_ip->reserved = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_hwpm_release_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
if (hwpm->active_chip->release_all_resources == NULL) {
|
||||
tegra_hwpm_err(hwpm, "release_resources HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = hwpm->active_chip->release_all_resources(hwpm);
|
||||
ret = tegra_hwpm_release_all_resources(hwpm);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm, "failed to release resources");
|
||||
return ret;
|
||||
@@ -93,23 +469,3 @@ int tegra_hwpm_release_resources(struct tegra_soc_hwpm *hwpm)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
tegra_hwpm_fn(hwpm, " ");
|
||||
|
||||
if (hwpm->active_chip->bind_reserved_resources == NULL) {
|
||||
tegra_hwpm_err(hwpm,
|
||||
"bind_reserved_resources HAL uninitialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = hwpm->active_chip->bind_reserved_resources(hwpm);
|
||||
if (ret != 0) {
|
||||
tegra_hwpm_err(hwpm, "failed to bind resources");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user