diff --git a/Source/hoc-clk/common/include/hocclk.h b/Source/hoc-clk/common/include/hocclk.h index 4ff74fab..3324c9ec 100644 --- a/Source/hoc-clk/common/include/hocclk.h +++ b/Source/hoc-clk/common/include/hocclk.h @@ -49,6 +49,7 @@ extern "C" { #include "hocclk/config.h" #include "hocclk/errors.h" #include "hocclk/psm_ext.h" +#include "hocclk/result.hpp" #ifdef __cplusplus } diff --git a/Source/hoc-clk/common/include/hocclk/result.hpp b/Source/hoc-clk/common/include/hocclk/result.hpp new file mode 100644 index 00000000..ecf66a4a --- /dev/null +++ b/Source/hoc-clk/common/include/hocclk/result.hpp @@ -0,0 +1,11 @@ +#pragma once +#include + +#define R_UNLESS(rc) \ + do { \ + if (R_FAILED(rc)) { \ + return; \ + } \ + } while (0) + +/* TODO: Add more Result macros. */ diff --git a/Source/hoc-clk/sysmodule/Makefile b/Source/hoc-clk/sysmodule/Makefile index d8815581..80a4fc84 100644 --- a/Source/hoc-clk/sysmodule/Makefile +++ b/Source/hoc-clk/sysmodule/Makefile @@ -22,7 +22,7 @@ CONFIG_DIR := horizon-oc BUILD := build OUTDIR := out RESOURCES := res -SOURCES := src src/nx/ipc ../common/src src/board src/display +SOURCES := src src/nx/ipc ../common/src src/board src/display src/tsensor DATA := data INCLUDES := ../common/include EXEFS_SRC := exefs_src diff --git a/Source/hoc-clk/sysmodule/src/aotag.cpp b/Source/hoc-clk/sysmodule/src/aotag.cpp deleted file mode 100644 index 47604a48..00000000 --- a/Source/hoc-clk/sysmodule/src/aotag.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * drivers/thermal/tegra_aotag.c - * - * TEGRA AOTAG (Always-On Thermal Alert Generator) driver. - * - * Copyright (c) 2014 - 2017, NVIDIA CORPORATION. All rights reserved. - * - * Copyright (c) 1994, Linus Torvalds - * - * Copyright (c) 2026, Souldbminer - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that 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 "aotag.hpp" -#include "mem_map.hpp" -#include -#include "file_utils.hpp" - -namespace aotag { - #define PMC_BASE 0x7000E400 - #define TEGRA_FUSE_CP_REV_0_3 (3) - #define FUSE_CP_REV 0x190 - u64 fuseVa = 0; - bool wasInit = false; - inline int tegra_fuse_readl(unsigned long base, u32* value) { - *value = *reinterpret_cast(fuseVa + base); - return 0; - } - #define REG_SET(r, mask, value) \ - ((r & ~(mask##_MASK)) | ((value<<(mask##_POS_START)) & mask##_MASK)) - - #define REG_GET(r, mask) \ - ((r & mask##_MASK) >> mask##_POS_START) - - #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff - #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13) - #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13 - #define CALIB_COEFFICIENT 1000000LL - #define FUSE_CACHE_OFFSET 0x800 - #define FUSE_TSENSOR_COMMON 0xA80 - #define SENSOR_CONFIG2_THERMA_SHIFT 16 - #define SENSOR_CONFIG2_THERMB_SHIFT 0 - - - static const struct TSensorFuse tegra_aotag_fuse = { - .fuse_base_cp_mask = 0x3ff << 11, - .fuse_base_cp_shift = 11, - .fuse_base_ft_mask = (u32)0x7ff << 21, - .fuse_base_ft_shift = 21, - .fuse_shift_ft_mask = 0x1f << 6, - .fuse_shift_ft_shift = 6, - .fuse_spare_realignment = 0, - }; - - static struct TSensorConfig tegra_aotag_config = { - .tall = 76, - .tiddq_en = 1, - .ten_count = 16, - .pdiv = 8, - .pdiv_ate = 8, - .tsample = 9, - .tsample_ate = 39, - }; - - static struct TSensorConfig tegra210b01_aotag_config = { - .tall = 76, - .tiddq_en = 1, - .ten_count = 16, - .pdiv = 12, - .pdiv_ate = 6, - .tsample = 19, - .tsample_ate = 39, - }; - - static const struct FuseCorrCoeff tegra_aotag_coeff = { - .alpha = 1063200, - .beta = -6749000, - }; - - static const struct FuseCorrCoeff tegra210b01_aotag_coeff = { - .alpha = 991100, - .beta = 1096200, - }; - - struct aotag_sensor_info_t { - struct TSensorConfig *config; - const struct TSensorFuse *fuse; - const struct FuseCorrCoeff *coeff; - s32 therm_a; - s32 therm_b; - }; - - struct aotag_platform_data { - struct TSensorConfig *config; - const struct FuseCorrCoeff *coeff; - }; - - static struct aotag_platform_data tegra210_plat_data = { - .config = &tegra_aotag_config, - .coeff = &tegra_aotag_coeff, - }; - - static struct aotag_platform_data tegra210b01_plat_data = { - .config = &tegra210b01_aotag_config, - .coeff = &tegra210b01_aotag_coeff, - }; - - - struct aotag_sensor_info_t aotag_sensor_info = { - .config = NULL, - .fuse = NULL, - .coeff = NULL, - .therm_a = 0, - .therm_b = 0, - }; - - struct aotag_sensor_info_t *info = &aotag_sensor_info; - struct aotag_platform_data *pdata = NULL; - - u32 tegra_pmc_readl(unsigned long offset) { - SecmonArgs args = {}; - args.X[0] = 0xF0000002; - args.X[1] = PMC_BASE + offset; - svcCallSecureMonitor(&args); - - if (args.X[1] == (PMC_BASE + offset)) { // if param 1 is identical read failed - return 0; - } - - return args.X[1]; - - } - void tegra_pmc_writel(u32 value, unsigned long offset) { - SecmonArgs args = {}; - args.X[0] = 0xF0000002; - args.X[1] = PMC_BASE + offset; - args.X[2] = 0xFFFFFFFF; - args.X[3] = (value); - svcCallSecureMonitor(&args); - } - - Result MapAddress(u64 &va, const u64 &physAddr, const char *name) { - Result mapResult = QueryMemoryMapping(&va, physAddr, 0x1000); - if (R_FAILED(mapResult)) { - fileUtils::LogLine("[aotag] Failed to map %s! %u", name, R_DESCRIPTION(mapResult)); - } - - return mapResult; - } - - static inline void set_bit(unsigned long nr, volatile void * addr) { - int *m = ((int *) addr) + (nr >> 5); - *m |= 1 << (nr & 31); - } - - - static inline void clear_bit(unsigned long nr, volatile void * addr) { - int *m = ((int *) addr) + (nr >> 5); - *m &= ~(1 << (nr & 31)); - } - - static inline s32 sign_extend32(u32 value, int index) { - u8 shift = 31 - index; - return (s32) (value << shift) >> shift; - } - - static inline s64 div64_s64(s64 dividend, s64 divisor) { - return dividend / divisor; - } - - static s64 div64_s64_precise(s64 a, s32 b) { - s64 r, al; - - al = a << 16; - - r = div64_s64(al * 2 + 1, 2 * b); - return r >> 16; - } - - void CalcTSensorCalib(const TSensorConfig *cfg, TSensorSharedCalib *shared, const FuseCorrCoeff *corr, u32 *calibration, u32 offset) { - u32 val, calib; - s32 actual_tsensor_ft, actual_tsensor_cp; - s32 delta_sens, delta_temp; - s32 mult, div; - s16 therma, thermb; - s64 temp; - tegra_fuse_readl(offset + FUSE_CACHE_OFFSET, &val); - - actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12); - val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK) >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT; - actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12); - - delta_sens = actual_tsensor_ft - actual_tsensor_cp; - delta_temp = shared->actual_temp_ft - shared->actual_temp_cp; - - mult = cfg->pdiv * cfg->tsample_ate; - div = cfg->tsample * cfg->pdiv_ate; - - temp = (s64)delta_temp * (1LL << 13) * mult; - therma = div64_s64_precise(temp, (s64)delta_sens * div); - - temp = ((s64)actual_tsensor_ft * shared->actual_temp_cp) - ((s64)actual_tsensor_cp * shared->actual_temp_ft); - thermb = div64_s64_precise(temp, delta_sens); - - temp = (s64)therma * corr->alpha; - therma = div64_s64_precise(temp, CALIB_COEFFICIENT); - - temp = (s64)thermb * corr->alpha + corr->beta; - thermb = div64_s64_precise(temp, CALIB_COEFFICIENT); - - calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) | ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT); - *calibration = calib; - } - - #define NOMINAL_CALIB_FT 105 - #define NOMINAL_CALIB_CP 25 - - - void CalcSharedCal(const TSensorFuse *tfuse, TSensorSharedCalib *shared) { - s32 shifted_cp, shifted_ft; - u32 val; - tegra_fuse_readl(FUSE_TSENSOR_COMMON, &val); - - shared->base_cp = (val & tfuse->fuse_base_cp_mask) >> tfuse->fuse_base_cp_shift; - shared->base_ft = (val & tfuse->fuse_base_ft_mask) >> tfuse->fuse_base_ft_shift; - - shifted_ft = (val & tfuse->fuse_shift_ft_mask) >> tfuse->fuse_shift_ft_shift; - shifted_ft = sign_extend32(shifted_ft, 4); - - if (tfuse->fuse_spare_realignment) { - tegra_fuse_readl(tfuse->fuse_spare_realignment + FUSE_CACHE_OFFSET, &val); - } - - shifted_cp = sign_extend32(val, 5); - - shared->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp; - shared->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft; - } - - void init(bool isMariko) { - constexpr u64 FusePa = 0x7000F000; - R_UNLESS(MapAddress(fuseVa, FusePa, "fuse")); - - if (isMariko) { - // u32 major, minor, rev; - pdata = &tegra210b01_plat_data; - info->config = &tegra210b01_aotag_config; - // tegra_fuse_readl(FUSE_CP_REV, &rev); - // minor = rev & 0x1f; - // major = (rev >> 5) & 0x3f; - // if (major == 0 && minor < TEGRA_FUSE_CP_REV_0_3) { - // info->config->tsample_ate -= 1; - // } - } else { - info->config = &tegra_aotag_config; - pdata = &tegra210_plat_data; - } - - info->fuse = &tegra_aotag_fuse; - info->coeff = pdata->coeff; - - struct aotag_sensor_info_t *ps_info = &aotag_sensor_info; - struct TSensorSharedCalib shared_fuses; - u32 therm_ab; - - CalcSharedCal(ps_info->fuse, &shared_fuses); - CalcTSensorCalib(ps_info->config, &shared_fuses, - ps_info->coeff, &therm_ab, AOTAG_FUSE_ADDR); - - ps_info->therm_a = REG_GET(therm_ab, CONFIG2_THERM_A); - ps_info->therm_b = REG_GET(therm_ab, CONFIG2_THERM_B); - - tegra_pmc_writel(therm_ab, PMC_TSENSOR_CONFIG2); - - struct aotag_sensor_info_t *i = info; - - unsigned long r = 0; - r = REG_SET(r, CONFIG0_TALL, i->config->tall); - tegra_pmc_writel(r, PMC_TSENSOR_CONFIG0); - - r = 0; - r = REG_SET(r, CONFIG1_TEN_COUNT, i->config->ten_count); - r = REG_SET(r, CONFIG1_TIDDQ_EN, i->config->tiddq_en); - r = REG_SET(r, CONFIG1_TSAMPLE, (i->config->tsample - 1)); - set_bit(CONFIG1_TEMP_ENABLE_POS, &r); - tegra_pmc_writel(r, PMC_TSENSOR_CONFIG1); - - r = 0; - r = REG_SET(r, TSENSOR_PDIV, i->config->pdiv); - tegra_pmc_writel(r, PMC_TSENSOR_PDIV0); - - r = tegra_pmc_readl(PMC_AOTAG_CFG); - set_bit(CFG_TAG_EN_POS, &r); - clear_bit(CFG_DISABLE_CLK_POS, &r); - tegra_pmc_writel(r, PMC_AOTAG_CFG); - fileUtils::LogLine("[aotag] Init complete!"); - wasInit = true; - } - s32 getTemp() - { - if(!wasInit) - return -125; - u32 regval = 0, abs = 0, fraction = 0, valid = 0, sign = 0; - s32 temp = 0; - regval = tegra_pmc_readl(PMC_TSENSOR_STATUS1); - valid = REG_GET(regval, STATUS1_TEMP_VALID); - - if (!valid) { - return -125; - } - abs = REG_GET(regval, STATUS1_TEMP_ABS); - fraction = REG_GET(regval, STATUS1_TEMP_FRAC); - sign = REG_GET(regval, STATUS1_TEMP_SIGN); - temp = (abs*1000) + (fraction*500); - if (sign) - temp = (-1) * (temp); - return temp; - } - - bool isInitialized() { - return wasInit; - } -} \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/board/board.cpp b/Source/hoc-clk/sysmodule/src/board/board.cpp index 815de1a4..f0f287ee 100644 --- a/Source/hoc-clk/sysmodule/src/board/board.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board.cpp @@ -39,10 +39,10 @@ #include "board_load.hpp" #include "board_volt.hpp" #include "board_misc.hpp" -#include "../soctherm.hpp" +#include "../tsensor/soctherm.hpp" +#include "../tsensor/aotag.hpp" #include "../integrations.hpp" #include "../file_utils.hpp" -#include "../aotag.hpp" namespace board { u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr; @@ -55,7 +55,7 @@ namespace board { PwmChannelSession iCon; u32 fd = 0, fd2 = 0; - + #define PMC_BASE 0x7000E400 void FetchHardwareInfos() { @@ -141,7 +141,7 @@ namespace board { batteryInfoInitialize(); FetchHardwareInfos(); - soctherm::Initialize(); // SOCTHERM must be init before AOTAG + tsensor::InitializeSoctherm(); // SOCTHERM must be init before AOTAG // PMC exosphere check SecmonArgs args = {}; args.X[0] = 0xF0000002; @@ -149,7 +149,7 @@ namespace board { svcCallSecureMonitor(&args); if (args.X[1] != PMC_BASE) { // if param 1 is identical read failed - aotag::init(GetSocType() == HocClkSocType_Mariko); + tsensor::InitializeAotag(GetSocType() == HocClkSocType_Mariko); } Result pwmCheck = 1; @@ -164,7 +164,7 @@ namespace board { rc = QueryMemoryMapping(&dsiVirtAddr, 0x54300000, 0x40000); ASSERT_RESULT_OK(rc, "QueryMemoryMapping (dsi)"); - + rc = QueryMemoryMapping(&apbVirtAddr, 0x70000000, 0x1000); ASSERT_RESULT_OK(rc, "QueryMemoryMapping (apb)"); diff --git a/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp b/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp index 684f1123..30b27b50 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp @@ -31,18 +31,19 @@ #include #include #include "board.hpp" -#include "../soctherm.hpp" +#include "../tsensor/soctherm.hpp" +#include "../tsensor/aotag.hpp" #include "bq24193.hpp" -#include "../aotag.hpp" #include "../config.hpp" + namespace board { s32 GetTemperatureMilli(HocClkThermalSensor sensor) { s32 millis = 0; BatteryChargeInfo info; - soctherm::TSensorTemps temps = {}; - soctherm::ReadSensors(temps); + tsensor::TSensorTemps temps = {}; + tsensor::ReadTSensors(temps); switch(sensor) { case HocClkThermalSensor_SOC: { @@ -79,8 +80,8 @@ namespace board { break; } case HocClkThermalSensor_MEM: { - if(board::GetSocType() == HocClkSocType_Mariko && aotag::isInitialized() && aotag::getTemp() > 0) { - millis = (temps.gpu * 0.45f) + (temps.pllx * 0.30f) + (temps.cpu * 0.15f) + (aotag::getTemp() * 0.10f) + 3000; + if (board::GetSocType() == HocClkSocType_Mariko && tsensor::IsInitialized() && tsensor::ReadAotag() > 0) { + millis = (temps.gpu * 0.45f) + (temps.pllx * 0.30f) + (temps.cpu * 0.15f) + (tsensor::ReadAotag() * 0.10f) + 3000; } else { millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem; } @@ -95,7 +96,7 @@ namespace board { break; } case HocClkThermalSensor_AO: { - millis = aotag::getTemp(); + millis = tsensor::ReadAotag(); break; } default: { diff --git a/Source/hoc-clk/sysmodule/src/mem_map.cpp b/Source/hoc-clk/sysmodule/src/mem_map.cpp index 3d3a0ccd..bbaf96db 100644 --- a/Source/hoc-clk/sysmodule/src/mem_map.cpp +++ b/Source/hoc-clk/sysmodule/src/mem_map.cpp @@ -16,15 +16,22 @@ */ #include +#include "file_utils.hpp" Result QueryMemoryMapping(u64* virtaddr, u64 physaddr, u64 size) { - if(hosversionAtLeast(10,0,0)) - { + if(hosversionAtLeast(10,0,0)) { u64 out_size; return svcQueryMemoryMapping(virtaddr, &out_size, physaddr, size); - } - else - { + } else { return svcLegacyQueryIoMapping(virtaddr, physaddr, size); } } + +Result MapAddress(u64 &va, const u64 &physAddr, const char *name) { + Result mapResult = QueryMemoryMapping(&va, physAddr, 0x1000); + if (R_FAILED(mapResult)) { + fileUtils::LogLine("Failed to map %s! %u", name, R_DESCRIPTION(mapResult)); + } + + return mapResult; +} diff --git a/Source/hoc-clk/sysmodule/src/mem_map.hpp b/Source/hoc-clk/sysmodule/src/mem_map.hpp index badc027f..b2913979 100644 --- a/Source/hoc-clk/sysmodule/src/mem_map.hpp +++ b/Source/hoc-clk/sysmodule/src/mem_map.hpp @@ -19,3 +19,4 @@ #include Result QueryMemoryMapping(u64* virtaddr, u64 physaddr, u64 size); +Result MapAddress(u64 &va, const u64 &physAddr, const char *name); diff --git a/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp b/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp new file mode 100644 index 00000000..0d76a363 --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp @@ -0,0 +1,241 @@ +/* + * drivers/thermal/tegra_aotag.c + * + * TEGRA AOTAG (Always-On Thermal Alert Generator) driver. + * + * Copyright (c) 2014 - 2017, NVIDIA CORPORATION. All rights reserved. + * + * Copyright (c) 1994, Linus Torvalds + * + * Copyright (c) 2026, Souldbminer + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that 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 "../mem_map.hpp" +#include "../file_utils.hpp" +#include "tsensor_common.hpp" +#include "aotag.hpp" + +namespace tsensor { + #define PMC_BASE 0x7000E400 + #define TEGRA_FUSE_CP_REV_0_3 (3) + #define FUSE_CP_REV 0x190 + + namespace { + u64 fuseVa = 0; + bool wasInit = false; + } + + #define REG_SET(r, mask, value) \ + ((r & ~(mask##_MASK)) | ((value<<(mask##_POS_START)) & mask##_MASK)) + + #define REG_GET(r, mask) \ + ((r & mask##_MASK) >> mask##_POS_START) + + #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff + + static const TSensorFuse tegra_aotag_fuse = { + .fuse_base_cp_mask = 0x3ff << 11, + .fuse_base_cp_shift = 11, + .fuse_base_ft_mask = (u32)0x7ff << 21, + .fuse_base_ft_shift = 21, + .fuse_shift_ft_mask = 0x1f << 6, + .fuse_shift_ft_shift = 6, + .fuse_spare_realignment = 0, + }; + + static TSensorConfig tegra_aotag_config = { + .tall = 76, + .tiddq_en = 1, + .ten_count = 16, + .pdiv = 8, + .pdiv_ate = 8, + .tsample = 9, + .tsample_ate = 39, + }; + + static TSensorConfig tegra210b01_aotag_config = { + .tall = 76, + .tiddq_en = 1, + .ten_count = 16, + .pdiv = 12, + .pdiv_ate = 6, + .tsample = 19, + .tsample_ate = 39, + }; + + static const FuseCorrCoeff tegra_aotag_coeff = { + .alpha = 1063200, + .beta = -6749000, + }; + + static const FuseCorrCoeff tegra210b01_aotag_coeff = { + .alpha = 991100, + .beta = 1096200, + }; + + struct aotag_sensor_info_t { + struct TSensorConfig *config; + const struct TSensorFuse *fuse; + const struct FuseCorrCoeff *coeff; + s32 therm_a; + s32 therm_b; + }; + + struct aotag_platform_data { + struct TSensorConfig *config; + const struct FuseCorrCoeff *coeff; + }; + + static aotag_platform_data tegra210_plat_data = { + .config = &tegra_aotag_config, + .coeff = &tegra_aotag_coeff, + }; + + static aotag_platform_data tegra210b01_plat_data = { + .config = &tegra210b01_aotag_config, + .coeff = &tegra210b01_aotag_coeff, + }; + + aotag_sensor_info_t aotag_sensor_info = { + .config = NULL, + .fuse = NULL, + .coeff = NULL, + .therm_a = 0, + .therm_b = 0, + }; + + aotag_sensor_info_t *info = &aotag_sensor_info; + aotag_platform_data *pdata = NULL; + + u32 ReadPmcReg(unsigned long offset) { + SecmonArgs args = {}; + args.X[0] = 0xF0000002; + args.X[1] = PMC_BASE + offset; + svcCallSecureMonitor(&args); + + if (args.X[1] == (PMC_BASE + offset)) { // if param 1 is identical read failed + return 0; + } + + return args.X[1]; + } + + void WritePmcReg(u32 value, unsigned long offset) { + SecmonArgs args = {}; + args.X[0] = 0xF0000002; + args.X[1] = PMC_BASE + offset; + args.X[2] = 0xFFFFFFFF; + args.X[3] = (value); + svcCallSecureMonitor(&args); + } + + static inline void SetBit(unsigned long nr, volatile void *addr) { + int *m = ((int *) addr) + (nr >> 5); + *m |= 1 << (nr & 31); + } + + static inline void ClearBit(unsigned long nr, volatile void *addr) { + int *m = ((int *) addr) + (nr >> 5); + *m &= ~(1 << (nr & 31)); + } + + void InitializeAotag(bool isMariko) { + constexpr u64 FusePa = 0x7000F000; + R_UNLESS(MapAddress(fuseVa, FusePa, "fuse")); + + if (isMariko) { + // u32 major, minor, rev; + pdata = &tegra210b01_plat_data; + info->config = &tegra210b01_aotag_config; + // tegra_fuse_readl(FUSE_CP_REV, &rev); + // minor = rev & 0x1f; + // major = (rev >> 5) & 0x3f; + // if (major == 0 && minor < TEGRA_FUSE_CP_REV_0_3) { + // info->config->tsample_ate -= 1; + // } + } else { + info->config = &tegra_aotag_config; + pdata = &tegra210_plat_data; + } + + info->fuse = &tegra_aotag_fuse; + info->coeff = pdata->coeff; + + aotag_sensor_info_t *ps_info = &aotag_sensor_info; + TSensorSharedCalib shared_fuses; + u32 therm_ab; + + CalcSharedCal(ps_info->fuse, &shared_fuses, fuseVa); + CalcTSensorCalib(ps_info->config, &shared_fuses, ps_info->coeff, &therm_ab, AOTAG_FUSE_ADDR, fuseVa); + + ps_info->therm_a = REG_GET(therm_ab, CONFIG2_THERM_A); + ps_info->therm_b = REG_GET(therm_ab, CONFIG2_THERM_B); + + WritePmcReg(therm_ab, PMC_TSENSOR_CONFIG2); + + aotag_sensor_info_t *i = info; + + unsigned long r = 0; + r = REG_SET(r, CONFIG0_TALL, i->config->tall); + WritePmcReg(r, PMC_TSENSOR_CONFIG0); + + r = 0; + r = REG_SET(r, CONFIG1_TEN_COUNT, i->config->ten_count); + r = REG_SET(r, CONFIG1_TIDDQ_EN, i->config->tiddq_en); + r = REG_SET(r, CONFIG1_TSAMPLE, (i->config->tsample - 1)); + SetBit(CONFIG1_TEMP_ENABLE_POS, &r); + WritePmcReg(r, PMC_TSENSOR_CONFIG1); + + r = 0; + r = REG_SET(r, TSENSOR_PDIV, i->config->pdiv); + WritePmcReg(r, PMC_TSENSOR_PDIV0); + + r = ReadPmcReg(PMC_AOTAG_CFG); + SetBit(CFG_TAG_EN_POS, &r); + ClearBit(CFG_DISABLE_CLK_POS, &r); + WritePmcReg(r, PMC_AOTAG_CFG); + fileUtils::LogLine("[aotag] Init complete!"); + wasInit = true; + } + + s32 ReadAotag() { + if (!wasInit) { + return -125; + } + + u32 regval = 0, abs = 0, fraction = 0, valid = 0, sign = 0; + s32 temp = 0; + regval = ReadPmcReg(PMC_TSENSOR_STATUS1); + valid = REG_GET(regval, STATUS1_TEMP_VALID); + + if (!valid) { + return -125; + } + + abs = REG_GET(regval, STATUS1_TEMP_ABS); + fraction = REG_GET(regval, STATUS1_TEMP_FRAC); + sign = REG_GET(regval, STATUS1_TEMP_SIGN); + temp = (abs * 1000) + (fraction * 500); + if (sign) { + temp = (-1) * (temp); + } + + return temp; + } + + bool IsInitialized() { + return wasInit; + } + +} diff --git a/Source/hoc-clk/sysmodule/src/aotag.hpp b/Source/hoc-clk/sysmodule/src/tsensor/aotag.hpp similarity index 75% rename from Source/hoc-clk/sysmodule/src/aotag.hpp rename to Source/hoc-clk/sysmodule/src/tsensor/aotag.hpp index c742ead1..6c9eff38 100644 --- a/Source/hoc-clk/sysmodule/src/aotag.hpp +++ b/Source/hoc-clk/sysmodule/src/tsensor/aotag.hpp @@ -5,7 +5,7 @@ * Copyright (c) 2014 - 2017, NVIDIA CORPORATION. All rights reserved. * * Copyright (c) 2026, Souldbminer - * + * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. @@ -18,86 +18,12 @@ */ #pragma once -#include "board/board.hpp" -namespace aotag { + +namespace tsensor { #define MASK(start, end) \ (((0xFFFFFFFF)< #include +#include "../board/board.hpp" +#include "../file_utils.hpp" +#include "../mem_map.hpp" #include "soctherm.hpp" -#include "board/board.hpp" -#include "file_utils.hpp" -#include "mem_map.hpp" +#include "tsensor_common.hpp" -namespace soctherm { +namespace tsensor { namespace { - #define FUSE_CACHE_OFFSET 0x800 - #define FUSE_TSENSOR_COMMON 0xA80 #define CAR_CLK_SOURCE_TSENSOR 0x3B8 #define CAR_CLK_OUT_ENB_V 0x360 @@ -44,9 +43,6 @@ namespace soctherm { #define CAR_CLK_SOURCE_TSENSOR_VAL 0x8000005E - #define NOMINAL_CALIB_FT 105 - #define NOMINAL_CALIB_CP 25 - #define THERMCTL_LEVEL0_GROUP_CPU 0x0 #define THERMCTL_LEVEL0_GROUP_GPU 0x4 #define THERMCTL_LEVEL0_GROUP_MEM 0x8 @@ -65,9 +61,7 @@ namespace soctherm { #define SENSOR_CONFIG2 8 #define SENSOR_CONFIG2_THERMA_MASK (0xffffu << 16) - #define SENSOR_CONFIG2_THERMA_SHIFT 16 #define SENSOR_CONFIG2_THERMB_MASK 0xffff - #define SENSOR_CONFIG2_THERMB_SHIFT 0 #define THERMCTL_THERMTRIP_CTL 0x80 @@ -126,9 +120,6 @@ namespace soctherm { #define TEGRA210_BPTT 9 #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff - #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13) - #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13 - #define CALIB_COEFFICIENT 1000000LL #define SENSOR_CONFIG0 0 #define SENSOR_CONFIG0_STOP BIT(0) @@ -420,53 +411,6 @@ namespace soctherm { bool isMariko; } - template - static inline T ReadReg(u64 base, u32 offset) { - return *reinterpret_cast(base + offset); - } - - template - static inline void WriteReg(u64 base, u32 offset, T value) { - *reinterpret_cast(base + offset) = value; - } - - template - static inline void SetBits(u64 base, u32 offset, T mask) { - WriteReg(base, offset, ReadReg(base, offset) | mask); - } - - template - static inline void ClearBits(u64 base, u32 offset, T mask) { - WriteReg(base, offset, ReadReg(base, offset) & ~mask); - } - - Result MapAddress(u64 &va, const u64 &physAddr, const char *name) { - Result mapResult = QueryMemoryMapping(&va, physAddr, 0x1000); - if (R_FAILED(mapResult)) { - fileUtils::LogLine("[Soctherm] Failed to map %s! %u", name, R_DESCRIPTION(mapResult)); - } - - return mapResult; - } - - static inline s32 sign_extend32(u32 value, int index) { - u8 shift = 31 - index; - return (s32) (value << shift) >> shift; - } - - static inline s64 div64_s64(s64 dividend, s64 divisor) { - return dividend / divisor; - } - - static s64 div64_s64_precise(s64 a, s32 b) { - s64 r, al; - - al = a << 16; - - r = div64_s64(al * 2 + 1, 2 * b); - return r >> 16; - } - bool IsDisabledThroughSleep() { return (ReadReg(carVa, CLK_RST_CONTROLLER_RST_DEVICES) & SWR_SOC_THERM_RST) || !(ReadReg(carVa, CLK_RST_CONTROLLER_CLK_OUT_ENB) & CLK_ENB_SOC_THERM); } @@ -529,7 +473,7 @@ namespace soctherm { WriteReg(socthermVa, TSENSOR_TSENSOR_CLKEN, TSENSOR_TSENSOR_ENABLE); } - void ReadSensors(TSensorTemps &temps) { + void ReadTSensors(TSensorTemps &temps) { if (IsDisabledThroughSleep()) { return; } @@ -549,65 +493,7 @@ namespace soctherm { } } - void CalcSharedCal(const TSensorFuse *tfuse, TSensorSharedCalib *shared, u64 fuseVa) { - s32 shifted_cp, shifted_ft; - - u32 val = ReadReg(fuseVa, FUSE_TSENSOR_COMMON); - - shared->base_cp = (val & tfuse->fuse_base_cp_mask) >> tfuse->fuse_base_cp_shift; - shared->base_ft = (val & tfuse->fuse_base_ft_mask) >> tfuse->fuse_base_ft_shift; - - shifted_ft = (val & tfuse->fuse_shift_ft_mask) >> tfuse->fuse_shift_ft_shift; - shifted_ft = sign_extend32(shifted_ft, 4); - - if (tfuse->fuse_spare_realignment) { - val = ReadReg(fuseVa, tfuse->fuse_spare_realignment + FUSE_CACHE_OFFSET); - } - - shifted_cp = sign_extend32(val, 5); - - shared->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp; - shared->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft; - } - - void CalcTSensorCalib(const TSensorConfig *cfg, TSensorSharedCalib *shared, const FuseCorrCoeff *corr, u32 *calibration, u32 offset, u64 fuseVa) { - u32 val, calib; - s32 actual_tsensor_ft, actual_tsensor_cp; - s32 delta_sens, delta_temp; - s32 mult, div; - s16 therma, thermb; - s64 temp; - - val = ReadReg(fuseVa, offset + FUSE_CACHE_OFFSET); - - actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12); - val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK) >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT; - actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12); - - delta_sens = actual_tsensor_ft - actual_tsensor_cp; - delta_temp = shared->actual_temp_ft - shared->actual_temp_cp; - - mult = cfg->pdiv * cfg->tsample_ate; - div = cfg->tsample * cfg->pdiv_ate; - - temp = (s64)delta_temp * (1LL << 13) * mult; - therma = div64_s64_precise(temp, (s64)delta_sens * div); - - temp = ((s64)actual_tsensor_ft * shared->actual_temp_cp) - ((s64)actual_tsensor_cp * shared->actual_temp_ft); - thermb = div64_s64_precise(temp, delta_sens); - - temp = (s64)therma * corr->alpha; - therma = div64_s64_precise(temp, CALIB_COEFFICIENT); - - temp = (s64)thermb * corr->alpha + corr->beta; - thermb = div64_s64_precise(temp, CALIB_COEFFICIENT); - - calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) | ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT); - - *calibration = calib; - } - - void Initialize() { + void InitializeSoctherm() { isMariko = board::GetSocType() == HocClkSocType_Mariko; constexpr u64 SocthermPa = 0x700E2000, FusePa = 0x7000F000, CarPa = 0x60006000; diff --git a/Source/hoc-clk/sysmodule/src/tsensor/soctherm.hpp b/Source/hoc-clk/sysmodule/src/tsensor/soctherm.hpp new file mode 100644 index 00000000..02a292c9 --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/tsensor/soctherm.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014 - 2019, NVIDIA CORPORATION. All rights reserved. + * + * Author: + * Mikko Perttunen + * + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + * + */ + +#pragma once + +#include +#include + +namespace tsensor { + + enum SocthermTSensor : u32 { + SocthermTSensor_CPU0 = 0, + SocthermTSensor_CPU1 = 1, + SocthermTSensor_CPU2 = 2, + SocthermTSensor_CPU3 = 3, + SocthermTSensor_GPU = 4, + SocthermTSensor_PLLX = 5, + SocthermTSensor_MEM0 = 6, + SocthermTSensor_MEM1 = 7, + SocthermTSensor_EnumMax = 8, + }; + + struct TSensorTemps { + s32 cpu; + s32 gpu; + s32 mem; + s32 pllx; + }; + + void InitializeSoctherm(); + void ReadTSensors(TSensorTemps &temps); + +} diff --git a/Source/hoc-clk/sysmodule/src/tsensor/tsensor_common.cpp b/Source/hoc-clk/sysmodule/src/tsensor/tsensor_common.cpp new file mode 100644 index 00000000..9be99147 --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/tsensor/tsensor_common.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 - 2019, NVIDIA CORPORATION. All rights reserved. + * + * Copyright (c) 1994, Linus Torvalds + * + * Author: + * Mikko Perttunen + * + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 "tsensor_common.hpp" + +namespace tsensor { + + static s64 div64_s64(s64 dividend, s64 divisor) { + return dividend / divisor; + } + + static s64 div64_s64_precise(s64 a, s32 b) { + s64 r, al; + + al = a << 16; + + r = div64_s64(al * 2 + 1, 2 * b); + return r >> 16; + } + + static s32 sign_extend32(u32 value, int index) { + u8 shift = 31 - index; + return (s32) (value << shift) >> shift; + } + + void CalcSharedCal(const TSensorFuse *tfuse, TSensorSharedCalib *shared, u64 fuseVa) { + constexpr u32 NominalCalibFt = 105; + constexpr u32 NominalCalibCp = 25; + + s32 shifted_cp, shifted_ft; + + u32 val = ReadReg(fuseVa, FUSE_TSENSOR_COMMON); + + shared->base_cp = (val & tfuse->fuse_base_cp_mask) >> tfuse->fuse_base_cp_shift; + shared->base_ft = (val & tfuse->fuse_base_ft_mask) >> tfuse->fuse_base_ft_shift; + + shifted_ft = (val & tfuse->fuse_shift_ft_mask) >> tfuse->fuse_shift_ft_shift; + shifted_ft = sign_extend32(shifted_ft, 4); + + if (tfuse->fuse_spare_realignment) { + val = ReadReg(fuseVa, tfuse->fuse_spare_realignment + FUSE_CACHE_OFFSET); + } + + shifted_cp = sign_extend32(val, 5); + + shared->actual_temp_cp = 2 * NominalCalibCp + shifted_cp; + shared->actual_temp_ft = 2 * NominalCalibFt + shifted_ft; + } + + void CalcTSensorCalib(const TSensorConfig *cfg, TSensorSharedCalib *shared, const FuseCorrCoeff *corr, u32 *calibration, u32 offset, u64 fuseVa) { + #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13 + #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13) + #define CALIB_COEFFICIENT 1000000LL + #define SENSOR_CONFIG2_THERMA_SHIFT 16 + #define SENSOR_CONFIG2_THERMB_SHIFT 0 + + u32 val, calib; + s32 actual_tsensor_ft, actual_tsensor_cp; + s32 delta_sens, delta_temp; + s32 mult, div; + s16 therma, thermb; + s64 temp; + + val = ReadReg(fuseVa, offset + FUSE_CACHE_OFFSET); + + actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12); + val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK) >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT; + actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12); + + delta_sens = actual_tsensor_ft - actual_tsensor_cp; + delta_temp = shared->actual_temp_ft - shared->actual_temp_cp; + + mult = cfg->pdiv * cfg->tsample_ate; + div = cfg->tsample * cfg->pdiv_ate; + + temp = (s64)delta_temp * (1LL << 13) * mult; + therma = div64_s64_precise(temp, (s64)delta_sens * div); + + temp = ((s64)actual_tsensor_ft * shared->actual_temp_cp) - ((s64)actual_tsensor_cp * shared->actual_temp_ft); + thermb = div64_s64_precise(temp, delta_sens); + + temp = (s64)therma * corr->alpha; + therma = div64_s64_precise(temp, CALIB_COEFFICIENT); + + temp = (s64)thermb * corr->alpha + corr->beta; + thermb = div64_s64_precise(temp, CALIB_COEFFICIENT); + + calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) | ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT); + + *calibration = calib; + } + +} \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/soctherm.hpp b/Source/hoc-clk/sysmodule/src/tsensor/tsensor_common.hpp similarity index 70% rename from Source/hoc-clk/sysmodule/src/soctherm.hpp rename to Source/hoc-clk/sysmodule/src/tsensor/tsensor_common.hpp index 1ac06a49..9ff6935d 100644 --- a/Source/hoc-clk/sysmodule/src/soctherm.hpp +++ b/Source/hoc-clk/sysmodule/src/tsensor/tsensor_common.hpp @@ -1,6 +1,8 @@ /* * Copyright (c) 2014 - 2019, NVIDIA CORPORATION. All rights reserved. * + * Copyright (c) 1994, Linus Torvalds + * * Author: * Mikko Perttunen * @@ -22,17 +24,10 @@ #pragma once -#include -#include +namespace tsensor { -namespace soctherm { - - #define R_UNLESS(rc) \ - do { \ - if (R_FAILED(rc)) { \ - return; \ - } \ - } while (0) + #define FUSE_TSENSOR_COMMON 0xA80 + #define FUSE_CACHE_OFFSET 0x800 struct TSensorConfig { u32 tall; @@ -101,26 +96,27 @@ namespace soctherm { u32 actual_temp_ft; }; - enum SocthermTSensor : u32 { - SocthermTSensor_CPU0 = 0, - SocthermTSensor_CPU1 = 1, - SocthermTSensor_CPU2 = 2, - SocthermTSensor_CPU3 = 3, - SocthermTSensor_GPU = 4, - SocthermTSensor_PLLX = 5, - SocthermTSensor_MEM0 = 6, - SocthermTSensor_MEM1 = 7, - SocthermTSensor_EnumMax = 8, - }; + template + static inline T ReadReg(u64 base, u32 offset) { + return *reinterpret_cast(base + offset); + } - struct TSensorTemps { - s32 cpu; - s32 gpu; - s32 mem; - s32 pllx; - }; + template + static inline void WriteReg(u64 base, u32 offset, T value) { + *reinterpret_cast(base + offset) = value; + } - void Initialize(); - void ReadSensors(TSensorTemps &temps); + template + static inline void SetBits(u64 base, u32 offset, T mask) { + WriteReg(base, offset, ReadReg(base, offset) | mask); + } + + template + static inline void ClearBits(u64 base, u32 offset, T mask) { + WriteReg(base, offset, ReadReg(base, offset) & ~mask); + } + + void CalcSharedCal(const TSensorFuse *tfuse, TSensorSharedCalib *shared, u64 fuseVa); + void CalcTSensorCalib(const TSensorConfig *cfg, TSensorSharedCalib *shared, const FuseCorrCoeff *corr, u32 *calibration, u32 offset, u64 fuseVa); }