summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2013-10-29 13:05:11 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-10-30 21:51:50 +0000
commitc7b930606b479d4747da224f6cf62fd8061e6af0 (patch)
tree71df4cab99a9598d429a3409f8416ec9490e9283
parent1d0102ae2cccdb4e798c196b0e6445c167efe4b6 (diff)
downloadchrome-ec-c7b930606b479d4747da224f6cf62fd8061e6af0.tar.gz
Separate common fan behavior from implementation
This looks like a lot, but it's really just moving the non-board-specific stuff from chip/lm4/fan.c into common/fan.c, updating the appropriate headers, and renaming functions to better match the new location. This is entirely code refactoring and renaming. No new functionality. BUG=chrome-os-partner:23530 BRANCH=none TEST=manual make runtests, build all platforms, build and test on Link. Change-Id: I7dc03d6732bad83cf838a86600b42a7cff5aa7aa Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/175012
-rw-r--r--board/falco/board.c2
-rw-r--r--board/host/build.mk1
-rw-r--r--board/host/fan.c67
-rw-r--r--chip/lm4/build.mk5
-rw-r--r--chip/lm4/fan.c363
-rw-r--r--chip/lm4/fan_chip.c180
-rw-r--r--chip/lm4/fan_chip.h27
-rw-r--r--chip/lm4/pwm.c14
-rw-r--r--common/build.mk3
-rw-r--r--common/fan.c337
-rw-r--r--common/pwm_fan.c27
-rw-r--r--common/thermal.c2
-rw-r--r--include/config.h2
-rw-r--r--include/fan.h32
-rw-r--r--test/test_config.h2
-rw-r--r--test/thermal.c2
-rw-r--r--test/thermal_falco.c2
17 files changed, 560 insertions, 508 deletions
diff --git a/board/falco/board.c b/board/falco/board.c
index 23da16230d..3e8b88da69 100644
--- a/board/falco/board.c
+++ b/board/falco/board.c
@@ -255,7 +255,7 @@ int board_discharge_on_ac(int enable)
* And never turn it off. Bah. That'll do wonders for battery life.
*/
#ifdef CONFIG_FAN_RPM_CUSTOM
-int pwm_fan_percent_to_rpm(int pct)
+int fan_percent_to_rpm(int pct)
{
const int FAN_MAX = 5050;
const int FAN_MIN = 2700;
diff --git a/board/host/build.mk b/board/host/build.mk
index 21e5383d86..4448f4b0b3 100644
--- a/board/host/build.mk
+++ b/board/host/build.mk
@@ -11,3 +11,4 @@ CHIP:=host
board-y=board.o
board-$(HAS_TASK_CHIPSET)+=chipset.o
board-$(CONFIG_BATTERY_MOCK)+=battery.o charger.o
+board-$(CONFIG_FAN)+=fan.o
diff --git a/board/host/fan.c b/board/host/fan.c
new file mode 100644
index 0000000000..b7a10de05c
--- /dev/null
+++ b/board/host/fan.c
@@ -0,0 +1,67 @@
+/* Copyright (c) 2013 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.
+ */
+
+/* Mocked fan implementation for tests */
+
+#include "fan.h"
+
+static int mock_enabled;
+void fan_set_enabled(int ch, int enabled)
+{
+ mock_enabled = enabled;
+}
+int fan_get_enabled(int ch)
+{
+ return mock_enabled;
+}
+
+static int mock_percent;
+void fan_set_duty(int ch, int percent)
+{
+ mock_percent = percent;
+}
+int fan_get_duty(int ch)
+{
+ return mock_percent;
+}
+
+static int mock_rpm_mode;
+void fan_set_rpm_mode(int ch, int rpm_mode)
+{
+ mock_rpm_mode = rpm_mode;
+}
+int fan_get_rpm_mode(int ch)
+{
+ return mock_rpm_mode;
+}
+
+static int mock_rpm;
+void fan_set_rpm_target(int ch, int rpm)
+{
+ mock_rpm = rpm;
+}
+int fan_get_rpm_actual(int ch)
+{
+ return mock_rpm;
+}
+int fan_get_rpm_target(int ch)
+{
+ return mock_rpm;
+}
+
+enum fan_status fan_get_status(int ch)
+{
+ return FAN_STATUS_LOCKED;
+}
+
+int fan_is_stalled(int ch)
+{
+ return 0;
+}
+
+void fan_channel_setup(int ch, unsigned int flags)
+{
+ /* nothing to do */
+}
diff --git a/chip/lm4/build.mk b/chip/lm4/build.mk
index 551df6e2ac..234c86b669 100644
--- a/chip/lm4/build.mk
+++ b/chip/lm4/build.mk
@@ -15,12 +15,13 @@ chip-y=clock.o gpio.o hwtimer.o jtag.o system.o uart.o
# Optional chip modules
chip-$(CONFIG_ADC)+=adc.o chip_temp_sensor.o
chip-$(CONFIG_EEPROM)+=eeprom.o
-chip-$(CONFIG_FAN)+=fan.o fan_chip.o
+chip-$(CONFIG_FAN)+=fan.o
chip-$(CONFIG_FLASH)+=flash.o
chip-$(CONFIG_I2C)+=i2c.o
chip-$(CONFIG_LPC)+=lpc.o
chip-$(CONFIG_PECI)+=peci.o
-chip-$(CONFIG_PWM)+=pwm.o fan_chip.o
+# pwm functions are implemented with the fan functions
+chip-$(CONFIG_PWM)+=pwm.o fan.o
chip-$(CONFIG_SPI)+=spi.o
chip-$(CONFIG_WATCHDOG)+=watchdog.o
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
diff --git a/chip/lm4/fan.c b/chip/lm4/fan.c
index e8a77c3e91..a342a49954 100644
--- a/chip/lm4/fan.c
+++ b/chip/lm4/fan.c
@@ -3,322 +3,173 @@
* found in the LICENSE file.
*/
-/* Chrome OS fan control */
+/* LM4 fan control module. */
#include "clock.h"
-#include "common.h"
-#include "console.h"
#include "fan.h"
-#include "fan_chip.h"
#include "gpio.h"
#include "hooks.h"
-#include "host_command.h"
-#include "pwm.h"
#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
#include "util.h"
-/* True if we're listening to the thermal control task. False if we're setting
- * things manually. */
-static int thermal_control_enabled;
+/* Maximum RPM for fan controller */
+#define MAX_RPM 0x1fff
-static void fan_set_enabled(int enable)
-{
- fan_chip_set_enabled(CONFIG_FAN_CH_CPU, enable);
+/* Maximum PWM for PWM controller */
+#define MAX_PWM 0x1ff
-#ifdef CONFIG_FAN_EN_GPIO
- gpio_set_level(CONFIG_FAN_EN_GPIO, enable);
-#endif /* CONFIG_FAN_EN_GPIO */
-}
+/*
+ * Scaling factor for requested/actual RPM for CPU fan. We need this because
+ * the fan controller on Blizzard filters tach pulses that are less than 64
+ * 15625Hz ticks apart, which works out to ~7000rpm on an unscaled fan. By
+ * telling the controller we actually have twice as many edges per revolution,
+ * the controller can handle fans that actually go twice as fast. See
+ * crosbug.com/p/7718.
+ */
+#define RPM_SCALE 2
-static void fan_set_thermal_control_enabled(int enable)
-{
- thermal_control_enabled = enable;
- /* If controlling the fan, need it in RPM-control mode */
- if (enable)
- fan_chip_channel_setup(CONFIG_FAN_CH_CPU,
- FAN_CHIP_USE_RPM_MODE);
+void fan_set_enabled(int ch, int enabled)
+{
+ if (enabled)
+ LM4_FAN_FANCTL |= (1 << ch);
+ else
+ LM4_FAN_FANCTL &= ~(1 << ch);
}
-/* The thermal task will only call this function with pct in [0,100]. */
-test_mockable void pwm_fan_set_percent_needed(int pct)
+int fan_get_enabled(int ch)
{
- int rpm;
-
- if (!thermal_control_enabled)
- return;
-
- rpm = pwm_fan_percent_to_rpm(pct);
-
- fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, rpm);
+ return (LM4_FAN_FANCTL & (1 << ch)) ? 1 : 0;
}
-static void fan_set_duty_cycle(int percent)
+void fan_set_duty(int ch, int percent)
{
- /* Move the fan to manual control */
- fan_chip_set_rpm_mode(CONFIG_FAN_CH_CPU, 0);
+ int duty;
+
+ if (percent < 0)
+ percent = 0;
+ else if (percent > 100)
+ percent = 100;
- /* Always enable the fan */
- fan_set_enabled(1);
+ duty = (MAX_PWM * percent + 50) / 100;
- /* Disable thermal engine automatic fan control. */
- fan_set_thermal_control_enabled(0);
+ /* Always enable the channel */
+ fan_set_enabled(ch, 1);
/* Set the duty cycle */
- fan_chip_set_duty(CONFIG_FAN_CH_CPU, percent);
+ LM4_FAN_FANCMD(ch) = duty << 16;
}
-/*****************************************************************************/
-/* Console commands */
-
-static int cc_fanauto(int argc, char **argv)
+int fan_get_duty(int ch)
{
- fan_set_thermal_control_enabled(1);
- return EC_SUCCESS;
+ return ((LM4_FAN_FANCMD(ch) >> 16) * 100 + MAX_PWM / 2) / MAX_PWM;
}
-DECLARE_CONSOLE_COMMAND(fanauto, cc_fanauto,
- NULL,
- "Enable thermal fan control",
- NULL);
-static int cc_faninfo(int argc, char **argv)
+int fan_get_rpm_mode(int ch)
{
- static const char * const human_status[] = {
- "not spinning", "changing", "locked", "frustrated"
- };
- int tmp;
-
- ccprintf("Actual: %4d rpm\n",
- fan_chip_get_rpm_actual(CONFIG_FAN_CH_CPU));
- ccprintf("Target: %4d rpm\n",
- fan_chip_get_rpm_target(CONFIG_FAN_CH_CPU));
- ccprintf("Duty: %d%%\n",
- fan_chip_get_duty(CONFIG_FAN_CH_CPU));
- tmp = fan_chip_get_status(CONFIG_FAN_CH_CPU);
- ccprintf("Status: %d (%s)\n", tmp, human_status[tmp]);
- ccprintf("Mode: %s\n",
- fan_chip_get_rpm_mode(CONFIG_FAN_CH_CPU) ? "rpm" : "duty");
- ccprintf("Auto: %s\n", thermal_control_enabled ? "yes" : "no");
- ccprintf("Enable: %s\n",
- fan_chip_get_enabled(CONFIG_FAN_CH_CPU) ? "yes" : "no");
-#ifdef CONFIG_FAN_PGOOD_GPIO
- ccprintf("Power: %s\n",
-#ifdef CONFIG_FAN_EN_GPIO
- gpio_get_level(CONFIG_FAN_EN_GPIO) &&
-#endif
- gpio_get_level(CONFIG_FAN_PGOOD_GPIO) ? "yes" : "no");
-#endif
-
-
- return EC_SUCCESS;
+ return (LM4_FAN_FANCH(ch) & 0x0001) ? 0 : 1;
}
-DECLARE_CONSOLE_COMMAND(faninfo, cc_faninfo,
- NULL,
- "Print fan info",
- NULL);
-static int cc_fanset(int argc, char **argv)
+void fan_set_rpm_mode(int ch, int rpm_mode)
{
- int rpm;
- char *e;
+ int was_enabled = fan_get_enabled(ch);
+ int was_rpm = fan_get_rpm_mode(ch);
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- rpm = strtoi(argv[1], &e, 0);
- if (*e == '%') { /* Wait, that's a percentage */
- ccprintf("Fan rpm given as %d%%\n", rpm);
- if (rpm < 0)
- rpm = 0;
- else if (rpm > 100)
- rpm = 100;
- rpm = pwm_fan_percent_to_rpm(rpm);
- } else if (*e) {
- return EC_ERROR_PARAM1;
+ if (!was_rpm && rpm_mode) {
+ /* Enable RPM control */
+ fan_set_enabled(ch, 0);
+ LM4_FAN_FANCH(ch) &= ~0x0001;
+ fan_set_enabled(ch, was_enabled);
+ } else if (was_rpm && !rpm_mode) {
+ /* Disable RPM mode */
+ fan_set_enabled(ch, 0);
+ LM4_FAN_FANCH(ch) |= 0x0001;
+ fan_set_enabled(ch, was_enabled);
}
-
- /* Move the fan to automatic control */
- fan_chip_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
-
- /* Always enable the fan */
- fan_set_enabled(1);
-
- /* Disable thermal engine automatic fan control. */
- fan_set_thermal_control_enabled(0);
-
- fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, rpm);
-
- ccprintf("Setting fan rpm target to %d\n", rpm);
-
- return EC_SUCCESS;
}
-DECLARE_CONSOLE_COMMAND(fanset, cc_fanset,
- "rpm | pct%",
- "Set fan speed",
- NULL);
-static int cc_fanduty(int argc, char **argv)
+int fan_get_rpm_actual(int ch)
{
- int percent = 0;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- percent = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- ccprintf("Setting fan duty cycle to %d%%\n", percent);
- fan_set_duty_cycle(percent);
-
- return EC_SUCCESS;
+ return (LM4_FAN_FANCST(ch) & MAX_RPM) * RPM_SCALE;
}
-DECLARE_CONSOLE_COMMAND(fanduty, cc_fanduty,
- "percent",
- "Set fan duty cycle",
- NULL);
-
-/*****************************************************************************/
-/* Host commands */
-static int hc_pwm_get_fan_target_rpm(struct host_cmd_handler_args *args)
+int fan_get_rpm_target(int ch)
{
- struct ec_response_pwm_get_fan_rpm *r = args->response;
-
- r->rpm = fan_chip_get_rpm_target(CONFIG_FAN_CH_CPU);
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
+ return (LM4_FAN_FANCMD(ch) & MAX_RPM) * RPM_SCALE;
}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_FAN_TARGET_RPM,
- hc_pwm_get_fan_target_rpm,
- EC_VER_MASK(0));
-static int hc_pwm_set_fan_target_rpm(struct host_cmd_handler_args *args)
+void fan_set_rpm_target(int ch, int rpm)
{
- const struct ec_params_pwm_set_fan_target_rpm *p = args->params;
+ /* Apply fan scaling */
+ if (rpm > 0)
+ rpm /= RPM_SCALE;
- fan_set_thermal_control_enabled(0);
- fan_chip_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
- fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, p->rpm);
+ /* Treat out-of-range requests as requests for maximum fan speed */
+ if (rpm < 0 || rpm > MAX_RPM)
+ rpm = MAX_RPM;
- return EC_RES_SUCCESS;
+ LM4_FAN_FANCMD(ch) = rpm;
}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_TARGET_RPM,
- hc_pwm_set_fan_target_rpm,
- EC_VER_MASK(0));
-static int hc_pwm_set_fan_duty(struct host_cmd_handler_args *args)
+/* The LM4 status is the original definition of enum fan_status */
+enum fan_status fan_get_status(int ch)
{
- const struct ec_params_pwm_set_fan_duty *p = args->params;
- fan_set_duty_cycle(p->percent);
-
- return EC_RES_SUCCESS;
+ return (LM4_FAN_FANSTS >> (2 * ch)) & 0x03;
}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_DUTY,
- hc_pwm_set_fan_duty,
- EC_VER_MASK(0));
-
-static int hc_thermal_auto_fan_ctrl(struct host_cmd_handler_args *args)
-{
- fan_set_thermal_control_enabled(1);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_THERMAL_AUTO_FAN_CTRL,
- hc_thermal_auto_fan_ctrl,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Hooks */
-
-#define PWMFAN_SYSJUMP_TAG 0x5046 /* "PF" */
-#define PWM_HOOK_VERSION 1
-/* Saved PWM state across sysjumps */
-struct pwm_fan_state {
- uint16_t fan_rpm;
- uint8_t fan_en;
- char pad; /* Pad to multiple of 4 bytes. */
-};
-
-static void pwm_fan_init(void)
+/**
+ * Return non-zero if fan is enabled but stalled.
+ */
+int fan_is_stalled(int ch)
{
- const struct pwm_fan_state *prev;
- uint16_t *mapped;
- int version, size;
- int i;
+ /* Must be enabled with non-zero target to stall */
+ if (!fan_get_enabled(ch) || fan_get_rpm_target(ch) == 0)
+ return 0;
- gpio_config_module(MODULE_PWM_FAN, 1);
-
- prev = (const struct pwm_fan_state *)
- system_get_jump_tag(PWMFAN_SYSJUMP_TAG, &version, &size);
- if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) {
- /* Restore previous state. */
- fan_chip_set_enabled(CONFIG_FAN_CH_CPU, prev->fan_en);
- fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, prev->fan_rpm);
- } else {
- /* Set initial fan speed to maximum */
- fan_chip_set_duty(CONFIG_FAN_CH_CPU, 100);
- }
-
- fan_set_thermal_control_enabled(1);
-
- /* Initialize memory-mapped data */
- mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
- for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++)
- mapped[i] = EC_FAN_SPEED_NOT_PRESENT;
+ /* Check for stall condition */
+ return (((LM4_FAN_FANSTS >> (2 * ch)) & 0x03) == 0) ? 1 : 0;
}
-DECLARE_HOOK(HOOK_INIT, pwm_fan_init, HOOK_PRIO_DEFAULT + 1);
-static void pwm_fan_second(void)
+void fan_channel_setup(int ch, unsigned int flags)
{
- uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
-
- if (fan_chip_is_stalled(CONFIG_FAN_CH_CPU)) {
- mapped[0] = EC_FAN_SPEED_STALLED;
+ if (flags & FAN_USE_RPM_MODE) {
/*
- * Issue warning. As we have thermal shutdown
- * protection, issuing warning here should be enough.
+ * Configure automatic/feedback mode:
+ * 0x8000 = bit 15 = auto-restart
+ * 0x0000 = bit 14 = slow acceleration
+ * 0x0000 = bits 13:11 = no hysteresis
+ * 0x0000 = bits 10:8 = start period (2<<0) edges
+ * 0x0000 = bits 7:6 = no fast start
+ * 0x0020 = bits 5:4 = average 4 edges when
+ * calculating RPM
+ * 0x000c = bits 3:2 = 8 pulses per revolution
+ * (see note at top of file)
+ * 0x0000 = bit 0 = automatic control
*/
- host_set_single_event(EC_HOST_EVENT_THERMAL);
- cprintf(CC_PWM, "[%T Fan stalled!]\n");
+ LM4_FAN_FANCH(ch) = 0x802c;
} else {
- mapped[0] = fan_chip_get_rpm_actual(CONFIG_FAN_CH_CPU);
+ /*
+ * Configure drive-only mode:
+ * 0x0000 = bit 15 = no auto-restart
+ * 0x0000 = bit 14 = slow acceleration
+ * 0x0000 = bits 13:11 = no hysteresis
+ * 0x0000 = bits 10:8 = start period (2<<0) edges
+ * 0x0000 = bits 7:6 = no fast start
+ * 0x0000 = bits 5:4 = no RPM averaging
+ * 0x0000 = bits 3:2 = 1 pulses per revolution
+ * 0x0001 = bit 0 = manual control
+ */
+ LM4_FAN_FANCH(ch) = 0x0001;
}
}
-DECLARE_HOOK(HOOK_SECOND, pwm_fan_second, HOOK_PRIO_DEFAULT);
-
-static void pwm_fan_preserve_state(void)
-{
- struct pwm_fan_state state;
-
- state.fan_en = fan_chip_get_enabled(CONFIG_FAN_CH_CPU);
- state.fan_rpm = fan_chip_get_rpm_target(CONFIG_FAN_CH_CPU);
-
- system_add_jump_tag(PWMFAN_SYSJUMP_TAG, PWM_HOOK_VERSION,
- sizeof(state), &state);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, pwm_fan_preserve_state, HOOK_PRIO_DEFAULT);
-static void pwm_fan_resume(void)
+static void fan_init(void)
{
- fan_chip_set_enabled(CONFIG_FAN_CH_CPU, 1);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, pwm_fan_resume, HOOK_PRIO_DEFAULT);
+ /* Enable the fan module and delay a few clocks */
+ clock_enable_peripheral(CGC_OFFSET_FAN, 0x1,
+ CGC_MODE_RUN | CGC_MODE_SLEEP);
-static void pwm_fan_S3_S5(void)
-{
- /* Take back fan control when the processor shuts down */
- fan_set_thermal_control_enabled(1);
- /* For now don't do anything with it. We'll have to turn it on again if
- * we need active cooling during heavy battery charging or something.
- */
- fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, 0);
- fan_chip_set_enabled(CONFIG_FAN_CH_CPU, 0); /* crosbug.com/p/8097 */
+ /* Disable all fans */
+ LM4_FAN_FANCTL = 0;
}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_fan_S3_S5, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pwm_fan_S3_S5, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_INIT, fan_init, HOOK_PRIO_INIT_PWM);
diff --git a/chip/lm4/fan_chip.c b/chip/lm4/fan_chip.c
deleted file mode 100644
index cef39b9b3d..0000000000
--- a/chip/lm4/fan_chip.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright (c) 2013 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.
- */
-
-/* LM4 fan control module. */
-
-#include "clock.h"
-#include "fan_chip.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "registers.h"
-#include "util.h"
-
-/* Maximum RPM for fan controller */
-#define MAX_RPM 0x1fff
-
-/* Maximum PWM for PWM controller */
-#define MAX_PWM 0x1ff
-
-/*
- * Scaling factor for requested/actual RPM for CPU fan. We need this because
- * the fan controller on Blizzard filters tach pulses that are less than 64
- * 15625Hz ticks apart, which works out to ~7000rpm on an unscaled fan. By
- * telling the controller we actually have twice as many edges per revolution,
- * the controller can handle fans that actually go twice as fast. See
- * crosbug.com/p/7718.
- */
-#define RPM_SCALE 2
-
-
-void fan_chip_set_enabled(int ch, int enabled)
-{
- if (enabled)
- LM4_FAN_FANCTL |= (1 << ch);
- else
- LM4_FAN_FANCTL &= ~(1 << ch);
-}
-
-int fan_chip_get_enabled(int ch)
-{
- return (LM4_FAN_FANCTL & (1 << ch)) ? 1 : 0;
-}
-
-void fan_chip_set_duty(int ch, int percent)
-{
- int duty;
-
- if (percent < 0)
- percent = 0;
- else if (percent > 100)
- percent = 100;
-
- duty = (MAX_PWM * percent + 50) / 100;
-
- /* Always enable the channel */
- fan_chip_set_enabled(ch, 1);
-
- /* Set the duty cycle */
- LM4_FAN_FANCMD(ch) = duty << 16;
-}
-
-int fan_chip_get_duty(enum pwm_channel ch)
-{
- return ((LM4_FAN_FANCMD(ch) >> 16) * 100 + MAX_PWM / 2) / MAX_PWM;
-}
-
-int fan_chip_get_rpm_mode(int ch)
-{
- return (LM4_FAN_FANCH(ch) & 0x0001) ? 0 : 1;
-}
-
-void fan_chip_set_rpm_mode(int ch, int rpm_mode)
-{
- int was_enabled = fan_chip_get_enabled(ch);
- int was_rpm = fan_chip_get_rpm_mode(ch);
-
- if (!was_rpm && rpm_mode) {
- /* Enable RPM control */
- fan_chip_set_enabled(ch, 0);
- LM4_FAN_FANCH(ch) &= ~0x0001;
- fan_chip_set_enabled(ch, was_enabled);
- } else if (was_rpm && !rpm_mode) {
- /* Disable RPM mode */
- fan_chip_set_enabled(ch, 0);
- LM4_FAN_FANCH(ch) |= 0x0001;
- fan_chip_set_enabled(ch, was_enabled);
- }
-}
-
-int fan_chip_get_rpm_actual(int ch)
-{
- return (LM4_FAN_FANCST(ch) & MAX_RPM) * RPM_SCALE;
-}
-
-int fan_chip_get_rpm_target(int ch)
-{
- return (LM4_FAN_FANCMD(ch) & MAX_RPM) * RPM_SCALE;
-}
-
-void fan_chip_set_rpm_target(int ch, int rpm)
-{
- /* Apply fan scaling */
- if (rpm > 0)
- rpm /= RPM_SCALE;
-
- /* Treat out-of-range requests as requests for maximum fan speed */
- if (rpm < 0 || rpm > MAX_RPM)
- rpm = MAX_RPM;
-
- LM4_FAN_FANCMD(ch) = rpm;
-}
-
-/*
- * 0 = stopped
- * 1 = changing
- * 2 = locked
- * 3 = unable to lock
- */
-int fan_chip_get_status(int ch)
-{
- return (LM4_FAN_FANSTS >> (2 * ch)) & 0x03;
-}
-
-/**
- * Return non-zero if fan is enabled but stalled.
- */
-int fan_chip_is_stalled(int ch)
-{
- /* Must be enabled with non-zero target to stall */
- if (!fan_chip_get_enabled(ch) || fan_chip_get_rpm_target(ch) == 0)
- return 0;
-
- /* Check for stall condition */
- return (((LM4_FAN_FANSTS >> (2 * ch)) & 0x03) == 0) ? 1 : 0;
-}
-
-void fan_chip_channel_setup(int ch, unsigned int flags)
-{
- if (flags & FAN_CHIP_USE_RPM_MODE) {
- /*
- * Configure automatic/feedback mode:
- * 0x8000 = bit 15 = auto-restart
- * 0x0000 = bit 14 = slow acceleration
- * 0x0000 = bits 13:11 = no hysteresis
- * 0x0000 = bits 10:8 = start period (2<<0) edges
- * 0x0000 = bits 7:6 = no fast start
- * 0x0020 = bits 5:4 = average 4 edges when
- * calculating RPM
- * 0x000c = bits 3:2 = 8 pulses per revolution
- * (see note at top of file)
- * 0x0000 = bit 0 = automatic control
- */
- LM4_FAN_FANCH(ch) = 0x802c;
- } else {
- /*
- * Configure drive-only mode:
- * 0x0000 = bit 15 = no auto-restart
- * 0x0000 = bit 14 = slow acceleration
- * 0x0000 = bits 13:11 = no hysteresis
- * 0x0000 = bits 10:8 = start period (2<<0) edges
- * 0x0000 = bits 7:6 = no fast start
- * 0x0000 = bits 5:4 = no RPM averaging
- * 0x0000 = bits 3:2 = 1 pulses per revolution
- * 0x0001 = bit 0 = manual control
- */
- LM4_FAN_FANCH(ch) = 0x0001;
- }
-}
-
-static void fan_chip_init(void)
-{
- /* Enable the fan module and delay a few clocks */
- clock_enable_peripheral(CGC_OFFSET_FAN, 0x1,
- CGC_MODE_RUN | CGC_MODE_SLEEP);
-
- /* Disable all fans */
- LM4_FAN_FANCTL = 0;
-}
-DECLARE_HOOK(HOOK_INIT, fan_chip_init, HOOK_PRIO_INIT_PWM);
diff --git a/chip/lm4/fan_chip.h b/chip/lm4/fan_chip.h
deleted file mode 100644
index 0ff92b1740..0000000000
--- a/chip/lm4/fan_chip.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (c) 2013 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.
- */
-
-/* LM4-specific fan control module */
-
-#ifndef __CROS_EC_LM4_FAN_CHIP_H
-#define __CROS_EC_LM4_FAN_CHIP_H
-
-void fan_chip_set_enabled(int ch, int enabled);
-int fan_chip_get_enabled(int ch);
-void fan_chip_set_duty(int ch, int percent);
-int fan_chip_get_duty(enum pwm_channel ch);
-int fan_chip_get_rpm_mode(int ch);
-void fan_chip_set_rpm_mode(int ch, int rpm_mode);
-int fan_chip_get_rpm_actual(int ch);
-int fan_chip_get_rpm_target(int ch);
-void fan_chip_set_rpm_target(int ch, int rpm);
-int fan_chip_get_status(int ch);
-int fan_chip_is_stalled(int ch);
-
-/* Maintain target RPM using tach input */
-#define FAN_CHIP_USE_RPM_MODE (1 << 0)
-void fan_chip_channel_setup(int ch, unsigned int flags);
-
-#endif /* __CROS_EC_LM4_FAN_CHIP_H */
diff --git a/chip/lm4/pwm.c b/chip/lm4/pwm.c
index 943aa0210f..c60a6be296 100644
--- a/chip/lm4/pwm.c
+++ b/chip/lm4/pwm.c
@@ -9,7 +9,7 @@
*/
#include "clock.h"
-#include "fan_chip.h"
+#include "fan.h"
#include "gpio.h"
#include "hooks.h"
#include "pwm.h"
@@ -19,12 +19,12 @@
void pwm_enable(enum pwm_channel ch, int enabled)
{
- fan_chip_set_enabled(pwm_channels[ch].channel, enabled);
+ fan_set_enabled(pwm_channels[ch].channel, enabled);
}
int pwm_get_enabled(enum pwm_channel ch)
{
- return fan_chip_get_enabled(pwm_channels[ch].channel);
+ return fan_get_enabled(pwm_channels[ch].channel);
}
void pwm_set_duty(enum pwm_channel ch, int percent)
@@ -42,12 +42,12 @@ void pwm_set_duty(enum pwm_channel ch, int percent)
pwm_enable(ch, 1);
/* Set the duty cycle */
- fan_chip_set_duty(pwm_channels[ch].channel, percent);
+ fan_set_duty(pwm_channels[ch].channel, percent);
}
int pwm_get_duty(enum pwm_channel ch)
{
- int percent = fan_chip_get_duty(pwm_channels[ch].channel);
+ int percent = fan_get_duty(pwm_channels[ch].channel);
if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW)
percent = 100 - percent;
@@ -60,10 +60,10 @@ static void pwm_init(void)
int i;
for (i = 0; i < PWM_CH_COUNT; ++i)
- fan_chip_channel_setup(pwm_channels[i].channel,
+ fan_channel_setup(pwm_channels[i].channel,
(pwm_channels[i].flags &
PWM_CONFIG_HAS_RPM_MODE)
- ? FAN_CHIP_USE_RPM_MODE : 0);
+ ? FAN_USE_RPM_MODE : 0);
}
/* The chip-specific fan module initializes before this. */
diff --git a/common/build.mk b/common/build.mk
index 15669a5dfe..98ef604e27 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -28,8 +28,7 @@ common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o
common-$(CONFIG_EXTPOWER_KIRBY)+=extpower_kirby.o
common-$(CONFIG_EXTPOWER_SNOW)+=extpower_snow.o
common-$(CONFIG_EXTPOWER_SPRING)+=extpower_spring.o
-# TODO(rspangler): Rename to CONFIG_PWM_FAN.
-common-$(CONFIG_FAN)+=pwm_fan.o
+common-$(CONFIG_FAN)+=fan.o
common-$(CONFIG_FLASH)+=flash.o
common-$(CONFIG_FMAP)+=fmap.o
common-$(CONFIG_I2C)+=i2c.o
diff --git a/common/fan.c b/common/fan.c
new file mode 100644
index 0000000000..635f541e02
--- /dev/null
+++ b/common/fan.c
@@ -0,0 +1,337 @@
+/* Copyright (c) 2013 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.
+ */
+
+/* Basic Chrome OS fan control */
+
+#include "common.h"
+#include "console.h"
+#include "fan.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "system.h"
+#include "util.h"
+
+/* True if we're listening to the thermal control task. False if we're setting
+ * things manually. */
+static int thermal_control_enabled;
+
+#ifndef CONFIG_FAN_RPM_CUSTOM
+/* This is the default implementation. It's only called over [0,100].
+ * Convert the percentage to a target RPM. We can't simply scale all
+ * the way down to zero because most fans won't turn that slowly, so
+ * we'll map [1,100] => [FAN_MIN,FAN_MAX], and [0] => "off".
+*/
+int fan_percent_to_rpm(int pct)
+{
+ int rpm;
+
+ if (!pct)
+ rpm = 0;
+ else
+ rpm = ((pct - 1) * CONFIG_FAN_RPM_MAX +
+ (100 - pct) * CONFIG_FAN_RPM_MIN) / 99;
+
+ return rpm;
+}
+#endif /* CONFIG_FAN_RPM_CUSTOM */
+
+/* The thermal task will only call this function with pct in [0,100]. */
+test_mockable void fan_set_percent_needed(int pct)
+{
+ int rpm;
+
+ if (!thermal_control_enabled)
+ return;
+
+ rpm = fan_percent_to_rpm(pct);
+
+ fan_set_rpm_target(CONFIG_FAN_CH_CPU, rpm);
+}
+
+static void set_enabled(int enable)
+{
+ fan_set_enabled(CONFIG_FAN_CH_CPU, enable);
+
+#ifdef CONFIG_FAN_EN_GPIO
+ gpio_set_level(CONFIG_FAN_EN_GPIO, enable);
+#endif /* CONFIG_FAN_EN_GPIO */
+}
+
+static void set_thermal_control_enabled(int enable)
+{
+ thermal_control_enabled = enable;
+
+ /* If controlling the fan, need it in RPM-control mode */
+ if (enable)
+ fan_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
+}
+
+static void set_duty_cycle(int percent)
+{
+ /* Move the fan to manual control */
+ fan_set_rpm_mode(CONFIG_FAN_CH_CPU, 0);
+
+ /* Always enable the fan */
+ set_enabled(1);
+
+ /* Disable thermal engine automatic fan control. */
+ set_thermal_control_enabled(0);
+
+ /* Set the duty cycle */
+ fan_set_duty(CONFIG_FAN_CH_CPU, percent);
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+static int cc_fanauto(int argc, char **argv)
+{
+ set_thermal_control_enabled(1);
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(fanauto, cc_fanauto,
+ NULL,
+ "Enable thermal fan control",
+ NULL);
+
+static int cc_faninfo(int argc, char **argv)
+{
+ static const char * const human_status[] = {
+ "not spinning", "changing", "locked", "frustrated"
+ };
+ int tmp;
+
+ ccprintf("Actual: %4d rpm\n",
+ fan_get_rpm_actual(CONFIG_FAN_CH_CPU));
+ ccprintf("Target: %4d rpm\n",
+ fan_get_rpm_target(CONFIG_FAN_CH_CPU));
+ ccprintf("Duty: %d%%\n",
+ fan_get_duty(CONFIG_FAN_CH_CPU));
+ tmp = fan_get_status(CONFIG_FAN_CH_CPU);
+ ccprintf("Status: %d (%s)\n", tmp, human_status[tmp]);
+ ccprintf("Mode: %s\n",
+ fan_get_rpm_mode(CONFIG_FAN_CH_CPU) ? "rpm" : "duty");
+ ccprintf("Auto: %s\n", thermal_control_enabled ? "yes" : "no");
+ ccprintf("Enable: %s\n",
+ fan_get_enabled(CONFIG_FAN_CH_CPU) ? "yes" : "no");
+#ifdef CONFIG_FAN_PGOOD_GPIO
+ ccprintf("Power: %s\n",
+#ifdef CONFIG_FAN_EN_GPIO
+ gpio_get_level(CONFIG_FAN_EN_GPIO) &&
+#endif
+ gpio_get_level(CONFIG_FAN_PGOOD_GPIO) ? "yes" : "no");
+#endif
+
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(faninfo, cc_faninfo,
+ NULL,
+ "Print fan info",
+ NULL);
+
+static int cc_fanset(int argc, char **argv)
+{
+ int rpm;
+ char *e;
+
+ if (argc < 2)
+ return EC_ERROR_PARAM_COUNT;
+
+ rpm = strtoi(argv[1], &e, 0);
+ if (*e == '%') { /* Wait, that's a percentage */
+ ccprintf("Fan rpm given as %d%%\n", rpm);
+ if (rpm < 0)
+ rpm = 0;
+ else if (rpm > 100)
+ rpm = 100;
+ rpm = fan_percent_to_rpm(rpm);
+ } else if (*e) {
+ return EC_ERROR_PARAM1;
+ }
+
+ /* Move the fan to automatic control */
+ fan_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
+
+ /* Always enable the fan */
+ set_enabled(1);
+
+ /* Disable thermal engine automatic fan control. */
+ set_thermal_control_enabled(0);
+
+ fan_set_rpm_target(CONFIG_FAN_CH_CPU, rpm);
+
+ ccprintf("Setting fan rpm target to %d\n", rpm);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(fanset, cc_fanset,
+ "rpm | pct%",
+ "Set fan speed",
+ NULL);
+
+static int cc_fanduty(int argc, char **argv)
+{
+ int percent = 0;
+ char *e;
+
+ if (argc < 2)
+ return EC_ERROR_PARAM_COUNT;
+
+ percent = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM1;
+
+ ccprintf("Setting fan duty cycle to %d%%\n", percent);
+ set_duty_cycle(percent);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(fanduty, cc_fanduty,
+ "percent",
+ "Set fan duty cycle",
+ NULL);
+
+/*****************************************************************************/
+/* Host commands */
+
+static int hc_pwm_get_fan_target_rpm(struct host_cmd_handler_args *args)
+{
+ struct ec_response_pwm_get_fan_rpm *r = args->response;
+
+ r->rpm = fan_get_rpm_target(CONFIG_FAN_CH_CPU);
+ args->response_size = sizeof(*r);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_FAN_TARGET_RPM,
+ hc_pwm_get_fan_target_rpm,
+ EC_VER_MASK(0));
+
+static int hc_pwm_set_fan_target_rpm(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_pwm_set_fan_target_rpm *p = args->params;
+
+ set_thermal_control_enabled(0);
+ fan_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
+ fan_set_rpm_target(CONFIG_FAN_CH_CPU, p->rpm);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_TARGET_RPM,
+ hc_pwm_set_fan_target_rpm,
+ EC_VER_MASK(0));
+
+static int hc_pwm_set_fan_duty(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_pwm_set_fan_duty *p = args->params;
+ set_duty_cycle(p->percent);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_DUTY,
+ hc_pwm_set_fan_duty,
+ EC_VER_MASK(0));
+
+static int hc_thermal_auto_fan_ctrl(struct host_cmd_handler_args *args)
+{
+ set_thermal_control_enabled(1);
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_THERMAL_AUTO_FAN_CTRL,
+ hc_thermal_auto_fan_ctrl,
+ EC_VER_MASK(0));
+
+
+/*****************************************************************************/
+/* Hooks */
+
+#define PWMFAN_SYSJUMP_TAG 0x5046 /* "PF" */
+#define PWM_HOOK_VERSION 1
+/* Saved PWM state across sysjumps */
+struct pwm_fan_state {
+ uint16_t fan_rpm;
+ uint8_t fan_en;
+ char pad; /* Pad to multiple of 4 bytes. */
+};
+
+static void pwm_fan_init(void)
+{
+ const struct pwm_fan_state *prev;
+ uint16_t *mapped;
+ int version, size;
+ int i;
+
+ gpio_config_module(MODULE_PWM_FAN, 1);
+
+ prev = (const struct pwm_fan_state *)
+ system_get_jump_tag(PWMFAN_SYSJUMP_TAG, &version, &size);
+ if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) {
+ /* Restore previous state. */
+ fan_set_enabled(CONFIG_FAN_CH_CPU, prev->fan_en);
+ fan_set_rpm_target(CONFIG_FAN_CH_CPU, prev->fan_rpm);
+ } else {
+ /* Set initial fan speed to maximum */
+ fan_set_duty(CONFIG_FAN_CH_CPU, 100);
+ }
+
+ set_thermal_control_enabled(1);
+
+ /* Initialize memory-mapped data */
+ mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
+ for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++)
+ mapped[i] = EC_FAN_SPEED_NOT_PRESENT;
+}
+DECLARE_HOOK(HOOK_INIT, pwm_fan_init, HOOK_PRIO_DEFAULT + 1);
+
+static void pwm_fan_second(void)
+{
+ uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
+
+ if (fan_is_stalled(CONFIG_FAN_CH_CPU)) {
+ mapped[0] = EC_FAN_SPEED_STALLED;
+ /*
+ * Issue warning. As we have thermal shutdown
+ * protection, issuing warning here should be enough.
+ */
+ host_set_single_event(EC_HOST_EVENT_THERMAL);
+ cprintf(CC_PWM, "[%T Fan stalled!]\n");
+ } else {
+ mapped[0] = fan_get_rpm_actual(CONFIG_FAN_CH_CPU);
+ }
+}
+DECLARE_HOOK(HOOK_SECOND, pwm_fan_second, HOOK_PRIO_DEFAULT);
+
+static void pwm_fan_preserve_state(void)
+{
+ struct pwm_fan_state state;
+
+ state.fan_en = fan_get_enabled(CONFIG_FAN_CH_CPU);
+ state.fan_rpm = fan_get_rpm_target(CONFIG_FAN_CH_CPU);
+
+ system_add_jump_tag(PWMFAN_SYSJUMP_TAG, PWM_HOOK_VERSION,
+ sizeof(state), &state);
+}
+DECLARE_HOOK(HOOK_SYSJUMP, pwm_fan_preserve_state, HOOK_PRIO_DEFAULT);
+
+static void pwm_fan_resume(void)
+{
+ fan_set_enabled(CONFIG_FAN_CH_CPU, 1);
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, pwm_fan_resume, HOOK_PRIO_DEFAULT);
+
+static void pwm_fan_S3_S5(void)
+{
+ /* Take back fan control when the processor shuts down */
+ set_thermal_control_enabled(1);
+ /* For now don't do anything with it. We'll have to turn it on again if
+ * we need active cooling during heavy battery charging or something.
+ */
+ fan_set_rpm_target(CONFIG_FAN_CH_CPU, 0);
+ fan_set_enabled(CONFIG_FAN_CH_CPU, 0); /* crosbug.com/p/8097 */
+}
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_fan_S3_S5, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pwm_fan_S3_S5, HOOK_PRIO_DEFAULT);
diff --git a/common/pwm_fan.c b/common/pwm_fan.c
deleted file mode 100644
index f84159a7ad..0000000000
--- a/common/pwm_fan.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (c) 2013 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.
- */
-
-#include "common.h"
-#include "fan.h"
-
-#ifndef CONFIG_FAN_RPM_CUSTOM
-/* This is the default implementation. It's only called over [0,100].
- * Convert the percentage to a target RPM. We can't simply scale all
- * the way down to zero because most fans won't turn that slowly, so
- * we'll map [1,100] => [FAN_MIN,FAN_MAX], and [0] => "off".
-*/
-int pwm_fan_percent_to_rpm(int pct)
-{
- int rpm;
-
- if (!pct)
- rpm = 0;
- else
- rpm = ((pct - 1) * CONFIG_FAN_RPM_MAX +
- (100 - pct) * CONFIG_FAN_RPM_MIN) / 99;
-
- return rpm;
-}
-#endif /* CONFIG_FAN_RPM_CUSTOM */
diff --git a/common/thermal.c b/common/thermal.c
index 26775f62eb..6d4708c0ef 100644
--- a/common/thermal.c
+++ b/common/thermal.c
@@ -156,7 +156,7 @@ static void thermal_control(void)
#ifdef CONFIG_FAN
/* Max fan needed is what's needed. */
- pwm_fan_set_percent_needed(fmax);
+ fan_set_percent_needed(fmax);
#endif
}
diff --git a/include/config.h b/include/config.h
index a82af12158..6df1558e19 100644
--- a/include/config.h
+++ b/include/config.h
@@ -351,7 +351,7 @@
/*
* Replace the default fan mapping with a board-specific function in board.c:
*
- * int pwm_fan_percent_to_rpm(int pct);
+ * int fan_percent_to_rpm(int pct);
*
*/
#undef CONFIG_FAN_RPM_CUSTOM
diff --git a/include/fan.h b/include/fan.h
index 7af956baae..acae150fc0 100644
--- a/include/fan.h
+++ b/include/fan.h
@@ -14,7 +14,7 @@
*
* @param pct Percentage of cooling effort needed (0 - 100)
*/
-void pwm_fan_set_percent_needed(int pct);
+void fan_set_percent_needed(int pct);
/**
* This function translates the percentage of cooling needed into a target RPM.
@@ -24,6 +24,34 @@ void pwm_fan_set_percent_needed(int pct);
* @param pct Percentage of cooling effort needed (always in [0,100])
* Return Target RPM for fan
*/
-int pwm_fan_percent_to_rpm(int pct);
+int fan_percent_to_rpm(int pct);
+
+
+/**
+ * These functions require chip-specific implementations.
+ */
+
+void fan_set_enabled(int ch, int enabled);
+int fan_get_enabled(int ch);
+void fan_set_duty(int ch, int percent);
+int fan_get_duty(int ch);
+void fan_set_rpm_mode(int ch, int rpm_mode);
+int fan_get_rpm_mode(int ch);
+void fan_set_rpm_target(int ch, int rpm);
+int fan_get_rpm_actual(int ch);
+int fan_get_rpm_target(int ch);
+int fan_is_stalled(int ch);
+
+enum fan_status {
+ FAN_STATUS_STOPPED = 0,
+ FAN_STATUS_CHANGING = 1,
+ FAN_STATUS_LOCKED = 2,
+ FAN_STATUS_FRUSTRATED = 3
+};
+enum fan_status fan_get_status(int ch);
+
+/* Maintain target RPM using tach input */
+#define FAN_USE_RPM_MODE (1 << 0)
+void fan_channel_setup(int ch, unsigned int flags);
#endif /* __CROS_EC_FAN_H */
diff --git a/test/test_config.h b/test/test_config.h
index 53144073e4..c18700e25e 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -52,6 +52,7 @@ int board_discharge_on_ac(int enabled);
#ifdef TEST_thermal
#define CONFIG_CHIPSET_CAN_THROTTLE
#define CONFIG_FAN
+#define CONFIG_FAN_CH_CPU 0
#define CONFIG_FAN_RPM_MAX 5000
#define CONFIG_FAN_RPM_MIN 1000
#define CONFIG_TEMP_SENSOR
@@ -65,6 +66,7 @@ int board_discharge_on_ac(int enabled);
#define CONFIG_CHIPSET_CAN_THROTTLE
#define CONFIG_EXTPOWER_FALCO
#define CONFIG_FAN
+#define CONFIG_FAN_CH_CPU 0
#define CONFIG_FAN_RPM_MAX 5000
#define CONFIG_FAN_RPM_MIN 1000
#define CONFIG_TEMP_SENSOR
diff --git a/test/thermal.c b/test/thermal.c
index fb10b1cd1e..deaac2f631 100644
--- a/test/thermal.c
+++ b/test/thermal.c
@@ -62,7 +62,7 @@ void host_throttle_cpu(int throttled)
host_throttled = throttled;
}
-void pwm_fan_set_percent_needed(int pct)
+void fan_set_percent_needed(int pct)
{
fan_pct = pct;
}
diff --git a/test/thermal_falco.c b/test/thermal_falco.c
index 87a00f57bb..1452a12692 100644
--- a/test/thermal_falco.c
+++ b/test/thermal_falco.c
@@ -81,7 +81,7 @@ void host_throttle_cpu(int throttled)
host_throttled = throttled;
}
-void pwm_fan_set_percent_needed(int pct)
+void fan_set_percent_needed(int pct)
{
fan_pct = pct;
}