diff options
Diffstat (limited to 'chip/it83xx/fan.c')
-rw-r--r-- | chip/it83xx/fan.c | 478 |
1 files changed, 0 insertions, 478 deletions
diff --git a/chip/it83xx/fan.c b/chip/it83xx/fan.c deleted file mode 100644 index adb3985025..0000000000 --- a/chip/it83xx/fan.c +++ /dev/null @@ -1,478 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Fan control module. */ - -#include "clock.h" -#include "fan.h" -#include "gpio.h" -#include "hooks.h" -#include "hwtimer_chip.h" -#include "math_util.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "util.h" - -#define TACH_EC_FREQ 8000000 -#define FAN_CTRL_BASED_MS 10 -#define FAN_CTRL_INTERVAL_MAX_MS 60 - -/* The sampling rate (fs) is FreqEC / 128 */ -#define TACH_DATA_VALID_TIMEOUT_MS (0xFFFF * 128 / (TACH_EC_FREQ / 1000)) - -/* - * Fan Speed (RPM) = 60 / (1/fs sec * {FnTMRR, FnTLRR} * P) - * n denotes 1 or 2. - * P denotes the numbers of square pulses per revolution. - * And {FnTMRR, FnTLRR} = 0000h denotes Fan Speed is zero. - * The sampling rate (fs) is FreqEC / 128. - */ -/* pulse, the numbers of square pulses per revolution. */ -#define TACH0_TO_RPM(pulse, raw) (60 * TACH_EC_FREQ / 128 / pulse / raw) -#define TACH1_TO_RPM(pulse, raw) (raw * 120 / (pulse * 2)) - -enum fan_output_s { - FAN_DUTY_I = 0x01, - FAN_DUTY_R = 0x02, - FAN_DUTY_OV = 0x03, - FAN_DUTY_DONE = 0x04, -}; - -struct fan_info { - unsigned int flags; - int fan_mode; - int fan_p; - int rpm_target; - int rpm_actual; - int tach_valid_ms; - int rpm_re; - int fan_ms; - int fan_ms_idx; - int startup_duty; - enum fan_status fan_sts; - int enabled; -}; -static struct fan_info fan_info_data[TACH_CH_COUNT]; - -static enum tach_ch_sel tach_bind(int ch) -{ - return fan_tach[pwm_channels[ch].channel].ch_tach; -} - -static void fan_set_interval(int ch) -{ - int diff, fan_ms; - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - diff = ABS(fan_info_data[tach_ch].rpm_target - - fan_info_data[tach_ch].rpm_actual) / 100; - - fan_ms = FAN_CTRL_INTERVAL_MAX_MS; - - fan_ms -= diff; - if (fan_ms < FAN_CTRL_BASED_MS) - fan_ms = FAN_CTRL_BASED_MS; - - fan_info_data[tach_ch].fan_ms = fan_ms; -} - -static void fan_init_start(int ch) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - fan_set_duty(ch, fan_info_data[tach_ch].startup_duty); -} - -static int fan_all_disabled(void) -{ - int fan, all_disabled = 0; - - for (fan = 0; fan < fan_get_count(); fan++) { - if (!fan_get_enabled(FAN_CH(fan))) - all_disabled++; - } - - if (all_disabled >= fan_get_count()) - return 1; - - return 0; -} - -void fan_set_enabled(int ch, int enabled) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - /* enable */ - if (enabled) { - if (tach_ch < TACH_CH_COUNT) - fan_info_data[tach_ch].fan_sts = FAN_STATUS_CHANGING; - - disable_sleep(SLEEP_MASK_FAN); - /* enable timer interrupt for fan control */ - ext_timer_start(FAN_CTRL_EXT_TIMER, 1); - /* disable */ - } else { - fan_set_duty(ch, 0); - - if (tach_ch < TACH_CH_COUNT) { - fan_info_data[tach_ch].rpm_actual = 0; - fan_info_data[tach_ch].fan_sts = FAN_STATUS_STOPPED; - } - } - - /* on/off */ - if (tach_ch < TACH_CH_COUNT) { - fan_info_data[tach_ch].enabled = enabled; - fan_info_data[tach_ch].tach_valid_ms = 0; - } - - pwm_enable(ch, enabled); - - if (!enabled) { - /* disable timer interrupt if all fan off. */ - if (fan_all_disabled()) { - ext_timer_stop(FAN_CTRL_EXT_TIMER, 1); - enable_sleep(SLEEP_MASK_FAN); - } - } -} - -int fan_get_enabled(int ch) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - return pwm_get_enabled(ch) && fan_info_data[tach_ch].enabled; - else - return 0; -} - -void fan_set_duty(int ch, int percent) -{ - pwm_set_duty(ch, percent); -} - -int fan_get_duty(int ch) -{ - return pwm_get_duty(ch); -} - -int fan_get_rpm_mode(int ch) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - return fan_info_data[tach_ch].fan_mode; - else - return EC_ERROR_UNKNOWN; -} - -void fan_set_rpm_mode(int ch, int rpm_mode) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - fan_info_data[tach_ch].fan_mode = rpm_mode; -} - -int fan_get_rpm_actual(int ch) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - return fan_info_data[tach_ch].rpm_actual; - else - return EC_ERROR_UNKNOWN; -} - -int fan_get_rpm_target(int ch) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - return fan_info_data[tach_ch].rpm_target; - else - return EC_ERROR_UNKNOWN; -} - -test_mockable void fan_set_rpm_target(int ch, int rpm) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - fan_info_data[tach_ch].rpm_target = rpm; -} - -enum fan_status fan_get_status(int ch) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - return fan_info_data[tach_ch].fan_sts; - else - return FAN_STATUS_STOPPED; -} - -/** - * Return non-zero if fan is enabled but stalled. - */ -int fan_is_stalled(int ch) -{ - /* Must be enabled with non-zero target to stall */ - if (!fan_get_enabled(ch) || - fan_get_rpm_target(ch) == 0 || - !fan_get_duty(ch)) - return 0; - - /* Check for stall condition */ - return fan_get_status(ch) == FAN_STATUS_STOPPED; -} - -void fan_channel_setup(int ch, unsigned int flags) -{ - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - if (tach_ch < TACH_CH_COUNT) - fan_info_data[tach_ch].flags = flags; -} - -static void fan_ctrl(int ch) -{ - int status = -1, adjust = 0; - int rpm_actual, rpm_target, rpm_re, duty; - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - fan_info_data[tach_ch].fan_ms_idx += FAN_CTRL_BASED_MS; - if (fan_info_data[tach_ch].fan_ms_idx > - fan_info_data[tach_ch].fan_ms) { - fan_info_data[tach_ch].fan_ms_idx = 0x00; - adjust = 1; - } - - if (adjust) { - /* get current pwm output duty */ - duty = fan_get_duty(ch); - - /* rpm mode */ - if (fan_info_data[tach_ch].fan_mode) { - rpm_actual = fan_info_data[tach_ch].rpm_actual; - rpm_target = fan_info_data[tach_ch].rpm_target; - rpm_re = fan_info_data[tach_ch].rpm_re; - - if (rpm_actual < (rpm_target - rpm_re)) { - if (duty == 100) { - status = FAN_DUTY_OV; - } else { - if (duty == 0) - fan_init_start(ch); - - pwm_duty_inc(ch); - status = FAN_DUTY_I; - } - } else if (rpm_actual > (rpm_target + rpm_re)) { - if (duty == 0) { - status = FAN_DUTY_OV; - } else { - pwm_duty_reduce(ch); - status = FAN_DUTY_R; - } - } else { - status = FAN_DUTY_DONE; - } - } else { - fan_info_data[tach_ch].fan_sts = FAN_STATUS_LOCKED; - } - - if (status == FAN_DUTY_DONE) { - fan_info_data[tach_ch].fan_sts = FAN_STATUS_LOCKED; - } else if ((status == FAN_DUTY_I) || (status == FAN_DUTY_R)) { - fan_info_data[tach_ch].fan_sts = FAN_STATUS_CHANGING; - } else if (status == FAN_DUTY_OV) { - fan_info_data[tach_ch].fan_sts = FAN_STATUS_FRUSTRATED; - - if (!fan_info_data[tach_ch].rpm_actual && duty) - fan_info_data[tach_ch].fan_sts = - FAN_STATUS_STOPPED; - } - } -} - -static int tach_ch_valid(enum tach_ch_sel tach_ch) -{ - int valid = 0; - - switch (tach_ch) { - case TACH_CH_TACH0A: - if ((IT83XX_PWM_TSWCTRL & 0x0C) == 0x08) - valid = 1; - break; - case TACH_CH_TACH1A: - if ((IT83XX_PWM_TSWCTRL & 0x03) == 0x02) - valid = 1; - break; - case TACH_CH_TACH0B: - if ((IT83XX_PWM_TSWCTRL & 0x0C) == 0x0C) - valid = 1; - break; - case TACH_CH_TACH1B: - if ((IT83XX_PWM_TSWCTRL & 0x03) == 0x03) - valid = 1; - break; - default: - break; - } - - return valid; -} - -static int get_tach0_rpm(int fan_p) -{ - uint16_t rpm; - - /* TACH0A / TACH0B data is valid */ - if (IT83XX_PWM_TSWCTRL & 0x08) { - rpm = (IT83XX_PWM_F1TMRR << 8) | IT83XX_PWM_F1TLRR; - - if (rpm) - rpm = TACH0_TO_RPM(fan_p, rpm); - - /* W/C */ - IT83XX_PWM_TSWCTRL |= 0x08; - return rpm; - } - return -1; -} - -static int get_tach1_rpm(int fan_p) -{ - uint16_t rpm; - - /* TACH1A / TACH1B data is valid */ - if (IT83XX_PWM_TSWCTRL & 0x02) { - rpm = (IT83XX_PWM_F2TMRR << 8) | IT83XX_PWM_F2TLRR; - - if (rpm) - rpm = TACH1_TO_RPM(fan_p, rpm); - - /* W/C */ - IT83XX_PWM_TSWCTRL |= 0x02; - return rpm; - } - return -1; -} - -static void proc_tach(int ch) -{ - int t_rpm; - enum tach_ch_sel tach_ch; - - tach_ch = tach_bind(ch); - - /* tachometer data valid */ - if (tach_ch_valid(tach_ch)) { - if ((tach_ch == TACH_CH_TACH0A) || (tach_ch == TACH_CH_TACH0B)) - t_rpm = get_tach0_rpm(fan_info_data[tach_ch].fan_p); - else - t_rpm = get_tach1_rpm(fan_info_data[tach_ch].fan_p); - - fan_info_data[tach_ch].rpm_actual = t_rpm; - fan_set_interval(ch); - fan_info_data[tach_ch].tach_valid_ms = 0; - } else { - fan_info_data[tach_ch].tach_valid_ms += FAN_CTRL_BASED_MS; - if (fan_info_data[tach_ch].tach_valid_ms > - TACH_DATA_VALID_TIMEOUT_MS) - fan_info_data[tach_ch].rpm_actual = 0; - } -} - -void fan_ext_timer_interrupt(void) -{ - int fan; - - task_clear_pending_irq(et_ctrl_regs[FAN_CTRL_EXT_TIMER].irq); - - for (fan = 0; fan < fan_get_count(); fan++) { - if (fan_get_enabled(FAN_CH(fan))) { - proc_tach(FAN_CH(fan)); - fan_ctrl(FAN_CH(fan)); - } - } -} - -static void fan_init(void) -{ - int ch, rpm_re, fan_p, s_duty; - enum tach_ch_sel tach_ch; - - for (ch = 0; ch < fan_get_count(); ch++) { - - rpm_re = fan_tach[pwm_channels[FAN_CH(ch)].channel].rpm_re; - fan_p = fan_tach[pwm_channels[FAN_CH(ch)].channel].fan_p; - s_duty = fan_tach[pwm_channels[FAN_CH(ch)].channel].s_duty; - tach_ch = tach_bind(FAN_CH(ch)); - - if (tach_ch < TACH_CH_COUNT) { - - if (tach_ch == TACH_CH_TACH0B) { - /* GPJ2 will select TACH0B as its alt. */ - IT83XX_GPIO_GRC5 |= 0x01; - /* bit2, to select TACH0B */ - IT83XX_PWM_TSWCTRL |= 0x04; - } else if (tach_ch == TACH_CH_TACH1B) { - /* GPJ3 will select TACH1B as its alt. */ - IT83XX_GPIO_GRC5 |= 0x02; - /* bit0, to select TACH1B */ - IT83XX_PWM_TSWCTRL |= 0x01; - } - - fan_info_data[tach_ch].flags = 0; - fan_info_data[tach_ch].fan_mode = 0; - fan_info_data[tach_ch].rpm_target = 0; - fan_info_data[tach_ch].rpm_actual = 0; - fan_info_data[tach_ch].tach_valid_ms = 0; - fan_info_data[tach_ch].fan_ms_idx = 0; - fan_info_data[tach_ch].enabled = 0; - fan_info_data[tach_ch].fan_p = fan_p; - fan_info_data[tach_ch].rpm_re = rpm_re; - fan_info_data[tach_ch].fan_ms = FAN_CTRL_BASED_MS; - fan_info_data[tach_ch].fan_sts = FAN_STATUS_STOPPED; - fan_info_data[tach_ch].startup_duty = s_duty; - } - } - - /* init external timer for fan control */ - ext_timer_ms(FAN_CTRL_EXT_TIMER, EXT_PSR_32P768K_HZ, 0, 0, - FAN_CTRL_BASED_MS, 1, 0); -} -DECLARE_HOOK(HOOK_INIT, fan_init, HOOK_PRIO_INIT_FAN); |