summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--chip/lm4/build.mk4
-rw-r--r--chip/lm4/fan.c172
-rw-r--r--chip/lm4/fan_chip.c180
-rw-r--r--chip/lm4/fan_chip.h27
-rw-r--r--chip/lm4/pwm.c89
6 files changed, 273 insertions, 203 deletions
diff --git a/Makefile b/Makefile
index 10a9c1f019..078b09c267 100644
--- a/Makefile
+++ b/Makefile
@@ -53,8 +53,8 @@ include util/lock/build.mk
includes+=$(includes-y)
-objs_from_dir=$(foreach obj, $($(2)-y), \
- $(out)/$(1)/$(firstword $($(2)-mock-$(PROJECT)-$(obj)) $(obj)))
+objs_from_dir=$(sort $(foreach obj, $($(2)-y), \
+ $(out)/$(1)/$(firstword $($(2)-mock-$(PROJECT)-$(obj)) $(obj))))
# Get all sources to build
all-y=$(call objs_from_dir,core/$(CORE),core)
diff --git a/chip/lm4/build.mk b/chip/lm4/build.mk
index 74ecd64d02..551df6e2ac 100644
--- a/chip/lm4/build.mk
+++ b/chip/lm4/build.mk
@@ -15,12 +15,12 @@ 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
+chip-$(CONFIG_FAN)+=fan.o fan_chip.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
+chip-$(CONFIG_PWM)+=pwm.o fan_chip.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 f584f69240..e8a77c3e91 100644
--- a/chip/lm4/fan.c
+++ b/chip/lm4/fan.c
@@ -3,12 +3,13 @@
* found in the LICENSE file.
*/
-/* PWM control module for Chromebook fans */
+/* Chrome OS fan control */
#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"
@@ -19,119 +20,27 @@
#include "timer.h"
#include "util.h"
-/*****************************************************************************/
-/* Chip-specific stuff */
-
-/* Maximum RPM for fan controller */
-#define MAX_RPM 0x1fff
-/* Max PWM for fan 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 CPU_FAN_SCALE 2
-
-static int fan_get_enabled(void)
-{
- return pwm_get_enabled(PWM_CH_FAN);
-}
+/* True if we're listening to the thermal control task. False if we're setting
+ * things manually. */
+static int thermal_control_enabled;
static void fan_set_enabled(int enable)
{
- pwm_enable(PWM_CH_FAN, enable);
+ fan_chip_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 int fan_get_rpm_mode(void)
-{
- return (LM4_FAN_FANCH(CONFIG_FAN_CH_CPU) & 0x0001) ? 0 : 1;
-}
-
-static void fan_set_rpm_mode(int rpm_mode)
-{
- int was_enabled = fan_get_enabled();
- int was_rpm = fan_get_rpm_mode();
-
- if (!was_rpm && rpm_mode) {
- /* Enable RPM control */
- fan_set_enabled(0);
- LM4_FAN_FANCH(CONFIG_FAN_CH_CPU) &= ~0x0001;
- fan_set_enabled(was_enabled);
- } else if (was_rpm && !rpm_mode) {
- /* Disable RPM mode */
- fan_set_enabled(0);
- LM4_FAN_FANCH(CONFIG_FAN_CH_CPU) |= 0x0001;
- fan_set_enabled(was_enabled);
- }
-}
-
-static int fan_get_rpm_actual(void)
-{
- return (LM4_FAN_FANCST(CONFIG_FAN_CH_CPU) & MAX_RPM) * CPU_FAN_SCALE;
+#endif /* CONFIG_FAN_EN_GPIO */
}
-static int fan_get_rpm_target(void)
-{
- return (LM4_FAN_FANCMD(CONFIG_FAN_CH_CPU) & MAX_RPM) * CPU_FAN_SCALE;
-}
-
-static void fan_set_rpm_target(int rpm)
-{
- /* Apply fan scaling */
- if (rpm > 0)
- rpm /= CPU_FAN_SCALE;
-
- /* Treat out-of-range requests as requests for maximum fan speed */
- if (rpm < 0 || rpm > MAX_RPM)
- rpm = MAX_RPM;
-
- LM4_FAN_FANCMD(CONFIG_FAN_CH_CPU) = rpm;
-}
-
-static int fan_get_status(void)
-{
- return (LM4_FAN_FANSTS >> (2 * CONFIG_FAN_CH_CPU)) & 0x03;
-}
-static const char * const human_status[] = {
- "not spinning", "changing", "locked", "frustrated"
-};
-
-/**
- * Return non-zero if fan is enabled but stalled.
- */
-static int fan_is_stalled(void)
-{
- /* Must be enabled with non-zero target to stall */
- if (!fan_get_enabled() || fan_get_rpm_target() == 0)
- return 0;
-
- /* Check for stall condition */
- return (((LM4_FAN_FANSTS >> (2 * CONFIG_FAN_CH_CPU)) & 0x03) == 0) ?
- 1 : 0;
-}
-
-/*****************************************************************************/
-/* Control functions */
-
-/* True if we're listening to the thermal control task. False if we're setting
- * things manually. */
-static int thermal_control_enabled;
-
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_set_rpm_mode(1);
+ fan_chip_channel_setup(CONFIG_FAN_CH_CPU,
+ FAN_CHIP_USE_RPM_MODE);
}
/* The thermal task will only call this function with pct in [0,100]. */
@@ -144,13 +53,13 @@ test_mockable void pwm_fan_set_percent_needed(int pct)
rpm = pwm_fan_percent_to_rpm(pct);
- fan_set_rpm_target(rpm);
+ fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, rpm);
}
static void fan_set_duty_cycle(int percent)
{
/* Move the fan to manual control */
- fan_set_rpm_mode(0);
+ fan_chip_set_rpm_mode(CONFIG_FAN_CH_CPU, 0);
/* Always enable the fan */
fan_set_enabled(1);
@@ -159,12 +68,7 @@ static void fan_set_duty_cycle(int percent)
fan_set_thermal_control_enabled(0);
/* Set the duty cycle */
- pwm_set_duty(PWM_CH_FAN, percent);
-}
-
-static int fan_get_duty_cycle(void)
-{
- return pwm_get_duty(PWM_CH_FAN);
+ fan_chip_set_duty(CONFIG_FAN_CH_CPU, percent);
}
/*****************************************************************************/
@@ -180,18 +84,26 @@ DECLARE_CONSOLE_COMMAND(fanauto, cc_fanauto,
"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());
- ccprintf("Target: %4d rpm\n", fan_get_rpm_target());
- ccprintf("Duty: %d%%\n", fan_get_duty_cycle());
- tmp = fan_get_status();
+
+ 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_get_rpm_mode() ? "rpm" : "duty");
+ 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_get_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
@@ -229,7 +141,7 @@ static int cc_fanset(int argc, char **argv)
}
/* Move the fan to automatic control */
- fan_set_rpm_mode(1);
+ fan_chip_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
/* Always enable the fan */
fan_set_enabled(1);
@@ -237,7 +149,7 @@ static int cc_fanset(int argc, char **argv)
/* Disable thermal engine automatic fan control. */
fan_set_thermal_control_enabled(0);
- fan_set_rpm_target(rpm);
+ fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, rpm);
ccprintf("Setting fan rpm target to %d\n", rpm);
@@ -277,7 +189,7 @@ 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();
+ r->rpm = fan_chip_get_rpm_target(CONFIG_FAN_CH_CPU);
args->response_size = sizeof(*r);
return EC_RES_SUCCESS;
@@ -291,8 +203,8 @@ 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;
fan_set_thermal_control_enabled(0);
- fan_set_rpm_mode(1);
- fan_set_rpm_target(p->rpm);
+ fan_chip_set_rpm_mode(CONFIG_FAN_CH_CPU, 1);
+ fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, p->rpm);
return EC_RES_SUCCESS;
}
@@ -346,11 +258,11 @@ static void pwm_fan_init(void)
system_get_jump_tag(PWMFAN_SYSJUMP_TAG, &version, &size);
if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) {
/* Restore previous state. */
- fan_set_enabled(prev->fan_en);
- fan_set_rpm_target(prev->fan_rpm);
+ 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 */
- pwm_fan_set_percent_needed(100);
+ fan_chip_set_duty(CONFIG_FAN_CH_CPU, 100);
}
fan_set_thermal_control_enabled(1);
@@ -366,7 +278,7 @@ static void pwm_fan_second(void)
{
uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
- if (fan_is_stalled()) {
+ if (fan_chip_is_stalled(CONFIG_FAN_CH_CPU)) {
mapped[0] = EC_FAN_SPEED_STALLED;
/*
* Issue warning. As we have thermal shutdown
@@ -375,7 +287,7 @@ static void pwm_fan_second(void)
host_set_single_event(EC_HOST_EVENT_THERMAL);
cprintf(CC_PWM, "[%T Fan stalled!]\n");
} else {
- mapped[0] = fan_get_rpm_actual();
+ mapped[0] = fan_chip_get_rpm_actual(CONFIG_FAN_CH_CPU);
}
}
DECLARE_HOOK(HOOK_SECOND, pwm_fan_second, HOOK_PRIO_DEFAULT);
@@ -384,8 +296,8 @@ static void pwm_fan_preserve_state(void)
{
struct pwm_fan_state state;
- state.fan_en = fan_get_enabled();
- state.fan_rpm = fan_get_rpm_target();
+ 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);
@@ -394,7 +306,7 @@ DECLARE_HOOK(HOOK_SYSJUMP, pwm_fan_preserve_state, HOOK_PRIO_DEFAULT);
static void pwm_fan_resume(void)
{
- fan_set_enabled(1);
+ fan_chip_set_enabled(CONFIG_FAN_CH_CPU, 1);
}
DECLARE_HOOK(HOOK_CHIPSET_RESUME, pwm_fan_resume, HOOK_PRIO_DEFAULT);
@@ -405,8 +317,8 @@ static void pwm_fan_S3_S5(void)
/* 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(0);
- fan_set_enabled(0); /* crosbug.com/p/8097 */
+ fan_chip_set_rpm_target(CONFIG_FAN_CH_CPU, 0);
+ fan_chip_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/chip/lm4/fan_chip.c b/chip/lm4/fan_chip.c
new file mode 100644
index 0000000000..cef39b9b3d
--- /dev/null
+++ b/chip/lm4/fan_chip.c
@@ -0,0 +1,180 @@
+/* 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
new file mode 100644
index 0000000000..0ff92b1740
--- /dev/null
+++ b/chip/lm4/fan_chip.h
@@ -0,0 +1,27 @@
+/* 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 6e52ebb369..943aa0210f 100644
--- a/chip/lm4/pwm.c
+++ b/chip/lm4/pwm.c
@@ -3,9 +3,13 @@
* found in the LICENSE file.
*/
-/* PWM control module for LM4 */
+/* PWM control module for LM4.
+ *
+ * On this chip, the PWM logic is implemented by the hardware FAN modules.
+ */
#include "clock.h"
+#include "fan_chip.h"
#include "gpio.h"
#include "hooks.h"
#include "pwm.h"
@@ -13,58 +17,39 @@
#include "registers.h"
#include "util.h"
-/* Maximum RPM for PWM controller */
-#define MAX_RPM 0x1fff
-
-/* Maximum PWM for PWM controller */
-#define MAX_PWM 0x1ff
-
-#define RPM_SCALE 2
-
void pwm_enable(enum pwm_channel ch, int enabled)
{
- const struct pwm_t *pwm = pwm_channels + ch;
- if (enabled)
- LM4_FAN_FANCTL |= (1 << pwm->channel);
- else
- LM4_FAN_FANCTL &= ~(1 << pwm->channel);
+ fan_chip_set_enabled(pwm_channels[ch].channel, enabled);
}
int pwm_get_enabled(enum pwm_channel ch)
{
- const struct pwm_t *pwm = pwm_channels + ch;
- return (LM4_FAN_FANCTL & (1 << pwm->channel)) ? 1 : 0;
+ return fan_chip_get_enabled(pwm_channels[ch].channel);
}
void pwm_set_duty(enum pwm_channel ch, int percent)
{
- const struct pwm_t *pwm = pwm_channels + ch;
- int duty;
-
if (percent < 0)
percent = 0;
else if (percent > 100)
percent = 100;
- if (pwm->flags & PWM_CONFIG_ACTIVE_LOW)
+ /* Assume the fan control is active high and invert it ourselves */
+ if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW)
percent = 100 - percent;
- duty = (MAX_PWM * percent + 50) / 100;
-
/* Always enable the channel */
pwm_enable(ch, 1);
/* Set the duty cycle */
- LM4_FAN_FANCMD(pwm->channel) = duty << 16;
+ fan_chip_set_duty(pwm_channels[ch].channel, percent);
}
int pwm_get_duty(enum pwm_channel ch)
{
- const struct pwm_t *pwm = pwm_channels + ch;
- int percent = ((LM4_FAN_FANCMD(pwm->channel) >> 16) * 100 + MAX_PWM / 2)
- / MAX_PWM;
+ int percent = fan_chip_get_duty(pwm_channels[ch].channel);
- if (pwm->flags & PWM_CONFIG_ACTIVE_LOW)
+ if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW)
percent = 100 - percent;
return percent;
@@ -73,47 +58,13 @@ int pwm_get_duty(enum pwm_channel ch)
static void pwm_init(void)
{
int i;
- const struct pwm_t *pwm;
-
- /* 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;
- for (i = 0; i < PWM_CH_COUNT; ++i) {
- pwm = pwm_channels + i;
-
- if (pwm->flags & PWM_CONFIG_HAS_RPM_MODE) {
- /*
- * Configure PWM:
- * 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(pwm->channel) = 0x802c;
- } else {
- /*
- * Configure keyboard backlight:
- * 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(pwm->channel) = 0x0001;
- }
- }
+ for (i = 0; i < PWM_CH_COUNT; ++i)
+ fan_chip_channel_setup(pwm_channels[i].channel,
+ (pwm_channels[i].flags &
+ PWM_CONFIG_HAS_RPM_MODE)
+ ? FAN_CHIP_USE_RPM_MODE : 0);
}
-DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_INIT_PWM);
+
+/* The chip-specific fan module initializes before this. */
+DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_DEFAULT);