2 * This file is part of the coreboot project.
4 * Copyright (C) 2011 Advanced Micro Devices, Inc.
5 * Copyright (C) 2014 Felix Held <felix-coreboot@felixheld.de>
6 * Copyright (C) 2014 Edward O'Callaghan <eocallaghan@alterapraxis.com>
7 * Copyright (C) 2018 Patrick Rudolph <siro@das-labor.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
21 #include <console/console.h>
22 #include <device/device.h>
23 #include <device/pnp.h>
25 #include <pc80/keyboard.h>
27 #include <superio/conf_mode.h>
31 uint8_t npcd378_hwm_read(const uint16_t iobase
, const uint16_t reg
)
33 outb((reg
>> 8) & 0xf, iobase
+ 0xff);
34 uint8_t reg8
= inb(iobase
+ (reg
& 0xff));
36 reg8
= inb(iobase
+ (reg
& 0xff));
38 outb(0, iobase
+ 0xff);
42 void npcd378_hwm_write(const uint16_t iobase
, const uint16_t reg
,
45 outb((reg
>> 8) & 0xf, iobase
+ 0xff);
46 outb(val
, iobase
+ (reg
& 0xff));
48 outb(0, iobase
+ 0xff);
51 void npcd378_hwm_write_start(const uint16_t iobase
)
53 u8 reg8
= npcd378_hwm_read(iobase
, NPCD837_HWM_WRITE_LOCK_CTRL
);
54 reg8
&= ~NPCD837_HWM_WRITE_LOCK_BIT
;
55 npcd378_hwm_write(iobase
, NPCD837_HWM_WRITE_LOCK_CTRL
, reg8
);
58 void npcd378_hwm_write_finished(const uint16_t iobase
)
60 u8 reg8
= npcd378_hwm_read(iobase
, NPCD837_HWM_WRITE_LOCK_CTRL
);
61 reg8
|= NPCD837_HWM_WRITE_LOCK_BIT
;
62 npcd378_hwm_write(iobase
, NPCD837_HWM_WRITE_LOCK_CTRL
, reg8
);
65 static void npcd378_init(struct device
*dev
)
73 switch (dev
->path
.pnp
.device
) {
74 /* TODO: Might potentially need code for FDC etc. */
76 pc_keyboard_init(PROBE_AUX_DEVICE
);
79 res
= find_resource(dev
, PNP_IDX_IO0
);
80 if (!res
|| !res
->base
) {
81 printk(BIOS_ERR
, "NPCD378: LDN%u IOBASE not set.\n",
86 npcd378_hwm_write_start(res
->base
);
88 if (!get_option(&fan_lvl
, "psu_fan_lvl") || fan_lvl
> 7)
91 pwm
= NPCD378_HWM_PSU_FAN_MIN
+
92 (NPCD378_HWM_PSU_FAN_MAX
- NPCD378_HWM_PSU_FAN_MIN
) *
95 /* Set PSU fan PWM lvl */
96 npcd378_hwm_write(res
->base
, NPCD378_HWM_PSU_FAN_PWM_CTRL
, pwm
);
97 printk(BIOS_INFO
, "NPCD378: PSU fan PWM 0x%02x\n", pwm
);
99 npcd378_hwm_write_finished(res
->base
);
104 static struct device_operations ops
= {
105 .read_resources
= pnp_read_resources
,
106 .set_resources
= pnp_set_resources
,
107 .enable_resources
= pnp_enable_resources
,
108 .enable
= pnp_alt_enable
,
109 .init
= npcd378_init
,
110 .ops_pnp_mode
= &pnp_conf_mode_8787_aa
,
113 static struct pnp_info pnp_dev_info
[] = {
114 { &ops
, NPCD378_FDC
, PNP_IO0
|PNP_IRQ0
|PNP_DRQ0
, 0x0ff8, },
115 { &ops
, NPCD378_PP
, PNP_IO0
|PNP_IRQ0
|PNP_DRQ0
, 0x0ff8, },
116 { &ops
, NPCD378_SP1
, PNP_IO0
|PNP_IRQ0
, 0x0ff8, },
117 { &ops
, NPCD378_SP2
, PNP_IO0
|PNP_IRQ0
, 0x0ff8, },
118 { &ops
, NPCD378_PWR
, PNP_IO0
|PNP_IO1
|PNP_IRQ0
|PNP_MSC0
|
119 PNP_MSC1
|PNP_MSC2
|PNP_MSC3
|PNP_MSC4
|PNP_MSC5
|PNP_MSC6
|PNP_MSC7
|
120 PNP_MSC8
|PNP_MSC9
|PNP_MSCA
|PNP_MSCB
|PNP_MSCC
|PNP_MSCD
|PNP_MSCE
,
122 { &ops
, NPCD378_AUX
, PNP_IRQ0
, 0x0fff, 0x0fff, },
123 { &ops
, NPCD378_KBC
, PNP_IO0
|PNP_IO1
|PNP_IRQ0
,
125 { &ops
, NPCD378_WDT1
, PNP_IO0
|PNP_MSC8
|PNP_MSC9
|
126 PNP_MSCA
|PNP_MSCB
|PNP_MSCC
|PNP_MSCD
|PNP_MSCE
, 0x0ff8},
127 { &ops
, NPCD378_HWM
, PNP_IO0
|PNP_MSC0
|PNP_MSC1
|PNP_MSC2
|PNP_MSC3
|
128 PNP_MSC4
|PNP_MSC5
|PNP_MSC6
|PNP_MSC7
|PNP_IRQ0
, 0x0ff8},
129 { &ops
, NPCD378_GPIO_PP_OD
, PNP_MSC0
|PNP_MSC1
|PNP_MSC2
|PNP_MSC3
|
130 PNP_MSC4
|PNP_MSC5
|PNP_MSC6
|PNP_MSC7
|PNP_MSC8
|PNP_MSC9
|PNP_MSCA
|
131 PNP_MSCB
|PNP_MSCC
|PNP_MSCD
|PNP_MSCE
},
132 { &ops
, NPCD378_I2C
, PNP_IO0
|PNP_IO1
|PNP_IRQ0
|PNP_MSC0
|
133 PNP_MSC1
|PNP_MSC2
|PNP_MSC3
|PNP_MSC4
|PNP_MSC5
|PNP_MSC6
|PNP_MSC7
|
134 PNP_MSC8
|PNP_MSC9
|PNP_MSCA
|PNP_MSCB
|PNP_MSCC
|PNP_MSCD
|PNP_MSCE
,
136 { &ops
, NPCD378_SUSPEND
, PNP_IO0
, 0x0ff8 },
137 { &ops
, NPCD378_GPIOA
, PNP_IO0
|PNP_MSC0
|PNP_MSC1
|PNP_MSC2
|PNP_MSC3
|
141 static void enable_dev(struct device
*dev
)
143 pnp_enable_devices(dev
, &ops
, ARRAY_SIZE(pnp_dev_info
), pnp_dev_info
);
146 struct chip_operations superio_nuvoton_npcd378_ops
= {
147 CHIP_NAME("NUVOTON NPCD378 Super I/O")
148 .enable_dev
= enable_dev
,