blob: cabac234cd9778ff5734e63b75a58f874459fca6 [file] [log] [blame]
Nico Hubera53266b2013-05-02 15:26:08 +02001/*
2 * This file is part of the coreboot project.
3 *
Nico Hubera53266b2013-05-02 15:26:08 +02004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Nico Hubera53266b2013-05-02 15:26:08 +020013 */
14
Nico Hubera53266b2013-05-02 15:26:08 +020015#include <console/console.h>
16#include <device/device.h>
17#include <device/pnp.h>
18#include <ec/acpi/ec.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +020019#include <option.h>
Nico Hubera53266b2013-05-02 15:26:08 +020020
21#include "ec.h"
22#include "chip.h"
23
24typedef struct ec_kontron_it8516e_config config_t;
25
26enum { /* EC commands */
Nico Huber6d6a2ac2013-07-12 14:35:00 +020027 IT8516E_CMD_SET_SYSTEMP_TYPE = 0x06,
28 IT8516E_CMD_GET_SYSTEMP_TYPE = 0x07,
Nico Hubera53266b2013-05-02 15:26:08 +020029 IT8516E_CMD_GET_FAN_MODE = 0x10,
30 IT8516E_CMD_SET_FAN_MODE = 0x11,
31 IT8516E_CMD_GET_FAN_PWM = 0x12,
32 IT8516E_CMD_SET_FAN_PWM = 0x13,
33 IT8516E_CMD_GET_FAN_SPEED = 0x14,
34 IT8516E_CMD_SET_FAN_SPEED = 0x15,
35 IT8516E_CMD_GET_FAN_TEMP = 0x16,
36 IT8516E_CMD_SET_FAN_TEMP = 0x17,
Nico Huber9ce71b32013-07-12 14:43:11 +020037 IT8516E_CMD_SET_FAN_LIMITS = 0x1a,
Nico Hubera53266b2013-05-02 15:26:08 +020038};
39
Nico Huber1f9f6782013-07-18 11:50:59 +020040/**
41 * Sets the type of the external temperature sensor used
42 *
43 * @param type Type of sensor to set
44 */
Nico Huber6d6a2ac2013-07-12 14:35:00 +020045static void it8516e_set_systemp_type(const u8 type)
46{
47 if (send_ec_command(IT8516E_CMD_SET_SYSTEMP_TYPE))
48 return;
49 send_ec_data(type);
50}
51
Nico Huber1f9f6782013-07-18 11:50:59 +020052/**
53 * Sets the operating mode of a fan
54 *
55 * @param idx Selects the fan; 0: CPU, 1: System
56 * @param mode Mode to set
57 */
Nico Hubera53266b2013-05-02 15:26:08 +020058static void it8516e_set_fan_mode(const u8 idx, const u8 mode)
59{
60 if (send_ec_command(IT8516E_CMD_SET_FAN_MODE))
61 return;
62 if (send_ec_data(idx))
63 return;
64 send_ec_data(mode);
65}
66
Nico Huber1f9f6782013-07-18 11:50:59 +020067/**
68 * Sets the PWM rate of a fan in IT8516E_MODE_PWM
69 *
70 * @param idx Selects the fan; 0: CPU, 1: System
71 * @param pwm PWM rate measured in 255ths
72 */
Nico Hubera53266b2013-05-02 15:26:08 +020073static void it8516e_set_fan_pwm(const u8 idx, const u8 pwm)
74{
75 if (send_ec_command(IT8516E_CMD_SET_FAN_PWM))
76 return;
77 if (send_ec_data(idx))
78 return;
79 send_ec_data(pwm);
80}
81
Nico Huber1f9f6782013-07-18 11:50:59 +020082/**
83 * Sets the target speed in RPM for a fan in IT8516E_MODE_SPEED
84 *
85 * @param idx Selects the fan; 0: CPU, 1: System
86 * @param speed Speed in RPM
87 */
Nico Hubera53266b2013-05-02 15:26:08 +020088static void it8516e_set_fan_speed(const u8 idx, const u16 speed)
89{
90 if (send_ec_command(IT8516E_CMD_SET_FAN_SPEED))
91 return;
92 if (send_ec_data(idx))
93 return;
94 if (send_ec_data(speed & 0xff))
95 return;
96 send_ec_data(speed >> 8);
97}
98
Nico Huber1f9f6782013-07-18 11:50:59 +020099/**
100 * Sets the target temperature for a fan in IT8516E_MODE_THERMAL
101 *
102 * @param idx Selects the fan; 0: CPU, 1: System
103 * @param temp Temperature in 64ths degree C
104 */
Nico Huber260c33b2013-07-18 11:27:30 +0200105static void it8516e_set_fan_temperature(const u8 idx, const u16 temp)
Nico Hubera53266b2013-05-02 15:26:08 +0200106{
107 if (send_ec_command(IT8516E_CMD_SET_FAN_TEMP))
108 return;
109 if (send_ec_data(idx))
110 return;
Nico Huber260c33b2013-07-18 11:27:30 +0200111 if (send_ec_data(temp & 0xff))
Nico Hubera53266b2013-05-02 15:26:08 +0200112 return;
Nico Huber260c33b2013-07-18 11:27:30 +0200113 send_ec_data(temp >> 8);
Nico Hubera53266b2013-05-02 15:26:08 +0200114}
115
Nico Huber1f9f6782013-07-18 11:50:59 +0200116/**
117 * Sets the minimum and maximum PWM rate of a fan in IT8516E_MODE_THERMAL
118 *
119 * @param idx Selects the fan; 0: CPU, 1: System
120 * @param min Minimum PWM rate in %
121 * @param max Maximum PWM rate in %
122 */
Nico Huber9ce71b32013-07-12 14:43:11 +0200123static void it8516e_set_fan_limits(const u8 idx, const u8 min, const u8 max)
124{
125 if (send_ec_command(IT8516E_CMD_SET_FAN_LIMITS))
126 return;
127 if (send_ec_data(idx))
128 return;
129 if (send_ec_data(min))
130 return;
131 send_ec_data(max);
132}
133
Nico Hubera53266b2013-05-02 15:26:08 +0200134static void it8516e_set_fan_from_options(const config_t *const config,
135 const u8 fan_idx)
136{
137 static char fanX_mode[] = "fanX_mode";
138 static char fanX_target[] = "fanX_target";
Nico Huber9ce71b32013-07-12 14:43:11 +0200139 static char fanX_min[] = "fanX_min";
140 static char fanX_max[] = "fanX_max";
Nico Hubera53266b2013-05-02 15:26:08 +0200141
Nico Huber9ce71b32013-07-12 14:43:11 +0200142 u8 fan_mode = config->default_fan_mode[fan_idx];
143 u16 fan_target = config->default_fan_target[fan_idx];
144 u8 fan_min = config->default_fan_min[fan_idx];
145 u8 fan_max = config->default_fan_max[fan_idx];
Nico Hubera53266b2013-05-02 15:26:08 +0200146
147 fanX_mode[3] = '1' + fan_idx;
148 get_option(&fan_mode, fanX_mode);
149 if (!fan_mode)
150 fan_mode = IT8516E_MODE_AUTO;
151 it8516e_set_fan_mode(fan_idx, fan_mode);
152
153 fanX_target[3] = '1' + fan_idx;
154 get_option(&fan_target, fanX_target);
155 switch (fan_mode) {
156 case IT8516E_MODE_AUTO:
157 printk(BIOS_DEBUG,
158 "Setting it8516e fan%d "
159 "control to auto.\n",
160 fan_idx + 1);
161 break;
162 case IT8516E_MODE_PWM:
163 printk(BIOS_DEBUG,
164 "Setting it8516e fan%d "
165 "control to %d%% PWM.\n",
166 fan_idx + 1, fan_target);
Nico Huberca4f0732013-07-18 12:27:00 +0200167 if (fan_target > 100) /* Constrain to 100% */
168 fan_target = 100;
Nico Huber942b6c22013-07-12 14:40:23 +0200169 it8516e_set_fan_pwm(fan_idx, (fan_target * 255) / 100);
Nico Hubera53266b2013-05-02 15:26:08 +0200170 break;
171 case IT8516E_MODE_SPEED:
172 printk(BIOS_DEBUG,
173 "Setting it8516e fan%d "
174 "control to %d RPMs.\n",
175 fan_idx + 1, fan_target);
176 it8516e_set_fan_speed(fan_idx, fan_target);
177 break;
178 case IT8516E_MODE_THERMAL:
179 printk(BIOS_DEBUG,
Nico Huber9ce71b32013-07-12 14:43:11 +0200180 "Setting it8516e fan%d control to %d C.\n",
Nico Hubera53266b2013-05-02 15:26:08 +0200181 fan_idx + 1, fan_target);
Nico Huberca4f0732013-07-18 12:27:00 +0200182 if (fan_target > 1024) /* Constrain to 1K */
183 fan_target = 1024;
Nico Huber260c33b2013-07-18 11:27:30 +0200184 it8516e_set_fan_temperature(fan_idx, fan_target * 64);
Nico Huber9ce71b32013-07-12 14:43:11 +0200185
186 fanX_min[3] = '1' + fan_idx;
187 fanX_max[3] = '1' + fan_idx;
188 get_option(&fan_min, fanX_min);
189 get_option(&fan_max, fanX_max);
190
191 if (!fan_max || fan_max > 100) /* Constrain fan_max to 100% */
192 fan_max = 100;
193 if (fan_min >= 100) /* Constrain fan_min to 99% */
194 fan_min = 99;
195 if (fan_max <= fan_min) /* If fan_min is the higher of the two,
196 it's safer for the hardware to keep
197 its value. Therefore, update fan_max. */
198 fan_max = fan_min + 1;
199
200 printk(BIOS_DEBUG,
201 "Setting it8516e fan%d limits to %d%% - %d%% PWM.\n",
202 fan_idx + 1, fan_min, fan_max);
203 it8516e_set_fan_limits(fan_idx, fan_min, fan_max);
Nico Hubera53266b2013-05-02 15:26:08 +0200204 break;
205 }
206}
207
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100208static void it8516e_pm2_init(struct device *dev)
Nico Hubera53266b2013-05-02 15:26:08 +0200209{
210 const config_t *const config = dev->chip_info;
211
212 /* TODO: Set frequency / divider? */
213
214 ec_set_ports(find_resource(dev, PNP_IDX_IO1)->base,
215 find_resource(dev, PNP_IDX_IO0)->base);
216
Nico Huber6d6a2ac2013-07-12 14:35:00 +0200217 u8 systemp_type = config->default_systemp;
218 get_option(&systemp_type, "systemp_type");
219 if (systemp_type >= IT8516E_SYSTEMP_LASTPLUSONE)
220 systemp_type = IT8516E_SYSTEMP_NONE;
221 it8516e_set_systemp_type(systemp_type);
222
Nico Hubera53266b2013-05-02 15:26:08 +0200223 it8516e_set_fan_from_options(config, 0);
224 it8516e_set_fan_from_options(config, 1);
225}
226
227static struct device_operations it8516e_pm2_ops = {
Nico Huber9cb09412013-06-15 15:30:19 +0200228 .read_resources = pnp_read_resources,
229 .set_resources = pnp_set_resources,
230 .enable_resources = pnp_enable_resources,
231 .enable = pnp_enable,
232 .init = it8516e_pm2_init
Nico Hubera53266b2013-05-02 15:26:08 +0200233};
234
235static struct pnp_info it8516e_dev_infos[] = {
Samuel Holland7daac912017-06-06 22:55:01 -0500236 { NULL, IT8516E_LDN_UART1, PNP_IO0 | PNP_IRQ0, 0x07f8, },
237 { NULL, IT8516E_LDN_UART2, PNP_IO0 | PNP_IRQ0, 0x07f8, },
238 { NULL, IT8516E_LDN_SWUC, PNP_IO0 | PNP_IRQ0, 0xffe0, },
Nico Hubera53266b2013-05-02 15:26:08 +0200239 { NULL, IT8516E_LDN_MOUSE, PNP_IRQ0, },
Samuel Holland7daac912017-06-06 22:55:01 -0500240 { NULL, IT8516E_LDN_KBD, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
241 { NULL, IT8516E_LDN_SMFI, PNP_IO0 | PNP_IRQ0, 0xfff0, },
242 { NULL, IT8516E_LDN_BRAM, PNP_IO0 | PNP_IO1, 0xfffe, 0xfffe, },
243 { NULL, IT8516E_LDN_PM1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
244 { &it8516e_pm2_ops, IT8516E_LDN_PM2, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
245 { NULL, IT8516E_LDN_PM3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
Nico Hubera53266b2013-05-02 15:26:08 +0200246};
247
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100248static void it8516e_enable(struct device *dev)
Nico Hubera53266b2013-05-02 15:26:08 +0200249{
250 pnp_enable_devices(dev, &pnp_ops,
251 ARRAY_SIZE(it8516e_dev_infos), it8516e_dev_infos);
252}
253
254const struct chip_operations ec_kontron_it8516e_ops = {
255 CHIP_NAME("Kontron (Fintec/ITE) IT8516E EC")
256 .enable_dev = it8516e_enable
257};