Files
linux-hwpm/common/tegra_hwpm_init.c
Vedashree Vidwans 53f8d0799c tegra: hwpm: update IP registration logic
HWPM supports various IPs which initialize at different times in boot
flow. Some IPs such as MSS, NVLINK initialize before HWPM device and
some IPs (VIC, OFA, NVDEC, NVDLA) are initialized after HWPM device.
Modify IP register function to store registration requests in a
linked list for IPs initialized before HWPM device is probed.
The linked list will be traversed to complete pending IP register
requests after HWPM device is initialized.
- Add struct tegra_hwpm_ip_ops internal to HWPM driver to include only
required ip_ops details.
- Replace init_fs_info HAL with finalize_chip_info to register ip_ops,
force enable IPs (if any).

Jira THWPM-41

Change-Id: I916b4fa50679e79025a941a9c1fc113bdfe92b41
Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2675472
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
2022-04-20 13:26:26 -07:00

245 lines
5.7 KiB
C

/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/reset.h>
#include <linux/clk.h>
#include <linux/dma-buf.h>
#include <soc/tegra/fuse.h>
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
#include <tegra_hwpm_log.h>
#include <tegra_hwpm_io.h>
#include <tegra_hwpm.h>
#include <tegra_hwpm_common.h>
#include <hal/t234/t234_hwpm_init.h>
int tegra_hwpm_init_chip_info(struct tegra_soc_hwpm *hwpm)
{
int err = -EINVAL;
tegra_hwpm_fn(hwpm, " ");
hwpm->device_info.chip = tegra_get_chip_id();
hwpm->device_info.chip_revision = tegra_get_major_rev();
hwpm->device_info.revision = tegra_chip_get_revision();
hwpm->device_info.platform = tegra_get_platform();
hwpm->dbg_mask = TEGRA_HWPM_DEFAULT_DBG_MASK;
switch (hwpm->device_info.chip) {
case 0x23:
switch (hwpm->device_info.chip_revision) {
case 0x4:
err = t234_hwpm_init_chip_info(hwpm);
break;
default:
tegra_hwpm_err(hwpm, "Chip 0x%x rev 0x%x not supported",
hwpm->device_info.chip,
hwpm->device_info.chip_revision);
break;
}
break;
default:
tegra_hwpm_err(hwpm, "Chip 0x%x not supported",
hwpm->device_info.chip);
break;
}
if (err != 0) {
tegra_hwpm_err(hwpm, "init_chip_info failed");
}
return err;
}
int tegra_hwpm_setup_sw(struct tegra_soc_hwpm *hwpm)
{
int ret = 0;
tegra_hwpm_fn(hwpm, " ");
if (hwpm->active_chip->finalize_chip_info == NULL) {
tegra_hwpm_err(hwpm, "finalize_chip_info uninitialized");
goto enodev;
}
ret = hwpm->active_chip->finalize_chip_info(hwpm);
if (ret < 0) {
tegra_hwpm_err(hwpm, "Unable to initialize chip fs_info");
goto fail;
}
/* Initialize SW state */
hwpm->bind_completed = false;
hwpm->full_alist_size = 0;
return 0;
enodev:
ret = -ENODEV;
fail:
return ret;
}
int tegra_hwpm_setup_hw(struct tegra_soc_hwpm *hwpm)
{
int ret = 0;
tegra_hwpm_fn(hwpm, " ");
/*
* Map PMA and RTR apertures
* PMA and RTR are hwpm apertures which include hwpm config registers.
* 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");
goto fail;
}
/* 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");
goto fail;
}
/* 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");
goto fail;
}
return 0;
enodev:
ret = -ENODEV;
fail:
return ret;
}
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);
}
int tegra_hwpm_release_hw(struct tegra_soc_hwpm *hwpm)
{
int ret = 0;
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");
goto fail;
}
/*
* Unmap PMA and RTR apertures
* Since, PMA and RTR hwpm apertures consist of hwpm config registers,
* 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");
goto fail;
}
return 0;
enodev:
ret = -ENODEV;
fail:
return ret;
}
void tegra_hwpm_release_sw_components(struct tegra_soc_hwpm *hwpm)
{
struct hwpm_ip_register_list *node = ip_register_list_head;
struct hwpm_ip_register_list *tmp_node = NULL;
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);
}
while (node != NULL) {
tmp_node = node;
node = tmp_node->next;
kfree(tmp_node);
}
kfree(hwpm->active_chip->chip_ips);
kfree(hwpm);
tegra_soc_hwpm_pdev = NULL;
}