Angel Pons has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/42136 )
Change subject: superio/nuvoton/nct6776: Add HWM API ......................................................................
superio/nuvoton/nct6776: Add HWM API
Tested with the usage examples on the Asrock B85M Pro4.
Change-Id: I3f2618eb112e2e3dc863c704817a2e87aa596a16 Signed-off-by: Angel Pons th3fanbus@gmail.com --- M src/mainboard/asrock/b85m_pro4/Kconfig M src/mainboard/asrock/b85m_pro4/bootblock.c M src/superio/nuvoton/nct6776/Kconfig M src/superio/nuvoton/nct6776/Makefile.inc A src/superio/nuvoton/nct6776/nct6776_hwm.c A src/superio/nuvoton/nct6776/nct6776_hwm.h 6 files changed, 291 insertions(+), 8 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/36/42136/1
diff --git a/src/mainboard/asrock/b85m_pro4/Kconfig b/src/mainboard/asrock/b85m_pro4/Kconfig index ecb2ba9..1fd13e7 100644 --- a/src/mainboard/asrock/b85m_pro4/Kconfig +++ b/src/mainboard/asrock/b85m_pro4/Kconfig @@ -17,6 +17,7 @@ select SOUTHBRIDGE_INTEL_LYNXPOINT select SUPERIO_NUVOTON_NCT6776 select SUPERIO_NUVOTON_NCT6776_COM_A + select SUPERIO_NUVOTON_NCT6776_HWM
config MAINBOARD_DIR string diff --git a/src/mainboard/asrock/b85m_pro4/bootblock.c b/src/mainboard/asrock/b85m_pro4/bootblock.c index f95fb52..2aef95a 100644 --- a/src/mainboard/asrock/b85m_pro4/bootblock.c +++ b/src/mainboard/asrock/b85m_pro4/bootblock.c @@ -1,28 +1,65 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#include <device/pnp_ops.h> +#include <southbridge/intel/lynxpoint/pch.h> #include <superio/nuvoton/common/nuvoton.h> #include <superio/nuvoton/nct6776/nct6776.h> -#include <southbridge/intel/lynxpoint/pch.h> +#include <superio/nuvoton/nct6776/nct6776_hwm.h>
#define GLOBAL_DEV PNP_DEV(0x2e, 0) #define SERIAL_DEV PNP_DEV(0x2e, NCT6776_SP1) #define ACPI_DEV PNP_DEV(0x2e, NCT6776_ACPI) +#define HWM_DEV PNP_DEV(0x2e, NCT6776_HWM_FPLED) + +#define HWM_BASE 0x290
void mainboard_config_superio(void) { nuvoton_pnp_enter_conf_state(GLOBAL_DEV);
- /* Select HWM/LED functions instead of floppy functions */ - pnp_write_config(GLOBAL_DEV, 0x1c, 0x03); - pnp_write_config(GLOBAL_DEV, 0x24, 0x24); - - /* Power RAM in S3 and let the PCH handle power failure actions */ - pnp_set_logical_device(ACPI_DEV); - pnp_write_config(ACPI_DEV, 0xe4, 0x70); + /* Select SIO pin states */ + pnp_write_config(GLOBAL_DEV, 0x1b, 0x68); + pnp_write_config(GLOBAL_DEV, 0x1c, 0x80); + pnp_write_config(GLOBAL_DEV, 0x24, 0x1c); + pnp_write_config(GLOBAL_DEV, 0x27, 0xd0); + pnp_write_config(GLOBAL_DEV, 0x2a, 0x62); + pnp_write_config(GLOBAL_DEV, 0x2f, 0x03);
nuvoton_pnp_exit_conf_state(GLOBAL_DEV);
+ /* Set up the HWM */ + nct6776_hwm_init(HWM_DEV, HWM_BASE); + + nct6776_hwm_force_fan_full_on(HWM_BASE, SYS_FAN); + nct6776_hwm_force_fan_full_on(HWM_BASE, CPU_FAN); + nct6776_hwm_force_fan_full_on(HWM_BASE, AUX_FAN); + + nct6776_hwm_enable_peci(HWM_BASE); + + struct nct6776_hwm_thermal_cruise_params tcp = { + .target_temp = 55, + .tolerance = 0, + .start_up_val = 1, + .stop_val = 0, + .stopduty_en = false, + .stop_time = 1, + .step_up_time = 1, + .step_down_time = 1, + .critical_temp = 60, + .temp_src = PECI_0, + }; + + nct6776_hwm_program_thermal_cruise(HWM_BASE, CPU_FAN, &tcp); + + struct nct6776_hwm_speed_cruise_params scp = { + .target_speed = 4095, + .tolerance = 0, + .step_up_time = 1, + .step_down_time = 1, + }; + + nct6776_hwm_program_speed_cruise(HWM_BASE, CPU_FAN, &scp); + /* Enable UART */ nuvoton_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); } diff --git a/src/superio/nuvoton/nct6776/Kconfig b/src/superio/nuvoton/nct6776/Kconfig index caa89b3..cf31635 100644 --- a/src/superio/nuvoton/nct6776/Kconfig +++ b/src/superio/nuvoton/nct6776/Kconfig @@ -8,3 +8,9 @@ bool depends on SUPERIO_NUVOTON_NCT6776 default n + +config SUPERIO_NUVOTON_NCT6776_HWM + bool + depends on SUPERIO_NUVOTON_NCT6776 + select SUPERIO_NUVOTON_COMMON_HWM + default n diff --git a/src/superio/nuvoton/nct6776/Makefile.inc b/src/superio/nuvoton/nct6776/Makefile.inc index a36361e..6cf2264 100644 --- a/src/superio/nuvoton/nct6776/Makefile.inc +++ b/src/superio/nuvoton/nct6776/Makefile.inc @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-or-later
ramstage-$(CONFIG_SUPERIO_NUVOTON_NCT6776) += superio.c + +all-$(CONFIG_SUPERIO_NUVOTON_NCT6776_HWM) += nct6776_hwm.c diff --git a/src/superio/nuvoton/nct6776/nct6776_hwm.c b/src/superio/nuvoton/nct6776/nct6776_hwm.c new file mode 100644 index 0000000..f89c3e1 --- /dev/null +++ b/src/superio/nuvoton/nct6776/nct6776_hwm.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <device/device.h> +#include <device/pnp.h> +#include <device/pnp_type.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 "nct6776_hwm.h" +#include "nct6776.h" + +#if ENV_PNP_SIMPLE_DEVICE +void nct6776_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 nct6776_hwm_force_fan_full_on( + const u16 base, + const enum nct6776_hwm_fan fan) +{ + nct6776_hwm_set_fan_mode(base, fan, FAN_MODE_MANUAL); + nct6776_hwm_set_fan_duty(base, fan, 0xff); +} + +void nct6776_hwm_program_thermal_cruise( + const u16 base, + const enum nct6776_hwm_fan fan, + const struct nct6776_hwm_thermal_cruise_params *const tcp) +{ + /* For safety reasons, disengage fan control before reconfiguring this output */ + nct6776_hwm_force_fan_full_on(base, fan); + + /* Now, program Thermal Cruise mode using the desired settings */ + pnp_update_hwm5_index(base, 0x00, 0x70, ((!!tcp->stopduty_en) << 7) | tcp->temp_src); + pnp_update_hwm5_index(base, 0x02, 0xf8, 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 */ + nct6776_hwm_set_fan_duty(base, fan, 0x7f); + + /* And enable Thermal Cruise mode */ + nct6776_hwm_set_fan_mode(base, fan, FAN_MODE_THERMAL_CRUISE); +} + +void nct6776_hwm_program_speed_cruise( + const u16 base, + const enum nct6776_hwm_fan fan, + const struct nct6776_hwm_speed_cruise_params *const scp) +{ + /* For safety reasons, disengage fan control before reconfiguring this output */ + nct6776_hwm_force_fan_full_on(base, fan); + + /* High bits of target speed and tolerance go into the same register */ + const u8 reg_0c = ((scp->tolerance << 1) & 0x70) | ((scp->target_speed >> 8) & 0x0f); + + /* Now, program Speed Cruise mode using the desired settings */ + pnp_update_hwm5_index(base, 0x0c, 0x80, reg_0c); + pnp_update_hwm5_index(base, 0x02, 0xf8, scp->tolerance); + + pnp_write_hwm5_index(base, 0x01, (u8)scp->target_speed); + 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 */ + nct6776_hwm_set_fan_duty(base, fan, 0x7f); + + /* And enable Thermal Cruise mode */ + nct6776_hwm_set_fan_mode(base, fan, FAN_MODE_SPEED_CRUISE); +} + +void nct6776_hwm_enable_peci(const u16 base) +{ + nuvoton_hwm_select_bank(base, 0); + pnp_update_hwm5_index(base, 0xae, 0xfc, 0x01); + + nuvoton_hwm_select_bank(base, 7); + + pnp_write_hwm5_index(base, 0x01, 0x95); + pnp_write_hwm5_index(base, 0x02, 0x02); + pnp_write_hwm5_index(base, 0x03, 0x30); + + pnp_write_hwm5_index(base, 0x09, 0x5c); +} diff --git a/src/superio/nuvoton/nct6776/nct6776_hwm.h b/src/superio/nuvoton/nct6776/nct6776_hwm.h new file mode 100644 index 0000000..3243b13 --- /dev/null +++ b/src/superio/nuvoton/nct6776/nct6776_hwm.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SUPERIO_NUVOTON_NCT6776_HWM_H +#define SUPERIO_NUVOTON_NCT6776_HWM_H + + +#include <device/device.h> +#include <device/pnp.h> +#include <device/pnp_type.h> +#include <device/pnp_ops.h> +#include <stdint.h> +#include <superio/conf_mode.h> +#include <superio/hwm5_conf.h> +#include <superio/nuvoton/common/hwm.h> +#include <superio/nuvoton/common/nuvoton.h> + +/* The values correspond to the HWM Bank number for each fan */ +enum nct6776_hwm_fan { + SYS_FAN = 1, + CPU_FAN = 2, + AUX_FAN = 3, +}; + +/* The values can be directly applied to the HWM registers for fan mode control */ +enum nct6776_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 nct6776_hwm_temp_src { + SYSTIN = 1, + CPUTIN = 2, + AUXTIN = 3, + SMBUSMASTER_0 = 4, + SMBUSMASTER_1 = 5, + SMBUSMASTER_2 = 6, + SMBUSMASTER_3 = 7, + SMBUSMASTER_4 = 8, + SMBUSMASTER_5 = 9, + SMBUSMASTER_6 = 10, + SMBUSMASTER_7 = 11, + PECI_0 = 12, + PECI_1 = 13, + PCH_CHIP_CPU_MAX_TEMP = 14, + PCH_CHIP_TEMP = 15, + PCH_CPU_TEMP = 16, + PCH_MCH_TEMP = 17, + PCH_DIM0_TEMP = 18, + PCH_DIM1_TEMP = 19, + PCH_DIM2_TEMP = 20, + PCH_DIM3_TEMP = 21, + BYTE_TEMP = 22 +}; + +struct nct6776_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 nct6776_hwm_temp_src temp_src; +}; + +struct nct6776_hwm_speed_cruise_params { + u16 target_speed; + u8 tolerance; + u8 step_up_time; + u8 step_down_time; +}; + +#if ENV_PNP_SIMPLE_DEVICE +void nct6776_hwm_init(pnp_devfn_t dev, const u16 base); +#endif + +/* Low level fan control functions */ +static inline void nct6776_hwm_set_temperature_source( + const u16 base, + const enum nct6776_hwm_fan fan, + const enum nct6776_hwm_temp_src temp_src) +{ + nuvoton_hwm_select_bank(base, fan); + pnp_update_hwm5_index(base, 0x00, 0xf0, temp_src); +} + +static inline void nct6776_hwm_set_fan_mode( + const u16 base, + const enum nct6776_hwm_fan fan, + const enum nct6776_hwm_fan_mode fan_mode) +{ + nuvoton_hwm_select_bank(base, fan); + pnp_update_hwm5_index(base, 0x02, 0x0f, fan_mode); +} + +static inline void nct6776_hwm_set_temperature_tolerance( + const u16 base, + const enum nct6776_hwm_fan fan, + const u8 tolerance) +{ + nuvoton_hwm_select_bank(base, fan); + pnp_update_hwm5_index(base, 0x02, 0xf8, tolerance); +} + +static inline void nct6776_hwm_set_fan_duty( + const u16 base, + const enum nct6776_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 nct6776_hwm_force_fan_full_on( + const u16 base, + const enum nct6776_hwm_fan fan); + +void nct6776_hwm_program_thermal_cruise( + const u16 base, + const enum nct6776_hwm_fan fan, + const struct nct6776_hwm_thermal_cruise_params *const tcp); + +void nct6776_hwm_program_speed_cruise( + const u16 base, + const enum nct6776_hwm_fan fan, + const struct nct6776_hwm_speed_cruise_params *const scp); + +void nct6776_hwm_enable_peci(const u16 base); + +#endif /* SUPERIO_NUVOTON_NCT6776_HWM_H */