From 10cd01aa1acf35d62a3465645d7e1a15e4983f77 Mon Sep 17 00:00:00 2001 From: Vedashree Vidwans Date: Mon, 22 Aug 2022 08:17:02 -0700 Subject: [PATCH] tegra: hwpm: use kstable available APIS - Some of the APIs are not available on stable kernel. Use kstable specific APIs with LINUX_KERNEL macro condition. - Temporarily comment functions that are not available on Kstable. - Next chip headers are renamed to accommodate more than one next chip. Update next chip includes in init.c and driver.c files. - Rename TEGRA_SOC_HWPM_IP_INACTIVE to TEGRA_HWPM_IP_INACTIVE to follow other macro/enum naming convention. - Use is_resource_active() HAL instead of chip specific function. - Create clock reset functions that will allow us to handle change in APIs on kstable. Jira THWPM-41 Change-Id: I55f58fa51cf9ae96ee9a9565942e68b3b2bb76ee Signed-off-by: Vedashree Vidwans Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2764840 Reviewed-by: svc-mobile-coverity Reviewed-by: Seema Khowala GVS: Gerrit_Virtual_Submit --- Makefile | 8 +- Makefile.linux.sources | 1 + common/resource.c | 2 +- hal/t234/t234_interface.c | 8 +- hal/t234/t234_ip.c | 3 +- include/tegra_hwpm.h | 6 +- include/tegra_hwpm_clk_rst.h | 58 +++++++++++ include/tegra_hwpm_soc.h | 42 ++++++++ include/tegra_hwpm_types.h | 4 + os/linux/clk_rst_utils.c | 195 +++++++++++++++++++++++++++++++++++ os/linux/clk_rst_utils.h | 29 ++++++ os/linux/debugfs.c | 1 - os/linux/driver.c | 74 +++---------- os/linux/ioctl.c | 79 +++----------- os/linux/ip_utils.c | 5 +- os/linux/mem_mgmt_utils.c | 22 +++- os/linux/regops_utils.c | 2 +- os/linux/soc_utils.c | 90 +++++++++++++++- os/linux/soc_utils.h | 4 + 19 files changed, 487 insertions(+), 146 deletions(-) create mode 100644 include/tegra_hwpm_clk_rst.h create mode 100644 os/linux/clk_rst_utils.c create mode 100644 os/linux/clk_rst_utils.h diff --git a/Makefile b/Makefile index 84376f3..2fea4b5 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,13 @@ ccflags-y += -I$(srctree.nvidia)/drivers/platform/tegra/hwpm # For OOT builds, set required config flags ifeq ($(CONFIG_TEGRA_OOT_MODULE),m) -CONFIG_TEGRA_T234_HWPM = y +CONFIG_TEGRA_HWPM_OOT := y +ccflags-y += -DCONFIG_TEGRA_HWPM_OOT + +CONFIG_TEGRA_FUSE_UPSTREAM := y +ccflags-y += -DCONFIG_TEGRA_FUSE_UPSTREAM + +CONFIG_TEGRA_T234_HWPM := y ccflags-y += -DCONFIG_TEGRA_T234_HWPM NVHWPM_OBJ = m else diff --git a/Makefile.linux.sources b/Makefile.linux.sources index cdeb7bf..e0caa0b 100644 --- a/Makefile.linux.sources +++ b/Makefile.linux.sources @@ -5,6 +5,7 @@ # SPDX-License-Identifier: GPL-2.0 nvhwpm-linux-objs += os/linux/aperture_utils.o +nvhwpm-linux-objs += os/linux/clk_rst_utils.o nvhwpm-linux-objs += os/linux/driver.o nvhwpm-linux-objs += os/linux/io_utils.o nvhwpm-linux-objs += os/linux/ip_utils.o diff --git a/common/resource.c b/common/resource.c index 8074e27..450959e 100644 --- a/common/resource.c +++ b/common/resource.c @@ -56,7 +56,7 @@ int tegra_hwpm_release_rtr(struct tegra_soc_hwpm *hwpm) int tegra_hwpm_reserve_resource(struct tegra_soc_hwpm *hwpm, u32 resource) { struct tegra_soc_hwpm_chip *active_chip = hwpm->active_chip; - u32 ip_idx = TEGRA_SOC_HWPM_IP_INACTIVE; + u32 ip_idx = TEGRA_HWPM_IP_INACTIVE; int err = 0; tegra_hwpm_fn(hwpm, " "); diff --git a/hal/t234/t234_interface.c b/hal/t234/t234_interface.c index 3e946ca..854dd58 100644 --- a/hal/t234/t234_interface.c +++ b/hal/t234/t234_interface.c @@ -219,7 +219,7 @@ static bool t234_hwpm_validate_hals(struct tegra_soc_hwpm *hwpm) bool t234_hwpm_is_ip_active(struct tegra_soc_hwpm *hwpm, u32 ip_enum, u32 *config_ip_index) { - u32 config_ip = TEGRA_SOC_HWPM_IP_INACTIVE; + u32 config_ip = TEGRA_HWPM_IP_INACTIVE; switch (ip_enum) { case TEGRA_HWPM_IP_VI: @@ -309,13 +309,13 @@ bool t234_hwpm_is_ip_active(struct tegra_soc_hwpm *hwpm, } *config_ip_index = config_ip; - return (config_ip != TEGRA_SOC_HWPM_IP_INACTIVE); + return (config_ip != TEGRA_HWPM_IP_INACTIVE); } bool t234_hwpm_is_resource_active(struct tegra_soc_hwpm *hwpm, u32 res_enum, u32 *config_ip_index) { - u32 config_ip = TEGRA_SOC_HWPM_IP_INACTIVE; + u32 config_ip = TEGRA_HWPM_IP_INACTIVE; switch (res_enum) { case TEGRA_HWPM_RESOURCE_VI: @@ -411,7 +411,7 @@ bool t234_hwpm_is_resource_active(struct tegra_soc_hwpm *hwpm, } *config_ip_index = config_ip; - return (config_ip != TEGRA_SOC_HWPM_IP_INACTIVE); + return (config_ip != TEGRA_HWPM_IP_INACTIVE); } u32 t234_get_rtr_int_idx(struct tegra_soc_hwpm *hwpm) diff --git a/hal/t234/t234_ip.c b/hal/t234/t234_ip.c index 4d3374f..72a76d0 100644 --- a/hal/t234/t234_ip.c +++ b/hal/t234/t234_ip.c @@ -38,7 +38,8 @@ int t234_hwpm_extract_ip_ops(struct tegra_soc_hwpm *hwpm, "Extract IP ops for resource enum %d info", resource_enum); /* Convert tegra_soc_hwpm_resource to internal enum */ - if (!(t234_hwpm_is_resource_active(hwpm, resource_enum, &ip_idx))) { + if (!(hwpm->active_chip->is_resource_active(hwpm, + resource_enum, &ip_idx))) { tegra_hwpm_dbg(hwpm, hwpm_dbg_ip_register, "SOC hwpm resource %d (base 0x%llx) is unconfigured", resource_enum, base_address); diff --git a/include/tegra_hwpm.h b/include/tegra_hwpm.h index 7546f1b..78244ca 100644 --- a/include/tegra_hwpm.h +++ b/include/tegra_hwpm.h @@ -16,7 +16,11 @@ #include -#define TEGRA_SOC_HWPM_IP_INACTIVE ~(0U) +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +#define TEGRA_HWPM_IP_INACTIVE ~(0U) /* These macro values should match TEGRA_SOC_HWPM_IP_STATUS_* */ #define TEGRA_HWPM_IP_STATUS_VALID 0U diff --git a/include/tegra_hwpm_clk_rst.h b/include/tegra_hwpm_clk_rst.h new file mode 100644 index 0000000..0b83060 --- /dev/null +++ b/include/tegra_hwpm_clk_rst.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TEGRA_HWPM_CLK_RST_H +#define TEGRA_HWPM_CLK_RST_H + +#ifdef __KERNEL__ +#include +#else +struct tegra_hwpm_os_linux; + +int tegra_hwpm_clk_rst_prepare_impl(struct tegra_hwpm_os_linux *hwpm_linux) +{ + return -EINVAL; +} + +int tegra_hwpm_clk_rst_set_rate_enable_impl( + struct tegra_hwpm_os_linux *hwpm_linux) +{ + return -EINVAL; +} + +int tegra_hwpm_clk_rst_disable_impl(struct tegra_hwpm_os_linux *hwpm_linux) +{ +} + +void tegra_hwpm_clk_rst_release_impl(struct tegra_hwpm_os_linux *hwpm_linux) +{ +} +#endif + +#define tegra_hwpm_clk_rst_prepare(hwpm_linux) \ + tegra_hwpm_clk_rst_prepare_impl(hwpm_linux) + +#define tegra_hwpm_clk_rst_set_rate_enable(hwpm_linux) \ + tegra_hwpm_clk_rst_set_rate_enable_impl(hwpm_linux) + +#define tegra_hwpm_clk_rst_disable(hwpm_linux) \ + tegra_hwpm_clk_rst_disable_impl(hwpm_linux) + +#define tegra_hwpm_clk_rst_release(hwpm_linux) \ + tegra_hwpm_clk_rst_release_impl(hwpm_linux) + +#endif /* TEGRA_HWPM_CLK_RST_H */ diff --git a/include/tegra_hwpm_soc.h b/include/tegra_hwpm_soc.h index 0a91969..697436f 100644 --- a/include/tegra_hwpm_soc.h +++ b/include/tegra_hwpm_soc.h @@ -14,9 +14,39 @@ #ifndef TEGRA_HWPM_SOC_H #define TEGRA_HWPM_SOC_H +#if defined(CONFIG_TEGRA_HWPM_OOT) +#define PLAT_SI 0 +#define PLAT_PRE_SI_QT 1 +#define PLAT_PRE_SI_VDK 8 +#define PLAT_PRE_SI_VSP 9 +#define PLAT_INVALID 10 + +#define TEGRA_FUSE_PRODUCTION_MODE 0x0 +#endif + #ifdef __KERNEL__ #include #else +u32 tegra_hwpm_get_chip_id_impl(void) +{ + return 0U; +} + +u32 tegra_hwpm_get_major_rev_impl(void) +{ + return 0U; +} + +u32 tegra_hwpm_chip_get_revision_impl(void) +{ + return 0U; +} + +u32 tegra_hwpm_get_platform_impl(void) +{ + return 0U; +} + bool tegra_hwpm_is_platform_simulation_impl(void) { return false; @@ -50,6 +80,18 @@ int tegra_hwpm_fuse_readl_prod_mode_impl(struct tegra_soc_hwpm *hwpm, u32 *val) #endif +#define tegra_hwpm_get_chip_id() \ + tegra_hwpm_get_chip_id_impl() + +#define tegra_hwpm_get_major_rev() \ + tegra_hwpm_get_major_rev_impl() + +#define tegra_hwpm_chip_get_revision() \ + tegra_hwpm_chip_get_revision_impl() + +#define tegra_hwpm_get_platform() \ + tegra_hwpm_get_platform_impl() + #define tegra_hwpm_is_platform_simulation() \ tegra_hwpm_is_platform_simulation_impl() diff --git a/include/tegra_hwpm_types.h b/include/tegra_hwpm_types.h index c4b6554..84ea7dd 100644 --- a/include/tegra_hwpm_types.h +++ b/include/tegra_hwpm_types.h @@ -19,6 +19,10 @@ #include #include #include +#if defined(CONFIG_TEGRA_HWPM_OOT) +#include +#include +#endif #endif #endif /* TEGRA_HWPM_TYPES_H */ diff --git a/os/linux/clk_rst_utils.c b/os/linux/clk_rst_utils.c new file mode 100644 index 0000000..b681213 --- /dev/null +++ b/os/linux/clk_rst_utils.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include +#include +#include +#include + +#define LA_CLK_RATE 625000000UL + +int tegra_hwpm_clk_rst_prepare_impl(struct tegra_hwpm_os_linux *hwpm_linux) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + /* + * Starting OOT config, clocks and resets are handled by UEFI layer + * Hence, do nothing. + */ + return 0; +#else + int ret = 0; + struct tegra_soc_hwpm *hwpm = &hwpm_linux->hwpm; + + if (tegra_hwpm_is_platform_silicon()) { + hwpm_linux->la_clk = devm_clk_get(hwpm_linux->dev, "la"); + if (IS_ERR(hwpm_linux->la_clk)) { + tegra_hwpm_err(hwpm, "Missing la clock"); + ret = PTR_ERR(hwpm_linux->la_clk); + goto fail; + } + + hwpm_linux->la_parent_clk = + devm_clk_get(hwpm_linux->dev, "parent"); + if (IS_ERR(hwpm_linux->la_parent_clk)) { + tegra_hwpm_err(hwpm, "Missing la parent clk"); + ret = PTR_ERR(hwpm_linux->la_parent_clk); + goto fail; + } + + hwpm_linux->la_rst = + devm_reset_control_get(hwpm_linux->dev, "la"); + if (IS_ERR(hwpm_linux->la_rst)) { + tegra_hwpm_err(hwpm, "Missing la reset"); + ret = PTR_ERR(hwpm_linux->la_rst); + goto fail; + } + + hwpm_linux->hwpm_rst = + devm_reset_control_get(hwpm_linux->dev, "hwpm"); + if (IS_ERR(hwpm_linux->hwpm_rst)) { + tegra_hwpm_err(hwpm, "Missing hwpm reset"); + ret = PTR_ERR(hwpm_linux->hwpm_rst); + goto fail; + } + } + +fail: + return ret; +#endif +} + +int tegra_hwpm_clk_rst_set_rate_enable_impl( + struct tegra_hwpm_os_linux *hwpm_linux) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + /* + * Starting OOT config, clocks and resets are handled by UEFI layer + * Hence, do nothing. + */ + return 0; +#else + int ret = 0; + struct tegra_soc_hwpm *hwpm = &hwpm_linux->hwpm; + + if (tegra_hwpm_is_platform_silicon()) { + ret = reset_control_assert(hwpm_linux->hwpm_rst); + if (ret < 0) { + tegra_hwpm_err(hwpm, "hwpm reset assert failed"); + goto fail; + } + ret = reset_control_assert(hwpm_linux->la_rst); + if (ret < 0) { + tegra_hwpm_err(hwpm, "la reset assert failed"); + goto fail; + } + /* Set required parent for la_clk */ + if (hwpm_linux->la_clk && hwpm_linux->la_parent_clk) { + ret = clk_set_parent( + hwpm_linux->la_clk, hwpm_linux->la_parent_clk); + if (ret < 0) { + tegra_hwpm_err(hwpm, + "la clk set parent failed"); + goto fail; + } + } + /* set la_clk rate to 625 MHZ */ + ret = clk_set_rate(hwpm_linux->la_clk, LA_CLK_RATE); + if (ret < 0) { + tegra_hwpm_err(hwpm, "la clock set rate failed"); + goto fail; + } + ret = clk_prepare_enable(hwpm_linux->la_clk); + if (ret < 0) { + tegra_hwpm_err(hwpm, "la clock enable failed"); + goto fail; + } + ret = reset_control_deassert(hwpm_linux->la_rst); + if (ret < 0) { + tegra_hwpm_err(hwpm, "la reset deassert failed"); + goto fail; + } + ret = reset_control_deassert(hwpm_linux->hwpm_rst); + if (ret < 0) { + tegra_hwpm_err(hwpm, "hwpm reset deassert failed"); + goto fail; + } + } + +fail: + return ret; +#endif +} + +int tegra_hwpm_clk_rst_disable_impl(struct tegra_hwpm_os_linux *hwpm_linux) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + /* + * Starting OOT config, clocks and resets are handled by UEFI layer + * Hence, do nothing. + */ + return 0; +#else + int ret = 0; + struct tegra_soc_hwpm *hwpm = &hwpm_linux->hwpm; + + if (tegra_hwpm_is_platform_silicon()) { + ret = reset_control_assert(hwpm_linux->hwpm_rst); + if (ret < 0) { + tegra_hwpm_err(hwpm, "hwpm reset assert failed"); + goto fail; + } + ret = reset_control_assert(hwpm_linux->la_rst); + if (ret < 0) { + tegra_hwpm_err(hwpm, "la reset assert failed"); + goto fail; + } + clk_disable_unprepare(hwpm_linux->la_clk); + } +fail: + return ret; +#endif +} + +void tegra_hwpm_clk_rst_release_impl(struct tegra_hwpm_os_linux *hwpm_linux) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + /* + * Starting OOT config, clocks and resets are handled by UEFI layer + * Hence, do nothing. + */ +#else + if (tegra_hwpm_is_platform_silicon()) { + if (hwpm_linux->la_clk) { + devm_clk_put(hwpm_linux->dev, hwpm_linux->la_clk); + } + if (hwpm_linux->la_parent_clk) { + devm_clk_put(hwpm_linux->dev, + hwpm_linux->la_parent_clk); + } + if (hwpm_linux->la_rst) { + reset_control_assert(hwpm_linux->la_rst); + } + if (hwpm_linux->hwpm_rst) { + reset_control_assert(hwpm_linux->hwpm_rst); + } + } +#endif +} diff --git a/os/linux/clk_rst_utils.h b/os/linux/clk_rst_utils.h new file mode 100644 index 0000000..6ade752 --- /dev/null +++ b/os/linux/clk_rst_utils.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TEGRA_HWPM_OS_LINUX_CLK_RST_UTILS_H +#define TEGRA_HWPM_OS_LINUX_CLK_RST_UTILS_H + +struct tegra_hwpm_os_linux; + +int tegra_hwpm_clk_rst_prepare_impl(struct tegra_hwpm_os_linux *hwpm_linux); +int tegra_hwpm_clk_rst_set_rate_enable_impl( + struct tegra_hwpm_os_linux *hwpm_linux); +int tegra_hwpm_clk_rst_disable_impl(struct tegra_hwpm_os_linux *hwpm_linux); +void tegra_hwpm_clk_rst_release_impl(struct tegra_hwpm_os_linux *hwpm_linux); + +#endif /* TEGRA_HWPM_OS_LINUX_CLK_RST_UTILS_H */ diff --git a/os/linux/debugfs.c b/os/linux/debugfs.c index ba4a150..95cc0cb 100644 --- a/os/linux/debugfs.c +++ b/os/linux/debugfs.c @@ -11,7 +11,6 @@ * more details. */ -#include #include #include diff --git a/os/linux/driver.c b/os/linux/driver.c index 6d1f426..4e1d5c0 100644 --- a/os/linux/driver.c +++ b/os/linux/driver.c @@ -16,11 +16,8 @@ #include #include #include -#include -#include #include #include -#include #include #include @@ -28,6 +25,7 @@ #include #include #include +#include #include #include @@ -68,10 +66,10 @@ static bool tegra_hwpm_read_support_soc_tools_prop(struct platform_device *pdev) static int tegra_hwpm_init_chip_info(struct tegra_hwpm_os_linux *hwpm_linux) { - hwpm_linux->device_info.chip = tegra_get_chip_id(); - hwpm_linux->device_info.chip_revision = tegra_get_major_rev(); - hwpm_linux->device_info.revision = tegra_chip_get_revision(); - hwpm_linux->device_info.platform = tegra_get_platform(); + hwpm_linux->device_info.chip = tegra_hwpm_get_chip_id(); + hwpm_linux->device_info.chip_revision = tegra_hwpm_get_major_rev(); + hwpm_linux->device_info.revision = tegra_hwpm_chip_get_revision(); + hwpm_linux->device_info.platform = tegra_hwpm_get_platform(); return 0; } @@ -146,37 +144,9 @@ static int tegra_hwpm_probe(struct platform_device *pdev) (void) dma_set_mask_and_coherent(hwpm_linux->dev, DMA_BIT_MASK(39)); - if (tegra_hwpm_is_platform_silicon()) { - hwpm_linux->la_clk = devm_clk_get(hwpm_linux->dev, "la"); - if (IS_ERR(hwpm_linux->la_clk)) { - tegra_hwpm_err(hwpm, "Missing la clock"); - ret = PTR_ERR(hwpm_linux->la_clk); - goto clock_reset_fail; - } - - hwpm_linux->la_parent_clk = - devm_clk_get(hwpm_linux->dev, "parent"); - if (IS_ERR(hwpm_linux->la_parent_clk)) { - tegra_hwpm_err(hwpm, "Missing la parent clk"); - ret = PTR_ERR(hwpm_linux->la_parent_clk); - goto clock_reset_fail; - } - - hwpm_linux->la_rst = - devm_reset_control_get(hwpm_linux->dev, "la"); - if (IS_ERR(hwpm_linux->la_rst)) { - tegra_hwpm_err(hwpm, "Missing la reset"); - ret = PTR_ERR(hwpm_linux->la_rst); - goto clock_reset_fail; - } - - hwpm_linux->hwpm_rst = - devm_reset_control_get(hwpm_linux->dev, "hwpm"); - if (IS_ERR(hwpm_linux->hwpm_rst)) { - tegra_hwpm_err(hwpm, "Missing hwpm reset"); - ret = PTR_ERR(hwpm_linux->hwpm_rst); - goto clock_reset_fail; - } + ret = tegra_hwpm_clk_rst_prepare(hwpm_linux); + if (ret != 0) { + goto clock_reset_fail; } tegra_hwpm_debugfs_init(hwpm_linux); @@ -198,10 +168,11 @@ static int tegra_hwpm_probe(struct platform_device *pdev) * Currently VDK doesn't have a fmodel for SOC HWPM. Therefore, we * enable fake registers on VDK for minimal testing. */ - if (tegra_hwpm_is_platform_simulation()) + if (tegra_hwpm_is_platform_simulation()) { hwpm->fake_registers_enabled = true; - else + } else { hwpm->fake_registers_enabled = false; + } platform_set_drvdata(pdev, hwpm); tegra_soc_hwpm_pdev = pdev; @@ -211,17 +182,7 @@ static int tegra_hwpm_probe(struct platform_device *pdev) init_chip_info_fail: init_sw_components_fail: - if (tegra_hwpm_is_platform_silicon()) { - if (hwpm_linux->la_clk) - devm_clk_put(hwpm_linux->dev, hwpm_linux->la_clk); - if (hwpm_linux->la_parent_clk) - devm_clk_put(hwpm_linux->dev, - hwpm_linux->la_parent_clk); - if (hwpm_linux->la_rst) - reset_control_assert(hwpm_linux->la_rst); - if (hwpm_linux->hwpm_rst) - reset_control_assert(hwpm_linux->hwpm_rst); - } + tegra_hwpm_clk_rst_release(hwpm_linux); clock_reset_fail: device_destroy(&hwpm_linux->class, hwpm_linux->dev_t); device_create: @@ -260,16 +221,7 @@ static int tegra_hwpm_remove(struct platform_device *pdev) return -ENODEV; } - if (tegra_hwpm_is_platform_silicon()) { - if (hwpm_linux->la_clk) - devm_clk_put(hwpm_linux->dev, hwpm_linux->la_clk); - if (hwpm_linux->la_parent_clk) - devm_clk_put(hwpm_linux->dev, hwpm_linux->la_parent_clk); - if (hwpm_linux->la_rst) - reset_control_assert(hwpm_linux->la_rst); - if (hwpm_linux->hwpm_rst) - reset_control_assert(hwpm_linux->hwpm_rst); - } + tegra_hwpm_clk_rst_release(hwpm_linux); tegra_hwpm_release_ip_register_node(hwpm); tegra_hwpm_release_sw_setup(hwpm); diff --git a/os/linux/ioctl.c b/os/linux/ioctl.c index 40cceba..0418b0d 100644 --- a/os/linux/ioctl.c +++ b/os/linux/ioctl.c @@ -12,8 +12,6 @@ */ #include -#include -#include #include #include #include @@ -31,13 +29,12 @@ #include #include #include +#include #include #include #include -#define LA_CLK_RATE 625000000UL - static int tegra_hwpm_get_device_info_ioctl(struct tegra_soc_hwpm *hwpm, struct tegra_soc_hwpm_device_info *device_info) { @@ -396,48 +393,9 @@ static int tegra_hwpm_open(struct inode *inode, struct file *filp) return -EAGAIN; } - if (tegra_hwpm_is_platform_silicon()) { - ret = reset_control_assert(hwpm_linux->hwpm_rst); - if (ret < 0) { - tegra_hwpm_err(hwpm, "hwpm reset assert failed"); - goto fail; - } - ret = reset_control_assert(hwpm_linux->la_rst); - if (ret < 0) { - tegra_hwpm_err(hwpm, "la reset assert failed"); - goto fail; - } - /* Set required parent for la_clk */ - if (hwpm_linux->la_clk && hwpm_linux->la_parent_clk) { - ret = clk_set_parent( - hwpm_linux->la_clk, hwpm_linux->la_parent_clk); - if (ret < 0) { - tegra_hwpm_err(hwpm, - "la clk set parent failed"); - goto fail; - } - } - /* set la_clk rate to 625 MHZ */ - ret = clk_set_rate(hwpm_linux->la_clk, LA_CLK_RATE); - if (ret < 0) { - tegra_hwpm_err(hwpm, "la clock set rate failed"); - goto fail; - } - ret = clk_prepare_enable(hwpm_linux->la_clk); - if (ret < 0) { - tegra_hwpm_err(hwpm, "la clock enable failed"); - goto fail; - } - ret = reset_control_deassert(hwpm_linux->la_rst); - if (ret < 0) { - tegra_hwpm_err(hwpm, "la reset deassert failed"); - goto fail; - } - ret = reset_control_deassert(hwpm_linux->hwpm_rst); - if (ret < 0) { - tegra_hwpm_err(hwpm, "hwpm reset deassert failed"); - goto fail; - } + ret = tegra_hwpm_clk_rst_set_rate_enable(hwpm_linux); + if (ret != 0) { + goto fail; } ret = tegra_hwpm_setup_hw(hwpm); @@ -499,11 +457,6 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp) tegra_hwpm_fn(hwpm, " "); - /* De-init driver on last close call only */ - if (!atomic_dec_and_test(&hwpm_linux->usage_count.var)) { - return 0; - } - if (hwpm->device_opened == false) { /* Device was not opened, do nothing */ return 0; @@ -541,20 +494,16 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp) goto fail; } - if (tegra_hwpm_is_platform_silicon()) { - ret = reset_control_assert(hwpm_linux->hwpm_rst); - if (ret < 0) { - tegra_hwpm_err(hwpm, "hwpm reset assert failed"); - err = ret; - goto fail; - } - ret = reset_control_assert(hwpm_linux->la_rst); - if (ret < 0) { - tegra_hwpm_err(hwpm, "la reset assert failed"); - err = ret; - goto fail; - } - clk_disable_unprepare(hwpm_linux->la_clk); + ret = tegra_hwpm_clk_rst_disable(hwpm_linux); + if (ret < 0) { + tegra_hwpm_err(hwpm, "Failed to release clock"); + err = ret; + goto fail; + } + + /* De-init driver on last close call only */ + if (!atomic_dec_and_test(&hwpm_linux->usage_count.var)) { + return 0; } hwpm->device_opened = false; diff --git a/os/linux/ip_utils.c b/os/linux/ip_utils.c index e7d6aa4..019e0c8 100644 --- a/os/linux/ip_utils.c +++ b/os/linux/ip_utils.c @@ -12,7 +12,6 @@ */ #include -#include #include #include @@ -196,7 +195,7 @@ int tegra_hwpm_complete_ip_register_impl(struct tegra_soc_hwpm *hwpm) static u32 tegra_hwpm_translate_soc_hwpm_ip(struct tegra_soc_hwpm *hwpm, enum tegra_soc_hwpm_ip ip_enum) { - u32 ip_enum_idx = TEGRA_SOC_HWPM_IP_INACTIVE; + u32 ip_enum_idx = TEGRA_HWPM_IP_INACTIVE; switch (ip_enum) { case TEGRA_SOC_HWPM_IP_VI: @@ -292,7 +291,7 @@ int tegra_hwpm_get_floorsweep_info(struct tegra_soc_hwpm *hwpm, u32 tegra_hwpm_translate_soc_hwpm_resource(struct tegra_soc_hwpm *hwpm, enum tegra_soc_hwpm_resource res_enum) { - u32 res_enum_idx = TEGRA_SOC_HWPM_IP_INACTIVE; + u32 res_enum_idx = TEGRA_HWPM_IP_INACTIVE; switch (res_enum) { case TEGRA_SOC_HWPM_RESOURCE_VI: diff --git a/os/linux/mem_mgmt_utils.c b/os/linux/mem_mgmt_utils.c index fc32369..2798865 100644 --- a/os/linux/mem_mgmt_utils.c +++ b/os/linux/mem_mgmt_utils.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -33,6 +32,11 @@ #include +#if defined(CONFIG_TEGRA_HWPM_OOT) +#include +MODULE_IMPORT_NS(DMA_BUF); +#endif + static int tegra_hwpm_dma_map_stream_buffer(struct tegra_soc_hwpm *hwpm, struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream) { @@ -85,6 +89,9 @@ static int tegra_hwpm_dma_map_mem_bytes_buffer(struct tegra_soc_hwpm *hwpm, struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream) { struct tegra_hwpm_os_linux *hwpm_linux = NULL; +#if defined(CONFIG_TEGRA_HWPM_OOT) + int err = 0; +#endif tegra_hwpm_fn(hwpm, " "); @@ -96,7 +103,7 @@ static int tegra_hwpm_dma_map_mem_bytes_buffer(struct tegra_soc_hwpm *hwpm, hwpm->mem_mgmt->mem_bytes_dma_buf = dma_buf_get(tegra_hwpm_safe_cast_u64_to_s32( - alloc_pma_stream->mem_bytes_buf_fd)); + alloc_pma_stream->mem_bytes_buf_fd)); if (IS_ERR(hwpm->mem_mgmt->mem_bytes_dma_buf)) { tegra_hwpm_err(hwpm, "Unable to get mem bytes dma_buf"); return PTR_ERR(hwpm->mem_mgmt->mem_bytes_dma_buf); @@ -119,6 +126,15 @@ static int tegra_hwpm_dma_map_mem_bytes_buffer(struct tegra_soc_hwpm *hwpm, hwpm->mem_mgmt->mem_bytes_buf_va = sg_dma_address(hwpm->mem_mgmt->mem_bytes_sgt->sgl); +#if defined(CONFIG_TEGRA_HWPM_OOT) + err = dma_buf_vmap(hwpm->mem_mgmt->mem_bytes_dma_buf, + (struct dma_buf_map *)hwpm->mem_mgmt->mem_bytes_kernel); + if (err != 0) { + tegra_hwpm_err(hwpm, + "Unable to map mem_bytes buffer into kernel VA space"); + return -ENOMEM; + } +#else hwpm->mem_mgmt->mem_bytes_kernel = dma_buf_vmap(hwpm->mem_mgmt->mem_bytes_dma_buf); if (!hwpm->mem_mgmt->mem_bytes_kernel) { @@ -126,6 +142,8 @@ static int tegra_hwpm_dma_map_mem_bytes_buffer(struct tegra_soc_hwpm *hwpm, "Unable to map mem_bytes buffer into kernel VA space"); return -ENOMEM; } +#endif + memset(hwpm->mem_mgmt->mem_bytes_kernel, 0, 32); return 0; diff --git a/os/linux/regops_utils.c b/os/linux/regops_utils.c index 417f445..be3dddb 100644 --- a/os/linux/regops_utils.c +++ b/os/linux/regops_utils.c @@ -24,7 +24,7 @@ static int tegra_hwpm_exec_reg_ops(struct tegra_soc_hwpm *hwpm, struct tegra_soc_hwpm_reg_op *reg_op) { bool found = false; - u32 ip_idx = TEGRA_SOC_HWPM_IP_INACTIVE; + u32 ip_idx = TEGRA_HWPM_IP_INACTIVE; u32 inst_idx = 0U, element_idx = 0U; u32 a_type = 0U; u32 reg_val = 0U; diff --git a/os/linux/soc_utils.c b/os/linux/soc_utils.c index 3e684fa..cf1de3a 100644 --- a/os/linux/soc_utils.c +++ b/os/linux/soc_utils.c @@ -11,29 +11,109 @@ * more details. */ -#include +#include +#include #include #include -bool tegra_hwpm_is_platform_simulation_impl(void) +#if defined(CONFIG_TEGRA_HWPM_OOT) +#if defined(CONFIG_TEGRA_NEXT1_HWPM) +#include +#endif +#endif + +u32 tegra_hwpm_get_chip_id_impl(void) { - return tegra_platform_is_vdk(); +#if defined(CONFIG_TEGRA_HWPM_OOT) + if (of_machine_is_compatible("nvidia,tegra234")) { + return 0x23U; + } +#ifdef CONFIG_TEGRA_NEXT1_HWPM + return tegra_hwpm_next1_get_chip_id_impl(); +#else + return 0x0U; +#endif /* CONFIG_TEGRA_NEXT1_HWPM */ +#else + return (u32)tegra_get_chip_id(); +#endif /* CONFIG_TEGRA_HWPM_OOT */ } -bool tegra_hwpm_is_platform_vsp_impl(void) +u32 tegra_hwpm_get_major_rev_impl(void) { - return tegra_platform_is_vsp(); +#if defined(CONFIG_TEGRA_HWPM_OOT) + if (of_machine_is_compatible("nvidia,tegra234")) { + return 0x4U; + } +#ifdef CONFIG_TEGRA_NEXT1_HWPM + return tegra_hwpm_next1_get_major_rev_impl(); +#else + return 0x0U; +#endif /* CONFIG_TEGRA_NEXT1_HWPM */ +#else + return (u32)tegra_get_major_rev(); +#endif +} + +u32 tegra_hwpm_chip_get_revision_impl(void) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + return 0x0U; +#else + return (u32)tegra_chip_get_revision(); +#endif +} + +u32 tegra_hwpm_get_platform_impl(void) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + if (of_machine_is_compatible("nvidia,tegra234")) { + return PLAT_SI; + } +#ifdef CONFIG_TEGRA_NEXT1_HWPM + return tegra_hwpm_next1_get_platform_impl(); +#else + return PLAT_INVALID; +#endif /* CONFIG_TEGRA_NEXT1_HWPM */ +#else + return (u32)tegra_get_platform(); +#endif } bool tegra_hwpm_is_platform_silicon_impl(void) { +#if defined(CONFIG_TEGRA_HWPM_OOT) return tegra_platform_is_silicon(); +#else + return tegra_platform_is_silicon(); +#endif +} + +bool tegra_hwpm_is_platform_simulation_impl(void) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + return tegra_hwpm_get_platform() == PLAT_PRE_SI_VDK; +#else + return tegra_platform_is_vdk(); +#endif +} + +bool tegra_hwpm_is_platform_vsp_impl(void) +{ +#if defined(CONFIG_TEGRA_HWPM_OOT) + return tegra_hwpm_get_platform() == PLAT_PRE_SI_VSP; +#else + return tegra_platform_is_vsp(); +#endif } bool tegra_hwpm_is_hypervisor_mode_impl(void) { +#if defined(CONFIG_TEGRA_HWPM_OOT) + return false; +#else return is_tegra_hypervisor_mode(); +#endif } int tegra_hwpm_fuse_readl_impl(struct tegra_soc_hwpm *hwpm, diff --git a/os/linux/soc_utils.h b/os/linux/soc_utils.h index 2cd6002..620f1af 100644 --- a/os/linux/soc_utils.h +++ b/os/linux/soc_utils.h @@ -16,6 +16,10 @@ struct tegra_soc_hwpm; +u32 tegra_hwpm_get_chip_id_impl(void); +u32 tegra_hwpm_get_major_rev_impl(void); +u32 tegra_hwpm_chip_get_revision_impl(void); +u32 tegra_hwpm_get_platform_impl(void); bool tegra_hwpm_is_platform_simulation_impl(void); bool tegra_hwpm_is_platform_vsp_impl(void); bool tegra_hwpm_is_platform_silicon_impl(void);