hoc-sys: add wip emc patcher and soctherm
This commit is contained in:
@@ -73,19 +73,19 @@ void EMCpatcher::ApplyEMCPatch()
|
||||
u64 emc_out_size = 0;
|
||||
Result rc;
|
||||
|
||||
rc = svcQueryMemoryMapping(&mc_virt_addr, &mc_out_size, MC_BASE, MC_EMC_BASE_SIZE); // map mc
|
||||
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping");
|
||||
// rc = svcQueryMemoryMapping(&mc_virt_addr, &mc_out_size, MC_BASE, MC_EMC_BASE_SIZE); // map mc
|
||||
// ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping");
|
||||
|
||||
rc = svcQueryMemoryMapping(&emc_virt_addr, &emc_out_size, EMC_BASE, MC_EMC_BASE_SIZE); // map emc
|
||||
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping");
|
||||
// rc = svcQueryMemoryMapping(&emc_virt_addr, &emc_out_size, EMC_BASE, MC_EMC_BASE_SIZE); // map emc
|
||||
// ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping");
|
||||
|
||||
write_reg64(emc_virt_addr, EMC_RAS_0, 1);
|
||||
write_reg64(EMC_BASE, EMC_RAS_0, 1);
|
||||
|
||||
write_reg64(emc_virt_addr, EMC_TIMING_CONTROL_0, 0x1); // apply shadow regs
|
||||
write_reg64(EMC_BASE, EMC_TIMING_CONTROL_0, 0x1); // apply shadow regs
|
||||
|
||||
|
||||
svcUnmapMemory((void *)mc_virt_addr, (void *)MC_BASE, MC_EMC_BASE_SIZE); // clean up
|
||||
svcUnmapMemory((void *)emc_virt_addr, (void *)EMC_BASE, MC_EMC_BASE_SIZE);
|
||||
// svcUnmapMemory((void *)mc_virt_addr, (void *)MC_BASE, MC_EMC_BASE_SIZE); // clean up
|
||||
// svcUnmapMemory((void *)emc_virt_addr, (void *)EMC_BASE, MC_EMC_BASE_SIZE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,33 @@
|
||||
#include <array>
|
||||
#include "errors.h"
|
||||
|
||||
static inline uint32_t read_reg64(uint64_t virt_addr, uint32_t offset) {
|
||||
return *(volatile uint32_t *)(virt_addr + offset);
|
||||
// Read a 32-bit register via libnx SVC
|
||||
static inline uint32_t read_reg64(uint64_t phys_addr, uint32_t offset) {
|
||||
uint32_t value = 0;
|
||||
Result rc = svcReadWriteRegister(&value, phys_addr + offset, 0, false);
|
||||
if (R_FAILED(rc)) {
|
||||
// Handle failure if needed
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void write_reg64(uint64_t virt_addr, uint32_t offset, uint32_t value) {
|
||||
*(volatile uint32_t *)(virt_addr + offset) = value;
|
||||
// Write a 32-bit register via libnx SVC
|
||||
static inline void write_reg64(uint64_t phys_addr, uint32_t offset, uint32_t value) {
|
||||
Result rc = svcReadWriteRegister(NULL, phys_addr + offset, value, true);
|
||||
if (R_FAILED(rc)) {
|
||||
// Handle failure if needed
|
||||
}
|
||||
}
|
||||
|
||||
// Bitfield helper remains the same
|
||||
static inline uint32_t set_bits(uint32_t reg_value, uint8_t start_bit, uint8_t end_bit, uint32_t value)
|
||||
{
|
||||
if (end_bit < start_bit || end_bit > 31)
|
||||
return reg_value;
|
||||
|
||||
// Create bit mask for the field
|
||||
uint32_t mask = ((1u << (end_bit - start_bit + 1)) - 1u) << start_bit;
|
||||
|
||||
// Clear target bits and insert new value
|
||||
reg_value = (reg_value & ~mask) | ((value << start_bit) & mask);
|
||||
|
||||
return reg_value;
|
||||
}
|
||||
|
||||
|
||||
131
Source/sys-clk/sysmodule/src/soctherm.h
Normal file
131
Source/sys-clk/sysmodule/src/soctherm.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/* * HOS soctherm driver by Souldbminer & Dominatorul * Licensed under the LGPLv3 */
|
||||
#ifndef _SOCTHERM_H_
|
||||
#define _SOCTHERM_H_
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
#define SOCTHERM_BASE 0x700E2000ULL
|
||||
|
||||
#define SENSOR_TEMP1 0x1c8
|
||||
#define SENSOR_TEMP2 0x1cc
|
||||
|
||||
#define SOC_THERM_THERMCTL_LEVEL0_GROUP_CPU_0 0x0
|
||||
#define SOC_THERM_THERMCTL_LEVEL0_GROUP_GPU_0 0x4
|
||||
#define SOC_THERM_THERMCTL_LEVEL0_GROUP_MEM_0 0x8
|
||||
#define SOC_THERM_THERMCTL_LEVEL0_GROUP_TSENSE_0 0xC
|
||||
|
||||
#define SENSOR_CPU0_CONFIG0 0xC0
|
||||
#define SENSOR_CPU1_CONFIG0 0xE0
|
||||
#define SENSOR_CPU2_CONFIG0 0x100
|
||||
#define SENSOR_CPU3_CONFIG0 0x120
|
||||
#define SENSOR_GPU_CONFIG0 0x180
|
||||
#define SENSOR_PLLX_CONFIG0 0x1A0
|
||||
|
||||
#define SENSOR_CPU0_CONFIG1 0xC4
|
||||
#define SENSOR_CPU1_CONFIG1 0xE4
|
||||
#define SENSOR_CPU2_CONFIG1 0x104
|
||||
#define SENSOR_CPU3_CONFIG1 0x124
|
||||
#define SENSOR_GPU_CONFIG1 0x184
|
||||
#define SENSOR_PLLX_CONFIG1 0x1A4
|
||||
|
||||
#define SENSOR_CPU0_STATUS 0xC8
|
||||
#define SENSOR_GPU_STATUS 0x188
|
||||
#define SENSOR_PLLX_STATUS 0x1A8
|
||||
|
||||
#define SENSOR_CONFIG0_STOP_MASK (1U << 0)
|
||||
#define SENSOR_CONFIG0_TALL_SHIFT 8
|
||||
#define SENSOR_CONFIG0_TALL_MASK (0xFFFFF << 8)
|
||||
|
||||
#define SENSOR_CONFIG1_TEMP_ENABLE_MASK (1U << 31)
|
||||
#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
|
||||
#define SENSOR_CONFIG1_TEN_COUNT_MASK (0x3F << 24)
|
||||
#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15
|
||||
#define SENSOR_CONFIG1_TIDDQ_EN_MASK (0x3F << 15)
|
||||
#define SENSOR_CONFIG1_TSAMPLE_SHIFT 0
|
||||
#define SENSOR_CONFIG1_TSAMPLE_MASK 0x3FF
|
||||
|
||||
#define SENSOR_STATUS_VALID_MASK (1U << 31)
|
||||
|
||||
#define TSENSOR_TALL_DEFAULT 16300
|
||||
#define TSENSOR_TIDDQ_EN_DEFAULT 1
|
||||
#define TSENSOR_TEN_COUNT_DEFAULT 1
|
||||
#define TSENSOR_TSAMPLE_DEFAULT 120
|
||||
|
||||
#define SENSOR_TEMP1_CPU_TEMP_MASK (0xFFFF << 16)
|
||||
#define SENSOR_TEMP1_GPU_TEMP_MASK 0xFFFF
|
||||
#define SENSOR_TEMP2_PLLX_TEMP_MASK 0xFFFF
|
||||
|
||||
#define READBACK_VALUE_MASK 0xFF00
|
||||
#define READBACK_VALUE_SHIFT 8
|
||||
#define READBACK_ADD_HALF (1 << 7)
|
||||
#define READBACK_NEGATE (1 << 0)
|
||||
|
||||
#define REG_GET_MASK(r, m) (((r) & (m)) >> (__builtin_ffs(m) - 1))
|
||||
|
||||
// Timing constants (in microseconds)
|
||||
#define SENSOR_STABILIZATION_DELAY_US 2000 // 2ms for sensor to stabilize
|
||||
#define SENSOR_READ_DELAY_US 100 // 100us between config operations
|
||||
|
||||
// Makes my life easier
|
||||
#define BITMASK(bits) (0UL | (bits))
|
||||
#define BIT(n) (1UL << (n))
|
||||
|
||||
#define WRITE_REG_BIT(addr, bit, val) do { \
|
||||
u32 _tmp; \
|
||||
svcReadWriteRegister(&_tmp, (addr), 0, false); \
|
||||
if (val) \
|
||||
_tmp |= (1U << (bit)); /* set bit */ \
|
||||
else \
|
||||
_tmp &= ~(1U << (bit)); /* clear bit */ \
|
||||
svcReadWriteRegister(&_tmp, (addr), 0, true); \
|
||||
} while (0)
|
||||
|
||||
typedef enum {
|
||||
SENSOR_CPU = 0,
|
||||
SENSOR_GPU = 1,
|
||||
SENSOR_PLLX = 2,
|
||||
} SocthermSensor;
|
||||
|
||||
void socthermInit(void) {
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU0_CONFIG0, 0, 0); // start cpu0
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU0_CONFIG1, 31, 1); // start cpu0
|
||||
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU1_CONFIG0, 0, 0); // start cpu1
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU1_CONFIG1, 31, 1); // start cpu1
|
||||
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU2_CONFIG0, 0, 0); // start cpu2
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU2_CONFIG1, 31, 1); // start cpu2
|
||||
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU3_CONFIG0, 0, 0); // start cpu3
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_CPU3_CONFIG1, 31, 1); // start cpu3
|
||||
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_GPU_CONFIG0, 0, 0); // start gpu
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_GPU_CONFIG1, 31, 1); // start gpu
|
||||
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_PLLX_CONFIG0, 0, 0); // start pllx
|
||||
WRITE_REG_BIT(SOCTHERM_BASE + SENSOR_PLLX_CONFIG1, 31, 1); // start pllx
|
||||
}
|
||||
|
||||
int socthermRead(SocthermSensor sensor) {
|
||||
switch(sensor) {
|
||||
case SENSOR_CPU: {
|
||||
u32 temp_reg;
|
||||
svcReadWriteRegister(&temp_reg, SOCTHERM_BASE + SENSOR_TEMP1, 0, false);
|
||||
return REG_GET_MASK(temp_reg, SENSOR_TEMP1_CPU_TEMP_MASK);
|
||||
}
|
||||
case SENSOR_GPU: {
|
||||
u32 temp_reg;
|
||||
svcReadWriteRegister(&temp_reg, SOCTHERM_BASE + SENSOR_TEMP1, 0, false);
|
||||
return REG_GET_MASK(temp_reg, SENSOR_TEMP1_GPU_TEMP_MASK);
|
||||
}
|
||||
case SENSOR_PLLX: {
|
||||
u32 temp_reg;
|
||||
svcReadWriteRegister(&temp_reg, SOCTHERM_BASE + SENSOR_TEMP2, 0, false);
|
||||
return REG_GET_MASK(temp_reg, SENSOR_TEMP2_PLLX_TEMP_MASK);
|
||||
}
|
||||
default:
|
||||
return -1; // Invalid sensor
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _SOCTHERM_H_
|
||||
Reference in New Issue
Block a user