git subrepo pull --force emummc
subrepo: subdir: "emummc" merged: "2fc47cbb8" upstream: origin: "https://github.com/lulle2007200/emuMMC.git" branch: "develop" commit: "2fc47cbb8" git-subrepo: version: "0.4.9" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "30db3b8"
This commit is contained in:
128
emummc/source/fatal/bdk/thermal/fan.c
vendored
Normal file
128
emummc/source/fatal/bdk/thermal/fan.c
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Fan driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* 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 <thermal/fan.h>
|
||||
#include <power/regulator_5v.h>
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
|
||||
void fan_set_duty(u32 duty)
|
||||
{
|
||||
static bool fan_init = false;
|
||||
static u16 curr_duty = -1;
|
||||
|
||||
if (duty > 236)
|
||||
duty = 236;
|
||||
|
||||
if (curr_duty == duty)
|
||||
return;
|
||||
|
||||
curr_duty = duty;
|
||||
|
||||
if (!fan_init)
|
||||
{
|
||||
// Fan tachometer.
|
||||
u32 pull_resistor = hw_get_chip_id() == GP_HIDREV_MAJOR_T210 ? PINMUX_PULL_UP : 0;
|
||||
PINMUX_AUX(PINMUX_AUX_CAM1_PWDN) = PINMUX_TRISTATE | PINMUX_INPUT_ENABLE | pull_resistor | 1;
|
||||
gpio_direction_input(GPIO_PORT_S, GPIO_PIN_7);
|
||||
|
||||
// Enable PWM if disabled.
|
||||
if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA)
|
||||
clock_enable_pwm();
|
||||
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Max PWM to disable fan.
|
||||
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1.
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_4, GPIO_MODE_SPIO); // Fan power mode.
|
||||
|
||||
fan_init = true;
|
||||
}
|
||||
|
||||
// Inverted polarity.
|
||||
u32 inv_duty = 236 - duty;
|
||||
|
||||
// If disabled send a 0 duty.
|
||||
if (inv_duty == 236)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%.
|
||||
regulator_5v_disable(REGULATOR_5V_FAN);
|
||||
|
||||
// Disable fan.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = PINMUX_INPUT_ENABLE | PINMUX_PARKED |
|
||||
PINMUX_TRISTATE | PINMUX_PULL_DOWN; // Set source to PWM1.
|
||||
}
|
||||
else // Set PWM duty.
|
||||
{
|
||||
// Fan power supply.
|
||||
regulator_5v_enable(REGULATOR_5V_FAN);
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16);
|
||||
|
||||
// Enable fan.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1.
|
||||
}
|
||||
}
|
||||
|
||||
void fan_get_speed(u32 *duty, u32 *rpm)
|
||||
{
|
||||
if (rpm)
|
||||
{
|
||||
u32 irq_count = 0;
|
||||
bool should_read = true;
|
||||
|
||||
// Poll irqs for 2 seconds. (5 seconds for accurate count).
|
||||
int timer = get_tmr_us() + 2000000;
|
||||
while ((timer - get_tmr_us()) > 0)
|
||||
{
|
||||
bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
||||
if (irq_val && should_read)
|
||||
{
|
||||
irq_count++;
|
||||
should_read = false;
|
||||
}
|
||||
else if (!irq_val)
|
||||
should_read = true;
|
||||
}
|
||||
|
||||
// Halve the irq count.
|
||||
irq_count /= 2;
|
||||
|
||||
// Calculate rpm based on triggered interrupts.
|
||||
*rpm = irq_count * (60 / 2);
|
||||
}
|
||||
|
||||
if (duty)
|
||||
*duty = 236 - ((PWM(PWM_CONTROLLER_PWM_CSR_1) >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
void fan_set_from_temp(u32 temp)
|
||||
{
|
||||
if (temp >= 52)
|
||||
fan_set_duty(102);
|
||||
else if (temp >= 47)
|
||||
fan_set_duty(76);
|
||||
else if (temp >= 42)
|
||||
fan_set_duty(51);
|
||||
else if (temp <= 39)
|
||||
fan_set_duty(0);
|
||||
}
|
||||
31
emummc/source/fatal/bdk/thermal/fan.h
vendored
Normal file
31
emummc/source/fatal/bdk/thermal/fan.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Fan driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __FAN_H_
|
||||
#define __FAN_H_
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
// Disable: 0 (0 RPM), min duty: 1 (960 RPM), max duty 235 (11000 RPM).
|
||||
void fan_set_duty(u32 duty);
|
||||
// Passing NULL ptr on either of the two, disables results.
|
||||
void fan_get_speed(u32 *duty, u32 *rpm);
|
||||
|
||||
void fan_set_from_temp(u32 temp);
|
||||
|
||||
#endif /* __FAN_H_ */
|
||||
87
emummc/source/fatal/bdk/thermal/tmp451.c
vendored
Normal file
87
emummc/source/fatal/bdk/thermal/tmp451.c
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
|
||||
*
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
*
|
||||
* 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 <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/t210.h>
|
||||
#include <thermal/tmp451.h>
|
||||
|
||||
u16 tmp451_get_soc_temp(bool intenger)
|
||||
{
|
||||
u8 val;
|
||||
u16 temp = 0;
|
||||
|
||||
val = i2c_recv_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TEMP_REG);
|
||||
if (intenger)
|
||||
return val;
|
||||
|
||||
temp = val << 8;
|
||||
val = i2c_recv_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_DEC_REG);
|
||||
temp |= ((val >> 4) * 625) / 100;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
u16 tmp451_get_pcb_temp(bool intenger)
|
||||
{
|
||||
u8 val;
|
||||
u16 temp = 0;
|
||||
|
||||
val = i2c_recv_byte(I2C_1, TMP451_I2C_ADDR, TMP451_PCB_TEMP_REG);
|
||||
if (intenger)
|
||||
return val;
|
||||
|
||||
temp = val << 8;
|
||||
val = i2c_recv_byte(I2C_1, TMP451_I2C_ADDR, TMP451_PCB_TMP_DEC_REG);
|
||||
temp |= ((val >> 4) * 625) / 100;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void tmp451_init()
|
||||
{
|
||||
// Disable ALARM and Range to 0 - 127 oC.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
|
||||
|
||||
// Set remote sensor offsets based on SoC.
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
// Set offset to 0 oC for Erista.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0);
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set offset to -12.5 oC for Mariko.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 oC.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC.
|
||||
}
|
||||
|
||||
// Set conversion rate to 32/s and make a read to update the reg.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
|
||||
tmp451_get_soc_temp(false);
|
||||
|
||||
// Set rate to every 4 seconds.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
|
||||
}
|
||||
|
||||
void tmp451_end()
|
||||
{
|
||||
// Place into shutdown mode to conserve power.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0);
|
||||
}
|
||||
46
emummc/source/fatal/bdk/thermal/tmp451.h
vendored
Normal file
46
emummc/source/fatal/bdk/thermal/tmp451.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
|
||||
*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __TMP451_H_
|
||||
#define __TMP451_H_
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define TMP451_I2C_ADDR 0x4C
|
||||
|
||||
#define TMP451_PCB_TEMP_REG 0x00
|
||||
#define TMP451_SOC_TEMP_REG 0x01
|
||||
|
||||
#define TMP451_CONFIG_REG 0x09
|
||||
#define TMP451_CNV_RATE_REG 0x0A
|
||||
|
||||
#define TMP451_SOC_TMP_DEC_REG 0x10
|
||||
#define TMP451_PCB_TMP_DEC_REG 0x15
|
||||
|
||||
#define TMP451_SOC_TMP_OFH_REG 0x11
|
||||
#define TMP451_SOC_TMP_OFL_REG 0x12
|
||||
|
||||
// If input is false, the return value is packed. MSByte is the integer in oC
|
||||
// and the LSByte is the decimal point truncated to 2 decimal places.
|
||||
// Otherwise it's an integer oC.
|
||||
u16 tmp451_get_soc_temp(bool integer);
|
||||
u16 tmp451_get_pcb_temp(bool integer);
|
||||
void tmp451_init();
|
||||
void tmp451_end();
|
||||
|
||||
#endif /* __TMP451_H_ */
|
||||
Reference in New Issue
Block a user