diff --git a/Makefile b/Makefile index 2ced4e5..10a82ee 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ obj-y += os/linux/log.o obj-y += os/linux/timers.o obj-y += os/linux/mem_mgmt_utils.o obj-y += os/linux/regops_utils.o +obj-y += os/linux/soc_utils.o obj-y += common/allowlist.o obj-y += common/aperture.o diff --git a/common/init.c b/common/init.c index 3cf4ce7..7ae21c7 100644 --- a/common/init.c +++ b/common/init.c @@ -24,19 +24,12 @@ #include #endif -static int tegra_hwpm_init_chip_info(struct tegra_soc_hwpm *hwpm) +static int tegra_hwpm_init_chip_ip_structures(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) { @@ -62,17 +55,9 @@ static int tegra_hwpm_init_chip_info(struct tegra_soc_hwpm *hwpm) if (err != 0) { tegra_hwpm_err(hwpm, "init_chip_info failed"); + return err; } - return err; -} - -static int tegra_hwpm_init_chip_ip_structures(struct tegra_soc_hwpm *hwpm) -{ - int err = 0; - - tegra_hwpm_fn(hwpm, " "); - err = tegra_hwpm_func_all_ip(hwpm, NULL, TEGRA_HWPM_INIT_IP_STRUCTURES); if (err != 0) { tegra_hwpm_err(hwpm, "failed init IP structures"); @@ -88,12 +73,6 @@ int tegra_hwpm_init_sw_components(struct tegra_soc_hwpm *hwpm) tegra_hwpm_fn(hwpm, " "); - err = tegra_hwpm_init_chip_info(hwpm); - if (err != 0) { - tegra_hwpm_err(hwpm, "Failed to initialize current chip info."); - return err; - } - err = tegra_hwpm_init_chip_ip_structures(hwpm); if (err != 0) { tegra_hwpm_err(hwpm, "IP structure init failed"); diff --git a/hal/t234/t234_ip.c b/hal/t234/t234_ip.c index 3954740..7dfece8 100644 --- a/hal/t234/t234_ip.c +++ b/hal/t234/t234_ip.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -199,26 +200,27 @@ int t234_hwpm_validate_current_config(struct tegra_soc_hwpm *hwpm) tegra_hwpm_fn(hwpm, " "); - if (!tegra_platform_is_silicon()) { + if (!tegra_hwpm_is_platform_silicon()) { return 0; } /* Read production mode fuse */ - err = tegra_fuse_readl(TEGRA_FUSE_PRODUCTION_MODE, &production_mode); + err = tegra_hwpm_fuse_readl_prod_mode(hwpm, &production_mode); if (err != 0) { tegra_hwpm_err(hwpm, "prod mode fuse read failed"); return err; } #define TEGRA_FUSE_SECURITY_MODE 0xA0U - err = tegra_fuse_readl(TEGRA_FUSE_SECURITY_MODE, &security_mode); + err = tegra_hwpm_fuse_readl(hwpm, + TEGRA_FUSE_SECURITY_MODE, &security_mode); if (err != 0) { tegra_hwpm_err(hwpm, "security mode fuse read failed"); return err; } #define TEGRA_FUSE_FA_MODE 0x48U - err = tegra_fuse_readl(TEGRA_FUSE_FA_MODE, &fa_mode); + err = tegra_hwpm_fuse_readl(hwpm, TEGRA_FUSE_FA_MODE, &fa_mode); if (err != 0) { tegra_hwpm_err(hwpm, "fa mode fuse read failed"); return err; @@ -295,7 +297,7 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) #if defined(CONFIG_T234_HWPM_IP_MSS_CHANNEL) /* MSS CHANNEL */ - if (is_tegra_hypervisor_mode()) { + if (tegra_hwpm_is_hypervisor_mode()) { ret = tegra_hwpm_set_fs_info_ip_ops(hwpm, NULL, addr_map_mc0_base_r(), T234_HWPM_IP_MSS_CHANNEL, true); @@ -319,7 +321,7 @@ int t234_hwpm_force_enable_ips(struct tegra_soc_hwpm *hwpm) } #endif - if (tegra_platform_is_silicon()) { + if (tegra_hwpm_is_platform_silicon()) { /* Static IP instances corresponding to silicon */ /* VI */ /* diff --git a/include/tegra_hwpm.h b/include/tegra_hwpm.h index 1fc5d82..6c26cb8 100644 --- a/include/tegra_hwpm.h +++ b/include/tegra_hwpm.h @@ -18,7 +18,6 @@ #include #include #include -#include #include diff --git a/include/tegra_hwpm_soc.h b/include/tegra_hwpm_soc.h new file mode 100644 index 0000000..0a91969 --- /dev/null +++ b/include/tegra_hwpm_soc.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef TEGRA_HWPM_SOC_H +#define TEGRA_HWPM_SOC_H + +#ifdef __KERNEL__ +#include +#else +bool tegra_hwpm_is_platform_simulation_impl(void) +{ + return false; +} + +bool tegra_hwpm_is_platform_vsp_impl(void) +{ + return false; +} + +bool tegra_hwpm_is_platform_silicon_impl(void) +{ + return true; +} + +bool tegra_hwpm_is_hypervisor_mode_impl(void) +{ + return false; +} + +int tegra_hwpm_fuse_readl_impl(struct tegra_soc_hwpm *hwpm, + u64 reg_offset, u32 *val) +{ + return -EINVAL; +} + +int tegra_hwpm_fuse_readl_prod_mode_impl(struct tegra_soc_hwpm *hwpm, u32 *val) +{ + return -EINVAL; +} + +#endif + +#define tegra_hwpm_is_platform_simulation() \ + tegra_hwpm_is_platform_simulation_impl() + +#define tegra_hwpm_is_platform_vsp() \ + tegra_hwpm_is_platform_vsp_impl() + +#define tegra_hwpm_is_platform_silicon() \ + tegra_hwpm_is_platform_silicon_impl() + +#define tegra_hwpm_is_hypervisor_mode() \ + tegra_hwpm_is_hypervisor_mode_impl() + +#define tegra_hwpm_fuse_readl(hwpm, reg_offset, val) \ + tegra_hwpm_fuse_readl_impl(hwpm, reg_offset, val) + +#define tegra_hwpm_fuse_readl_prod_mode(hwpm, val) \ + tegra_hwpm_fuse_readl_prod_mode_impl(hwpm, val) + +#endif /* TEGRA_HWPM_SOC_H */ diff --git a/os/linux/driver.c b/os/linux/driver.c index 252fd7c..1bf914d 100644 --- a/os/linux/driver.c +++ b/os/linux/driver.c @@ -20,11 +20,11 @@ #include #include #include - #include -#include #include +#include +#include #include #include #include @@ -64,6 +64,20 @@ static bool tegra_hwpm_read_support_soc_tools_prop(struct platform_device *pdev) return allow_node; } +static int tegra_hwpm_init_chip_info(struct tegra_soc_hwpm *hwpm) +{ + tegra_hwpm_fn(hwpm, " "); + + hwpm->dbg_mask = TEGRA_HWPM_DEFAULT_DBG_MASK; + + 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(); + + return 0; +} + static int tegra_hwpm_probe(struct platform_device *pdev) { int ret = 0; @@ -132,7 +146,7 @@ static int tegra_hwpm_probe(struct platform_device *pdev) (void) dma_set_mask_and_coherent(hwpm->dev, DMA_BIT_MASK(39)); - if (tegra_platform_is_silicon()) { + if (tegra_hwpm_is_platform_silicon()) { hwpm->la_clk = devm_clk_get(hwpm->dev, "la"); if (IS_ERR(hwpm->la_clk)) { tegra_hwpm_err(hwpm, "Missing la clock"); @@ -163,6 +177,12 @@ static int tegra_hwpm_probe(struct platform_device *pdev) } tegra_hwpm_debugfs_init(hwpm); + ret = tegra_hwpm_init_chip_info(hwpm); + if (ret != 0) { + tegra_hwpm_err(hwpm, "Failed to initialize current chip info."); + goto init_chip_info_fail; + } + ret = tegra_hwpm_init_sw_components(hwpm); if (ret != 0) { tegra_hwpm_err(hwpm, "Failed to init sw components"); @@ -173,7 +193,7 @@ 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_platform_is_vdk()) + if (tegra_hwpm_is_platform_simulation()) hwpm->fake_registers_enabled = true; else hwpm->fake_registers_enabled = false; @@ -184,8 +204,9 @@ static int tegra_hwpm_probe(struct platform_device *pdev) tegra_hwpm_dbg(hwpm, hwpm_info, "Probe successful!"); goto success; +init_chip_info_fail: init_sw_components_fail: - if (tegra_platform_is_silicon()) { + if (tegra_hwpm_is_platform_silicon()) { if (hwpm->la_clk) devm_clk_put(hwpm->dev, hwpm->la_clk); if (hwpm->la_parent_clk) @@ -226,7 +247,7 @@ static int tegra_hwpm_remove(struct platform_device *pdev) return -ENODEV; } - if (tegra_platform_is_silicon()) { + if (tegra_hwpm_is_platform_silicon()) { if (hwpm->la_clk) devm_clk_put(hwpm->dev, hwpm->la_clk); if (hwpm->la_parent_clk) diff --git a/os/linux/ioctl.c b/os/linux/ioctl.c index 56c36bc..3679d21 100644 --- a/os/linux/ioctl.c +++ b/os/linux/ioctl.c @@ -22,15 +22,15 @@ #include #include #include -#include #include -#include -#include +#include #include #include -#include +#include +#include #include +#include #include #define LA_CLK_RATE 625000000UL @@ -391,7 +391,7 @@ static int tegra_hwpm_open(struct inode *inode, struct file *filp) return -EAGAIN; } - if (tegra_platform_is_silicon()) { + if (tegra_hwpm_is_platform_silicon()) { ret = reset_control_assert(hwpm->hwpm_rst); if (ret < 0) { tegra_hwpm_err(hwpm, "hwpm reset assert failed"); @@ -527,7 +527,7 @@ static int tegra_hwpm_release(struct inode *inode, struct file *filp) goto fail; } - if (tegra_platform_is_silicon()) { + if (tegra_hwpm_is_platform_silicon()) { ret = reset_control_assert(hwpm->hwpm_rst); if (ret < 0) { tegra_hwpm_err(hwpm, "hwpm reset assert failed"); diff --git a/os/linux/soc_utils.c b/os/linux/soc_utils.c new file mode 100644 index 0000000..3e684fa --- /dev/null +++ b/os/linux/soc_utils.c @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#include + +#include +#include + +bool tegra_hwpm_is_platform_simulation_impl(void) +{ + return tegra_platform_is_vdk(); +} + +bool tegra_hwpm_is_platform_vsp_impl(void) +{ + return tegra_platform_is_vsp(); +} + +bool tegra_hwpm_is_platform_silicon_impl(void) +{ + return tegra_platform_is_silicon(); +} + +bool tegra_hwpm_is_hypervisor_mode_impl(void) +{ + return is_tegra_hypervisor_mode(); +} + +int tegra_hwpm_fuse_readl_impl(struct tegra_soc_hwpm *hwpm, + u64 reg_offset, u32 *val) +{ + u32 fuse_val = 0U; + int err = 0; + + err = tegra_fuse_readl(reg_offset, &fuse_val); + if (err != 0) { + return err; + } + + *val = fuse_val; + return 0; +} + +int tegra_hwpm_fuse_readl_prod_mode_impl(struct tegra_soc_hwpm *hwpm, u32 *val) +{ + return tegra_hwpm_fuse_readl(hwpm, TEGRA_FUSE_PRODUCTION_MODE, val); +} diff --git a/os/linux/soc_utils.h b/os/linux/soc_utils.h new file mode 100644 index 0000000..2cd6002 --- /dev/null +++ b/os/linux/soc_utils.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef TEGRA_HWPM_OS_LINUX_SOC_UTILS_H +#define TEGRA_HWPM_OS_LINUX_SOC_UTILS_H + +struct tegra_soc_hwpm; + +bool tegra_hwpm_is_platform_simulation_impl(void); +bool tegra_hwpm_is_platform_vsp_impl(void); +bool tegra_hwpm_is_platform_silicon_impl(void); +bool tegra_hwpm_is_hypervisor_mode_impl(void); +int tegra_hwpm_fuse_readl_impl(struct tegra_soc_hwpm *hwpm, + u64 reg_offset, u32 *val); +int tegra_hwpm_fuse_readl_prod_mode_impl(struct tegra_soc_hwpm *hwpm, u32 *val); + +#endif /* TEGRA_HWPM_OS_LINUX_SOC_UTILS_H */