Skip to content

Commit

Permalink
query TI TMP451 sensor directly for temps
Browse files Browse the repository at this point in the history
ts service seems bugged/unreliable in HOS 19.0.0, and has few sessions available anyway
  • Loading branch information
p-sam committed Oct 14, 2024
1 parent 3ba7cbc commit ed4ba7b
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 67 deletions.
2 changes: 2 additions & 0 deletions sysmodule/lib/nxExt/include/nxExt.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#pragma once

#include "nxExt/apm_ext.h"
#include "nxExt/i2c.h"
#include "nxExt/t210.h"
#include "nxExt/max17050.h"
#include "nxExt/tmp451.h"
#include "nxExt/ipc_server.h"
#include "nxExt/cpp/lockable_mutex.h"
24 changes: 24 additions & 0 deletions sysmodule/lib/nxExt/include/nxExt/i2c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]>, <[email protected]>, <[email protected]>
* 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

#ifdef __cplusplus
extern "C"
{
#endif

#include <switch.h>

Result i2csessionExtSendU8Receive(I2cSession* s, u8 in, void* out, u8 out_size);

#ifdef __cplusplus
}
#endif
27 changes: 27 additions & 0 deletions sysmodule/lib/nxExt/include/nxExt/tmp451.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]>, <[email protected]>, <[email protected]>
* 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

#ifdef __cplusplus
extern "C"
{
#endif

#include <switch.h>

Result tmp451Initialize(void);
void tmp451Exit(void);
s32 tmp451TempPcb(void);
s32 tmp451TempSoc(void);

#ifdef __cplusplus
}
#endif
28 changes: 28 additions & 0 deletions sysmodule/lib/nxExt/src/i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]>, <[email protected]>, <[email protected]>
* 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 "nxExt/i2c.h"

#define I2C_CMD_SND 0
#define I2C_CMD_RCV 1

Result i2csessionExtSendU8Receive(I2cSession* s, u8 in, void* out, u8 out_size)
{
u8 cmdlist[5] = {
I2C_CMD_SND | (I2cTransactionOption_Start << 6),
sizeof(in),
in,

I2C_CMD_RCV | (I2cTransactionOption_All << 6),
out_size
};

return i2csessionExecuteCommandList(s, out, out_size, cmdlist, sizeof(cmdlist));
}
19 changes: 4 additions & 15 deletions sysmodule/lib/nxExt/src/max17050.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
*/

#include "nxExt/max17050.h"
#include "nxExt/i2c.h"

#define MAX17050_WAIT_NS 1175800000UL
#define MAX17050_WAIT_NS 1000000000UL

#define MAX17050_VCELL 0x09
#define MAX17050_Current 0x0A
Expand All @@ -39,28 +40,16 @@ static u64 g_update_ticks = 0;
static s32 g_power_now = 0;
static s32 g_power_avg = 0;

static Result _max17050_get_reg(u8 reg, u16* out)
{
Result rc = i2csessionSendAuto(&g_i2c_session, &reg, sizeof(reg), I2cTransactionOption_All);

if(R_SUCCEEDED(rc))
{
rc = i2csessionReceiveAuto(&g_i2c_session, out, sizeof(*out), I2cTransactionOption_All);
}

return rc;
}

static Result _max17050_get_power(u8 creg, u8 vreg, s32 *out_mw)
{
u16 current = 0;
u16 voltage = 0;

Result rc = _max17050_get_reg(creg, &current);
Result rc = i2csessionExtSendU8Receive(&g_i2c_session, creg, &current, sizeof(current));

if(R_SUCCEEDED(rc))
{
rc = _max17050_get_reg(vreg, &voltage);
rc = i2csessionExtSendU8Receive(&g_i2c_session, vreg, &voltage, sizeof(voltage));
}

if(R_SUCCEEDED(rc))
Expand Down
14 changes: 7 additions & 7 deletions sysmodule/lib/nxExt/src/t210.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,6 @@ static void _clock_update_freqs(void)
return;
}

const u32 osc = 38400000;
u32 coeff = GPU_TRIM_SYS_GPCPLL(GPU_TRIM_SYS_GPCPLL_COEFF);
u32 divm = coeff & 0xFF;
u32 divn = (coeff >> 8) & 0xFF;
u32 divp = (coeff >> 16) & 0x3F;
g_gpu_freq = osc * divn / (divm * divp) / 2;

if (!g_act_base)
{
_svcQueryMemoryMappingFallback(&g_act_base, 0x6000C000ul, 0x1000);
Expand All @@ -239,6 +232,13 @@ static void _clock_update_freqs(void)
return;
}

const u32 osc = 38400000;
u32 coeff = GPU_TRIM_SYS_GPCPLL(GPU_TRIM_SYS_GPCPLL_COEFF);
u32 divm = coeff & 0xFF;
u32 divn = (coeff >> 8) & 0xFF;
u32 divp = (coeff >> 16) & 0x3F;
g_gpu_freq = osc * divn / (divm * divp) / 2;

u32 emc_freq = g_mem_freq / 1000;

// Check if actmon is disabled
Expand Down
102 changes: 102 additions & 0 deletions sysmodule/lib/nxExt/src/tmp451.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
*
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2024 p-sam
*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "nxExt/tmp451.h"
#include "nxExt/i2c.h"

#define TMP451_WAIT_NS 1000000000UL

#define TMP451_PCB_TEMP_REG 0x00
#define TMP451_SOC_TEMP_REG 0x01

#define TMP451_SOC_TMP_DEC_REG 0x10
#define TMP451_PCB_TMP_DEC_REG 0x15

static I2cSession g_i2c_session;
static u64 g_update_ticks = 0;
static s32 g_temp_pcb = 0;
static s32 g_temp_soc = 0;

static Result _tmp451_get_temp(u8 reg, u8 dec_reg, s32* out)
{
u8 val = 0;
Result rc = i2csessionExtSendU8Receive(&g_i2c_session, reg, &val, sizeof(val));

if(R_SUCCEEDED(rc))
{
*out = (s32)val * 1000;
rc = i2csessionExtSendU8Receive(&g_i2c_session, dec_reg, &val, sizeof(val));
}

if(R_SUCCEEDED(rc))
{
*out += ((s32)(val >> 4) * 625) / 10;
}

return rc;
}

static void _tmp451_update()
{
u64 ticks = armGetSystemTick();
if(armTicksToNs(ticks - g_update_ticks) <= TMP451_WAIT_NS)
{
return;
}

g_update_ticks = ticks;

if(!serviceIsActive(&g_i2c_session.s))
{
return;
}

_tmp451_get_temp(TMP451_PCB_TEMP_REG, TMP451_PCB_TMP_DEC_REG, &g_temp_pcb);
_tmp451_get_temp(TMP451_SOC_TEMP_REG, TMP451_SOC_TMP_DEC_REG, &g_temp_soc);
}

Result tmp451Initialize(void)
{
Result rc = i2cInitialize();

if(R_SUCCEEDED(rc))
{
rc = i2cOpenSession(&g_i2c_session, I2cDevice_Tmp451);
}

return rc;
}

void tmp451Exit(void)
{
i2csessionClose(&g_i2c_session);
i2cExit();
}

s32 tmp451TempPcb(void)
{
_tmp451_update();
return g_temp_pcb;
}

s32 tmp451TempSoc(void)
{
_tmp451_update();
return g_temp_soc;
}
50 changes: 6 additions & 44 deletions sysmodule/src/board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ void Board::Initialize()
rc = psmInitialize();
ASSERT_RESULT_OK(rc, "psmInitialize");

rc = tsInitialize();
ASSERT_RESULT_OK(rc, "tsInitialize");

if(HOSSVC_HAS_TC)
{
rc = tcInitialize();
Expand All @@ -100,6 +97,9 @@ void Board::Initialize()
rc = max17050Initialize();
ASSERT_RESULT_OK(rc, "max17050Initialize");

rc = tmp451Initialize();
ASSERT_RESULT_OK(rc, "max17050Initialize");

FetchHardwareInfos();
}

Expand All @@ -116,14 +116,14 @@ void Board::Exit()

apmExtExit();
psmExit();
tsExit();

if(HOSSVC_HAS_TC)
{
tcExit();
}

max17050Exit();
tmp451Exit();
}

SysClkProfile Board::GetProfile()
Expand Down Expand Up @@ -292,55 +292,17 @@ void Board::ResetToStock()
}
}

std::int32_t Board::GetTsTemperatureMilli(TsLocation location)
{
Result rc;
std::int32_t millis = 0;

if(hosversionAtLeast(19,0,0))
{
// TODO: see https://github.com/retronx-team/sys-clk/issues/85
}
else if(hosversionAtLeast(17,0,0))
{
TsSession session = {0};
float temp = 0;

rc = tsOpenSession(&session, ((u32)location + 1) | 0x41000000);
ASSERT_RESULT_OK(rc, "tsOpenSession(%u)", location);

rc = tsSessionGetTemperature(&session, &temp);
ASSERT_RESULT_OK(rc, "tsSessionGetTemperature(%u)", location);
millis = temp * 1000;

tsSessionClose(&session);
}
else if(hosversionAtLeast(14,0,0))
{
rc = tsGetTemperature(location, &millis);
ASSERT_RESULT_OK(rc, "tsGetTemperature(%u)", location);
millis *= 1000;
}
else
{
rc = tsGetTemperatureMilliC(location, &millis);
ASSERT_RESULT_OK(rc, "tsGetTemperatureMilliC(%u)", location);
}

return millis;
}

std::uint32_t Board::GetTemperatureMilli(SysClkThermalSensor sensor)
{
std::int32_t millis = 0;

if(sensor == SysClkThermalSensor_SOC)
{
millis = GetTsTemperatureMilli(TsLocation_External);
millis = tmp451TempSoc();
}
else if(sensor == SysClkThermalSensor_PCB)
{
millis = GetTsTemperatureMilli(TsLocation_Internal);
millis = tmp451TempPcb();
}
else if(sensor == SysClkThermalSensor_Skin)
{
Expand Down
1 change: 0 additions & 1 deletion sysmodule/src/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,4 @@ class Board
static void FetchHardwareInfos();
static PcvModule GetPcvModule(SysClkModule sysclkModule);
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
static std::int32_t GetTsTemperatureMilli(TsLocation location);
};

0 comments on commit ed4ba7b

Please sign in to comment.