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
This commit is contained in:
Vedashree Vidwans
2022-02-25 14:36:58 -08:00
committed by mobile promotions
parent 09ca7098e4
commit 53f8d0799c
25 changed files with 179 additions and 270 deletions

View File

@@ -11,6 +11,7 @@
* more details.
*/
#include <linux/slab.h>
#include <soc/tegra/fuse.h>
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
@@ -19,19 +20,76 @@
#include <tegra_hwpm.h>
struct platform_device *tegra_soc_hwpm_pdev;
struct hwpm_ip_register_list *ip_register_list_head;
#define REGISTER_IP true
#define UNREGISTER_IP false
static int tegra_hwpm_alloc_ip_register_list_node(
struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops,
struct hwpm_ip_register_list **node_ptr)
{
struct hwpm_ip_register_list *new_node = NULL;
new_node = kzalloc(sizeof(struct hwpm_ip_register_list), GFP_KERNEL);
if (new_node == NULL) {
tegra_hwpm_err(NULL,
"struct hwpm_ip_register_list node allocation failed");
return -ENOMEM;
}
new_node->next = NULL;
/* Copy given ip register details to node */
memcpy(&new_node->ip_ops, hwpm_ip_ops,
sizeof(struct tegra_soc_hwpm_ip_ops));
(*node_ptr) = new_node;
return 0;
}
static int tegra_hwpm_note_ip_register(
struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
{
int err = 0;
struct hwpm_ip_register_list *node;
if (ip_register_list_head == NULL) {
err = tegra_hwpm_alloc_ip_register_list_node(hwpm_ip_ops,
&ip_register_list_head);
if (err != 0) {
tegra_hwpm_err(NULL,
"failed to note ip registration");
return err;
}
} else {
node = ip_register_list_head;
while (node->next != NULL) {
node = node->next;
}
err = tegra_hwpm_alloc_ip_register_list_node(hwpm_ip_ops,
&node->next);
if (err != 0) {
tegra_hwpm_err(NULL,
"failed to note ip registration");
return err;
}
}
return err;
}
void tegra_soc_hwpm_ip_register(struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops)
{
struct tegra_soc_hwpm *hwpm = NULL;
int ret = 0;
if (tegra_soc_hwpm_pdev == NULL) {
tegra_hwpm_dbg(hwpm, hwpm_info,
"IP %d trying to register. HWPM device not available",
hwpm_ip_ops->ip_index);
ret = tegra_hwpm_note_ip_register(hwpm_ip_ops);
if (ret != 0) {
tegra_hwpm_err(NULL,
"Couldn't save IP register details");
}
} else {
if (hwpm_ip_ops->ip_dev == NULL) {
tegra_hwpm_err(hwpm, "IP dev to register is NULL");