diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mainboard/hp/compaq_8200_elite_sff/cmos.default | 1 | ||||
-rw-r--r-- | src/mainboard/hp/compaq_8200_elite_sff/cmos.layout | 4 | ||||
-rw-r--r-- | src/superio/nuvoton/npcd378/npcd378.h | 44 | ||||
-rw-r--r-- | src/superio/nuvoton/npcd378/superio.c | 64 |
4 files changed, 111 insertions, 2 deletions
diff --git a/src/mainboard/hp/compaq_8200_elite_sff/cmos.default b/src/mainboard/hp/compaq_8200_elite_sff/cmos.default index 390d231fb1..1d88415039 100644 --- a/src/mainboard/hp/compaq_8200_elite_sff/cmos.default +++ b/src/mainboard/hp/compaq_8200_elite_sff/cmos.default @@ -4,3 +4,4 @@ power_on_after_fail=Enable nmi=Enable sata_mode=AHCI gfx_uma_size=32M +psu_fan_lvl=3 diff --git a/src/mainboard/hp/compaq_8200_elite_sff/cmos.layout b/src/mainboard/hp/compaq_8200_elite_sff/cmos.layout index e90af85a09..f2d2331e63 100644 --- a/src/mainboard/hp/compaq_8200_elite_sff/cmos.layout +++ b/src/mainboard/hp/compaq_8200_elite_sff/cmos.layout @@ -51,7 +51,9 @@ entries # coreboot config options: console #392 3 r 0 unused 395 4 e 6 debug_level -#399 9 r 0 unused +#399 1 r 0 unused +400 3 h 0 psu_fan_lvl +#403 5 r 0 unused # coreboot config options: southbridge 408 1 e 1 nmi diff --git a/src/superio/nuvoton/npcd378/npcd378.h b/src/superio/nuvoton/npcd378/npcd378.h index 732dd000f3..53541a9efb 100644 --- a/src/superio/nuvoton/npcd378/npcd378.h +++ b/src/superio/nuvoton/npcd378/npcd378.h @@ -17,6 +17,50 @@ #ifndef SUPERIO_NUVOTON_NPCD378_H #define SUPERIO_NUVOTON_NPCD378_H +/* HWM at LDN8 */ +#define NPCD837_HWM_WRITE_LOCK_CTRL 0x4 +#define NPCD837_HWM_WRITE_LOCK_BIT 0x1 + +#define NPCD378_HWM_PSU_FAN_MIN 0x17 +#define NPCD378_HWM_PSU_FAN_MAX 0xf8 +#define NPCD378_HWM_PSU_FAN_PWM_CTRL 0x198 + +/* + * Read HWM register at specific page and offset. + * + * @param iobase IOBASE address of LDN8 + * @param reg MSB is page, LSB sets the offset in selected page + * + * @return Byte read from HWM + */ +uint8_t npcd378_hwm_read(const uint16_t iobase, const uint16_t reg); + +/* + * Write to HWM register at specific page and offset. + * + * @param iobase IOBASE address of LDN8 + * @param reg MSB is page, LSB sets the offset in selected page + * @param val The value to write to HWM register + */ +void npcd378_hwm_write(const uint16_t iobase, const uint16_t reg, + const uint8_t val); + +/* + * Notify SuperIO a host-to-device transfer is ongoing. + * Has to be called before any register in HWM is written to. + * + * @param iobase IOBASE address of LDN8 + */ +void npcd378_hwm_write_start(const uint16_t iobase); + +/* + * Notify SuperIO a host-to-device transfer has finished. + * Has to be called after any register in HWM was written to. + * + * @param iobase IOBASE address of LDN8 + */ +void npcd378_hwm_write_finished(const uint16_t iobase); + /* Logical Device Numbers (LDN). */ /* Default Nuvoton hardware: */ #define NPCD378_FDC 0x00 /* Floppy */ diff --git a/src/superio/nuvoton/npcd378/superio.c b/src/superio/nuvoton/npcd378/superio.c index d468884c82..013225de32 100644 --- a/src/superio/nuvoton/npcd378/superio.c +++ b/src/superio/nuvoton/npcd378/superio.c @@ -18,24 +18,86 @@ */ #include <arch/io.h> +#include <console/console.h> #include <device/device.h> #include <device/pnp.h> +#include <option.h> #include <pc80/keyboard.h> #include <stdlib.h> #include <superio/conf_mode.h> #include "npcd378.h" +uint8_t npcd378_hwm_read(const uint16_t iobase, const uint16_t reg) +{ + outb((reg >> 8) & 0xf, iobase + 0xff); + uint8_t reg8 = inb(iobase + (reg & 0xff)); + if (reg8 == 0xff) + reg8 = inb(iobase + (reg & 0xff)); + + outb(0, iobase + 0xff); + return reg8; +} + +void npcd378_hwm_write(const uint16_t iobase, const uint16_t reg, + const uint8_t val) +{ + outb((reg >> 8) & 0xf, iobase + 0xff); + outb(val, iobase + (reg & 0xff)); + + outb(0, iobase + 0xff); +} + +void npcd378_hwm_write_start(const uint16_t iobase) +{ + u8 reg8 = npcd378_hwm_read(iobase, NPCD837_HWM_WRITE_LOCK_CTRL); + reg8 &= ~NPCD837_HWM_WRITE_LOCK_BIT; + npcd378_hwm_write(iobase, NPCD837_HWM_WRITE_LOCK_CTRL, reg8); +} + +void npcd378_hwm_write_finished(const uint16_t iobase) +{ + u8 reg8 = npcd378_hwm_read(iobase, NPCD837_HWM_WRITE_LOCK_CTRL); + reg8 |= NPCD837_HWM_WRITE_LOCK_BIT; + npcd378_hwm_write(iobase, NPCD837_HWM_WRITE_LOCK_CTRL, reg8); +} + static void npcd378_init(struct device *dev) { + struct resource *res; + uint8_t pwm, fan_lvl; + if (!dev->enabled) return; switch (dev->path.pnp.device) { - /* TODO: Might potentially need code for HWM or FDC etc. */ + /* TODO: Might potentially need code for FDC etc. */ case NPCD378_KBC: pc_keyboard_init(PROBE_AUX_DEVICE); break; + case NPCD378_HWM: + res = find_resource(dev, PNP_IDX_IO0); + if (!res || !res->base) { + printk(BIOS_ERR, "NPCD378: LDN%u IOBASE not set.\n", + NPCD378_HWM); + break; + } + + npcd378_hwm_write_start(res->base); + + if (!get_option(&fan_lvl, "psu_fan_lvl") || fan_lvl > 7) + fan_lvl = 3; + + pwm = NPCD378_HWM_PSU_FAN_MIN + + (NPCD378_HWM_PSU_FAN_MAX - NPCD378_HWM_PSU_FAN_MIN) * + fan_lvl / 7; + + /* Set PSU fan PWM lvl */ + npcd378_hwm_write(res->base, NPCD378_HWM_PSU_FAN_PWM_CTRL, pwm); + printk(BIOS_INFO, "NPCD378: PSU fan PWM 0x%02x\n", pwm); + + npcd378_hwm_write_finished(res->base); + break; } } |