Richard Spiegel has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/33623
Change subject: superio/fintek: Add f81803a ......................................................................
superio/fintek: Add f81803a
In preparation for padmelon board, add f81803a plus the capability to control the fan with the superio.
BUG=b:none. TEST=Tested later with padmelon board.
Change-Id: I3d336e76bccc38452b1b1aefef5d4a4f7ee129a8 Signed-off-by: Richard Spiegel richard.spiegel@silverbackltd.com --- M src/superio/fintek/Makefile.inc A src/superio/fintek/common/fan_control.h A src/superio/fintek/f81803a/Kconfig A src/superio/fintek/f81803a/Makefile.inc A src/superio/fintek/f81803a/acpi/superio.asl A src/superio/fintek/f81803a/f81803a.h A src/superio/fintek/f81803a/f81803a_hwm.h A src/superio/fintek/f81803a/fan_control.c A src/superio/fintek/f81803a/superio.c 9 files changed, 820 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/23/33623/1
diff --git a/src/superio/fintek/Makefile.inc b/src/superio/fintek/Makefile.inc index 796e519..db683fd 100644 --- a/src/superio/fintek/Makefile.inc +++ b/src/superio/fintek/Makefile.inc @@ -26,3 +26,4 @@ subdirs-y += f81216h subdirs-y += f81865f subdirs-y += f81866d +subdirs-y += f81803a diff --git a/src/superio/fintek/common/fan_control.h b/src/superio/fintek/common/fan_control.h new file mode 100644 index 0000000..8828c4b --- /dev/null +++ b/src/superio/fintek/common/fan_control.h @@ -0,0 +1,109 @@ +/* + * 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> + +#define EXTERNAL_SENSOR1 1 +#define EXTERNAL_SENSOR2 2 +#define EXTERNAL_SENSOR3 3 +#define EXTERNAL_SENSOR_4 4 +#define TEMP_SENSOR_THERMISTOR 0 +#define TEMP_SENSOR_BJT 1 +#define TEMP_SENSOR_DEFAULT 2 + +#define FAN_TYPE_PWM_PUSH_PULL 0 +#define FAN_TYPE_DAC_POWER 1 +#define FAN_TYPE_PWM_OPEN_DRAIN 2 +#define FAN_TYPE_SET_BY_STRAP 3 +#define FAN_TYPE_PWM_CHECK 1 /* bit 0 must be 0 for PWM */ + +#define FAN_MODE_AUTO_RPM 0 +#define FAN_MODE_AUTO_PWM_DAC 1 +#define FAN_MODE_MANUAL_RPM 2 +#define FAN_MODE_MANUAL_PWM_DAC 3 +#define FAN_MODE_DEFAULT 4 + +#define FAN_PWM_FREQ_23500 0 +#define FAN_PWM_FREQ_11750 1 +#define FAN_PWM_FREQ_5875 2 +#define FAN_PWM_FREQ_220 3 + +#define FAN_TEMP_PECI 0 +#define FAN_TEMP_EXTERNAL_1 1 +#define FAN_TEMP_EXTERNAL_2 2 +#define FAN_TEMP_TSI 4 +#define FAN_TEMP_MXM 5 + +#define FAN_UP_RATE_2HZ 0 +#define FAN_UP_RATE_5HZ 1 +#define FAN_UP_RATE_10HZ 2 +#define FAN_UP_RATE_20HZ 3 +#define FAN_UP_RATE_DEFAULT 4 +#define FAN_UP_RATE_JUMP 8 + +#define FAN_DOWN_RATE_2HZ 0 +#define FAN_DOWN_RATE_5HZ 1 +#define FAN_DOWN_RATE_10HZ 2 +#define FAN_DOWN_RATE_20HZ 3 +#define FAN_DOWN_RATE_DEFAULT 4 +#define FAN_DOWN_RATE_SAME_AS_UP 5 +#define FAN_DOWN_RATE_JUMP 8 + +#define FAN_FOLLOW_STEP 0 +#define FAN_FOLLOW_INTERPOLATION 1 + +#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 -20 +#define HWM_STATUS_SECTIONS_WRONG_ORDER -21 +#define HWM_STATUS_WARNING_SENSOR_DISCONECTED 1 +#define HWM_STATUS_WARNING_FAN_NOT_PWM 2 + +/* + * 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 + +int set_sensor_type(u16 base_address, u8 sensor, u8 type); +int set_fan_temperature_source(u16 base_address, u8 fan, u8 source); +int set_fan_type_mode(u16 base_address, u8 fan, u8 type, u8 mode); +int set_pwm_frequency(u16 base_address, u8 fan, u8 frequency); +int set_sections(u16 base_address, u8 fan, u8 *boundaries, u8 *sections); +int set_fan_speed_change_rate(u16 base_address, u8 fan, u8 rate_up, + u8 rate_down); + +#endif /* SUPERIO_FINTEK_FAN_CONTROL_H */ diff --git a/src/superio/fintek/f81803a/Kconfig b/src/superio/fintek/f81803a/Kconfig new file mode 100644 index 0000000..f1f6ef3 --- /dev/null +++ b/src/superio/fintek/f81803a/Kconfig @@ -0,0 +1,24 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2009 Ronald G. Minnich +## Copyright (C) 2014 Edward O'Callaghan eocallaghan@alterapraxis.com +## +## 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. +## + +config SUPERIO_FINTEK_F81803A + bool + select SUPERIO_FINTEK_COMMON_PRE_RAM + +config SUPERIO_FINTEK_F81803A_FAN_CONTROL + bool + depends on SUPERIO_FINTEK_COMMON_PRE_RAM + default n diff --git a/src/superio/fintek/f81803a/Makefile.inc b/src/superio/fintek/f81803a/Makefile.inc new file mode 100644 index 0000000..a953b4a --- /dev/null +++ b/src/superio/fintek/f81803a/Makefile.inc @@ -0,0 +1,24 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2011 Advanced Micro Devices, Inc. +## +## 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; either version 2 of the License, or +## (at your option) any later version. +## +## 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. +## + +ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) +bootblock-$(CONFIG_SUPERIO_FINTEK_F81803A) += ../common/early_serial.c +endif + +romstage-$(CONFIG_SUPERIO_FINTEK_F81803A) += ../common/early_serial.c + +ramstage-$(CONFIG_SUPERIO_FINTEK_F81803A) += superio.c +ramstage-$(CONFIG_SUPERIO_FINTEK_F81803A_FAN_CONTROL) += fan_control.c diff --git a/src/superio/fintek/f81803a/acpi/superio.asl b/src/superio/fintek/f81803a/acpi/superio.asl new file mode 100644 index 0000000..7568131 --- /dev/null +++ b/src/superio/fintek/f81803a/acpi/superio.asl @@ -0,0 +1,155 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Christoph Grenz christophg+cb@grenz-bonn.de + * Copyright (C) 2013 secunet Security Networks AG + * + * 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 this file into a mainboard's DSDT _SB device tree and it will + * expose the F81803A SuperIO and some of its functionality. + * + * It allows the change of IO ports, IRQs and DMA settings on logical + * devices, disabling and reenabling logical devices and controlling power + * saving mode on logical devices or the whole chip. + * + * LDN State + * 0x1 UARTA Implemented, partially tested + * 0x2 UARTB UART only, partially tested + * 0x4 HWM Not implemented + * 0x5 KBC Implemented, untested + * 0x6 GPIO6 Not implemented + * 0x7 WDT0&PLED Not implemented + * 0xa ACPI/PME/ERP Partially implemented + * + * Controllable through preprocessor defines: + * SUPERIO_DEV Device identifier for this SIO (e.g. SIO0) + * SUPERIO_PNP_BASE I/o address of the first PnP configuration register + * F81803A_SHOW_UARTA If defined, UARTA will be exposed. + * F81803A_SHOW_UARTB If defined, UARTB will be exposed. + * F81803A_SHOW_KBC If defined, the KBC will be exposed. + * F81803A_SHOW_PS2M If defined, PS/2 mouse support will be exposed. + * F81803A_SHOW_HWMON If defined, the hardware monitor will be exposed. + * F81803A_SHOW_PME If defined, the PME/EARP/ACPI will be exposed. + */ +#undef SUPERIO_DEV +#define SUPERIO_DEV SIO0 +#undef SUPERIO_CHIP_NAME +#define SUPERIO_CHIP_NAME F81803A +#define SUPERIO_PNP_BASE 0x4E +#define F81803A_SHOW_PME +#include <superio/acpi/pnp.asl> + + + +Device(SUPERIO_DEV) { + Name (_HID, EisaId("PNP0A05")) + Name (_STR, Unicode("Fintek F81803A Super I/O")) + Name (_UID, SUPERIO_UID(SUPERIO_DEV,)) + + /* Mutex for accesses to the configuration ports */ + Mutex(CRMX, 1) + + /* SuperIO configuration ports */ + OperationRegion (CREG, SystemIO, SUPERIO_PNP_BASE, 0x02) + Field (CREG, ByteAcc, NoLock, Preserve) + { + PNP_ADDR_REG, 8, + PNP_DATA_REG, 8 + } + IndexField (ADDR, DATA, ByteAcc, NoLock, Preserve) + { + Offset (0x07), + PNP_LOGICAL_DEVICE, 8, /* Logical device selector */ + Offset (0x30), + PNP_DEVICE_ACTIVE, 1, /* Logical device activation */ + Offset (0x60), + PNP_IO0_HIGH_BYTE, 8, /* First I/O port base - high byte */ + PNP_IO0_LOW_BYTE, 8, /* First I/O port base - low byte */ + Offset (0x62), + PNP_IO1_HIGH_BYTE, 8, /* Second I/O port base - high byte */ + PNP_IO1_LOW_BYTE, 8, /* Second I/O port base - low byte */ + Offset (0x70), + PNP_IRQ0, 8, /* First IRQ */ + offset(0xFB), + APC5, 8, /* PME ACPI Control Register 5 */ + } + + Method(_CRS) + { + /* Announce the used i/o ports to the OS */ + Return (ResourceTemplate () { + IO (Decode16, SUPERIO_PNP_BASE, SUPERIO_PNP_BASE, 0x01, 0x02) + }) + } + + #undef PNP_ENTER_MAGIC_1ST + #undef PNP_ENTER_MAGIC_2ND + #undef PNP_ENTER_MAGIC_3RD + #undef PNP_ENTER_MAGIC_4TH + #undef PNP_EXIT_MAGIC_1ST + #undef PNP_EXIT_SPECIAL_REG + #undef PNP_EXIT_SPECIAL_VAL + #define PNP_ENTER_MAGIC_1ST 0x87 + #define PNP_ENTER_MAGIC_2ND 0x87 + #define PNP_EXIT_MAGIC_1ST 0xaa + #include <superio/acpi/pnp_config.asl> + +#ifdef F81803A_SHOW_UARTA + #undef SUPERIO_UART_LDN + #undef SUPERIO_UART_DDN + #undef SUPERIO_UART_PM_REG + #undef SUPERIO_UART_PM_VAL + #undef SUPERIO_UART_PM_LDN + #define SUPERIO_UART_LDN 1 + #define SUPERIO_UART_PM_REG UAPW + #define SUPERIO_UART_PM_VAL 0 + #define SUPERIO_UART_PM_LDN PNP_NO_LDN_CHANGE + #include <superio/acpi/pnp_uart.asl> +#endif + +#ifdef F81803A_SHOW_UARTB + #undef SUPERIO_UART_LDN + #undef SUPERIO_UART_DDN + #undef SUPERIO_UART_PM_REG + #undef SUPERIO_UART_PM_VAL + #undef SUPERIO_UART_PM_LDN + #define SUPERIO_UART_LDN 2 + #define SUPERIO_UART_PM_REG UBPW + #define SUPERIO_UART_PM_VAL 0 + #define SUPERIO_UART_PM_LDN PNP_NO_LDN_CHANGE + #include <superio/acpi/pnp_uart.asl> +#endif + +#ifdef F81803A_SHOW_PME + #undef SUPERIO_PME_LDN + #define SUPERIO_PME_LDN 0x0A + + OperationRegion(APCx, SystemIO, APC5, 0x01) + Field(APCx, ByteAcc, Nolock, Preserve) /* bits in PME ACPI CONTROL Reg 5*/ + { + Offset(0x00), /*Control Reg 5 */ + , 7, + PSIN, 1 /* PSIN_FLAG */ + } + + /* routine to clear PSIN_FLAG in ACPI_CONTROL_REG_5 of SIO */ + Method(CPSI, 0, Serialized) + { + /* DBG0("SIO CPSI")*/ + ENTER_CONFIG_MODE(SUPERIO_PME_LDN) + Store(1, PSIN) + EXIT_CONFIG_MODE() + } +#endif + +} diff --git a/src/superio/fintek/f81803a/f81803a.h b/src/superio/fintek/f81803a/f81803a.h new file mode 100644 index 0000000..a5e9329 --- /dev/null +++ b/src/superio/fintek/f81803a/f81803a.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +/* + * Datasheet: + * - Name: F81803A + */ + +#ifndef SUPERIO_FINTEK_F81803_H +#define SUPERIO_FINTEK_F81803_H + +/* Logical Device Numbers (LDN) */ +#define F81803A_SP1 0x01 /* UART1 */ +#define F81803A_SP2 0x02 /* UART2 */ +#define F81803A_HWM 0x04 /* Hardware Monitor */ +#define F81803A_KBC 0x05 /* Keyboard/Mouse */ +#define F81803A_GPIO 0x06 /* General Purpose I/O (GPIO) */ +#define F81803A_WDT 0x07 /* Watch Dog Timer */ +#define F81803A_PME 0x0a /* Power Management Events (PME) */ + +/* registers in Fintek F81803A */ +#define LDN_REG 0x07 + +/* Global Control Registers */ +#define CLOCK_SELECT_REG 0x26 +#define FUNC_PROG_SELECT (1<<3) +#define PORT_SELECT_REG 0x27 + +#define TSI_LEVEL_SELECT_REG 0x28 /* FUNC_PROG_SEL = 0 */ +#define TSI_PIN_SELECT_REG 0x28 /* FUNC_PROG_SEL = 1 */ +#define MULTI_FUNC_SEL_REG1 0x29 +#define MULTI_FUNC_SEL_REG2 0x2A +#define MULTI_FUNC_SEL_REG3 0x2B +#define MULTI_FUNC_SEL_REG 0x2C +#define WAKEUP_CONTROL_REG 0x2d + +/* LUN A - PME, ACPI, ERP */ +#define PME_DEVICE_ENABLE_REG 0x30 +#define PME_ENABLE (1<<0) +#define PME_ERP_ENABLE_REG 0xE0 +#define ERP_ENABLE (1<<7) +#define ERP_PME_EN (1<<1) +#define ERP_PSOUT_EN (1<<0) +#define PME_ERP_CONTROL_1_REG 0xE1 +#define PME_ERP_CONTROL_2_REG 0xE2 +#define PME_ERP_PSIN_DEBOUNCE_REG 0xE3 +#define PME_ERP_WAKEUP_ENABLE_REG 0xE8 +#define PME_ERP_MODE_SELECT_REG 0xEC +#define PME_EVENT_ENABLE_1_REG 0xF0 +#define PME_EVENT_STATUS_1_REG 0xF1 +#define PME_EVENT_ENABLE_2_REG 0xF2 +#define PME_EVENT_STATUS_2_REG 0xF3 +#define PME_ACPI_CONTROL_1_REG 0xF4 +#define PME_ACPI_CONTROL_2_REG 0xF5 +#define PME_ACPI_CONTROL_3_REG 0xF6 +#define PME_ACPI_CONTROL_4_REG 0xF7 +#define PME_ACPI_CONTROL_5_REG 0xFB +#define PME_ACPI_CONTROL_6_REG 0xFC + +#endif /* SUPERIO_FINTEK_F81803_H */ diff --git a/src/superio/fintek/f81803a/f81803a_hwm.h b/src/superio/fintek/f81803a/f81803a_hwm.h new file mode 100644 index 0000000..2fba52b --- /dev/null +++ b/src/superio/fintek/f81803a/f81803a_hwm.h @@ -0,0 +1,92 @@ +/* + * 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_F81803_HWM_H +#define SUPERIO_FINTEK_F81803_HWM_H + +#define TP_SENSOR_TYPE 0x6b +#define TP_SENSOR1_TYPE_SHIFT 1 +#define TP_SENSOR2_TYPE_SHIFT 2 +#define TP_SENSOR_TYPE_MASK 0x01 +#define TP_DIODE_STATUS 0x6f +#define TP_MMX_OPEN 0x40 +#define TP_PECI_OPEN 0x20 +#define TP_TSI_OPEN 0x10 +#define TP_EXTERNAL_SENSOR2_OPEN 0x04 +#define TP_EXTERNAL_SENSOR1_OPEN 0x02 + +#define FAN_TYPE_REG 0x94 +#define FAN1_TYPE_SHIFT 0 +#define FAN2_TYPE_SHIFT 2 +#define FAN_TYPE_MASK 0x03 +#define FAN_MODE_REG 0x96 +#define FAN1_MODE_SHIFT 0 +#define FAN2_MODE_SHIFT 4 +#define FAN_MODE_MASK 0x07 +#define FAN1_FREQ_SEL_ADD_SHIFT 3 /* FUNC_PROG_SEL = 1 */ +#define FAN2_FREQ_SEL_ADD_SHIFT 4 /* FUNC_PROG_SEL = 1 */ +#define FAN_UP_RATE_REG 0x9a +#define FAN1_UP_RATE_SHIFT 0 +#define FAN2_UP_RATE_SHIFT 2 +#define FAN_UP_RATE_MASK 0x03 +#define FAN_DOWN_RATE_REG 0x9b +#define FAN1_DOWN_RATE_SHIFT 0 +#define FAN2_DOWN_RATE_SHIFT 2 +#define FAN_DOWN_RATE_MASK 0x03 +#define FAN_DOWN_RATE_DIFF_FROM_UP_SHIFT 7 /* FUNC_PROG_SEL = 1 */ +#define FAN_DIRECT_LOAD_EN_SHIFT 6 /* FUNC_PROG_SEL = 1 */ +#define FAN_FAULT_TIME_REG 0x9f +#define FAN_FUNC_PROG_SEL_SHIFT 7 + +#define FAN1_BOUND_TEMP1 0xa6 +#define FAN1_BOUND_TEMP2 0xa7 +#define FAN1_BOUND_TEMP3 0xa8 +#define FAN1_BOUND_TEMP4 0xa9 +#define FAN1_SECTION_SPEED1 0xaa +#define FAN1_SECTION_SPEED2 0xab +#define FAN1_SECTION_SPEED3 0xac +#define FAN1_SECTION_SPEED4 0xad +#define FAN1_SECTION_SPEED5 0xae +#define FAN2_BOUND_TEMP1 0xb6 +#define FAN2_BOUND_TEMP2 0xb7 +#define FAN2_BOUND_TEMP3 0xb8 +#define FAN2_BOUND_TEMP4 0xb9 +#define FAN2_SECTION_SPEED1 0xba +#define FAN2_SECTION_SPEED2 0xbb +#define FAN2_SECTION_SPEED3 0xbc +#define FAN2_SECTION_SPEED4 0xbd +#define FAN2_SECTION_SPEED5 0xbe +#define FAN_DETAIL_SKIP (FAN2_BOUND_TEMP1 - FAN1_BOUND_TEMP1) + +#define FAN1_TMP_MAPPING 0xaf +#define FAN2_TMP_MAPPING 0xbf +#define FAN_TEMP_SEL_HIGH_SHIFT 7 +#define FAN_PWM_FREQ_SEL_SHIFT 6 +#define FAN_INTERPOLATION_SHIFT 4 +#define FAN_JUMP_UP_SHIFT 3 +#define FAN_JUMP_DOWN_SHIFT 2 +#define FAN_TEMP_SEL_LOW_SHIFT 0 +#define FAN_TEMP_SEL_LOW_MASK 0x03 +#define FAN_BIT_MASK 0x01 + +#define STATUS_INVALID_VALUE -1 +#define STATUS_INVALID_ORDER -2 + +#define FIRST_FAN 1 +#define LAST_FAN 2 +#define MAX_DUTY 100 + +#endif /* SUPERIO_FINTEK_F81803_HWM_H */ diff --git a/src/superio/fintek/f81803a/fan_control.c b/src/superio/fintek/f81803a/fan_control.c new file mode 100644 index 0000000..47c8086 --- /dev/null +++ b/src/superio/fintek/f81803a/fan_control.c @@ -0,0 +1,263 @@ +/* + * 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 "../common/fan_control.h" +#include "f81803a_hwm.h" + +static void write_hwm_reg(u16 address, u8 index, u8 value) +{ + u16 index_add, data_add; + index_add = address | 0x0001; /* force odd address */ + data_add = index_add + 1; + outb(index, index_add); + outb(value, data_add); +} + +static u8 read_hwm_reg(u16 address, u8 index) +{ + u16 index_add, data_add; + index_add = address | 0x0001; /* force odd address */ + data_add = index_add + 1; + outb(index, index_add); + return inb(data_add); +} + +static void read_and_or_write(u16 address, u8 index, u8 shift, u8 mask, + u8 value) +{ + u8 use_mask, use_value; + u8 temp = read_hwm_reg(address, index); + + use_mask = mask << shift; + use_value = (value & mask) << shift; + temp &= ~use_mask; + temp |= use_value; + write_hwm_reg(address, index, temp); +} + +static inline void set_prog_sel(u16 address, u8 value) +{ + read_and_or_write(address, FAN_FAULT_TIME_REG, FAN_FUNC_PROG_SEL_SHIFT, + FAN_BIT_MASK, value); +} + +static int check_value_seq(u8 *values, u8 count) +{ + u8 last_value = 128; /* max value is 127 */ + u8 current_value, i; + for (i = 0; i < count; i++) { + current_value = values[i]; + if (current_value > 127) + return STATUS_INVALID_VALUE; + if (current_value >= last_value) + return STATUS_INVALID_ORDER; + last_value = current_value; + } + return HWM_STATUS_SUCCESS; +} + +int set_sensor_type(u16 base_address, u8 sensor, u8 type) +{ + u8 sensor_status = read_hwm_reg(base_address, TP_DIODE_STATUS); + if (sensor == TEMP_SENSOR_DEFAULT) + return HWM_STATUS_SUCCESS; + switch (sensor) { + case EXTERNAL_SENSOR1: + if (sensor_status & TP_EXTERNAL_SENSOR1_OPEN) + return HWM_STATUS_WARNING_SENSOR_DISCONECTED; + read_and_or_write(base_address, TP_SENSOR_TYPE, + TP_SENSOR1_TYPE_SHIFT, TP_SENSOR_TYPE_MASK, type); + break; + case EXTERNAL_SENSOR2: + if (sensor_status & TP_EXTERNAL_SENSOR2_OPEN) + return HWM_STATUS_WARNING_SENSOR_DISCONECTED; + read_and_or_write(base_address, TP_SENSOR_TYPE, + TP_SENSOR2_TYPE_SHIFT, TP_SENSOR_TYPE_MASK, type); + break; + default: + return HWM_STATUS_INVALID_TEMP_SENSOR; + } + return HWM_STATUS_SUCCESS; +} + +int set_fan_temperature_source(u16 base_address, u8 fan, u8 source) +{ + u8 index, high_value, low_value; + + if ((fan < FIRST_FAN) || (fan > LAST_FAN)) + return HWM_STATUS_INVALID_FAN; + index = FAN1_TMP_MAPPING; + if (fan == LAST_FAN) + index += FAN_DETAIL_SKIP; + high_value = (source >> 2) & FAN_BIT_MASK; + low_value = source & FAN_TEMP_SEL_LOW_MASK; + read_and_or_write(base_address, index, FAN_TEMP_SEL_HIGH_SHIFT, + FAN_BIT_MASK, high_value); + read_and_or_write(base_address, index, FAN_TEMP_SEL_LOW_SHIFT, + FAN_TEMP_SEL_LOW_MASK, low_value); + return HWM_STATUS_SUCCESS; +} + +int set_fan_type_mode(u16 base_address, u8 fan, u8 type, u8 mode) +{ + u8 shift; + + if ((fan < FIRST_FAN) || (fan > LAST_FAN)) + return HWM_STATUS_INVALID_FAN; + set_prog_sel(base_address, 0); + if (type < FAN_TYPE_SET_BY_STRAP) { + shift = FAN1_TYPE_SHIFT; + if (fan == LAST_FAN) + shift = FAN2_TYPE_SHIFT; + read_and_or_write(base_address, FAN_TYPE_REG, shift, + FAN_TYPE_MASK, type); + } + if (mode < FAN_MODE_DEFAULT) { + shift = FAN1_MODE_SHIFT; + if (fan == LAST_FAN) + shift = FAN2_MODE_SHIFT; + read_and_or_write(base_address, FAN_MODE_REG, shift, + FAN_MODE_MASK, mode); + } + return HWM_STATUS_SUCCESS; +} + +int set_pwm_frequency(u16 base_address, u8 fan, u8 frequency) +{ + u8 shift, index, byte; + + if ((fan < FIRST_FAN) || (fan > LAST_FAN)) + return HWM_STATUS_INVALID_FAN; + byte = read_hwm_reg(base_address, FAN_TYPE_REG); + shift = FAN1_TYPE_SHIFT; + if (fan == LAST_FAN) + shift = FAN2_TYPE_SHIFT; + if (((byte >> shift) & FAN_TYPE_PWM_CHECK) == FAN_TYPE_PWM_CHECK) + return HWM_STATUS_WARNING_FAN_NOT_PWM; + set_prog_sel(base_address, 1); + shift = FAN1_FREQ_SEL_ADD_SHIFT; + if (fan == LAST_FAN) + shift = FAN2_FREQ_SEL_ADD_SHIFT; + byte = (frequency >> 1) & FAN_BIT_MASK; + read_and_or_write(base_address, FAN_MODE_REG, shift, FAN_BIT_MASK, + byte); + set_prog_sel(base_address, 0); + index = FAN1_TMP_MAPPING; + if (fan == LAST_FAN) + index += FAN_DETAIL_SKIP; + byte = frequency & FAN_BIT_MASK; + read_and_or_write(base_address, index, FAN_PWM_FREQ_SEL_SHIFT, + FAN_BIT_MASK, byte); + return HWM_STATUS_SUCCESS; +} + +int set_sections(u16 base_address, u8 fan, u8 *boundaries, u8 *sections) +{ + int status, temp; + u8 i, index, value; + + if ((fan < FIRST_FAN) || (fan > LAST_FAN)) + return HWM_STATUS_INVALID_FAN; + status = check_value_seq(boundaries, + fintek_boundaries_size); + if (status != HWM_STATUS_SUCCESS) { + if (status == STATUS_INVALID_VALUE) + return HWM_STATUS_INVALID_BOUNDARY_VALUE; + return HWM_STATUS_BOUNDARY_WRONG_ORDER; + } + status = check_value_seq(sections, + fintek_sections_size); + if (status != HWM_STATUS_SUCCESS) { + if (status == STATUS_INVALID_VALUE) + return HWM_STATUS_INVALID_SECTION_VALUE; + return HWM_STATUS_SECTIONS_WRONG_ORDER; + } + index = FAN1_BOUND_TEMP1; + if (fan == LAST_FAN) + index += FAN_DETAIL_SKIP; + for (i = 0; i < fintek_boundaries_size; i++) { + value = boundaries[i]; + write_hwm_reg(base_address, index, value); + index++; + } + index = FAN1_SECTION_SPEED1; + if (fan == LAST_FAN) + index += FAN_DETAIL_SKIP; + for (i = 0; i < fintek_sections_size; i++) { + value = sections[i]; + if (value > 100) + return HWM_STATUS_INVALID_SECTION_VALUE; + temp = (255 * value) / 100; + value = (u8) (temp & 0x00ff); + write_hwm_reg(base_address, index, value); + index++; + } + return HWM_STATUS_SUCCESS; +} + +int set_fan_speed_change_rate(u16 base_address, u8 fan, u8 rate_up, + u8 rate_down) +{ + u8 shift, index; + + if ((fan < FIRST_FAN) || (fan > LAST_FAN)) + return HWM_STATUS_INVALID_FAN; + + index = FAN1_TMP_MAPPING; + if (fan == LAST_FAN) + index += FAN_DETAIL_SKIP; + shift = FAN1_UP_RATE_SHIFT; + if (fan == LAST_FAN) + shift = FAN2_UP_RATE_SHIFT; + + if (rate_up == FAN_UP_RATE_JUMP) { + read_and_or_write(base_address, index, FAN_JUMP_UP_SHIFT, + FAN_BIT_MASK, 1); + } else { + read_and_or_write(base_address, index, FAN_JUMP_UP_SHIFT, + FAN_BIT_MASK, 0); + if (rate_up < FAN_UP_RATE_DEFAULT) { + read_and_or_write(base_address, FAN_UP_RATE_REG, + shift, FAN_UP_RATE_MASK, rate_up); + } + } + + shift = FAN1_DOWN_RATE_SHIFT; + if (fan == LAST_FAN) + shift = FAN2_DOWN_RATE_SHIFT; + if (rate_down == FAN_DOWN_RATE_JUMP) { + read_and_or_write(base_address, index, FAN_JUMP_DOWN_SHIFT, + FAN_BIT_MASK, 1); + } else { + read_and_or_write(base_address, index, FAN_JUMP_UP_SHIFT, + FAN_BIT_MASK, 0); + set_prog_sel(base_address, 1); + if (rate_down < FAN_DOWN_RATE_DEFAULT) { + read_and_or_write(base_address, FAN_DOWN_RATE_REG, + shift, FAN_DOWN_RATE_MASK, rate_down); + read_and_or_write(base_address, FAN_DOWN_RATE_REG, + FAN_DOWN_RATE_DIFF_FROM_UP_SHIFT, + FAN_BIT_MASK, 0); + } + if (rate_down == FAN_DOWN_RATE_SAME_AS_UP) { + read_and_or_write(base_address, FAN_DOWN_RATE_REG, + FAN_DOWN_RATE_DIFF_FROM_UP_SHIFT, + FAN_BIT_MASK, 1); + } + set_prog_sel(base_address, 0); + } + return HWM_STATUS_SUCCESS; +} diff --git a/src/superio/fintek/f81803a/superio.c b/src/superio/fintek/f81803a/superio.c new file mode 100644 index 0000000..2f78244 --- /dev/null +++ b/src/superio/fintek/f81803a/superio.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 <device/device.h> +#include <device/pnp.h> +#include <superio/conf_mode.h> +#include <console/console.h> +#include <stdlib.h> +#include <pc80/keyboard.h> +#include "f81803a.h" + +static void f81803a_pme_init(struct device *dev) +{ + pnp_enter_conf_mode(dev); + pnp_write_config(dev, LDN_REG, F81803A_PME); + /* enable ERP function*/ + /* also set PSIN to generate PSOUT*/ + pnp_write_config(dev, PME_ERP_ENABLE_REG, ERP_ENABLE | ERP_PSOUT_EN); + pnp_exit_conf_mode(dev); +} + +static void f81803a_init(struct device *dev) +{ + if (!dev->enabled) + return; + switch (dev->path.pnp.device) { + /* TODO: Might potentially need code for HWM or FDC etc. */ + case F81803A_KBC: + pc_keyboard_init(NO_AUX_DEVICE); + break; + case F81803A_PME: + f81803a_pme_init(dev); + break; + } + +} + +static struct device_operations ops = { + .read_resources = pnp_read_resources, + .set_resources = pnp_set_resources, + .enable_resources = pnp_enable_resources, + .enable = pnp_alt_enable, + .init = f81803a_init, + .ops_pnp_mode = &pnp_conf_mode_8787_aa, +}; + +static struct pnp_info pnp_dev_info[] = { + /* TODO: Some of the 0x7f8 etc. values may not be correct. */ + { &ops, F81803A_SP1, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { &ops, F81803A_SP2, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { &ops, F81803A_HWM, PNP_IO0 | PNP_IRQ0, 0xff8, }, + { &ops, F81803A_KBC, PNP_IO0 | PNP_IRQ0 | PNP_IRQ1, 0x07ff, }, + { &ops, F81803A_GPIO, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + //{ &ops, F81803A_WDT, PNP_IO0, 0x7f8 }, + { &ops, F81803A_PME, }, +}; + +static void enable_dev(struct device *dev) +{ + printk(BIOS_INFO, "F81803A : %s\n", __func__); + pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info); +} + +struct chip_operations superio_fintek_f81803a_ops = { + .enable_dev = enable_dev +};