diff --git a/src/superio/fintek/Makefile.mk b/src/superio/fintek/Makefile.mk index b9cfe4da5a..5e9708f9a9 100644 --- a/src/superio/fintek/Makefile.mk +++ b/src/superio/fintek/Makefile.mk @@ -11,3 +11,4 @@ subdirs-y += f71869ad subdirs-y += f81865f subdirs-y += f81866d subdirs-y += f81803a +subdirs-y += f81966d diff --git a/src/superio/fintek/f81966d/Kconfig b/src/superio/fintek/f81966d/Kconfig new file mode 100644 index 0000000000..3f66f466da --- /dev/null +++ b/src/superio/fintek/f81966d/Kconfig @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config SUPERIO_FINTEK_F81966D + bool + select SUPERIO_FINTEK_COMMON_PRE_RAM diff --git a/src/superio/fintek/f81966d/Makefile.mk b/src/superio/fintek/f81966d/Makefile.mk new file mode 100644 index 0000000000..7016b0c83b --- /dev/null +++ b/src/superio/fintek/f81966d/Makefile.mk @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +ramstage-$(CONFIG_SUPERIO_FINTEK_F81966D) += f81966d_hwm.c f81966d_uart.c f81966d_gpio.c +ramstage-$(CONFIG_SUPERIO_FINTEK_F81966D) += superio.c diff --git a/src/superio/fintek/f81966d/chip.h b/src/superio/fintek/f81966d/chip.h new file mode 100644 index 0000000000..2e75e2434d --- /dev/null +++ b/src/superio/fintek/f81966d/chip.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SUPERIO_FINTEK_F81966D_CHIP_H +#define SUPERIO_FINTEK_F81966D_CHIP_H + +#include + +struct superio_fintek_f81966d_config { + /* AMD TSI */ + uint8_t hwm_amd_tsi_addr; + uint8_t hwm_amd_tsi_control; + + /* Fan control */ + uint8_t hwm_fan_select; + uint8_t hwm_fan_mode; + uint8_t hwm_fan3_control; + uint8_t hwm_fan2_temp_map_select; + + uint8_t hwm_fan2_bound1; + uint8_t hwm_fan2_bound2; + uint8_t hwm_fan2_bound3; + uint8_t hwm_fan2_bound4; + uint8_t hwm_fan2_seg1_speed; + uint8_t hwm_fan2_seg2_speed; + uint8_t hwm_fan2_seg3_speed; + uint8_t hwm_fan2_seg4_speed; + uint8_t hwm_fan2_seg5_speed; + + /* Temp sensor type */ + uint8_t hwm_temp_sens_type; + + /* gpio control, range bits [0:7] map to GPIOx0:GPIOx7 */ + uint8_t use_gpio0; + uint8_t gpio0_enable; + uint8_t gpio0_data; + uint8_t gpio0_drive; + + uint8_t use_gpio1; + uint8_t gpio1_enable; + uint8_t gpio1_data; + uint8_t gpio1_drive; + + uint8_t use_gpio2; + uint8_t gpio2_enable; + uint8_t gpio2_data; + + uint8_t use_gpio3; + uint8_t gpio3_enable; + uint8_t gpio3_data; + uint8_t gpio3_drive; + + uint8_t use_gpio4; + uint8_t gpio4_enable; + uint8_t gpio4_data; + uint8_t gpio4_drive; + + uint8_t use_gpio5; + uint8_t gpio5_enable; + uint8_t gpio5_data; + uint8_t gpio5_drive; + + uint8_t use_gpio6; + uint8_t gpio6_enable; + uint8_t gpio6_data; + uint8_t gpio6_drive; + + uint8_t use_gpio7; + uint8_t gpio7_enable; + uint8_t gpio7_data; + uint8_t gpio7_drive; + + uint8_t use_gpio8; + uint8_t gpio8_enable; + uint8_t gpio8_data; + uint8_t gpio8_drive; + + uint8_t use_gpio9; + uint8_t gpio9_enable; + uint8_t gpio9_data; + uint8_t gpio9_drive; +}; + +#endif /* SUPERIO_FINTEK_F81966D_CHIP_H */ diff --git a/src/superio/fintek/f81966d/f81966d.h b/src/superio/fintek/f81966d/f81966d.h new file mode 100644 index 0000000000..871ce853b7 --- /dev/null +++ b/src/superio/fintek/f81966d/f81966d.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SUPERIO_FINTEK_F81966_H +#define SUPERIO_FINTEK_F81966_H + +/* + * Datasheet: + * - Name: F81966D/A, Release Date: Oct 2023, Version: V0.21P + */ + +/* General registers */ +#define LDN_REG 0x07 +#define PORT_SELECT_REGISTER 0x27 +#define MULTI_FUNC_SEL1_REG 0x28 +#define MULTI_FUNC_SEL3_REG 0x29 +#define GPIO_FUNC_SEL_REG 0x2A /* differs on bank: 0=11/10 1=13/12 2=15/14 3=17/16 */ +#define MULTI_FUNC_SEL4_REG 0x2B +#define MULTI_FUNC_SEL5_REG 0x2C +#define IRQ_SHARE_REGISTER 0xF0 +#define FIFO_SEL_MODE 0xF6 + +/* Logical Device Numbers (LDN) */ +#define F81966D_SP1 0x10 /* UART1 */ +#define F81966D_SP2 0x11 /* UART2 */ +#define F81966D_SP3 0x12 /* UART3 */ +#define F81966D_SP4 0x13 /* UART4 */ +#define F81966D_SP5 0x14 /* UART5 */ +#define F81966D_SP6 0x15 /* UART6 */ +#define F81966D_PP 0x03 /* Parallel Port */ +#define F81966D_HWM 0x04 /* Hardware Monitor */ +#define F81966D_KBC 0x05 /* Keyboard/Mouse */ +#define F81966D_GPIO 0x06 /* General Purpose I/O (GPIO) */ +#define F81966D_WDT 0x07 /* Watchdog */ +#define F81966D_PME 0x0A /* Power Management Events (PME) */ +#define F81966D_SPI 0x0F /* SPI */ + +/* Register addresses for HWM */ +/* Choose between AMD and Intel */ +#define HWM_AMD_TSI_ADDR 0x08 +#define HWM_AMD_TSI_CONTROL_REG 0x0A +/* Set temp sensors type */ +#define TEMP_SENS_TYPE_REG 0x6B +/* FAN prog sel */ +#define HWM_FAN3_CONTROL 0x9A +#define HWM_FAN_SEL 0x94 +#define HWM_FAN_MODE 0x96 +#define HWM_FAN2_TEMP_MAP_SEL 0xBF +/* Fan 2 - 4 Boundaries */ +#define HWM_FAN2_BOUND1 0xB6 +#define HWM_FAN2_BOUND2 0xB7 +#define HWM_FAN2_BOUND3 0xB8 +#define HWM_FAN2_BOUND4 0xB9 +/* Fan 2 - 5 Segment speeds */ +#define HWM_FAN2_SEG1_SPEED_COUNT 0xBA +#define HWM_FAN2_SEG2_SPEED_COUNT 0xBB +#define HWM_FAN2_SEG3_SPEED_COUNT 0xBC +#define HWM_FAN2_SEG4_SPEED_COUNT 0xBD +#define HWM_FAN2_SEG5_SPEED_COUNT 0xBE + +/* Register addresses for GPIO */ +/* GPIO registers */ +#define GPIO0X_OUTPUT_ENABLE_REGISTER 0xF0 +#define GPIO1X_OUTPUT_ENABLE_REGISTER 0xE0 +#define GPIO2X_OUTPUT_ENABLE_REGISTER 0xD0 +#define GPIO3X_OUTPUT_ENABLE_REGISTER 0xC0 +#define GPIO4X_OUTPUT_ENABLE_REGISTER 0xB0 +#define GPIO5X_OUTPUT_ENABLE_REGISTER 0xA0 +#define GPIO6X_OUTPUT_ENABLE_REGISTER 0x90 +#define GPIO7X_OUTPUT_ENABLE_REGISTER 0x80 +#define GPIO8X_OUTPUT_ENABLE_REGISTER 0x88 +#define GPIO9X_OUTPUT_ENABLE_REGISTER 0x98 +#define GPIO0X_OUTPUT_DATA_REGISTER 0xF1 +#define GPIO1X_OUTPUT_DATA_REGISTER 0xE1 +#define GPIO2X_OUTPUT_DATA_REGISTER 0xD1 +#define GPIO3X_OUTPUT_DATA_REGISTER 0xC1 +#define GPIO4X_OUTPUT_DATA_REGISTER 0xB1 +#define GPIO5X_OUTPUT_DATA_REGISTER 0xA1 +#define GPIO6X_OUTPUT_DATA_REGISTER 0x91 +#define GPIO7X_OUTPUT_DATA_REGISTER 0x81 +#define GPIO8X_OUTPUT_DATA_REGISTER 0x89 +#define GPIO9X_OUTPUT_DATA_REGISTER 0x99 +#define GPIO0X_DRIVE_ENABLE_REGISTER 0xF3 +#define GPIO1X_DRIVE_ENABLE_REGISTER 0xE3 +#define GPIO3X_DRIVE_ENABLE_REGISTER 0xC3 +#define GPIO4X_DRIVE_ENABLE_REGISTER 0xB3 +#define GPIO5X_DRIVE_ENABLE_REGISTER 0xA3 +#define GPIO6X_DRIVE_ENABLE_REGISTER 0x93 +#define GPIO7X_DRIVE_ENABLE_REGISTER 0x83 +#define GPIO8X_DRIVE_ENABLE_REGISTER 0x8B +#define GPIO9X_DRIVE_ENABLE_REGISTER 0x9B + +#endif /* SUPERIO_FINTEK_F81966_H */ diff --git a/src/superio/fintek/f81966d/f81966d_gpio.c b/src/superio/fintek/f81966d/f81966d_gpio.c new file mode 100644 index 0000000000..32180c5963 --- /dev/null +++ b/src/superio/fintek/f81966d/f81966d_gpio.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include "fintek_internal.h" +#include "chip.h" +#include "f81966d.h" + +/* + * Set the values for the register using the mask + * The mask has the writable bits high so the write the bits [3:2] & [0] the mask would be + * 0xd = 0b00001101. + */ +void set_reg(struct device *dev, u8 port, u8 mask, u8 val) +{ + u8 tmp = pnp_read_config(dev, port); + pnp_write_config(dev, port, (tmp & ~mask) | (val & mask)); +} + +/* + * Select a bank as indicated by the spec. + * Write the BANKID and 0 registers in the same call. + */ +u8 select_bank(struct device *dev, u8 bank) +{ + if (bank > 3) { + printk(BIOS_WARNING, "%s: GPIO Bank not in range.\n", __func__); + return -1; + } + /* write 0x27[3:2] = BANKID, 0x27[0] = 0 */ + set_reg(dev, PORT_SELECT_REGISTER, 0x0D, (bank << 2)); + return 0; +} + +/* + * F81966D_gpio_init enables all necessary registers for GPIO + * Fintek needs to know if pins are used as GPIO or UART pins + * Share interrupt usage needs to be enabled + */ +void f81966d_gpio_init(struct device *dev) +{ + struct superio_fintek_f81966d_config *conf = dev->chip_info; + struct resource *res = probe_resource(dev, PNP_IDX_IO0); + u8 tmp; + + if (!res) { + printk(BIOS_WARNING, "%s: No GPIO resource found.\n", __func__); + return; + } + + pnp_enter_conf_mode(dev); + + if (conf->use_gpio0) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0x1F, 0x1F); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x0C, 0x00); + + select_bank(dev, 1); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0x44, 0x0); + + set_reg(dev, GPIO0X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio0_enable); + set_reg(dev, GPIO0X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio0_data); + set_reg(dev, GPIO0X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio0_drive); + } + + if (conf->use_gpio1) { + select_bank(dev, 0); + set_reg(dev, GPIO_FUNC_SEL_REG, 0x77, 0x000); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x8C, 0x00); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0x10, 0x0); + + select_bank(dev, 1); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0x21, 0x0); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x0C, 0x00); + set_reg(dev, GPIO_FUNC_SEL_REG, 0x77, 0x000); + + select_bank(dev, 2); + set_reg(dev, GPIO_FUNC_SEL_REG, 0x77, 0x000); + + select_bank(dev, 3); + set_reg(dev, GPIO_FUNC_SEL_REG, 0x77, 0x000); + + set_reg(dev, GPIO1X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio1_enable); + set_reg(dev, GPIO1X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio1_data); + set_reg(dev, GPIO1X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio1_drive); + } + + if (conf->use_gpio2) { + select_bank(dev, 2); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0xFF, 0xFF); + select_bank(dev, 1); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0x02, 0x0); + + set_reg(dev, GPIO2X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio2_enable); + set_reg(dev, GPIO2X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio2_data); + } + + if (conf->use_gpio3) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL3_REG, 0x30, 0x00); + + set_reg(dev, GPIO3X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio3_enable); + set_reg(dev, GPIO3X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio3_data); + set_reg(dev, GPIO3X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio3_drive); + } + + if (conf->use_gpio4) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL3_REG, 0xC0, 0x00); + + set_reg(dev, GPIO4X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio4_enable); + set_reg(dev, GPIO4X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio4_data); + set_reg(dev, GPIO4X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio4_drive); + } + + if (conf->use_gpio5) { + set_reg(dev, PORT_SELECT_REGISTER, 0x02, 0x00); + + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x03, 0x00); + select_bank(dev, 1); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x10, 0x00); + + /* set in/output pins */ + set_reg(dev, GPIO5X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio5_enable); + set_reg(dev, GPIO5X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio5_data); + set_reg(dev, GPIO5X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio5_drive); + } + + if (conf->use_gpio6) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x0C, 0x00); + set_reg(dev, MULTI_FUNC_SEL4_REG, 0xE0, 0xE0); + + set_reg(dev, GPIO6X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio6_enable); + set_reg(dev, GPIO6X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio6_data); + set_reg(dev, GPIO6X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio6_drive); + } + + if (conf->use_gpio7) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x20, 0x20); + set_reg(dev, MULTI_FUNC_SEL4_REG, 0x01, 0x00); + + set_reg(dev, GPIO7X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio7_enable); + set_reg(dev, GPIO7X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio7_data); + set_reg(dev, GPIO7X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio7_drive); + } + + if (conf->use_gpio8) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL1_REG, 0x60, 0x20); + + set_reg(dev, GPIO8X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio8_enable); + set_reg(dev, GPIO8X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio8_data); + set_reg(dev, GPIO8X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio8_drive); + } + + if (conf->use_gpio9) { + select_bank(dev, 0); + set_reg(dev, MULTI_FUNC_SEL4_REG, 0x02, 0x00); + select_bank(dev, 1); + set_reg(dev, MULTI_FUNC_SEL5_REG, 0x80, 0x00); + select_bank(dev, 3); + set_reg(dev, MULTI_FUNC_SEL4_REG, 0xFF, 0xFF); + + set_reg(dev, GPIO9X_OUTPUT_ENABLE_REGISTER, 0xFF, conf->gpio8_enable); + set_reg(dev, GPIO9X_OUTPUT_DATA_REGISTER, 0xFF, conf->gpio8_data); + set_reg(dev, GPIO9X_DRIVE_ENABLE_REGISTER, 0xFF, conf->gpio8_drive); + } + + /* Select GPIO in LDN register */ + pnp_write_config(dev, LDN_REG, dev->path.pnp.device & 0xFF); + /* Set IRQ trigger mode from active low to high (Bit 3) */ + tmp = pnp_read_config(dev, FIFO_SEL_MODE); + pnp_write_config(dev, FIFO_SEL_MODE, tmp | 0x8); + /* Enable share interrupt (Bit 0) */ + pnp_write_config(dev, IRQ_SHARE_REGISTER, 0x01); + + pnp_exit_conf_mode(dev); +} diff --git a/src/superio/fintek/f81966d/f81966d_hwm.c b/src/superio/fintek/f81966d/f81966d_hwm.c new file mode 100644 index 0000000000..1e995a92ac --- /dev/null +++ b/src/superio/fintek/f81966d/f81966d_hwm.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* Setup only for Fan2 + * TODO: Add support for Fan1 and Fan3 + */ + +#include +#include +#include +#include +#include "fintek_internal.h" +#include "chip.h" +#include "f81966d.h" + +void f81966d_hwm_init(struct device *dev) +{ + struct resource *res = probe_resource(dev, PNP_IDX_IO0); + + if (!res) { + printk(BIOS_WARNING, "Super I/O HWM: No HWM resource found.\n"); + return; + } + + const struct superio_fintek_f81966d_config *reg = dev->chip_info; + u16 port = res->base; + + /* Use AMD TSI */ + pnp_write_hwm5_index(port, HWM_AMD_TSI_ADDR, reg->hwm_amd_tsi_addr); + pnp_write_hwm5_index(port, HWM_AMD_TSI_CONTROL_REG, reg->hwm_amd_tsi_control); + + /* Set temp1 sensor to thermistor */ + pnp_write_hwm5_index(port, TEMP_SENS_TYPE_REG, reg->hwm_temp_sens_type); + + /* Select FAN Type */ + pnp_write_hwm5_index(port, HWM_FAN_SEL, reg->hwm_fan_select); + + /* Select FAN Mode*/ + pnp_write_hwm5_index(port, HWM_FAN_MODE, reg->hwm_fan_mode); + + /* Set Boundaries */ + pnp_write_hwm5_index(port, HWM_FAN2_BOUND1, reg->hwm_fan2_bound1); + pnp_write_hwm5_index(port, HWM_FAN2_BOUND2, reg->hwm_fan2_bound2); + pnp_write_hwm5_index(port, HWM_FAN2_BOUND3, reg->hwm_fan2_bound3); + pnp_write_hwm5_index(port, HWM_FAN2_BOUND4, reg->hwm_fan2_bound4); + + /* Set Speed */ + pnp_write_hwm5_index(port, HWM_FAN2_SEG1_SPEED_COUNT, reg->hwm_fan2_seg1_speed); + pnp_write_hwm5_index(port, HWM_FAN2_SEG2_SPEED_COUNT, reg->hwm_fan2_seg2_speed); + pnp_write_hwm5_index(port, HWM_FAN2_SEG3_SPEED_COUNT, reg->hwm_fan2_seg3_speed); + pnp_write_hwm5_index(port, HWM_FAN2_SEG4_SPEED_COUNT, reg->hwm_fan2_seg4_speed); + pnp_write_hwm5_index(port, HWM_FAN2_SEG5_SPEED_COUNT, reg->hwm_fan2_seg5_speed); + + /* Set Fan control freq */ + pnp_write_hwm5_index(port, HWM_FAN3_CONTROL, reg->hwm_fan3_control); + pnp_write_hwm5_index(port, HWM_FAN2_TEMP_MAP_SEL, reg->hwm_fan2_temp_map_select); +} diff --git a/src/superio/fintek/f81966d/f81966d_uart.c b/src/superio/fintek/f81966d/f81966d_uart.c new file mode 100644 index 0000000000..8c2b69722d --- /dev/null +++ b/src/superio/fintek/f81966d/f81966d_uart.c @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include "fintek_internal.h" +#include "chip.h" +#include "f81966d.h" + +/* + * F81966D_uart_init enables all necessary registers for UART 3/4 + * Fintek needs to know if pins are used as GPIO or UART pins + * Share interrupt usage needs to be enabled + */ +void f81966d_uart_init(struct device *dev) +{ + struct resource *res = probe_resource(dev, PNP_IDX_IO0); + u8 tmp; + + if (!res) { + printk(BIOS_WARNING, "%s: No UART resource found.\n", __func__); + return; + } + + pnp_enter_conf_mode(dev); + + /* + * Set Port Select Register (Bit 0) = 0 + * before accessing Multi Function Select 3 Register + */ + tmp = pnp_read_config(dev, PORT_SELECT_REGISTER); + pnp_write_config(dev, PORT_SELECT_REGISTER, tmp & 0xFE); + + /* Set UART 3 function (Bit 4/5), otherwise pin 36-43 are GPIO */ + if (dev->path.pnp.device == F81966D_SP3) { + tmp = pnp_read_config(dev, MULTI_FUNC_SEL3_REG); + pnp_write_config(dev, MULTI_FUNC_SEL3_REG, tmp | 0x30); + } + + /* Set UART 4 function (Bit 6/7), otherwise pin 44-51 are GPIO */ + if (dev->path.pnp.device == F81966D_SP4) { + tmp = pnp_read_config(dev, MULTI_FUNC_SEL3_REG); + pnp_write_config(dev, MULTI_FUNC_SEL3_REG, tmp | 0xC0); + } + + /* Select UART X in LDN register */ + pnp_write_config(dev, LDN_REG, dev->path.pnp.device & 0xff); + /* Set IRQ trigger mode from active low to high (Bit 3) */ + tmp = pnp_read_config(dev, FIFO_SEL_MODE); + pnp_write_config(dev, FIFO_SEL_MODE, tmp | 0x8); + /* Enable share interrupt (Bit 0) */ + pnp_write_config(dev, IRQ_SHARE_REGISTER, 0x01); + + pnp_exit_conf_mode(dev); +} diff --git a/src/superio/fintek/f81966d/fintek_internal.h b/src/superio/fintek/f81966d/fintek_internal.h new file mode 100644 index 0000000000..0e2142f925 --- /dev/null +++ b/src/superio/fintek/f81966d/fintek_internal.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef SUPERIO_FINTEK_F81966D_INTERNAL_H +#define SUPERIO_FINTEK_F81966D_INTERNAL_H + +#include + +void f81966d_hwm_init(struct device *dev); +void f81966d_uart_init(struct device *dev); +void f81966d_gpio_init(struct device *dev); + +void set_reg(struct device *dev, u8 port, u8 mask, u8 val); +u8 select_bank(struct device *dev, u8 bank); + +#endif /* SUPERIO_FINTEK_F81966D_INTERNAL_H */ diff --git a/src/superio/fintek/f81966d/superio.c b/src/superio/fintek/f81966d/superio.c new file mode 100644 index 0000000000..a3b5527c85 --- /dev/null +++ b/src/superio/fintek/f81966d/superio.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include + +#include "chip.h" +#include "fintek_internal.h" +#include "f81966d.h" + +static void f81966d_init(struct device *dev) +{ + if (!dev->enabled) + return; + + switch (dev->path.pnp.device) { + case F81966D_KBC: + pc_keyboard_init(NO_AUX_DEVICE); + break; + case F81966D_HWM: + /* Fixing temp sensor read out and init Fan control */ + f81966d_hwm_init(dev); + break; + case F81966D_SP1: + /* Enable Uart1 and IRQ share register */ + f81966d_uart_init(dev); + break; + case F81966D_SP2: + /* Enable Uart2 and IRQ share register */ + f81966d_uart_init(dev); + break; + case F81966D_SP3: + /* Enable Uart3 and IRQ share register */ + f81966d_uart_init(dev); + break; + case F81966D_SP4: + /* Enable Uart4 and IRQ share register */ + f81966d_uart_init(dev); + break; + case F81966D_GPIO: + /* Enable GPIO */ + f81966d_gpio_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 = f81966d_init, + .ops_pnp_mode = &pnp_conf_mode_8787_aa, +}; + +static struct pnp_info pnp_dev_info[] = { + /* TODO: some of the 0x7f8 values may need to be corrected. */ + { NULL, F81966D_SP1, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { NULL, F81966D_SP2, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { NULL, F81966D_SP3, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { NULL, F81966D_SP4, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { NULL, F81966D_SP5, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { NULL, F81966D_SP6, PNP_IO0 | PNP_IRQ0, 0x7f8, }, + { NULL, F81966D_KBC, PNP_IO0 | PNP_IRQ0 | PNP_IRQ1, 0x07ff, }, + { NULL, F81966D_PP, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, 0x07f8, }, + { NULL, F81966D_HWM, PNP_IO0 | PNP_IRQ0, 0xff8, }, + { NULL, F81966D_GPIO, PNP_IO0, 0xff8, }, + { NULL, F81966D_PME, }, + { NULL, F81966D_WDT, }, + { NULL, F81966D_SPI, }, +}; + +static void enable_dev(struct device *dev) +{ + pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info); +} + +struct chip_operations superio_fintek_f81966d_ops = { + .name = "Fintek F81966D-I Super I/O", + .enable_dev = enable_dev +};