blob: fc852a93d35c341495e90544dcd6d1089afcb4e6 [file] [log] [blame]
Angel Pons210a0082020-04-02 23:48:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Nico Hubera53266b2013-05-02 15:26:08 +02003
Nico Hubera53266b2013-05-02 15:26:08 +02004#include <console/console.h>
5#include <device/device.h>
6#include <device/pnp.h>
7#include <ec/acpi/ec.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02008#include <option.h>
Nico Hubera53266b2013-05-02 15:26:08 +02009
10#include "ec.h"
11#include "chip.h"
12
13typedef struct ec_kontron_it8516e_config config_t;
14
15enum { /* EC commands */
Nico Huber6d6a2ac2013-07-12 14:35:00 +020016 IT8516E_CMD_SET_SYSTEMP_TYPE = 0x06,
17 IT8516E_CMD_GET_SYSTEMP_TYPE = 0x07,
Nico Hubera53266b2013-05-02 15:26:08 +020018 IT8516E_CMD_GET_FAN_MODE = 0x10,
19 IT8516E_CMD_SET_FAN_MODE = 0x11,
20 IT8516E_CMD_GET_FAN_PWM = 0x12,
21 IT8516E_CMD_SET_FAN_PWM = 0x13,
22 IT8516E_CMD_GET_FAN_SPEED = 0x14,
23 IT8516E_CMD_SET_FAN_SPEED = 0x15,
24 IT8516E_CMD_GET_FAN_TEMP = 0x16,
25 IT8516E_CMD_SET_FAN_TEMP = 0x17,
Nico Huber9ce71b32013-07-12 14:43:11 +020026 IT8516E_CMD_SET_FAN_LIMITS = 0x1a,
Nico Hubera53266b2013-05-02 15:26:08 +020027};
28
Nico Huber1f9f6782013-07-18 11:50:59 +020029/**
30 * Sets the type of the external temperature sensor used
31 *
32 * @param type Type of sensor to set
33 */
Nico Huber6d6a2ac2013-07-12 14:35:00 +020034static void it8516e_set_systemp_type(const u8 type)
35{
36 if (send_ec_command(IT8516E_CMD_SET_SYSTEMP_TYPE))
37 return;
38 send_ec_data(type);
39}
40
Nico Huber1f9f6782013-07-18 11:50:59 +020041/**
42 * Sets the operating mode of a fan
43 *
44 * @param idx Selects the fan; 0: CPU, 1: System
45 * @param mode Mode to set
46 */
Nico Hubera53266b2013-05-02 15:26:08 +020047static void it8516e_set_fan_mode(const u8 idx, const u8 mode)
48{
49 if (send_ec_command(IT8516E_CMD_SET_FAN_MODE))
50 return;
51 if (send_ec_data(idx))
52 return;
53 send_ec_data(mode);
54}
55
Nico Huber1f9f6782013-07-18 11:50:59 +020056/**
57 * Sets the PWM rate of a fan in IT8516E_MODE_PWM
58 *
59 * @param idx Selects the fan; 0: CPU, 1: System
60 * @param pwm PWM rate measured in 255ths
61 */
Nico Hubera53266b2013-05-02 15:26:08 +020062static void it8516e_set_fan_pwm(const u8 idx, const u8 pwm)
63{
64 if (send_ec_command(IT8516E_CMD_SET_FAN_PWM))
65 return;
66 if (send_ec_data(idx))
67 return;
68 send_ec_data(pwm);
69}
70
Nico Huber1f9f6782013-07-18 11:50:59 +020071/**
72 * Sets the target speed in RPM for a fan in IT8516E_MODE_SPEED
73 *
74 * @param idx Selects the fan; 0: CPU, 1: System
75 * @param speed Speed in RPM
76 */
Nico Hubera53266b2013-05-02 15:26:08 +020077static void it8516e_set_fan_speed(const u8 idx, const u16 speed)
78{
79 if (send_ec_command(IT8516E_CMD_SET_FAN_SPEED))
80 return;
81 if (send_ec_data(idx))
82 return;
83 if (send_ec_data(speed & 0xff))
84 return;
85 send_ec_data(speed >> 8);
86}
87
Nico Huber1f9f6782013-07-18 11:50:59 +020088/**
89 * Sets the target temperature for a fan in IT8516E_MODE_THERMAL
90 *
91 * @param idx Selects the fan; 0: CPU, 1: System
92 * @param temp Temperature in 64ths degree C
93 */
Nico Huber260c33b2013-07-18 11:27:30 +020094static void it8516e_set_fan_temperature(const u8 idx, const u16 temp)
Nico Hubera53266b2013-05-02 15:26:08 +020095{
96 if (send_ec_command(IT8516E_CMD_SET_FAN_TEMP))
97 return;
98 if (send_ec_data(idx))
99 return;
Nico Huber260c33b2013-07-18 11:27:30 +0200100 if (send_ec_data(temp & 0xff))
Nico Hubera53266b2013-05-02 15:26:08 +0200101 return;
Nico Huber260c33b2013-07-18 11:27:30 +0200102 send_ec_data(temp >> 8);
Nico Hubera53266b2013-05-02 15:26:08 +0200103}
104
Nico Huber1f9f6782013-07-18 11:50:59 +0200105/**
106 * Sets the minimum and maximum PWM rate of a fan in IT8516E_MODE_THERMAL
107 *
108 * @param idx Selects the fan; 0: CPU, 1: System
109 * @param min Minimum PWM rate in %
110 * @param max Maximum PWM rate in %
111 */
Nico Huber9ce71b32013-07-12 14:43:11 +0200112static void it8516e_set_fan_limits(const u8 idx, const u8 min, const u8 max)
113{
114 if (send_ec_command(IT8516E_CMD_SET_FAN_LIMITS))
115 return;
116 if (send_ec_data(idx))
117 return;
118 if (send_ec_data(min))
119 return;
120 send_ec_data(max);
121}
122
Nico Hubera53266b2013-05-02 15:26:08 +0200123static void it8516e_set_fan_from_options(const config_t *const config,
124 const u8 fan_idx)
125{
126 static char fanX_mode[] = "fanX_mode";
127 static char fanX_target[] = "fanX_target";
Nico Huber9ce71b32013-07-12 14:43:11 +0200128 static char fanX_min[] = "fanX_min";
129 static char fanX_max[] = "fanX_max";
Nico Hubera53266b2013-05-02 15:26:08 +0200130
Nico Huber9ce71b32013-07-12 14:43:11 +0200131 u8 fan_mode = config->default_fan_mode[fan_idx];
132 u16 fan_target = config->default_fan_target[fan_idx];
133 u8 fan_min = config->default_fan_min[fan_idx];
134 u8 fan_max = config->default_fan_max[fan_idx];
Nico Hubera53266b2013-05-02 15:26:08 +0200135
136 fanX_mode[3] = '1' + fan_idx;
137 get_option(&fan_mode, fanX_mode);
138 if (!fan_mode)
139 fan_mode = IT8516E_MODE_AUTO;
140 it8516e_set_fan_mode(fan_idx, fan_mode);
141
142 fanX_target[3] = '1' + fan_idx;
143 get_option(&fan_target, fanX_target);
144 switch (fan_mode) {
145 case IT8516E_MODE_AUTO:
146 printk(BIOS_DEBUG,
147 "Setting it8516e fan%d "
148 "control to auto.\n",
149 fan_idx + 1);
150 break;
151 case IT8516E_MODE_PWM:
152 printk(BIOS_DEBUG,
153 "Setting it8516e fan%d "
154 "control to %d%% PWM.\n",
155 fan_idx + 1, fan_target);
Nico Huberca4f0732013-07-18 12:27:00 +0200156 if (fan_target > 100) /* Constrain to 100% */
157 fan_target = 100;
Nico Huber942b6c22013-07-12 14:40:23 +0200158 it8516e_set_fan_pwm(fan_idx, (fan_target * 255) / 100);
Nico Hubera53266b2013-05-02 15:26:08 +0200159 break;
160 case IT8516E_MODE_SPEED:
161 printk(BIOS_DEBUG,
162 "Setting it8516e fan%d "
163 "control to %d RPMs.\n",
164 fan_idx + 1, fan_target);
165 it8516e_set_fan_speed(fan_idx, fan_target);
166 break;
167 case IT8516E_MODE_THERMAL:
168 printk(BIOS_DEBUG,
Nico Huber9ce71b32013-07-12 14:43:11 +0200169 "Setting it8516e fan%d control to %d C.\n",
Nico Hubera53266b2013-05-02 15:26:08 +0200170 fan_idx + 1, fan_target);
Nico Huberca4f0732013-07-18 12:27:00 +0200171 if (fan_target > 1024) /* Constrain to 1K */
172 fan_target = 1024;
Nico Huber260c33b2013-07-18 11:27:30 +0200173 it8516e_set_fan_temperature(fan_idx, fan_target * 64);
Nico Huber9ce71b32013-07-12 14:43:11 +0200174
175 fanX_min[3] = '1' + fan_idx;
176 fanX_max[3] = '1' + fan_idx;
177 get_option(&fan_min, fanX_min);
178 get_option(&fan_max, fanX_max);
179
180 if (!fan_max || fan_max > 100) /* Constrain fan_max to 100% */
181 fan_max = 100;
182 if (fan_min >= 100) /* Constrain fan_min to 99% */
183 fan_min = 99;
184 if (fan_max <= fan_min) /* If fan_min is the higher of the two,
185 it's safer for the hardware to keep
186 its value. Therefore, update fan_max. */
187 fan_max = fan_min + 1;
188
189 printk(BIOS_DEBUG,
190 "Setting it8516e fan%d limits to %d%% - %d%% PWM.\n",
191 fan_idx + 1, fan_min, fan_max);
192 it8516e_set_fan_limits(fan_idx, fan_min, fan_max);
Nico Hubera53266b2013-05-02 15:26:08 +0200193 break;
194 }
195}
196
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100197static void it8516e_pm2_init(struct device *dev)
Nico Hubera53266b2013-05-02 15:26:08 +0200198{
199 const config_t *const config = dev->chip_info;
200
201 /* TODO: Set frequency / divider? */
202
203 ec_set_ports(find_resource(dev, PNP_IDX_IO1)->base,
204 find_resource(dev, PNP_IDX_IO0)->base);
205
Nico Huber6d6a2ac2013-07-12 14:35:00 +0200206 u8 systemp_type = config->default_systemp;
207 get_option(&systemp_type, "systemp_type");
208 if (systemp_type >= IT8516E_SYSTEMP_LASTPLUSONE)
209 systemp_type = IT8516E_SYSTEMP_NONE;
210 it8516e_set_systemp_type(systemp_type);
211
Nico Hubera53266b2013-05-02 15:26:08 +0200212 it8516e_set_fan_from_options(config, 0);
213 it8516e_set_fan_from_options(config, 1);
214}
215
216static struct device_operations it8516e_pm2_ops = {
Nico Huber9cb09412013-06-15 15:30:19 +0200217 .read_resources = pnp_read_resources,
218 .set_resources = pnp_set_resources,
219 .enable_resources = pnp_enable_resources,
220 .enable = pnp_enable,
221 .init = it8516e_pm2_init
Nico Hubera53266b2013-05-02 15:26:08 +0200222};
223
224static struct pnp_info it8516e_dev_infos[] = {
Samuel Holland7daac912017-06-06 22:55:01 -0500225 { NULL, IT8516E_LDN_UART1, PNP_IO0 | PNP_IRQ0, 0x07f8, },
226 { NULL, IT8516E_LDN_UART2, PNP_IO0 | PNP_IRQ0, 0x07f8, },
227 { NULL, IT8516E_LDN_SWUC, PNP_IO0 | PNP_IRQ0, 0xffe0, },
Nico Hubera53266b2013-05-02 15:26:08 +0200228 { NULL, IT8516E_LDN_MOUSE, PNP_IRQ0, },
Samuel Holland7daac912017-06-06 22:55:01 -0500229 { NULL, IT8516E_LDN_KBD, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
230 { NULL, IT8516E_LDN_SMFI, PNP_IO0 | PNP_IRQ0, 0xfff0, },
231 { NULL, IT8516E_LDN_BRAM, PNP_IO0 | PNP_IO1, 0xfffe, 0xfffe, },
232 { NULL, IT8516E_LDN_PM1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
233 { &it8516e_pm2_ops, IT8516E_LDN_PM2, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
234 { NULL, IT8516E_LDN_PM3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
Nico Hubera53266b2013-05-02 15:26:08 +0200235};
236
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100237static void it8516e_enable(struct device *dev)
Nico Hubera53266b2013-05-02 15:26:08 +0200238{
239 pnp_enable_devices(dev, &pnp_ops,
240 ARRAY_SIZE(it8516e_dev_infos), it8516e_dev_infos);
241}
242
243const struct chip_operations ec_kontron_it8516e_ops = {
244 CHIP_NAME("Kontron (Fintec/ITE) IT8516E EC")
245 .enable_dev = it8516e_enable
246};