diff --git a/src/app/main/fan.c b/src/app/main/fan.c index 9f7614914..5b71f568f 100644 --- a/src/app/main/fan.c +++ b/src/app/main/fan.c @@ -146,23 +146,62 @@ static uint8_t fan_get_duty(const struct Fan *const fan, int16_t temp) { return duty; } -static uint16_t fan_get_tach0_rpm(void) { - uint16_t rpm = (F1TMRR << 8) | F1TLRR; +static int16_t fan_get_tach0_rpm(void) { + if (TSWCTLR & T0DVS) { + uint16_t rpm = (F1TMRR << 8) | F1TLRR; - if (rpm) - rpm = TACH_TO_RPM(rpm); + if (rpm) + rpm = TACH_TO_RPM(rpm); - return rpm; + TSWCTLR |= T0DVS; + + return rpm; + } + + return -1; } -static uint16_t fan_get_tach1_rpm(void) { - uint16_t rpm = (F2TMRR << 8) | F2TLRR; +static int16_t fan_get_tach1_rpm(void) { + if (TSWCTLR & T1DVS) { + uint16_t rpm = (F2TMRR << 8) | F2TLRR; + + if (rpm) + rpm = TACH_TO_RPM(rpm); + + TSWCTLR |= T1DVS; + + return rpm; + } + + return -1; +} + +#if CONFIG_EC_ITE_IT8587E +// IT8587 does not have TACH2 control +static int16_t fan_get_tach2_rpm(void) { + uint16_t rpm = (F3TMRR << 8) | F3TLRR; if (rpm) rpm = TACH_TO_RPM(rpm); return rpm; } +#else +static int16_t fan_get_tach2_rpm(void) { + if (TSWCTLR2 & T2DVS) { + uint16_t rpm = (F3TMRR << 8) | F3TLRR; + + if (rpm) + rpm = TACH_TO_RPM(rpm); + + TSWCTLR2 |= T2DVS; + + return rpm; + } + + return -1; +} +#endif // Update the target duty of the fans based on system temps. // Interval: 1sec diff --git a/src/ec/ite/include/ec/gpio.h b/src/ec/ite/include/ec/gpio.h index 9167c2ad7..6d91196bf 100644 --- a/src/ec/ite/include/ec/gpio.h +++ b/src/ec/ite/include/ec/gpio.h @@ -43,9 +43,14 @@ void gpio_debug(void); volatile uint8_t __xdata __at(0x1600) GCR; volatile uint8_t __xdata __at(0x16F0) GCR1; volatile uint8_t __xdata __at(0x16F1) GCR2; +#define TACH2AEN BIT(0) + volatile uint8_t __xdata __at(0x16F2) GCR3; volatile uint8_t __xdata __at(0x16F3) GCR4; volatile uint8_t __xdata __at(0x16F4) GCR5; +#define TACH0BEN BIT(0) +#define TACH1BEN BIT(1) + volatile uint8_t __xdata __at(0x16F5) GCR6; volatile uint8_t __xdata __at(0x16F6) GCR7; volatile uint8_t __xdata __at(0x16F7) GCR8; @@ -56,6 +61,8 @@ volatile uint8_t __xdata __at(0x16FB) GCR12; volatile uint8_t __xdata __at(0x16FC) GCR13; volatile uint8_t __xdata __at(0x16FD) GCR14; volatile uint8_t __xdata __at(0x16FE) GCR15; +#define TACH2BEN BIT(3) + volatile uint8_t __xdata __at(0x16E0) GCR16; volatile uint8_t __xdata __at(0x16E1) GCR17; volatile uint8_t __xdata __at(0x16E2) GCR18; diff --git a/src/ec/ite/include/ec/pwm.h b/src/ec/ite/include/ec/pwm.h index e0dc3d625..0c803823c 100644 --- a/src/ec/ite/include/ec/pwm.h +++ b/src/ec/ite/include/ec/pwm.h @@ -61,12 +61,35 @@ volatile uint8_t __xdata __at(0x180F) PCSGR; volatile uint8_t __xdata __at(0x1823) ZTIER; // Tachometer switch control register volatile uint8_t __xdata __at(0x1848) TSWCTLR; +#define T1CHSEL BIT(0) +#define T1DVS BIT(1) +#define T0CHSEL BIT(2) +#define T0DVS BIT(3) + +volatile uint8_t __xdata __at(0x1845) F3TLRR; // CFLRR on IT8587 +volatile uint8_t __xdata __at(0x1846) F3TMRR; // CFMRR on IT8587 #if CONFIG_EC_ITE_IT5570E || CONFIG_EC_ITE_IT5571E +// Tachometer switch control register 2 +volatile uint8_t __xdata __at(0x184F) TSWCTLR2; +#define T2CHSEL BIT(0) +#define T2DVS BIT(1) + // PWM Load Counter Control Register volatile uint8_t __xdata __at(0x185A) PWMLCCR; #endif +enum TachCh { + TACH_CH_0A = 0, // GPD6 + TACH_CH_1A, // GPD7 + TACH_CH_0B, // GPJ2 + TACH_CH_1B, // GPJ3 + TACH_CH_2A, // GPJ0 +#if CONFIG_EC_ITE_IT5570E || CONFIG_EC_ITE_IT5571E + TACH_CH_2B, // GPJ1 +#endif +}; + void pwm_init(void); #endif // _EC_PWM_H diff --git a/src/ec/ite/pwm.c b/src/ec/ite/pwm.c index a41f5ed73..3db64ce1c 100644 --- a/src/ec/ite/pwm.c +++ b/src/ec/ite/pwm.c @@ -2,10 +2,61 @@ #include #include +#include + +// TODO: Define per-board +// All boards use T0A/T1A, so just declare it here for now based on FAN2_PWM +#ifdef FAN2_PWM +#define NR_TACHS 2 +#else +#define NR_TACHS 1 +#endif + +const enum TachCh board_tachs[NR_TACHS] = { + TACH_CH_0A, +#ifdef FAN2_PWM + TACH_CH_1A, +#endif +}; + +static void pwm_tach_init(void) { + for (uint8_t i = 0; i < NR_TACHS; i++) { + switch (board_tachs[i]) { + case TACH_CH_0B: + GCR5 |= TACH0BEN; + TSWCTLR |= T0CHSEL; + break; + + case TACH_CH_1B: + GCR5 |= TACH1BEN; + TSWCTLR |= T1CHSEL; + break; + + case TACH_CH_2A: + GCR2 |= TACH2AEN; + // CHSEL default is `A` (0) at init. + break; + +#if CONFIG_EC_ITE_IT5570E || CONFIG_EC_ITE_IT5571E + case TACH_CH_2B: + GCR15 |= TACH2BEN; + TSWCTLR2 |= T2CHSEL; + break; +#endif + + // XXX: SDCC 4.2.0 (Ubuntu 24.04) fails with "error 126: unreachable + // code" if these are placed as the first cases. + case TACH_CH_0A: + case TACH_CH_1A: + // T0A/T1A always available + // CHSEL default is `A` (0) at init. + break; + } + } +} void pwm_init(void) { - // Set T0CHSEL to TACH0A and T1CHSEL to TACH1A - TSWCTLR = 0; + pwm_tach_init(); // Disable PWM ZTIER = 0;