Attention is currently required from: Martin Roth, Felix Held. Paul Menzel has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/50709 )
Change subject: sio/nuvoton/nct5572d: Add HWM API ......................................................................
sio/nuvoton/nct5572d: Add HWM API
Change-Id: Ide9d5668a123ffe4c3770de7df16986338f4e2d6 Signed-off-by: Paul Menzel pmenzel@molgen.mpg.de --- M src/superio/nuvoton/nct5572d/Kconfig M src/superio/nuvoton/nct5572d/Makefile.inc A src/superio/nuvoton/nct5572d/nct5572d_hwm.c A src/superio/nuvoton/nct5572d/nct5572d_hwm.h 4 files changed, 251 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/50709/1
diff --git a/src/superio/nuvoton/nct5572d/Kconfig b/src/superio/nuvoton/nct5572d/Kconfig index 5db826d..c169991 100644 --- a/src/superio/nuvoton/nct5572d/Kconfig +++ b/src/superio/nuvoton/nct5572d/Kconfig @@ -5,3 +5,9 @@ select SUPERIO_NUVOTON_COMMON_PRE_RAM select HAVE_POWER_STATE_AFTER_FAILURE select HAVE_POWER_STATE_PREVIOUS_AFTER_FAILURE + +config SUPERIO_NUVOTON_NCT5572D_HWM + bool + depends on SUPERIO_NUVOTON_NCT5572D + select SUPERIO_NUVOTON_COMMON_HWM + default n diff --git a/src/superio/nuvoton/nct5572d/Makefile.inc b/src/superio/nuvoton/nct5572d/Makefile.inc index d044794..f6222e1 100644 --- a/src/superio/nuvoton/nct5572d/Makefile.inc +++ b/src/superio/nuvoton/nct5572d/Makefile.inc @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-or-later
ramstage-$(CONFIG_SUPERIO_NUVOTON_NCT5572D) += superio.c + +all-$(CONFIG_SUPERIO_NUVOTON_NCT5572D_HWM) += nct5572d_hwm.c diff --git a/src/superio/nuvoton/nct5572d/nct5572d_hwm.c b/src/superio/nuvoton/nct5572d/nct5572d_hwm.c new file mode 100644 index 0000000..84907be --- /dev/null +++ b/src/superio/nuvoton/nct5572d/nct5572d_hwm.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <device/device.h> +#include <device/pnp.h> +#include <device/pnp_ops.h> +#include <superio/conf_mode.h> +#include <superio/hwm5_conf.h> +#include <superio/nuvoton/common/hwm.h> +#include <superio/nuvoton/common/nuvoton.h> +#include <types.h> + +#include "nct5572d_hwm.h" + +#if ENV_PNP_SIMPLE_DEVICE +void nct5572d_hwm_init(pnp_devfn_t dev, const u16 base) +{ + nuvoton_pnp_enter_conf_state(dev); + + pnp_set_logical_device(dev); + pnp_set_enable(dev, 1); + pnp_set_iobase(dev, 0x60, base); + + nuvoton_pnp_exit_conf_state(dev); +} +#endif + +/* Higher order fan control functions */ +void nct5572d_hwm_force_fan_full_on( + const u16 base, + const enum nct5572d_hwm_fan fan) +{ + nct5572d_hwm_set_fan_mode(base, fan, FAN_MODE_MANUAL); + nct5572d_hwm_set_fan_duty(base, fan, 0xff); +} + +void nct5572d_hwm_program_thermal_cruise( + const u16 base, + const enum nct5572d_hwm_fan fan, + const struct nct5572d_hwm_thermal_cruise_params *const tcp) +{ + /* For safety reasons, disengage fan control before reconfiguring this output */ + nct5572d_hwm_force_fan_full_on(base, fan); + + /* High bits of stop duty enable and temperature source go into the same register */ + const u8 temp = (((!!tcp->stopduty_en) << 7) & 0x80) | (tcp->temp_src & 0x0f); + + /* Now, program Thermal Cruise mode using the desired settings */ + pnp_unset_and_set_hwm5_index(base, 0x00, 0x8f, temp); + pnp_unset_and_set_hwm5_index(base, 0x02, 0x07, tcp->tolerance); + + pnp_write_hwm5_index(base, 0x01, tcp->target_temp); + pnp_write_hwm5_index(base, 0x06, tcp->start_up_val); + pnp_write_hwm5_index(base, 0x05, tcp->stop_val); + pnp_write_hwm5_index(base, 0x07, tcp->stop_time); + pnp_write_hwm5_index(base, 0x03, tcp->step_up_time); + pnp_write_hwm5_index(base, 0x04, tcp->step_down_time); + pnp_write_hwm5_index(base, 0x35, tcp->critical_temp); + + /* Set fan speed to midpoint */ + nct5572d_hwm_set_fan_duty(base, fan, 0x7f); + + /* And enable Thermal Cruise mode */ + nct5572d_hwm_set_fan_mode(base, fan, FAN_MODE_THERMAL_CRUISE); +} + +void nct5572d_hwm_program_speed_cruise( + const u16 base, + const enum nct5572d_hwm_fan fan, + const struct nct5572d_hwm_speed_cruise_params *const scp) +{ + /* For safety reasons, disengage fan control before reconfiguring this output */ + nct5572d_hwm_force_fan_full_on(base, fan); + + /* Calculate count value and clamp to 12 bits, which is about 330 rpm */ + const u16 target_count = MIN((1350 * 1000) / scp->target_speed, 0x0fff); + + /* High bits of target speed and tolerance go into the same register */ + const u8 temp = ((scp->tolerance << 1) & 0x70) | ((target_count >> 8) & 0x0f); + + /* Now, program Speed Cruise mode using the desired settings */ + pnp_unset_and_set_hwm5_index(base, 0x0c, 0x7f, temp); + pnp_unset_and_set_hwm5_index(base, 0x02, 0x07, scp->tolerance & 0x07); + + pnp_write_hwm5_index(base, 0x01, (u8)target_count); + pnp_write_hwm5_index(base, 0x03, scp->step_up_time); + pnp_write_hwm5_index(base, 0x04, scp->step_down_time); + + /* Set fan speed to midpoint */ + nct5572d_hwm_set_fan_duty(base, fan, 0x7f); + + /* And enable Speed Cruise mode */ + nct5572d_hwm_set_fan_mode(base, fan, FAN_MODE_SPEED_CRUISE); +} + +/* FIXME: This always enables Agent 1 only, make it configurable */ +void nct5572d_hwm_enable_peci(const u16 base, const u8 tcc_activation_temp) +{ + nuvoton_hwm_select_bank(base, 7); + pnp_write_hwm5_index(base, 0x03, 0x30); + pnp_write_hwm5_index(base, 0x09, tcc_activation_temp); + pnp_write_hwm5_index(base, 0x01, 0x95); + + nuvoton_hwm_select_bank(base, 0); + pnp_unset_and_set_hwm5_index(base, 0xae, 0x03, 0x02); +} diff --git a/src/superio/nuvoton/nct5572d/nct5572d_hwm.h b/src/superio/nuvoton/nct5572d/nct5572d_hwm.h new file mode 100644 index 0000000..2ccb88f --- /dev/null +++ b/src/superio/nuvoton/nct5572d/nct5572d_hwm.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SUPERIO_NUVOTON_NCT5572D_HWM_H +#define SUPERIO_NUVOTON_NCT5572D_HWM_H + +#include <device/device.h> +#include <device/pnp.h> +#include <device/pnp_ops.h> +#include <superio/conf_mode.h> +#include <superio/hwm5_conf.h> +#include <superio/nuvoton/common/hwm.h> +#include <superio/nuvoton/common/nuvoton.h> +#include <types.h> + +/* The values correspond to the HWM Bank number for each fan */ +enum nct5572d_hwm_fan { + SYS_FAN = 1, + CPU_FAN = 2, + AUX_FAN0 = 3, + AUX_FAN1 = 8, + AUX_FAN2 = 9, +}; + +/* The values can be directly applied to the HWM registers for fan mode control */ +enum nct5572d_hwm_fan_mode { + FAN_MODE_MANUAL = 0x0 << 4, + FAN_MODE_THERMAL_CRUISE = 0x1 << 4, + FAN_MODE_SPEED_CRUISE = 0x2 << 4, + FAN_MODE_SMART_FAN_IV = 0x4 << 4, +}; + +enum nct5572d_hwm_temp_src { + SYSTIN = 1, + CPUTIN = 2, + AUXTIN0 = 3, + AUXTIN1 = 4, + AUXTIN2 = 5, + AUXTIN3 = 6, + /* Note that value 7 is reserved */ + SMBUSMASTER_0 = 8, + SMBUSMASTER_1 = 9, + SMBUSMASTER_2 = 10, + SMBUSMASTER_3 = 11, + SMBUSMASTER_4 = 12, + SMBUSMASTER_5 = 13, + SMBUSMASTER_6 = 14, + SMBUSMASTER_7 = 15, + PECI_0 = 16, + PECI_1 = 17, + PCH_CHIP_CPU_MAX_TEMP = 18, + PCH_CHIP_TEMP = 19, + PCH_CPU_TEMP = 20, + PCH_MCH_TEMP = 21, + PCH_DIM0_TEMP = 22, + PCH_DIM1_TEMP = 23, + PCH_DIM2_TEMP = 24, + PCH_DIM3_TEMP = 25, + BYTE_TEMP = 26, +}; + +struct nct5572d_hwm_thermal_cruise_params { + u8 target_temp; + u8 tolerance; + u8 start_up_val; + u8 stop_val; + bool stopduty_en; + u8 stop_time; + u8 step_up_time; + u8 step_down_time; + u8 critical_temp; + enum nct5572d_hwm_temp_src temp_src; +}; + +struct nct5572d_hwm_speed_cruise_params { + u16 target_speed; + u8 tolerance; + u8 step_up_time; + u8 step_down_time; +}; + +#if ENV_PNP_SIMPLE_DEVICE +void nct5572d_hwm_init(pnp_devfn_t dev, const u16 base); +#endif + +/* Low level fan control functions */ +static inline void nct5572d_hwm_set_sysfan_out_voltage_mode( + const u16 base, + const bool is_voltage) +{ + nuvoton_hwm_select_bank(base, 0); + pnp_unset_and_set_hwm5_index(base, 0x04, 0x01, !!is_voltage); +} + +static inline void nct5572d_hwm_set_temperature_source( + const u16 base, + const enum nct5572d_hwm_fan fan, + const enum nct5572d_hwm_temp_src temp_src) +{ + nuvoton_hwm_select_bank(base, fan); + pnp_unset_and_set_hwm5_index(base, 0x00, 0x1f, temp_src); +} + +static inline void nct5572d_hwm_set_fan_mode( + const u16 base, + const enum nct5572d_hwm_fan fan, + const enum nct5572d_hwm_fan_mode fan_mode) +{ + nuvoton_hwm_select_bank(base, fan); + pnp_unset_and_set_hwm5_index(base, 0x02, 0xf0, fan_mode); +} + +static inline void nct5572d_hwm_set_fan_duty( + const u16 base, + const enum nct5572d_hwm_fan fan, + const u8 speed) +{ + nuvoton_hwm_select_bank(base, fan); + pnp_write_hwm5_index(base, 0x09, speed); +} + +/* Higher order fan control functions */ +void nct5572d_hwm_force_fan_full_on( + const u16 base, + const enum nct5572d_hwm_fan fan); + +void nct5572d_hwm_program_thermal_cruise( + const u16 base, + const enum nct5572d_hwm_fan fan, + const struct nct5572d_hwm_thermal_cruise_params *const tcp); + +void nct5572d_hwm_program_speed_cruise( + const u16 base, + const enum nct5572d_hwm_fan fan, + const struct nct5572d_hwm_speed_cruise_params *const scp); + +void nct5572d_hwm_enable_peci(const u16 base, const u8 tcc_activation_temp); + +#endif /* SUPERIO_NUVOTON_NCT5572D_HWM_H */