blob: 30368e8f91a47125455aad8b79cb57cc9eac0141 [file] [log] [blame]
Stefan Reinauer36a22682008-10-29 04:52:57 +00001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00004 * Copyright (C) 2007-2009 coresystems GmbH
Stefan Reinauer36a22682008-10-29 04:52:57 +00005 *
Uwe Hermann2bb4acf2010-03-01 17:19:55 +00006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
Stefan Reinauer36a22682008-10-29 04:52:57 +00009 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Stefan Reinauer36a22682008-10-29 04:52:57 +000014 */
15
Arthur Heymanscf278382018-12-16 01:04:24 +010016#include <string.h>
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000017#include <types.h>
Stefan Reinauer36a22682008-10-29 04:52:57 +000018#include <device/device.h>
Stefan Reinauer3c7f46b2009-02-27 23:09:55 +000019#include <console/console.h>
Vladimir Serbinenkoa2a906e2014-09-01 01:41:37 +020020#include <drivers/intel/gma/int15.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +020021#include <option.h>
Elyes HAOUASedfe1252019-10-08 21:44:02 +020022#include <superio/hwm5_conf.h>
Felix Held35103fd2019-12-15 12:11:44 +010023#include <superio/nuvoton/common/hwm.h>
Stefan Reinauer36a22682008-10-29 04:52:57 +000024
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000025/* Hardware Monitor */
26
27static u16 hwm_base = 0xa00;
28
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000029#define FAN_CRUISE_CONTROL_DISABLED 0
30#define FAN_CRUISE_CONTROL_SPEED 1
31#define FAN_CRUISE_CONTROL_THERMAL 2
32
33#define FAN_SPEED_5625 0
Elyes HAOUASf10b5ff2016-10-06 19:49:55 +020034
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000035
36struct fan_speed {
37 u8 fan_in;
38 u16 fan_speed;
39};
40
Elyes HAOUASf10b5ff2016-10-06 19:49:55 +020041/* FANIN Target Speed Register */
42/* FANIN = 337500 / RPM */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000043struct fan_speed fan_speeds[] = {
44 { 0x3c, 5625 }, { 0x41, 5192 }, { 0x47, 4753 }, { 0x4e, 4326 },
45 { 0x56, 3924 }, { 0x5f, 3552 }, { 0x69, 3214 }, { 0x74, 2909 },
46 { 0x80, 2636 }, { 0x8d, 2393 }, { 0x9b, 2177 }, { 0xaa, 1985 },
47 { 0xba, 1814 }, { 0xcb, 1662 }, { 0xdd, 1527 }, { 0xf0, 1406 }
48};
49
50struct temperature {
51 u8 deg_celsius;
52 u8 deg_fahrenheit;
53};
54
55struct temperature temperatures[] = {
Stefan Reinauer14e22772010-04-27 06:56:47 +000056 { 30, 86 }, { 33, 91 }, { 36, 96 }, { 39, 102 },
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000057 { 42, 107 }, { 45, 113 }, { 48, 118 }, { 51, 123 },
58 { 54, 129 }, { 57, 134 }, { 60, 140 }, { 63, 145 },
59 { 66, 150 }, { 69, 156 }, { 72, 161 }, { 75, 167 }
60};
61
62static void hwm_setup(void)
63{
64 int cpufan_control = 0, sysfan_control = 0;
65 int cpufan_speed = 0, sysfan_speed = 0;
66 int cpufan_temperature = 0, sysfan_temperature = 0;
67
Varad Gautam06ef0462015-03-11 09:54:41 +053068 cpufan_control = FAN_CRUISE_CONTROL_DISABLED;
69 get_option(&cpufan_control, "cpufan_cruise_control");
70 cpufan_speed = FAN_SPEED_5625;
71 get_option(&cpufan_speed, "cpufan_speed");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000072
Varad Gautam06ef0462015-03-11 09:54:41 +053073 sysfan_control = FAN_CRUISE_CONTROL_DISABLED;
74 get_option(&sysfan_control, "sysfan_cruise_control");
75 sysfan_speed = FAN_SPEED_5625;
76 get_option(&sysfan_speed, "sysfan_speed");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000077
Felix Held35103fd2019-12-15 12:11:44 +010078 nuvoton_hwm_select_bank(hwm_base, 0);
Elyes HAOUASedfe1252019-10-08 21:44:02 +020079 pnp_write_hwm5_index(hwm_base, 0x59, 0x20); /* Diode Selection */
80 pnp_write_hwm5_index(hwm_base, 0x5d, 0x0f); /* All Sensors Diode, not Thermistor */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000081
Felix Held35103fd2019-12-15 12:11:44 +010082 nuvoton_hwm_select_bank(hwm_base, 4);
Elyes HAOUASedfe1252019-10-08 21:44:02 +020083 pnp_write_hwm5_index(hwm_base, 0x54, 0xf1); /* SYSTIN temperature offset */
84 pnp_write_hwm5_index(hwm_base, 0x55, 0x19); /* CPUTIN temperature offset */
85 pnp_write_hwm5_index(hwm_base, 0x56, 0xfc); /* AUXTIN temperature offset */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000086
Felix Held35103fd2019-12-15 12:11:44 +010087 nuvoton_hwm_select_bank(hwm_base, 0x80); /* Default */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000088
89 u8 fan_config = 0;
Elyes HAOUASf10b5ff2016-10-06 19:49:55 +020090 /* 00 FANOUT is Manual Mode */
91 /* 01 FANOUT is Thermal Cruise Mode */
92 /* 10 FANOUT is Fan Speed Cruise Mode */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +000093 switch (cpufan_control) {
94 case FAN_CRUISE_CONTROL_SPEED: fan_config |= (2 << 4); break;
95 case FAN_CRUISE_CONTROL_THERMAL: fan_config |= (1 << 4); break;
96 }
97 switch (sysfan_control) {
98 case FAN_CRUISE_CONTROL_SPEED: fan_config |= (2 << 2); break;
99 case FAN_CRUISE_CONTROL_THERMAL: fan_config |= (1 << 2); break;
100 }
Elyes HAOUASf10b5ff2016-10-06 19:49:55 +0200101 /* This register must be written first */
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200102 pnp_write_hwm5_index(hwm_base, 0x04, fan_config);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000103
104 switch (cpufan_control) {
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200105 case FAN_CRUISE_CONTROL_SPEED: /* CPUFANIN target speed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000106 printk(BIOS_DEBUG, "Fan Cruise Control setting CPU fan to %d RPM\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000107 fan_speeds[cpufan_speed].fan_speed);
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200108 pnp_write_hwm5_index(hwm_base, 0x06, fan_speeds[cpufan_speed].fan_in);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000109 break;
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200110 case FAN_CRUISE_CONTROL_THERMAL: /* CPUFANIN target temperature */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000111 printk(BIOS_DEBUG, "Fan Cruise Control setting CPU fan to activation at %d deg C/%d deg F\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000112 temperatures[cpufan_temperature].deg_celsius,
113 temperatures[cpufan_temperature].deg_fahrenheit);
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200114 pnp_write_hwm5_index(hwm_base, 0x06,
115 temperatures[cpufan_temperature].deg_celsius);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000116 break;
117 }
118
119 switch (sysfan_control) {
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200120 case FAN_CRUISE_CONTROL_SPEED: /* SYSFANIN target speed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000121 printk(BIOS_DEBUG, "Fan Cruise Control setting system fan to %d RPM\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000122 fan_speeds[sysfan_speed].fan_speed);
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200123 pnp_write_hwm5_index(hwm_base, 0x05, fan_speeds[sysfan_speed].fan_in);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000124 break;
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200125 case FAN_CRUISE_CONTROL_THERMAL: /* SYSFANIN target temperature */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000126 printk(BIOS_DEBUG, "Fan Cruise Control setting system fan to activation at %d deg C/%d deg F\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000127 temperatures[sysfan_temperature].deg_celsius,
128 temperatures[sysfan_temperature].deg_fahrenheit);
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200129 pnp_write_hwm5_index(hwm_base, 0x05,
130 temperatures[sysfan_temperature].deg_celsius);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000131 break;
132 }
133
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200134 pnp_write_hwm5_index(hwm_base, 0x0e, 0x02); /* Fan Output Step Down Time */
135 pnp_write_hwm5_index(hwm_base, 0x0f, 0x02); /* Fan Output Step Up Time */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000136
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200137 pnp_write_hwm5_index(hwm_base, 0x47, 0xaf); /* FAN divisor register */
138 pnp_write_hwm5_index(hwm_base, 0x4b, 0x84); /* AUXFANIN speed divisor */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000139
Elyes HAOUASedfe1252019-10-08 21:44:02 +0200140 pnp_write_hwm5_index(hwm_base, 0x40, 0x01); /* Init, but no SMI# */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000141}
142
Elyes HAOUASf10b5ff2016-10-06 19:49:55 +0200143/* mainboard_enable is executed as first thing after */
144/* enumerate_buses(). */
Stefan Reinauerc6f2bd02010-01-19 21:15:01 +0000145
Elyes HAOUASf65f297e2018-05-04 22:09:07 +0200146static void mainboard_enable(struct device *dev)
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000147{
Vladimir Serbinenkoa2a906e2014-09-01 01:41:37 +0200148 install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, GMA_INT15_PANEL_FIT_DEFAULT, GMA_INT15_BOOT_DISPLAY_DEFAULT, 3);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000149 hwm_setup();
150}
151
Arthur Heymanscf278382018-12-16 01:04:24 +0100152static void mainboard_init(void *chip_info)
153{
154 int i;
155 struct device *dev;
156
157 for (i = 1; i <= 3; i++) {
158 int ethernet_disable = 0;
159 char cmos_option_name[] = "ethernetx";
160 snprintf(cmos_option_name, sizeof(cmos_option_name),
161 "ethernet%01d", i);
162 get_option(&ethernet_disable, cmos_option_name);
163 if (!ethernet_disable)
164 continue;
165 printk(BIOS_DEBUG, "Disabling Ethernet NIC #%d\n", i);
Elyes HAOUASd2abe932019-01-23 14:18:34 +0100166 dev = pcidev_on_root(28, i - 1);
Arthur Heymanscf278382018-12-16 01:04:24 +0100167 if (dev == NULL) {
168 printk(BIOS_ERR,
169 "Disabling Ethernet NIC: Cannot find 00:1c.%d!\n",
170 i - 1);
171 continue;
172 }
173 dev->enabled = 0;
174 }
175}
176
Carl-Daniel Hailfinger7ad11e82009-02-18 20:41:57 +0000177struct chip_operations mainboard_ops = {
Arthur Heymanscf278382018-12-16 01:04:24 +0100178 .init = mainboard_init,
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000179 .enable_dev = mainboard_enable,
Stefan Reinauer36a22682008-10-29 04:52:57 +0000180};