tegra: hwpm: combine common functionality

- Many HWPM functions are performed on all apertures of all instances of
all IPs. Define below resource utility functions to perform a task on
all IPs, instances and apertures:
  - tegra_hwpm_func_all_IPs
  - tegra_hwpm_func_single_ip
  - tegra_hwpm_func_all_instance
  - tegra_hwpm_func_single_instance
  - tegra_hwpm_func_all_perfmuxes
  - tegra_hwpm_func_all_perfmons
  - tegra_hwpm_func_single_aperture
- Modify below functions to use above mentioned utility functions:
  - get allowlist size
  - combine allowlist
  - reserve resources
  - bind resources
  - release resources

This will make code more legible and maintainable.

This patch also defines new function that validates all HAL
initializations for the chip.

Jira THWPM-41

Change-Id: Icaeba4d94187b97022c0a6626584e7d61ab6d0e4
Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2705524
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-04-30 22:49:36 -07:00
committed by mobile promotions
parent c5b3d09518
commit 25f0737897
9 changed files with 621 additions and 647 deletions

View File

@@ -28,92 +28,6 @@
#include <tegra_hwpm_common.h>
#include <tegra_hwpm_static_analysis.h>
static int tegra_hwpm_get_alist_size(struct tegra_soc_hwpm *hwpm)
{
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
u32 ip_idx;
u32 perfmux_idx, perfmon_idx;
unsigned long inst_idx = 0UL;
unsigned long floorsweep_info = 0UL;
struct hwpm_ip *chip_ip = NULL;
hwpm_ip_perfmux *perfmux = NULL;
hwpm_ip_perfmon *perfmon = NULL;
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];
/* 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) {
/* Add perfmux alist size to full alist size */
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;
}
if (perfmux->alist) {
hwpm->full_alist_size =
tegra_hwpm_safe_add_u64(
hwpm->full_alist_size,
perfmux->alist_size);
} else {
tegra_hwpm_err(hwpm, "IP %d"
" perfmux %d NULL alist",
ip_idx, perfmux_idx);
}
}
/* Add perfmon alist size to full alist size */
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;
}
if (perfmon->alist) {
hwpm->full_alist_size =
tegra_hwpm_safe_add_u64(
hwpm->full_alist_size,
perfmon->alist_size);
} else {
tegra_hwpm_err(hwpm, "IP %d"
" perfmon %d NULL alist",
ip_idx, perfmon_idx);
}
}
}
}
return 0;
}
int tegra_hwpm_get_allowlist_size(struct tegra_soc_hwpm *hwpm)
{
@@ -123,7 +37,7 @@ int tegra_hwpm_get_allowlist_size(struct tegra_soc_hwpm *hwpm)
tegra_hwpm_fn(hwpm, " ");
ret = tegra_hwpm_get_alist_size(hwpm);
ret = tegra_hwpm_func_all_ip(hwpm, NULL, TEGRA_HWPM_GET_ALIST_SIZE);
if (ret != 0) {
tegra_hwpm_err(hwpm, "get_alist_size failed");
return ret;
@@ -134,100 +48,29 @@ int tegra_hwpm_get_allowlist_size(struct tegra_soc_hwpm *hwpm)
static int tegra_hwpm_combine_alist(struct tegra_soc_hwpm *hwpm, u64 *alist)
{
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
u32 ip_idx;
u32 perfmux_idx, perfmon_idx;
unsigned long inst_idx = 0UL;
unsigned long floorsweep_info = 0UL;
struct hwpm_ip *chip_ip = NULL;
hwpm_ip_perfmux *perfmux = NULL;
hwpm_ip_perfmon *perfmon = NULL;
u64 full_alist_idx = 0;
struct tegra_hwpm_func_args func_args;
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];
func_args.alist = alist;
func_args.full_alist_idx = 0ULL;
/* Skip unavailable IPs */
if (!chip_ip->reserved) {
continue;
}
if (chip_ip->fs_mask == 0U) {
/* No IP instance is available */
continue;
}
if (hwpm->active_chip->copy_alist == NULL) {
tegra_hwpm_err(hwpm, "copy_alist uninitialized");
return -ENODEV;
}
floorsweep_info = (unsigned long)chip_ip->fs_mask;
for_each_set_bit(inst_idx, &floorsweep_info, 32U) {
/* Copy perfmux alist to full alist array */
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->copy_alist(hwpm,
perfmux, alist, &full_alist_idx);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d"
" perfmux %d alist copy failed",
ip_idx, perfmux_idx);
goto fail;
}
}
/* Copy perfmon alist to full alist array */
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->copy_alist(hwpm,
perfmon, alist, &full_alist_idx);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d"
" perfmon %d alist copy failed",
ip_idx, perfmon_idx);
goto fail;
}
}
}
err = tegra_hwpm_func_all_ip(hwpm, &func_args,
TEGRA_HWPM_COMBINE_ALIST);
if (err != 0) {
tegra_hwpm_err(hwpm, "combine alist failed");
return err;
}
/* Check size of full alist with hwpm->full_alist_size*/
if (full_alist_idx != hwpm->full_alist_size) {
if (func_args.full_alist_idx != hwpm->full_alist_size) {
tegra_hwpm_err(hwpm, "full_alist_size 0x%llx doesn't match "
"max full_alist_idx 0x%llx",
hwpm->full_alist_size, full_alist_idx);
hwpm->full_alist_size, func_args.full_alist_idx);
err = -EINVAL;
}
fail:
return err;
}
@@ -253,10 +96,7 @@ int tegra_hwpm_update_allowlist(struct tegra_soc_hwpm *hwpm,
tegra_hwpm_err(hwpm, "Invalid allowlist size");
return -EINVAL;
}
if (hwpm->active_chip->get_alist_buf_size == NULL) {
tegra_hwpm_err(hwpm, "alist_buf_size uninitialized");
return -ENODEV;
}
alist_buf_size = tegra_hwpm_safe_mult_u64(hwpm->full_alist_size,
hwpm->active_chip->get_alist_buf_size(hwpm));

View File

@@ -81,10 +81,6 @@ int tegra_hwpm_init_sw_components(struct tegra_soc_hwpm *hwpm)
return err;
}
if (hwpm->active_chip->init_chip_ip_structures == NULL) {
tegra_hwpm_err(hwpm, "init_chip_ip_structures uninitialized");
}
err = hwpm->active_chip->init_chip_ip_structures(hwpm);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP structure init failed");
@@ -101,11 +97,7 @@ void tegra_hwpm_release_sw_components(struct tegra_soc_hwpm *hwpm)
tegra_hwpm_fn(hwpm, " ");
if (hwpm->active_chip->release_sw_setup == NULL) {
tegra_hwpm_err(hwpm, "release_sw_setup uninitialized");
} else {
hwpm->active_chip->release_sw_setup(hwpm);
}
hwpm->active_chip->release_sw_setup(hwpm);
while (node != NULL) {
tmp_node = node;
@@ -152,20 +144,12 @@ int tegra_hwpm_setup_hw(struct tegra_soc_hwpm *hwpm)
* Map/reserve these apertures to get MMIO address required for hwpm
* configuration (following steps).
*/
if (hwpm->active_chip->reserve_pma == NULL) {
tegra_hwpm_err(hwpm, "reserve_pma uninitialized");
goto enodev;
}
ret = hwpm->active_chip->reserve_pma(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to reserve PMA aperture");
goto fail;
}
if (hwpm->active_chip->reserve_rtr == NULL) {
tegra_hwpm_err(hwpm, "reserve_rtr uninitialized");
goto enodev;
}
ret = hwpm->active_chip->reserve_rtr(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to reserve RTR aperture");
@@ -173,10 +157,6 @@ int tegra_hwpm_setup_hw(struct tegra_soc_hwpm *hwpm)
}
/* Disable SLCG */
if (hwpm->active_chip->disable_slcg == NULL) {
tegra_hwpm_err(hwpm, "disable_slcg uninitialized");
goto enodev;
}
ret = hwpm->active_chip->disable_slcg(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to disable SLCG");
@@ -184,10 +164,6 @@ int tegra_hwpm_setup_hw(struct tegra_soc_hwpm *hwpm)
}
/* Program PROD values */
if (hwpm->active_chip->init_prod_values == NULL) {
tegra_hwpm_err(hwpm, "init_prod_values uninitialized");
goto enodev;
}
ret = hwpm->active_chip->init_prod_values(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to set PROD values");
@@ -195,8 +171,6 @@ int tegra_hwpm_setup_hw(struct tegra_soc_hwpm *hwpm)
}
return 0;
enodev:
ret = -ENODEV;
fail:
return ret;
}
@@ -205,10 +179,6 @@ int tegra_hwpm_disable_triggers(struct tegra_soc_hwpm *hwpm)
{
tegra_hwpm_fn(hwpm, " ");
if (hwpm->active_chip->disable_triggers == NULL) {
tegra_hwpm_err(hwpm, "disable_triggers uninitialized");
return -ENODEV;
}
return hwpm->active_chip->disable_triggers(hwpm);
}
@@ -219,10 +189,6 @@ int tegra_hwpm_release_hw(struct tegra_soc_hwpm *hwpm)
tegra_hwpm_fn(hwpm, " ");
/* Enable SLCG */
if (hwpm->active_chip->enable_slcg == NULL) {
tegra_hwpm_err(hwpm, "enable_slcg uninitialized");
goto enodev;
}
ret = hwpm->active_chip->enable_slcg(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to enable SLCG");
@@ -235,20 +201,12 @@ int tegra_hwpm_release_hw(struct tegra_soc_hwpm *hwpm)
* these aperture mappings are required to reset hwpm config.
* Hence, explicitly unmap/release these apertures as a last step.
*/
if (hwpm->active_chip->release_rtr == NULL) {
tegra_hwpm_err(hwpm, "release_rtr uninitialized");
goto enodev;
}
ret = hwpm->active_chip->release_rtr(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to release RTR aperture");
goto fail;
}
if (hwpm->active_chip->release_pma == NULL) {
tegra_hwpm_err(hwpm, "release_pma uninitialized");
goto enodev;
}
ret = hwpm->active_chip->release_pma(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to release PMA aperture");
@@ -256,8 +214,6 @@ int tegra_hwpm_release_hw(struct tegra_soc_hwpm *hwpm)
}
return 0;
enodev:
ret = -ENODEV;
fail:
return ret;
}

View File

@@ -464,11 +464,6 @@ static int tegra_hwpm_complete_ip_register(struct tegra_soc_hwpm *hwpm)
tegra_hwpm_fn(hwpm, " ");
if (hwpm->active_chip->extract_ip_ops == NULL) {
tegra_hwpm_err(hwpm, "extract_ip_ops uninitialized");
return -ENODEV;
}
while (node != NULL) {
tegra_hwpm_dbg(hwpm, hwpm_info, "IP ext idx %d info",
node->ip_ops.ip_index);
@@ -507,10 +502,6 @@ int tegra_hwpm_finalize_chip_info(struct tegra_soc_hwpm *hwpm)
return ret;
}
if (hwpm->active_chip->force_enable_ips == NULL) {
tegra_hwpm_err(hwpm, "force_enable_ips uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->force_enable_ips(hwpm);
if (ret != 0) {
tegra_hwpm_err(hwpm, "Failed to force enable IPs");

View File

@@ -169,10 +169,6 @@ int tegra_hwpm_map_stream_buffer(struct tegra_soc_hwpm *hwpm,
}
/* Configure memory management */
if (hwpm->active_chip->enable_mem_mgmt == NULL) {
tegra_hwpm_err(hwpm, "enable memory mgmt HAL uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->enable_mem_mgmt(hwpm, alloc_pma_stream);
if (ret != 0) {
tegra_hwpm_err(hwpm, "Failed to configure stream memory");
@@ -183,20 +179,12 @@ int tegra_hwpm_map_stream_buffer(struct tegra_soc_hwpm *hwpm,
fail:
/* Invalidate memory config */
if (hwpm->active_chip->invalidate_mem_config == NULL) {
tegra_hwpm_err(hwpm, "invalidate_mem_config HAL uninitialized");
return -ENODEV;
}
err = hwpm->active_chip->invalidate_mem_config(hwpm);
if (err != 0) {
tegra_hwpm_err(hwpm, "Failed to invalidate memory config");
}
/* Disable memory management */
if (hwpm->active_chip->disable_mem_mgmt == NULL) {
tegra_hwpm_err(hwpm, "disable_mem_mgmt HAL uninitialized");
return -ENODEV;
}
err = hwpm->active_chip->disable_mem_mgmt(hwpm);
if (err != 0) {
tegra_hwpm_err(hwpm, "Failed to disable memory management");
@@ -224,10 +212,6 @@ int tegra_hwpm_clear_mem_pipeline(struct tegra_soc_hwpm *hwpm)
bool timeout = false;
u32 *mem_bytes_kernel_u32 = (u32 *)(hwpm->mem_bytes_kernel);
if (hwpm->active_chip->stream_mem_bytes == NULL) {
tegra_hwpm_err(hwpm, "stream_mem_bytes uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->stream_mem_bytes(hwpm);
if (ret != 0) {
tegra_hwpm_err(hwpm,
@@ -243,10 +227,6 @@ int tegra_hwpm_clear_mem_pipeline(struct tegra_soc_hwpm *hwpm)
}
}
if (hwpm->active_chip->disable_pma_streaming == NULL) {
tegra_hwpm_err(hwpm, "disable_pma_streaming uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->disable_pma_streaming(hwpm);
if (ret != 0) {
tegra_hwpm_err(hwpm, "Failed to disable pma streaming");
@@ -254,10 +234,6 @@ int tegra_hwpm_clear_mem_pipeline(struct tegra_soc_hwpm *hwpm)
}
/* Disable memory management */
if (hwpm->active_chip->disable_mem_mgmt == NULL) {
tegra_hwpm_err(hwpm, "disable_mem_mgmt HAL uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->disable_mem_mgmt(hwpm);
if (ret != 0) {
tegra_hwpm_err(hwpm, "Failed to disable memory management");
@@ -282,10 +258,6 @@ int tegra_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
tegra_hwpm_fn(hwpm, " ");
/* Update SW get pointer */
if (hwpm->active_chip->update_mem_bytes_get_ptr == NULL) {
tegra_hwpm_err(hwpm, "update_mem_bytes_get_ptr uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->update_mem_bytes_get_ptr(hwpm,
update_get_put->mem_bump);
if (ret != 0) {
@@ -295,10 +267,6 @@ int tegra_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
/* Stream MEM_BYTES value to MEM_BYTES buffer */
if (update_get_put->b_stream_mem_bytes) {
if (hwpm->active_chip->stream_mem_bytes == NULL) {
tegra_hwpm_err(hwpm, "stream_mem_bytes uninitialized");
return -ENODEV;
}
ret = hwpm->active_chip->stream_mem_bytes(hwpm);
if (ret != 0) {
tegra_hwpm_err(hwpm,
@@ -308,11 +276,6 @@ int tegra_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
/* Read HW put pointer */
if (update_get_put->b_read_mem_head) {
if (hwpm->active_chip->get_mem_bytes_put_ptr == NULL) {
tegra_hwpm_err(hwpm,
"get_mem_bytes_put_ptr uninitialized");
return -ENODEV;
}
update_get_put->mem_head =
hwpm->active_chip->get_mem_bytes_put_ptr(hwpm);
tegra_hwpm_dbg(hwpm, hwpm_verbose,
@@ -321,11 +284,6 @@ int tegra_hwpm_update_mem_bytes(struct tegra_soc_hwpm *hwpm,
/* Check overflow error status */
if (update_get_put->b_check_overflow) {
if (hwpm->active_chip->membuf_overflow_status == NULL) {
tegra_hwpm_err(hwpm,
"membuf_overflow_status uninitialized");
return -ENODEV;
}
update_get_put->b_overflowed =
(u8) hwpm->active_chip->membuf_overflow_status(hwpm);
tegra_hwpm_dbg(hwpm, hwpm_verbose, "OVERFLOWED = %u",

View File

@@ -19,160 +19,418 @@
#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 tegra_hwpm_func_single_aperture(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip,
u32 inst_idx, u32 aperture_idx, enum hwpm_aperture_type a_type)
{
struct hwpm_ip_aperture *aperture = NULL;
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;
if (a_type == HWPM_APERTURE_PERFMUX) {
aperture = chip_ip->ip_perfmux[aperture_idx];
} else if (a_type == HWPM_APERTURE_PERFMON) {
aperture = chip_ip->ip_perfmon[aperture_idx];
} else {
tegra_hwpm_err(hwpm, "INVALID a_type %d", a_type);
return -EINVAL;
}
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))) {
if (aperture == NULL) {
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);
if (aperture->hw_inst_mask != BIT(inst_idx)) {
return 0;
}
switch (iia_func) {
case TEGRA_HWPM_GET_ALIST_SIZE:
if (aperture->alist) {
hwpm->full_alist_size =
tegra_hwpm_safe_add_u64(
hwpm->full_alist_size,
aperture->alist_size);
} else {
tegra_hwpm_err(hwpm, "IP %d"
" aperture type %d idx %d NULL alist",
ip_idx, a_type, aperture_idx);
}
break;
case TEGRA_HWPM_COMBINE_ALIST:
err = hwpm->active_chip->copy_alist(hwpm,
aperture, func_args->alist, &func_args->full_alist_idx);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d"
" aperture type %d idx %d alist copy failed",
ip_idx, a_type, aperture_idx);
return err;
}
break;
case TEGRA_HWPM_RESERVE_GIVEN_RESOURCE:
if (a_type == HWPM_APERTURE_PERFMUX) {
err = tegra_hwpm_perfmux_reserve(hwpm, aperture);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d reserve failed",
ip_idx, aperture_idx);
goto fail;
}
} else if (a_type == HWPM_APERTURE_PERFMON) {
err = tegra_hwpm_perfmon_reserve(hwpm, aperture);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d reserve failed",
ip_idx, aperture_idx);
goto fail;
}
}
break;
case TEGRA_HWPM_RELEASE_RESOURCES:
if (a_type == HWPM_APERTURE_PERFMUX) {
ret = hwpm->active_chip->perfmux_disable(hwpm, aperture);
if (ret != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d disable failed",
ip_idx, aperture_idx);
}
ret = tegra_hwpm_perfmux_release(hwpm, aperture);
if (ret != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d release failed",
ip_idx, aperture_idx);
}
} else if (a_type == HWPM_APERTURE_PERFMON) {
ret = hwpm->active_chip->perfmon_disable(hwpm, aperture);
if (ret != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d disable failed",
ip_idx, aperture_idx);
}
ret = tegra_hwpm_perfmon_release(hwpm, aperture);
if (ret != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d release failed",
ip_idx, aperture_idx);
}
}
break;
case TEGRA_HWPM_BIND_RESOURCES:
err = hwpm->active_chip->zero_alist_regs(hwpm, aperture);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d zero regs failed",
ip_idx, aperture_idx);
goto fail;
}
if (a_type == HWPM_APERTURE_PERFMON) {
err = hwpm->active_chip->perfmon_enable(hwpm, aperture);
if (err != 0) {
tegra_hwpm_err(hwpm, "IP %d aperture"
" type %d idx %d enable failed",
ip_idx, aperture_idx);
goto fail;
}
}
break;
default:
tegra_hwpm_err(hwpm, "func 0x%x unknown", iia_func);
return -EINVAL;
break;
}
chip_ip->reserved = true;
return 0;
fail:
if (hwpm->active_chip->perfmon_disable == NULL) {
tegra_hwpm_err(hwpm, "perfmon_disable HAL uninitialized");
return -ENODEV;
return err;
}
int tegra_hwpm_func_all_perfmons(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip,
u32 inst_idx)
{
u32 perfmon_idx;
int err = 0;
for (perfmon_idx = 0U; perfmon_idx < chip_ip->num_perfmon_slots;
perfmon_idx++) {
err = tegra_hwpm_func_single_aperture(
hwpm, func_args, iia_func, ip_idx,
chip_ip, inst_idx, perfmon_idx, HWPM_APERTURE_PERFMON);
if (err < 0) {
tegra_hwpm_err(hwpm,
"IP %d inst %d perfmon %d func 0x%x failed",
ip_idx, inst_idx, perfmon_idx, iia_func);
goto fail;
}
}
if (hwpm->active_chip->perfmux_disable == NULL) {
tegra_hwpm_err(hwpm, "perfmux_disable HAL uninitialized");
return -ENODEV;
return 0;
fail:
return err;
}
int tegra_hwpm_func_all_perfmuxes(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip,
u32 inst_idx)
{
u32 perfmux_idx;
int err = 0;
for (perfmux_idx = 0U; perfmux_idx < chip_ip->num_perfmux_slots;
perfmux_idx++) {
err = tegra_hwpm_func_single_aperture(
hwpm, func_args, iia_func, ip_idx,
chip_ip, inst_idx, perfmux_idx, HWPM_APERTURE_PERFMUX);
if (err < 0) {
tegra_hwpm_err(hwpm,
"IP %d inst %d perfmux %d func 0x%x failed",
ip_idx, inst_idx, perfmux_idx, iia_func);
goto fail;
}
}
/* 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];
return 0;
fail:
return err;
}
if (perfmon == NULL) {
continue;
}
int tegra_hwpm_func_all_inst(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip)
{
unsigned long inst_idx = 0UL;
unsigned long floorsweep_info = 0UL;
unsigned long reserved_insts = 0UL;
int err = 0;
if (perfmon->hw_inst_mask != BIT(inst_idx)) {
continue;
}
/* Execute tasks for all instances if any */
floorsweep_info = (unsigned long)chip_ip->fs_mask;
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);
}
for_each_set_bit(inst_idx, &floorsweep_info, 32U) {
switch (iia_func) {
case TEGRA_HWPM_GET_ALIST_SIZE:
/* do nothing, continue to apertures */
break;
case TEGRA_HWPM_COMBINE_ALIST:
func_args->full_alist_idx = 0ULL;
break;
case TEGRA_HWPM_RESERVE_GIVEN_RESOURCE:
/* do nothing, continue to apertures */
break;
case TEGRA_HWPM_BIND_RESOURCES:
/* do nothing, continue to instances */
break;
case TEGRA_HWPM_RELEASE_RESOURCES:
/* do nothing, continue to instances */
break;
default:
tegra_hwpm_err(hwpm, "func 0x%x unknown", iia_func);
goto fail;
break;
}
/* 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];
/* Continue functionality for all apertures */
err = tegra_hwpm_func_all_perfmuxes(
hwpm, func_args, iia_func, ip_idx, chip_ip, inst_idx);
if (err < 0) {
tegra_hwpm_err(hwpm, "IP %d inst %d func 0x%x failed",
ip_idx, inst_idx, iia_func);
goto fail;
}
if (perfmux == NULL) {
continue;
}
err = tegra_hwpm_func_all_perfmons(
hwpm, func_args, iia_func, ip_idx, chip_ip, inst_idx);
if (err < 0) {
tegra_hwpm_err(hwpm, "IP %d inst %d func 0x%x failed",
ip_idx, inst_idx, iia_func);
goto fail;
}
if (perfmux->hw_inst_mask != BIT(inst_idx)) {
continue;
}
/* Post execute functionality */
switch (iia_func) {
case TEGRA_HWPM_GET_ALIST_SIZE:
/* do nothing, continue to apertures */
break;
case TEGRA_HWPM_COMBINE_ALIST:
/* do nothing, continue to apertures */
break;
case TEGRA_HWPM_RESERVE_GIVEN_RESOURCE:
reserved_insts |= BIT(inst_idx);
break;
case TEGRA_HWPM_BIND_RESOURCES:
/* do nothing, continue to instances */
break;
case TEGRA_HWPM_RELEASE_RESOURCES:
/* do nothing, continue to instances */
break;
default:
tegra_hwpm_err(hwpm, "func 0x%x unknown", iia_func);
goto fail;
break;
}
}
ret = hwpm->active_chip->perfmux_disable(hwpm, perfmux);
if (ret != 0) {
return 0;
fail:
if (iia_func == TEGRA_HWPM_RESERVE_GIVEN_RESOURCE) {
/* Revert previously reserved instances of this IP */
for_each_set_bit(inst_idx, &reserved_insts, 32U) {
/* Release all apertures belonging to this instance */
err = tegra_hwpm_func_all_perfmuxes(hwpm, func_args,
TEGRA_HWPM_RELEASE_RESOURCES, ip_idx,
chip_ip, inst_idx);
if (err < 0) {
tegra_hwpm_err(hwpm,
"IP %d perfmux %d disable failed",
ip_idx, perfmux_idx);
"IP %d inst %d func 0x%x failed",
ip_idx, inst_idx, iia_func);
return err;
}
ret = tegra_hwpm_perfmux_release(hwpm, perfmux);
if (ret != 0) {
err = tegra_hwpm_func_all_perfmons(hwpm, func_args,
TEGRA_HWPM_RELEASE_RESOURCES, ip_idx,
chip_ip, inst_idx);
if (err < 0) {
tegra_hwpm_err(hwpm,
"IP %d perfmux %d release failed",
ip_idx, perfmux_idx);
"IP %d inst %d func 0x%x failed",
ip_idx, inst_idx, iia_func);
return err;
}
}
}
return err;
}
int tegra_hwpm_func_single_ip(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx)
{
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
struct hwpm_ip *chip_ip = active_chip->chip_ips[ip_idx];
int err = 0;
tegra_hwpm_fn(hwpm, " ");
if (chip_ip == NULL) {
tegra_hwpm_err(hwpm, "IP %d not populated", ip_idx);
return -ENODEV;
}
switch (iia_func) {
case TEGRA_HWPM_GET_ALIST_SIZE:
case TEGRA_HWPM_COMBINE_ALIST:
case TEGRA_HWPM_BIND_RESOURCES:
/* Skip unavailable IPs */
if (!chip_ip->reserved) {
return 0;
}
if (chip_ip->fs_mask == 0U) {
/* No IP instance is available */
return 0;
}
break;
case TEGRA_HWPM_RESERVE_GIVEN_RESOURCE:
/* 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;
}
/* Skip IPs which are already reserved */
if (chip_ip->reserved) {
tegra_hwpm_dbg(hwpm, hwpm_info,
"Chip IP %d already reserved", ip_idx);
return 0;
}
/* Make sure IP override is not enabled */
if (chip_ip->override_enable) {
tegra_hwpm_dbg(hwpm, hwpm_info,
"Chip IP %d not available", ip_idx);
return 0;
}
break;
case TEGRA_HWPM_RELEASE_RESOURCES:
/* 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))) {
return 0;
}
/* Skip unavailable IPs */
if (!chip_ip->reserved) {
return 0;
}
if (chip_ip->fs_mask == 0U) {
/* No IP instance is available */
return 0;
}
break;
default:
tegra_hwpm_err(hwpm, "func 0x%x unknown", iia_func);
goto fail;
break;
}
/* Continue functionality for all instances in this IP */
err = tegra_hwpm_func_all_inst(hwpm, func_args, iia_func,
ip_idx, chip_ip);
if (err < 0) {
tegra_hwpm_err(hwpm, "IP %d func 0x%x failed",
ip_idx, iia_func);
goto fail;
}
/* Post execute functionality */
if (iia_func == TEGRA_HWPM_RESERVE_GIVEN_RESOURCE) {
chip_ip->reserved = true;
}
if (iia_func == TEGRA_HWPM_RELEASE_RESOURCES) {
chip_ip->reserved = false;
}
return 0;
fail:
return err;
}
int tegra_hwpm_func_all_ip(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func)
{
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
u32 ip_idx;
int err = 0;
tegra_hwpm_fn(hwpm, " ");
for (ip_idx = 0U; ip_idx < active_chip->get_ip_max_idx(hwpm);
ip_idx++) {
err = tegra_hwpm_func_single_ip(
hwpm, func_args, iia_func, ip_idx);
if (err < 0) {
tegra_hwpm_err(hwpm, "IP %d func 0x%x failed",
ip_idx, iia_func);
goto fail;
}
}
return 0;
fail:
return err;
}
int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
{
struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip;
struct hwpm_ip *chip_ip = NULL;
u32 ip_idx = TEGRA_SOC_HWPM_IP_INACTIVE;
int ret = 0;
int err = 0;
tegra_hwpm_fn(hwpm, " ");
@@ -192,266 +450,28 @@ int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource)
return -EINVAL;
}
/* Get IP structure from ip_idx */
chip_ip = active_chip->chip_ips[ip_idx];
/* Skip IPs which are already reserved (covers PMA and RTR case) */
if (chip_ip->reserved) {
tegra_hwpm_dbg(hwpm, hwpm_info,
"Chip IP %d already reserved", ip_idx);
return 0;
}
/* Make sure IP override is not enabled */
if (chip_ip->override_enable) {
tegra_hwpm_dbg(hwpm, hwpm_info,
"Chip IP %d not available", ip_idx);
return 0;
}
ret = tegra_hwpm_reserve_given_resource(hwpm, ip_idx);
if (ret != 0) {
tegra_hwpm_err(hwpm, "Failed to reserve resource %d", resource);
return ret;
err = tegra_hwpm_func_single_ip(hwpm, NULL,
TEGRA_HWPM_RESERVE_GIVEN_RESOURCE, ip_idx);
if (err != 0) {
tegra_hwpm_err(hwpm, "failed to reserve IP %d", ip_idx);
return err;
}
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;
err = tegra_hwpm_func_all_ip(hwpm, NULL, TEGRA_HWPM_BIND_RESOURCES);
if (err != 0) {
tegra_hwpm_err(hwpm, "failed to bind resources");
return err;
}
return 0;
}
@@ -461,7 +481,7 @@ int tegra_hwpm_release_resources(struct tegra_soc_hwpm *hwpm)
tegra_hwpm_fn(hwpm, " ");
ret = tegra_hwpm_release_all_resources(hwpm);
ret = tegra_hwpm_func_all_ip(hwpm, NULL, TEGRA_HWPM_RELEASE_RESOURCES);
if (ret != 0) {
tegra_hwpm_err(hwpm, "failed to release resources");
return ret;

View File

@@ -71,6 +71,181 @@ struct tegra_soc_hwpm_chip t234_chip_info = {
.release_sw_setup = tegra_hwpm_release_sw_setup,
};
static bool t234_hwpm_validate_hals(struct tegra_soc_hwpm *hwpm)
{
if (hwpm->active_chip->is_ip_active == NULL) {
tegra_hwpm_err(hwpm, "is_ip_active HAL uninitialized");
return false;
}
if (hwpm->active_chip->is_resource_active == NULL) {
tegra_hwpm_err(hwpm, "is_resource_active HAL uninitialized");
return false;
}
if (hwpm->active_chip->get_pma_int_idx == NULL) {
tegra_hwpm_err(hwpm, "get_pma_int_idx HAL uninitialized");
return false;
}
if (hwpm->active_chip->get_rtr_int_idx == NULL) {
tegra_hwpm_err(hwpm, "get_rtr_int_idx HAL uninitialized");
return false;
}
if (hwpm->active_chip->get_ip_max_idx == NULL) {
tegra_hwpm_err(hwpm, "get_ip_max_idx HAL uninitialized");
return false;
}
if (hwpm->active_chip->init_chip_ip_structures == NULL) {
tegra_hwpm_err(hwpm, "init_chip_ip_structures uninitialized");
return false;
}
if (hwpm->active_chip->extract_ip_ops == NULL) {
tegra_hwpm_err(hwpm, "extract_ip_ops uninitialized");
return false;
}
if (hwpm->active_chip->force_enable_ips == NULL) {
tegra_hwpm_err(hwpm, "force_enable_ips uninitialized");
return false;
}
if (hwpm->active_chip->get_fs_info == NULL) {
tegra_hwpm_err(hwpm, "get_fs_info uninitialized");
return false;
}
if (hwpm->active_chip->init_prod_values == NULL) {
tegra_hwpm_err(hwpm, "init_prod_values uninitialized");
return false;
}
if (hwpm->active_chip->disable_slcg == NULL) {
tegra_hwpm_err(hwpm, "disable_slcg uninitialized");
return false;
}
if (hwpm->active_chip->enable_slcg == NULL) {
tegra_hwpm_err(hwpm, "enable_slcg uninitialized");
return false;
}
if (hwpm->active_chip->reserve_pma == NULL) {
tegra_hwpm_err(hwpm, "reserve_pma uninitialized");
return false;
}
if (hwpm->active_chip->reserve_rtr == NULL) {
tegra_hwpm_err(hwpm, "reserve_rtr uninitialized");
return false;
}
if (hwpm->active_chip->release_pma == NULL) {
tegra_hwpm_err(hwpm, "release_pma uninitialized");
return false;
}
if (hwpm->active_chip->release_rtr == NULL) {
tegra_hwpm_err(hwpm, "release_rtr uninitialized");
return false;
}
if (hwpm->active_chip->perfmon_enable == NULL) {
tegra_hwpm_err(hwpm, "perfmon_enable HAL uninitialized");
return false;
}
if (hwpm->active_chip->perfmon_disable == NULL) {
tegra_hwpm_err(hwpm, "perfmon_disable HAL uninitialized");
return false;
}
if (hwpm->active_chip->perfmux_disable == NULL) {
tegra_hwpm_err(hwpm, "perfmux_disable HAL uninitialized");
return false;
}
if (hwpm->active_chip->disable_triggers == NULL) {
tegra_hwpm_err(hwpm, "disable_triggers uninitialized");
return false;
}
if (hwpm->active_chip->disable_mem_mgmt == NULL) {
tegra_hwpm_err(hwpm, "disable_mem_mgmt HAL uninitialized");
return false;
}
if (hwpm->active_chip->enable_mem_mgmt == NULL) {
tegra_hwpm_err(hwpm, "enable_mem_mgmt HAL uninitialized");
return false;
}
if (hwpm->active_chip->invalidate_mem_config == NULL) {
tegra_hwpm_err(hwpm, "invalidate_mem_config HAL uninitialized");
return false;
}
if (hwpm->active_chip->stream_mem_bytes == NULL) {
tegra_hwpm_err(hwpm, "stream_mem_bytes uninitialized");
return false;
}
if (hwpm->active_chip->disable_pma_streaming == NULL) {
tegra_hwpm_err(hwpm, "disable_pma_streaming uninitialized");
return false;
}
if (hwpm->active_chip->update_mem_bytes_get_ptr == NULL) {
tegra_hwpm_err(hwpm, "update_mem_bytes_get_ptr uninitialized");
return false;
}
if (hwpm->active_chip->get_mem_bytes_put_ptr == NULL) {
tegra_hwpm_err(hwpm, "get_mem_bytes_put_ptr uninitialized");
return false;
}
if (hwpm->active_chip->membuf_overflow_status == NULL) {
tegra_hwpm_err(hwpm, "membuf_overflow_status uninitialized");
return false;
}
if (hwpm->active_chip->get_alist_buf_size == NULL) {
tegra_hwpm_err(hwpm, "alist_buf_size uninitialized");
return false;
}
if (hwpm->active_chip->zero_alist_regs == NULL) {
tegra_hwpm_err(hwpm, "zero_alist_regs HAL uninitialized");
return false;
}
if (hwpm->active_chip->copy_alist == NULL) {
tegra_hwpm_err(hwpm, "copy_alist HAL uninitialized");
return false;
}
if (hwpm->active_chip->check_alist == NULL) {
tegra_hwpm_err(hwpm, "check_alist uninitialized");
return false;
}
if (hwpm->active_chip->exec_reg_ops == NULL) {
tegra_hwpm_err(hwpm, "exec_reg_ops uninitialized");
return false;
}
if (hwpm->active_chip->release_sw_setup == NULL) {
tegra_hwpm_err(hwpm, "release_sw_setup uninitialized");
return false;
}
return true;
}
bool t234_hwpm_is_ip_active(struct tegra_soc_hwpm *hwpm,
u32 ip_index, u32 *config_ip_index)
{
@@ -354,5 +529,8 @@ int t234_hwpm_init_chip_info(struct tegra_soc_hwpm *hwpm)
t234_active_ip_info[T234_HWPM_IP_VIC] = &t234_hwpm_ip_vic;
#endif
if (!t234_hwpm_validate_hals(hwpm)) {
return -EINVAL;
}
return 0;
}

View File

@@ -98,6 +98,25 @@ struct tegra_hwpm_ip_ops {
__u64 reg_offset, __u32 *reg_data);
};
struct tegra_hwpm_func_args {
u64 *alist;
u64 full_alist_idx;
};
enum tegra_hwpm_funcs {
TEGRA_HWPM_GET_ALIST_SIZE,
TEGRA_HWPM_COMBINE_ALIST,
TEGRA_HWPM_RESERVE_GIVEN_RESOURCE,
TEGRA_HWPM_BIND_RESOURCES,
TEGRA_HWPM_RELEASE_RESOURCES,
};
enum hwpm_aperture_type {
HWPM_APERTURE_INVALID,
HWPM_APERTURE_PERFMUX,
HWPM_APERTURE_PERFMON,
};
struct hwpm_ip_aperture {
/*
* Indicates which domain (HWPM or IP) aperture belongs to,

View File

@@ -14,11 +14,15 @@
#ifndef TEGRA_HWPM_COMMON_H
#define TEGRA_HWPM_COMMON_H
enum tegra_hwpm_funcs;
enum hwpm_aperture_type;
struct tegra_hwpm_func_args;
struct tegra_soc_hwpm;
struct tegra_soc_hwpm_exec_reg_ops;
struct tegra_soc_hwpm_ip_floorsweep_info;
struct tegra_soc_hwpm_alloc_pma_stream;
struct tegra_soc_hwpm_update_get_put;
struct hwpm_ip;
struct tegra_soc_hwpm_ip_ops;
struct hwpm_ip_aperture;
typedef struct hwpm_ip_aperture hwpm_ip_perfmon;
@@ -27,6 +31,27 @@ typedef struct hwpm_ip_aperture hwpm_ip_perfmux;
int tegra_hwpm_init_sw_components(struct tegra_soc_hwpm *hwpm);
void tegra_hwpm_release_sw_components(struct tegra_soc_hwpm *hwpm);
int tegra_hwpm_func_single_aperture(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip,
u32 inst_idx, u32 aperture_idx, enum hwpm_aperture_type a_type);
int tegra_hwpm_func_all_perfmons(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip, u32 inst_idx);
int tegra_hwpm_func_all_perfmuxes(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip, u32 inst_idx);
int tegra_hwpm_func_all_inst(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx, struct hwpm_ip *chip_ip);
int tegra_hwpm_func_single_ip(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func, u32 ip_idx);
int tegra_hwpm_func_all_ip(struct tegra_soc_hwpm *hwpm,
struct tegra_hwpm_func_args *func_args,
enum tegra_hwpm_funcs iia_func);
int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource);
int tegra_hwpm_release_resources(struct tegra_soc_hwpm *hwpm);
int tegra_hwpm_bind_resources(struct tegra_soc_hwpm *hwpm);

View File

@@ -106,10 +106,6 @@ void tegra_soc_hwpm_ip_register(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
tegra_hwpm_dbg(hwpm, hwpm_info,
"Register IP 0x%llx", hwpm_ip_ops->ip_base_address);
if (hwpm->active_chip->extract_ip_ops == NULL) {
tegra_hwpm_err(hwpm, "extract_ip_ops uninitialized");
return;
}
ret = hwpm->active_chip->extract_ip_ops(hwpm,
hwpm_ip_ops, REGISTER_IP);
if (ret < 0) {
@@ -141,10 +137,6 @@ void tegra_soc_hwpm_ip_unregister(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
tegra_hwpm_dbg(hwpm, hwpm_info,
"Unregister IP 0x%llx", hwpm_ip_ops->ip_base_address);
if (hwpm->active_chip->extract_ip_ops == NULL) {
tegra_hwpm_err(hwpm, "extract_ip_ops uninitialized");
return;
}
ret = hwpm->active_chip->extract_ip_ops(hwpm,
hwpm_ip_ops, UNREGISTER_IP);
if (ret < 0) {
@@ -162,11 +154,6 @@ int tegra_hwpm_get_floorsweep_info(struct tegra_soc_hwpm *hwpm,
tegra_hwpm_fn(hwpm, " ");
if (hwpm->active_chip->get_fs_info == NULL) {
tegra_hwpm_err(hwpm, "get_fs_info uninitialized");
return -ENODEV;
}
for (i = 0U; i < fs_info->num_queries; i++) {
ret = hwpm->active_chip->get_fs_info(
hwpm, (u32)fs_info->ip_fsinfo[i].ip_type,