From bf17e53c8f6f9aa0325213ae754bf0de6c4cde3e Mon Sep 17 00:00:00 2001 From: Lightos1 <124387232+Lightos1@users.noreply.github.com> Date: Tue, 31 Mar 2026 23:26:18 +0200 Subject: [PATCH] add soctherm --- .../rewrite-hoc-clk/common/include/sysclk.h | 5 +- .../common/include/sysclk/soctherm.hpp | 46 ++ Source/rewrite-hoc-clk/sysmodule/perms.json | 115 ++-- .../sysmodule/src/board/board.cpp | 3 + .../sysmodule/src/soctherm.cpp | 630 ++++++++++++++++++ .../sysmodule/src/soctherm.hpp | 128 ++++ 6 files changed, 865 insertions(+), 62 deletions(-) create mode 100644 Source/rewrite-hoc-clk/common/include/sysclk/soctherm.hpp create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/soctherm.cpp create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/soctherm.hpp diff --git a/Source/rewrite-hoc-clk/common/include/sysclk.h b/Source/rewrite-hoc-clk/common/include/sysclk.h index c44f506b..9b6091c2 100644 --- a/Source/rewrite-hoc-clk/common/include/sysclk.h +++ b/Source/rewrite-hoc-clk/common/include/sysclk.h @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -49,6 +49,7 @@ extern "C" { #include "sysclk/config.h" #include "sysclk/errors.h" #include "sysclk/psm_ext.h" +#include "sysclk/soctherm.hpp" #ifdef __cplusplus } diff --git a/Source/rewrite-hoc-clk/common/include/sysclk/soctherm.hpp b/Source/rewrite-hoc-clk/common/include/sysclk/soctherm.hpp new file mode 100644 index 00000000..51f50e7e --- /dev/null +++ b/Source/rewrite-hoc-clk/common/include/sysclk/soctherm.hpp @@ -0,0 +1,46 @@ +/* + * 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 . + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * wrote this file. As long as you retain this notice you can do whatever you + * want with this stuff. If you meet any of us some day, and you think this + * stuff is worth it, you can buy us a beer in return. - The sys-clk authors + * -------------------------------------------------------------------------- + */ + +#pragma once + +#include +#include + +namespace soctherm { + + struct TSensorTemps { + s32 cpu; + s32 gpu; + s32 mem; + s32 pllx; + }; + +} diff --git a/Source/rewrite-hoc-clk/sysmodule/perms.json b/Source/rewrite-hoc-clk/sysmodule/perms.json index b5c09894..f7778a05 100644 --- a/Source/rewrite-hoc-clk/sysmodule/perms.json +++ b/Source/rewrite-hoc-clk/sysmodule/perms.json @@ -3,7 +3,7 @@ "title_id": "0x00FF0000636C6BFF", "title_id_range_min": "0x00FF0000636C6BFF", "title_id_range_max": "0x00FF0000636C6BFF", - "main_thread_stack_size": "0x0000C000", + "main_thread_stack_size": "0x0000D000", "main_thread_priority": 16, "default_cpu_id": 3, "process_category": 1, @@ -29,44 +29,63 @@ "lowest_cpu_id": 0, "highest_cpu_id": 3 } - }, - { - "type": "map", - "value": { - "address": "0x60006000", - "size": "0x1000", - "is_ro": false, - "is_io": true + }, { + "type": "map", + "value": { + "address": "0x60006000", + "is_ro": false, + "size": "0x00001000", + "is_io": true } - }, - { - "type": "map", - "value": { - "address": "0x57000000", - "size": "0x1000000", - "is_ro": false, - "is_io": true + }, { + "type": "map", + "value": { + "address": "0x57000000", + "is_ro": false, + "size": "0x01000000", + "is_io": true } - }, - { - "type": "map", - "value": { - "address": "0x6000C000", - "size": "0x1000", - "is_ro": false, - "is_io": true + }, { + "type": "map", + "value": { + "address": "0x6000c000", + "is_ro": false, + "size": "0x00001000", + "is_io": true } - }, - { - "type": "map", - "value": { - "address": "0x70110000", - "size": "0x1000", - "is_ro": false, - "is_io": true + }, { + "type": "map", + "value": { + "address": "0x7000f000", + "is_ro": false, + "size": "0x00001000", + "is_io": true } - }, - { + }, { + "type": "map", + "value": { + "address": "0x700e2000", + "is_ro": false, + "size": "0x00001000", + "is_io": true + } + }, { + "type": "map", + "value": { + "address": "0x70110000", + "is_ro": false, + "size": "0x00001000", + "is_io": true + } + }, { + "type": "map", + "value": { + "address": "0x54300000", + "size": "0x40000", + "is_ro": false, + "is_io": true + } + }, { "type": "syscalls", "value": { "svcUnknown": "0x00", @@ -211,30 +230,6 @@ "force_debug_prod": false, "force_debug": true } - }, { - "type": "map", - "value": { - "address": "0x60006000", - "size": "0x1000", - "is_ro": false, - "is_io": true - } - }, { - "type": "map", - "value": { - "address": "0x54300000", - "size": "0x40000", - "is_ro": false, - "is_io": true - } - }, { - "type": "map", - "value": { - "address": "0x7001b000", - "size": "0x1000", - "is_ro": false, - "is_io": true - } } ] -} \ No newline at end of file +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp index 350c5abc..e4bb154f 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp @@ -39,6 +39,7 @@ #include "board_load.hpp" #include "board_volt.hpp" #include "board_misc.hpp" +#include "../soctherm.hpp" namespace board { @@ -134,6 +135,8 @@ namespace board { batteryInfoInitialize(); FetchHardwareInfos(); + soctherm::Initialize(); + Result pwmCheck = 1; if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { pwmCheck = pwmOpenSession2(&iCon, 0x3D000001); diff --git a/Source/rewrite-hoc-clk/sysmodule/src/soctherm.cpp b/Source/rewrite-hoc-clk/sysmodule/src/soctherm.cpp new file mode 100644 index 00000000..4ade4c34 --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/soctherm.cpp @@ -0,0 +1,630 @@ +/* + * 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 . + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * wrote this file. As long as you retain this notice you can do whatever you + * want with this stuff. If you meet any of us some day, and you think this + * stuff is worth it, you can buy us a beer in return. - The sys-clk authors + * -------------------------------------------------------------------------- + */ + +#include +#include +#include "soctherm.hpp" +#include "board/board.hpp" +#include "file_utils.hpp" + +namespace soctherm { + + namespace { + + #define FUSE_CACHE_OFFSET 0x800 + #define FUSE_TSENSOR_COMMON 0xA80 + #define CAR_CLK_SOURCE_TSENSOR 0x3B8 + #define CAR_CLK_OUT_ENB_V 0x360 + + #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 + #define THERMCTL_LEVEL0_GROUP_TSENSE 0xc + + #define TEGRA124_SOCTHERM_SENSOR_CPU 0 + #define TEGRA124_SOCTHERM_SENSOR_MEM 1 + #define TEGRA124_SOCTHERM_SENSOR_GPU 2 + #define TEGRA124_SOCTHERM_SENSOR_PLLX 3 + #define TEGRA124_SOCTHERM_SENSOR_NUM 4 + + #define TEGRA_SOCTHERM_THROT_LEVEL_NONE 0 + #define TEGRA_SOCTHERM_THROT_LEVEL_LOW 1 + #define TEGRA_SOCTHERM_THROT_LEVEL_MED 2 + #define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 3 + + #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 + + #define SENSOR_PDIV 0x1c0 + #define SENSOR_PDIV_CPU_MASK (0xf << 12) + #define SENSOR_PDIV_GPU_MASK (0xf << 8) + #define SENSOR_PDIV_MEM_MASK (0xf << 4) + #define SENSOR_PDIV_PLLX_MASK (0xf << 0) + + #define SENSOR_HOTSPOT_OFF 0x1c4 + #define SENSOR_HOTSPOT_CPU_MASK (0xff << 16) + #define SENSOR_HOTSPOT_GPU_MASK (0xff << 8) + #define SENSOR_HOTSPOT_MEM_MASK (0xff << 0) + + #define SENSOR_HW_PLLX_OFFSET_EN 0x1e4 + #define SENSOR_HW_PLLX_OFFSET_MEM_EN_MASK BIT(2) + #define SENSOR_HW_PLLX_OFFSET_CPU_EN_MASK BIT(1) + #define SENSOR_HW_PLLX_OFFSET_GPU_EN_MASK BIT(0) + + #define SENSOR_HW_PLLX_OFFSET_MIN 0x1e8 + #define SENSOR_HW_PLLX_OFFSET_MAX 0x1ec + #define SENSOR_HW_PLLX_OFFSET_MEM_MASK (0xff << 16) + #define SENSOR_HW_PLLX_OFFSET_GPU_MASK (0xff << 8) + #define SENSOR_HW_PLLX_OFFSET_CPU_MASK (0xff << 0) + + #define SENSOR_TEMP1 0x1c8 + #define SENSOR_TEMP1_CPU_TEMP_MASK (0xffffu << 16) + #define SENSOR_TEMP1_GPU_TEMP_MASK 0xffff + #define SENSOR_TEMP2 0x1cc + #define SENSOR_TEMP2_MEM_TEMP_MASK (0xffffu << 16) + #define SENSOR_TEMP2_PLLX_TEMP_MASK 0xffff + + #define SENSOR_VALID 0x1e0 + #define SENSOR_GPU_VALID_MASK BIT(9) + #define SENSOR_CPU_VALID_MASK 0xf + #define SENSOR_MEM_VALID_MASK (0x3 << 10) + + #define TEGRA210_THERMTRIP_ANY_EN_MASK (0x1u << 31) + #define TEGRA210_THERMTRIP_MEM_EN_MASK (0x1 << 30) + #define TEGRA210_THERMTRIP_GPU_EN_MASK (0x1 << 29) + #define TEGRA210_THERMTRIP_CPU_EN_MASK (0x1 << 28) + #define TEGRA210_THERMTRIP_TSENSE_EN_MASK (0x1 << 27) + #define TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK (0x1ff << 18) + #define TEGRA210_THERMTRIP_CPU_THRESH_MASK (0x1ff << 9) + #define TEGRA210_THERMTRIP_TSENSE_THRESH_MASK 0x1ff + + #define TEGRA210_THERM_IRQ_MEM_MASK (0x3 << 24) + #define TEGRA210_THERM_IRQ_GPU_MASK (0x3 << 16) + #define TEGRA210_THERM_IRQ_CPU_MASK (0x3 << 8) + #define TEGRA210_THERM_IRQ_TSENSE_MASK (0x3 << 0) + + #define TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK (0x1ff << 18) + #define TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK (0x1ff << 9) + + #define TEGRA210_THRESH_GRAIN 500 + #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) + #define SENSOR_CONFIG0_CPTR_OVER BIT(2) + #define SENSOR_CONFIG0_OVER BIT(3) + #define SENSOR_CONFIG0_TCALC_OVER BIT(4) + #define SENSOR_CONFIG0_TALL_MASK (0xfffff << 8) + #define SENSOR_CONFIG0_TALL_SHIFT 8 + + #define PDIV_RATE_T210B0 0xCC0C + #define PDIV_RATE_T210 0x8888 + #define HOTSPOT_VAL 0xA0500 + + #define SENSOR_CONFIG1 4 + #define SENSOR_CONFIG1_TSAMPLE_MASK 0x3ff + #define SENSOR_CONFIG1_TSAMPLE_SHIFT 0 + #define SENSOR_CONFIG1_TIDDQ_EN_MASK (0x3f << 15) + #define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15 + #define SENSOR_CONFIG1_TEN_COUNT_MASK (0x3f << 24) + #define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24 + #define SENSOR_CONFIG1_TEMP_ENABLE BIT(31) + + #define READBACK_VALUE_MASK 0xff00 + #define READBACK_VALUE_SHIFT 8 + #define READBACK_ADD_HALF BIT(7) + #define READBACK_NEGATE BIT(0) + + #define PDIV_MASK_T210B0 0xFFFF00F0 + #define HOTSPOT_MASK_T210B0 0xFF0000FF + + #define PDIV_MASK_T210 0xFFFF0000 + #define HOTSPOT_MASK_T210 0xFF000000 + + #define TSENSOR_TSENSOR_CLKEN 0x1DC + #define TSENSOR_TSENSOR_ENABLE 225 + + const TSensorFuse tfuse = { + .fuse_base_cp_mask = 0x3ff << 11, + .fuse_base_cp_shift = 11, + .fuse_base_ft_mask = 0x7ffu << 21, + .fuse_base_ft_shift = 21, + .fuse_shift_ft_mask = 0x1f << 6, + .fuse_shift_ft_shift = 6, + .fuse_spare_realignment = 0, + }; + + const TSensorConfig eristaConf = { + .tall = 16300, + .tiddq_en = 1, + .ten_count = 1, + .pdiv = 8, + .pdiv_ate = 8, + .tsample = 120, + .tsample_ate = 480, + }; + + const TSensorConfig marikoConf = { + .tall = 16300, + .tiddq_en = 1, + .ten_count = 1, + .pdiv = 12, + .pdiv_ate = 6, + .tsample = 240, + .tsample_ate = 480, + }; + + const struct TSensorGroup tSensorGroupCpu = { + .name = "cpu", + .id = TEGRA124_SOCTHERM_SENSOR_CPU, + .sensor_temp_offset = SENSOR_TEMP1, + .sensor_temp_mask = SENSOR_TEMP1_CPU_TEMP_MASK, + .pdiv_mask = SENSOR_PDIV_CPU_MASK, + .pllx_hotspot_diff = 10, + .pllx_hotspot_mask = SENSOR_HOTSPOT_CPU_MASK, + .hw_pllx_offset_mask = SENSOR_HW_PLLX_OFFSET_CPU_MASK, + .hw_pllx_offset_en_mask = SENSOR_HW_PLLX_OFFSET_CPU_EN_MASK, + .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK, + .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, + .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK, + .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU, + .thermctl_isr_mask = TEGRA210_THERM_IRQ_CPU_MASK, + .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, + .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, + }; + + const struct TSensorGroup tSensorGroupGpu = { + .name = "gpu", + .id = TEGRA124_SOCTHERM_SENSOR_GPU, + .sensor_temp_offset = SENSOR_TEMP1, + .sensor_temp_mask = SENSOR_TEMP1_GPU_TEMP_MASK, + .pdiv_mask = SENSOR_PDIV_GPU_MASK, + .pllx_hotspot_diff = 5, + .pllx_hotspot_mask = SENSOR_HOTSPOT_GPU_MASK, + .hw_pllx_offset_mask = SENSOR_HW_PLLX_OFFSET_GPU_MASK, + .hw_pllx_offset_en_mask = SENSOR_HW_PLLX_OFFSET_GPU_EN_MASK, + .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK, + .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, + .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK, + .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU, + .thermctl_isr_mask = TEGRA210_THERM_IRQ_GPU_MASK, + .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, + .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, + }; + + const struct TSensorGroup tSensorGroupPll = { + .name = "pll", + .id = TEGRA124_SOCTHERM_SENSOR_PLLX, + .sensor_temp_offset = SENSOR_TEMP2, + .sensor_temp_mask = SENSOR_TEMP2_PLLX_TEMP_MASK, + .pdiv_mask = SENSOR_PDIV_PLLX_MASK, + .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK, + .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, + .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK, + .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE, + .thermctl_isr_mask = TEGRA210_THERM_IRQ_TSENSE_MASK, + .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, + .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, + }; + + const struct TSensorGroup eristaTSensorGroupMem = { + .name = "mem", + .id = TEGRA124_SOCTHERM_SENSOR_MEM, + .sensor_temp_offset = SENSOR_TEMP2, + .sensor_temp_mask = SENSOR_TEMP2_MEM_TEMP_MASK, + .pdiv_mask = SENSOR_PDIV_MEM_MASK, + .pllx_hotspot_diff = 0, + .pllx_hotspot_mask = SENSOR_HOTSPOT_MEM_MASK, + .hw_pllx_offset_mask = SENSOR_HW_PLLX_OFFSET_MEM_MASK, + .hw_pllx_offset_en_mask = SENSOR_HW_PLLX_OFFSET_MEM_EN_MASK, + .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK, + .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, + .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK, + .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM, + .thermctl_isr_mask = TEGRA210_THERM_IRQ_MEM_MASK, + .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, + .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, + }; + + const TSensor eristaTSensors[] = { + { + .name = "cpu0", + .base = 0xc0, + .config = &eristaConf, + .calib_fuse_offset = 0x198, + .fuse_corr = { + .alpha = 1085000, + .beta = 3244200, + }, + .group = &tSensorGroupCpu, + }, { + .name = "cpu1", + .base = 0xe0, + .config = &eristaConf, + .calib_fuse_offset = 0x184, + .fuse_corr = { + .alpha = 1126200, + .beta = -67500, + }, + .group = &tSensorGroupCpu, + }, { + .name = "cpu2", + .base = 0x100, + .config = &eristaConf, + .calib_fuse_offset = 0x188, + .fuse_corr = { + .alpha = 1098400, + .beta = 2251100, + }, + .group = &tSensorGroupCpu, + }, { + .name = "cpu3", + .base = 0x120, + .config = &eristaConf, + .calib_fuse_offset = 0x22c, + .fuse_corr = { + .alpha = 1108000, + .beta = 602700, + }, + .group = &tSensorGroupCpu, + }, { + .name = "gpu", + .base = 0x180, + .config = &eristaConf, + .calib_fuse_offset = 0x254, + .fuse_corr = { + .alpha = 1074300, + .beta = 2734900, + }, + .group = &tSensorGroupGpu, + }, { + .name = "pllx", + .base = 0x1a0, + .config = &eristaConf, + .calib_fuse_offset = 0x260, + .fuse_corr = { + .alpha = 1039700, + .beta = 6829100, + }, + .group = &tSensorGroupPll, + }, { + .name = "mem0", + .base = 0x140, + .config = &eristaConf, + .calib_fuse_offset = 0x258, + .fuse_corr = { + .alpha = 1069200, + .beta = 3549900, + }, + .group = &eristaTSensorGroupMem, + }, { + .name = "mem1", + .base = 0x160, + .config = &eristaConf, + .calib_fuse_offset = 0x25c, + .fuse_corr = { + .alpha = 1173700, + .beta = -6263600, + }, + .group = &eristaTSensorGroupMem, + }, + }; + + const TSensor marikoTSensors[] = { + { + .name = "cpu0", + .base = 0xc0, + .config = &marikoConf, + .calib_fuse_offset = 0x198, + .fuse_corr = { + .alpha = 1085000, + .beta = 3244200, + }, + .group = &tSensorGroupCpu, + }, { + .name = "cpu1", + .base = 0xe0, + .config = &marikoConf, + .calib_fuse_offset = 0x184, + .fuse_corr = { + .alpha = 1126200, + .beta = -67500, + }, + .group = &tSensorGroupCpu, + }, { + .name = "cpu2", + .base = 0x100, + .config = &marikoConf, + .calib_fuse_offset = 0x188, + .fuse_corr = { + .alpha = 1098400, + .beta = 2251100, + }, + .group = &tSensorGroupCpu, + }, { + .name = "cpu3", + .base = 0x120, + .config = &marikoConf, + .calib_fuse_offset = 0x22c, + .fuse_corr = { + .alpha = 1108000, + .beta = 602700, + }, + .group = &tSensorGroupCpu, + }, { + .name = "gpu", + .base = 0x180, + .config = &marikoConf, + .calib_fuse_offset = 0x254, + .fuse_corr = { + .alpha = 1074300, + .beta = 2734900, + }, + .group = &tSensorGroupGpu, + }, { + .name = "pllx", + .base = 0x1a0, + .config = &marikoConf, + .calib_fuse_offset = 0x260, + .fuse_corr = { + .alpha = 1039700, + .beta = 6829100, + }, + .group = &tSensorGroupPll, + }, + }; + + u32 calib[SocthermTSensor_EnumMax] = {}; + u64 socthermVa; + 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) { + u64 outSize; + Result mapResult = svcQueryMemoryMapping(&va, &outSize, 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; + } + + void EnableSensor(const TSensor *sensor, u32 sensorIdx) { + u32 val = sensor->config->tall << SENSOR_CONFIG0_TALL_SHIFT; + WriteReg(socthermVa, sensor->base + SENSOR_CONFIG0, val); + + val = (sensor->config->tsample - 1) << SENSOR_CONFIG1_TSAMPLE_SHIFT; + val |= sensor->config->tiddq_en << SENSOR_CONFIG1_TIDDQ_EN_SHIFT; + val |= sensor->config->ten_count << SENSOR_CONFIG1_TEN_COUNT_SHIFT; + val |= SENSOR_CONFIG1_TEMP_ENABLE; + WriteReg(socthermVa, sensor->base + SENSOR_CONFIG1, val); + WriteReg(socthermVa, sensor->base + SENSOR_CONFIG2, calib[sensorIdx]); + } + + s32 TranslateTemp(u16 val) { + s32 t; + + t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000; + if (val & READBACK_ADD_HALF) { + t += 500; + } + + if (val & READBACK_NEGATE) { + t *= -1; + } + + return t; + } + + void ReadSensors(TSensorTemps &temps) { + temps.cpu = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP1) >> 16); + temps.gpu = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP1) & SENSOR_TEMP1_GPU_TEMP_MASK); + temps.pllx = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP2) & SENSOR_TEMP2_PLLX_TEMP_MASK); + + if (board::GetSocType() == SysClkSocType_Erista) { + temps.mem = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP2) >> 16); + } else { + temps.mem = -1; + } + } + + void StartSensors() { + if (!ReadReg(socthermVa, TSENSOR_TSENSOR_CLKEN)) { + u32 pdiv, hotspot; + + if (isMariko) { + for (u32 i = 0; i < std::size(marikoTSensors); ++i) { + EnableSensor(&marikoTSensors[i], i); + } + + pdiv = (ReadReg(socthermVa, SENSOR_PDIV) & PDIV_MASK_T210B0) | PDIV_RATE_T210B0; + hotspot = (ReadReg(socthermVa, SENSOR_HOTSPOT_OFF) & HOTSPOT_MASK_T210B0) | HOTSPOT_VAL; + } else { + for (u32 i = 0; i < std::size(eristaTSensors); ++i) { + EnableSensor(&eristaTSensors[i], i); + } + + pdiv = (ReadReg(socthermVa, SENSOR_PDIV) & PDIV_MASK_T210) | PDIV_RATE_T210; + hotspot = (ReadReg(socthermVa, SENSOR_HOTSPOT_OFF) & HOTSPOT_MASK_T210) | HOTSPOT_VAL; + + EnableSensor(&eristaTSensors[SocthermTSensor_MEM0], SocthermTSensor_MEM0); + EnableSensor(&eristaTSensors[SocthermTSensor_MEM1], SocthermTSensor_MEM1); + } + + WriteReg(socthermVa, SENSOR_PDIV, pdiv); + WriteReg(socthermVa, SENSOR_HOTSPOT_OFF, hotspot); + WriteReg(socthermVa, TSENSOR_TSENSOR_CLKEN, TSENSOR_TSENSOR_ENABLE); + } + } + + 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() { + u64 carVa, fuseVa; + isMariko = board::GetSocType() == SysClkSocType_Mariko; + + constexpr u64 SocthermPa = 0x700E2000, FusePa = 0x7000F000, CarPa = 0x60006000; + R_UNLESS(MapAddress(socthermVa, SocthermPa, "soctherm")); + R_UNLESS(MapAddress( fuseVa, FusePa, "fuse")); + R_UNLESS(MapAddress( carVa, CarPa, "car")); + + WriteReg(carVa, CAR_CLK_SOURCE_TSENSOR, CAR_CLK_SOURCE_TSENSOR_VAL); + SetBits(carVa, CAR_CLK_OUT_ENB_V, 0x10); + svcSleepThread(2000); + + TSensorSharedCalib sharedCal = {}; + CalcSharedCal(&tfuse, &sharedCal, fuseVa); + + if (isMariko) { + for (u32 i = 0; i < std::size(marikoTSensors); ++i) { + CalcTSensorCalib(marikoTSensors[i].config, &sharedCal, &marikoTSensors[i].fuse_corr, &calib[i], marikoTSensors[i].calib_fuse_offset, fuseVa); + } + } else { + for (u32 i = 0; i < std::size(eristaTSensors); ++i) { + CalcTSensorCalib(eristaTSensors[i].config, &sharedCal, &eristaTSensors[i].fuse_corr, &calib[i], eristaTSensors[i].calib_fuse_offset, fuseVa); + } + } + + StartSensors(); + + fileUtils::LogLine("[Soctherm] Finished init."); + } + +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/soctherm.hpp b/Source/rewrite-hoc-clk/sysmodule/src/soctherm.hpp new file mode 100644 index 00000000..75a7f67f --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/soctherm.hpp @@ -0,0 +1,128 @@ +/* + * 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 . + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * wrote this file. As long as you retain this notice you can do whatever you + * want with this stuff. If you meet any of us some day, and you think this + * stuff is worth it, you can buy us a beer in return. - The sys-clk authors + * -------------------------------------------------------------------------- + */ + +#pragma once + +#include +#include + +namespace soctherm { + + #define R_UNLESS(rc) \ + do { \ + if (R_FAILED(rc)) { \ + return; \ + } \ + } while (0) + + struct TSensorConfig { + u32 tall; + u32 tiddq_en; + u32 ten_count; + u32 pdiv; + u32 pdiv_ate; + u32 tsample; + u32 tsample_ate; + }; + + struct FuseCorrCoeff { + s32 alpha; + s32 beta; + }; + + struct TSensorGroup { + const char *name; + u8 id; + u16 sensor_temp_offset; + u32 sensor_temp_mask; + u32 pdiv_mask; + u32 pllx_hotspot_diff; + u32 pllx_hotspot_mask; + u32 hw_pllx_offset_mask; + u32 hw_pllx_offset_en_mask; + u32 thermtrip_enable_mask; + u32 thermtrip_any_en_mask; + u32 thermtrip_threshold_mask; + u16 thermctl_lvl0_offset; + u32 thermctl_isr_mask; + u32 thermctl_lvl0_up_thresh_mask; + u32 thermctl_lvl0_dn_thresh_mask; + }; + + struct TSensorGroupOffsets { + u32 max; + u32 min; + u32 hw_offsetting_en; + const TSensorGroup *ttg; + }; + + struct TSensor { + const char *name; + const u32 base; + const TSensorConfig *config; + const u32 calib_fuse_offset; + const FuseCorrCoeff fuse_corr; + const TSensorGroup *group; + }; + + struct TSensorFuse { + u32 fuse_base_cp_mask; + u32 fuse_base_cp_shift; + u32 fuse_base_ft_mask; + u32 fuse_base_ft_shift; + u32 fuse_shift_ft_mask; + u32 fuse_shift_ft_shift; + u32 fuse_spare_realignment; + }; + + struct TSensorSharedCalib { + u32 base_cp; + u32 base_ft; + u32 actual_temp_cp; + 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, + }; + + void Initialize(); + void ReadSensors(TSensorTemps &temps); + +}