summaryrefslogtreecommitdiff
path: root/src/superio/fintek/common
diff options
context:
space:
mode:
authorRichard Spiegel <richard.spiegel@amd.corp-partner.google.com>2019-06-19 13:57:55 -0700
committerFelix Held <felix-coreboot@felixheld.de>2019-07-26 20:33:16 +0000
commitae5b3671b39f26b79685496d79845f9a4f3975db (patch)
treeecf8c1767c981718967af471c3df5d8b415d8758 /src/superio/fintek/common
parent150a61e103c9c8001a0fc7905c02d0c065b7f126 (diff)
superio/fintek: Add f81803A
Add f81803A plus the capability to control the fan with any fintek SIO. This will be done through a common API, though currently only F81803A will have it implemented. BUG=none. TEST=Tested later with padmelon board. Change-Id: I3d336e76bccc38452b1b1aefef5d4a4f7ee129a8 Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/33623 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Diffstat (limited to 'src/superio/fintek/common')
-rw-r--r--src/superio/fintek/common/fan_api_call.c63
-rw-r--r--src/superio/fintek/common/fan_control.h199
2 files changed, 262 insertions, 0 deletions
diff --git a/src/superio/fintek/common/fan_api_call.c b/src/superio/fintek/common/fan_api_call.c
new file mode 100644
index 0000000000..1bd5b2e7d4
--- /dev/null
+++ b/src/superio/fintek/common/fan_api_call.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 Richard Spiegel <richard.spiegel@silverbackltd.com>
+ * Copyright (C) 2019 Silverback ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include "fan_control.h"
+
+static int check_status(int status)
+{
+ if (status < HWM_STATUS_SUCCESS)
+ return status;
+ return HWM_STATUS_SUCCESS; /* positive values are warnings only */
+}
+
+int set_fan(struct fintek_fan *fan_init)
+{
+ int s;
+
+ s = set_sensor_type(CONFIG_HWM_PORT, fan_init->sensor, fan_init->stype);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ s = set_fan_temperature_source(CONFIG_HWM_PORT, fan_init->fan, fan_init->temp_source);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ s = set_fan_type_mode(CONFIG_HWM_PORT, fan_init->fan, fan_init->ftype, fan_init->fmode);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ s = set_pwm_frequency(CONFIG_HWM_PORT, fan_init->fan, fan_init->fan_freq);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ s = set_fan_speed_change_rate(CONFIG_HWM_PORT, fan_init->fan, fan_init->rate_up,
+ fan_init->rate_down);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ s = set_fan_follow(CONFIG_HWM_PORT, fan_init->fan, fan_init->follow);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ s = set_sections(CONFIG_HWM_PORT, fan_init->fan, fan_init->boundaries,
+ fan_init->sections);
+ if (check_status(s) != HWM_STATUS_SUCCESS)
+ return s;
+
+ printk(BIOS_DEBUG, "Fan %d completed\n", fan_init->fan);
+ return HWM_STATUS_SUCCESS;
+}
diff --git a/src/superio/fintek/common/fan_control.h b/src/superio/fintek/common/fan_control.h
new file mode 100644
index 0000000000..fbe784bfa1
--- /dev/null
+++ b/src/superio/fintek/common/fan_control.h
@@ -0,0 +1,199 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 Richard Spiegel <richard.spiegel@silverbackltd.com>
+ * Copyright (C) 2019 Silverback ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef SUPERIO_FINTEK_FAN_CONTROL_H
+#define SUPERIO_FINTEK_FAN_CONTROL_H
+
+#include <stdint.h>
+#include <arch/io.h>
+
+typedef enum {
+ IGNORE_SENSOR = 0,
+ EXTERNAL_SENSOR1,
+ EXTERNAL_SENSOR2,
+ EXTERNAL_SENSOR3,
+ EXTERNAL_SENSOR4
+} external_sensor;
+
+typedef enum {
+ TEMP_SENSOR_THERMISTOR = 0,
+ TEMP_SENSOR_BJT,
+ TEMP_SENSOR_DEFAULT
+} temp_sensor_type;
+
+typedef enum {
+ FAN_TYPE_PWM_PUSH_PULL = 0,
+ FAN_TYPE_DAC_POWER,
+ FAN_TYPE_PWM_OPEN_DRAIN,
+ FAN_TYPE_RESERVED
+} fan_type;
+#define FAN_TYPE_PWM_CHECK 1 /* bit 0 must be 0 for PWM */
+
+typedef enum {
+ FAN_MODE_AUTO_RPM = 0,
+ FAN_MODE_AUTO_PWM_DAC,
+ FAN_MODE_MANUAL_RPM,
+ FAN_MODE_MANUAL_PWM_DAC,
+ FAN_MODE_DEFAULT
+} fan_mode;
+
+typedef enum {
+ FAN_PWM_FREQ_23500 = 0,
+ FAN_PWM_FREQ_11750,
+ FAN_PWM_FREQ_5875,
+ FAN_PWM_FREQ_220
+} fan_pwm_freq;
+
+typedef enum {
+ FAN_TEMP_PECI = 0,
+ FAN_TEMP_EXTERNAL_1,
+ FAN_TEMP_EXTERNAL_2,
+ FAN_TEMP_TSI = 4,
+ FAN_TEMP_MXM,
+} fan_temp_source;
+
+typedef enum {
+ FAN_UP_RATE_2HZ = 0,
+ FAN_UP_RATE_5HZ,
+ FAN_UP_RATE_10HZ,
+ FAN_UP_RATE_20HZ,
+ FAN_UP_RATE_DEFAULT,
+ FAN_UP_RATE_JUMP = 8
+} fan_rate_up;
+
+typedef enum {
+ FAN_DOWN_RATE_2HZ = 0,
+ FAN_DOWN_RATE_5HZ,
+ FAN_DOWN_RATE_10HZ,
+ FAN_DOWN_RATE_20HZ,
+ FAN_DOWN_RATE_DEFAULT,
+ FAN_DOWN_RATE_SAME_AS_UP,
+ FAN_DOWN_RATE_JUMP = 8
+} fan_rate_down;
+
+typedef enum {
+ FAN_FOLLOW_STEP = 0,
+ FAN_FOLLOW_INTERPOLATION
+} fan_follow;
+
+struct fintek_fan {
+ uint8_t fan;
+ external_sensor sensor;
+ temp_sensor_type stype;
+ fan_temp_source temp_source;
+ fan_type ftype;
+ fan_mode fmode;
+ fan_pwm_freq fan_freq;
+ fan_rate_up rate_up;
+ fan_rate_down rate_down;
+ fan_follow follow;
+ uint8_t *boundaries;
+ uint8_t *sections;
+};
+
+#define HWM_STATUS_SUCCESS 0
+#define HWM_STATUS_INVALID_FAN -1
+#define HWM_STATUS_INVALID_TEMP_SOURCE -2
+#define HWM_STATUS_INVALID_TYPE -3
+#define HWM_STATUS_INVALID_MODE -4
+#define HWM_STATUS_INVALID_RATE -5
+#define HWM_STATUS_INVALID_FREQUENCY -6
+#define HWM_STATUS_INVALID_TEMP_SENSOR -7
+#define HWM_STATUS_INVALID_BOUNDARY_VALUE -8
+#define HWM_STATUS_INVALID_SECTION_VALUE -9
+#define HWM_STATUS_BOUNDARY_WRONG_ORDER -10
+#define HWM_STATUS_SECTIONS_WRONG_ORDER -11
+#define HWM_STATUS_WARNING_SENSOR_DISCONECTED 1
+#define HWM_STATUS_WARNING_FAN_NOT_PWM 2
+
+#define CPU_DAMAGE_TEMP 110
+
+/*
+ * Boundaries order is from highest temp. to lowest. Values from 0 to 127.
+ * Boundaries should be defined as u8 boundaries[FINTEK_BOUNDARIES_SIZE].
+ */
+#define FINTEK_BOUNDARIES_SIZE 4
+/*
+ * Section defines the duty_cycle/voltage to be used based on where the
+ * temperature lies with respect to the boundaries. There are 5 sections
+ * (4 boundaries) and the order must be from highest to lowest. Values
+ * from 0% to 100%, will be converted internally to percent of 255.
+ * Sections should be defined as u8 sections[FINTEK_SECTIONS_SIZE].
+ */
+#define FINTEK_SECTIONS_SIZE 5
+
+/*
+ * When using external sensor, its type must be defined. When using PECI,
+ * TSI or MXM use IGNORE_SENSOR to indicate so.
+ */
+int set_sensor_type(u16 base_address, external_sensor sensor,
+ temp_sensor_type type);
+
+/*
+ * Define the temperature source used to control a fan.
+ */
+int set_fan_temperature_source(u16 base_address, u8 fan,
+ fan_temp_source source);
+
+/*
+ * Define if fan is controlled through PWM or absolute voltage powering it
+ * (DAC). Then, under mode, define if control is automatic (SIO) or manual
+ * (CPU, through ACPI). Notice there needs to be a match between type and
+ * mode (PWM with PWM or DAC with DAC).
+ */
+int set_fan_type_mode(u16 base_address, u8 fan, fan_type type, fan_mode mode);
+
+/*
+ * For fans controlled through pulse width, define the base frequency used.
+ */
+int set_pwm_frequency(u16 base_address, u8 fan, fan_pwm_freq frequency);
+
+/*
+ * For fintek SIO HWM there are 4 (temperature) boundaries points, defining
+ * 5 sections (1 fan speed per section). Start with the highest temperature/
+ * speed. Temperature is in Celsius, speed is in percentile of max speed. The
+ * highest speed should be 100%, no requirements for minimum speed, could be
+ * 0 or above 0.
+ */
+int set_sections(u16 base_address, u8 fan, u8 *boundaries, u8 *sections);
+
+/*
+ * Define how often temperature is measured to change fan speed.
+ */
+int set_fan_speed_change_rate(u16 base_address, u8 fan, fan_rate_up rate_up,
+ fan_rate_down rate_down);
+
+/*
+ * There a 2 ways a fan can be controlled: A single speed per section, or
+ * interpolation. Under interpolation, the section speed is the speed at the
+ * lowest temperature of the section (0 Celsius for the lowest section), and
+ * it's the speed of the next section at the boundary to the next section.
+ * In between these 2 points, it's a linear function. For example, midway
+ * between temperature points it'll have a speed that is midway between the
+ * section speed and next section speed. Obviously, there's no variation for
+ * the highest section, reason why it must be 100% max speed.
+ */
+int set_fan_follow(u16 base_address, u8 fan, fan_follow follow);
+
+/*
+ * This is an upper level API which calls all the above APIs in the
+ * appropriate order. Any API failure will be displayed. Alerts will
+ * also be displayed, but will not interrupt the sequence, while errors
+ * will interrupt the sequence.
+ */
+int set_fan(struct fintek_fan *fan_init);
+
+#endif /* SUPERIO_FINTEK_FAN_CONTROL_H */