blob: 0f807debf82e916decae7eba0b6ba48d116fb079 [file] [log] [blame]
Sean Rhodes296994b2021-10-14 20:58:15 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
Sean Rhodes296994b2021-10-14 20:58:15 +01004#include <device/device.h>
5#include <device/pnp.h>
6#include <ec/acpi/ec.h>
7#include <option.h>
8#include <pc80/keyboard.h>
Sean Rhodes0579c602023-02-16 15:00:14 +00009#include <halt.h>
Sean Rhodes296994b2021-10-14 20:58:15 +010010
11#include "ec.h"
12#include "ecdefs.h"
13
Sean Rhodes6082ee52022-03-09 08:07:30 +000014uint16_t ec_get_version(void)
Sean Rhodes296994b2021-10-14 20:58:15 +010015{
16 return (ec_read(ECRAM_MAJOR_VERSION) << 8) | ec_read(ECRAM_MINOR_VERSION);
17}
18
19static uint8_t get_ec_value_from_option(const char *name,
20 unsigned int fallback,
21 const uint8_t *lut,
22 size_t lut_size)
23{
24 unsigned int index = get_uint_option(name, fallback);
25 if (index >= lut_size)
26 index = fallback;
27 return lut[index];
28}
29
Sean Rhodes0579c602023-02-16 15:00:14 +000030static void ec_mirror_with_count(void)
31{
32 unsigned int cmos_mirror_flag_counter = get_uint_option("mirror_flag_counter", UINT_MAX);
33
34 if (cmos_mirror_flag_counter != UINT_MAX) {
35 printk(BIOS_DEBUG, "ITE: mirror_flag_counter = %u\n", cmos_mirror_flag_counter);
36
37 /* Avoid boot loops by only trying a state change once */
38 if (cmos_mirror_flag_counter < MIRROR_ATTEMPTS) {
39 cmos_mirror_flag_counter++;
40 set_uint_option("mirror_flag_counter", cmos_mirror_flag_counter);
41 printk(BIOS_DEBUG, "ITE: Mirror attempt %u/%u.\n", cmos_mirror_flag_counter,
42 MIRROR_ATTEMPTS);
43
44 /* Write the EC mirror flag */
45 ec_write(ECRAM_MIRROR_FLAG, MIRROR_ENABLED);
46
47 /* Check what has been written */
48 if (ec_read(ECRAM_MIRROR_FLAG) == MIRROR_ENABLED)
49 poweroff();
50 } else {
51 /*
52 * If the mirror flags fails after 1 attempt, it will
53 * likely need a cold boot, or recovering.
54 */
55 printk(BIOS_ERR, "ITE: Failed to mirror the EC in %u attempts!\n",
56 MIRROR_ATTEMPTS);
57 }
58 } else {
59 printk(BIOS_DEBUG, "ITE: Powering Off");
60 /* Write the EC mirror flag */
61 ec_write(ECRAM_MIRROR_FLAG, MIRROR_ENABLED);
62
63 /* Check what has been written */
64 if (ec_read(ECRAM_MIRROR_FLAG) == MIRROR_ENABLED)
65 poweroff();
66 }
67}
68
69
70void ec_mirror_flag(void)
71{
72 /*
73 * For the mirror flag to work, the status of the EC pin must be known
74 * at all times, which means external power. This can be either a DC
75 * charger, or PD with CCG6. PD with an ANX7447 requires configuration
76 * from the EC, so the update will interrupt this.
77 *
78 * This means we can unconditionally apply the mirror flag to devices
79 * that have CCG6, present on devices with TBT, but have a manual
80 * flag for devices without it.
81 */
82 if (CONFIG(EC_STARLABS_MIRROR_SUPPORT) &&
83 (CONFIG(SOC_INTEL_COMMON_BLOCK_TCSS) || get_uint_option("mirror_flag", 0)) &&
84 (ec_get_version() != CONFIG_EC_STARLABS_MIRROR_VERSION)) {
85 printk(BIOS_ERR, "ITE: System and EC ROM version mismatch.\n");
86 ec_mirror_with_count();
87 }
88}
89
Sean Rhodes6082ee52022-03-09 08:07:30 +000090static uint16_t ec_get_chip_id(unsigned int port)
Sean Rhodes296994b2021-10-14 20:58:15 +010091{
92 return (pnp_read_index(port, ITE_CHIPID1) << 8) |
93 pnp_read_index(port, ITE_CHIPID2);
94}
95
96static void merlin_init(struct device *dev)
97{
98 if (!dev->enabled)
99 return;
100
101 /*
102 * The address/data IO port pair for the ite EC are configurable
103 * through the EC domain and are fixed by the EC's firmware blob. If
104 * the value(s) passed through the "dev" structure don't match the
105 * expected values then output severe warnings.
106 */
107 if (dev->path.pnp.port != ITE_FIXED_ADDR) {
108 printk(BIOS_ERR, "ITE: Incorrect ports defined in devicetree.cb.\n");
109 printk(BIOS_ERR, "ITE: Serious operational issues will arise.\n");
110 return;
111 }
112
Sean Rhodes6082ee52022-03-09 08:07:30 +0000113 const uint16_t chip_id = ec_get_chip_id(dev->path.pnp.port);
Sean Rhodes296994b2021-10-14 20:58:15 +0100114
115 if (chip_id != ITE_CHIPID_VAL) {
116 printk(BIOS_ERR, "ITE: Expected chip ID 0x%04x, but got 0x%04x instead.\n",
117 ITE_CHIPID_VAL, chip_id);
118 return;
119 }
120
Sean Rhodes0579c602023-02-16 15:00:14 +0000121 ec_mirror_flag();
122
Sean Rhodes296994b2021-10-14 20:58:15 +0100123 pc_keyboard_init(NO_AUX_DEVICE);
124
125 /*
126 * Restore settings from CMOS into EC RAM:
127 *
128 * kbl_timeout
129 * fn_ctrl_swap
130 * max_charge
131 * fan_mode
132 * fn_lock_state
133 * trackpad_state
134 * kbl_brightness
135 * kbl_state
136 */
137
138 /*
139 * Keyboard Backlight Timeout
140 *
141 * Setting: kbl_timeout
142 *
143 * Values: 30 Seconds, 1 Minute, 3 Minutes, 5 Minutes, Never
144 * Default: 30 Seconds
145 *
146 */
147 const uint8_t kbl_timeout[] = {
148 SEC_30,
149 MIN_1,
150 MIN_3,
151 MIN_5,
152 NEVER
153 };
154
155 ec_write(ECRAM_KBL_TIMEOUT,
156 get_ec_value_from_option("kbl_timeout",
157 0,
158 kbl_timeout,
159 ARRAY_SIZE(kbl_timeout)));
160
161 /*
162 * Fn Ctrl Reverse
163 *
164 * Setting: fn_ctrl_swap
165 *
166 * Values: Enabled, Disabled
167 * Default: Disabled
168 *
169 */
170 const uint8_t fn_ctrl_swap[] = {
171 FN_CTRL,
172 CTRL_FN
173 };
174
175 ec_write(ECRAM_FN_CTRL_REVERSE,
176 get_ec_value_from_option("fn_ctrl_swap",
Sean Rhodesc45cfad2023-04-25 22:51:57 +0100177 0,
Sean Rhodes296994b2021-10-14 20:58:15 +0100178 fn_ctrl_swap,
179 ARRAY_SIZE(fn_ctrl_swap)));
180
181 /*
182 * Maximum Charge Level
183 *
184 * Setting: max_charge
185 *
186 * Values: 60%, 80%, 100%
187 * Default: 100%
188 *
189 */
190 const uint8_t max_charge[] = {
191 CHARGE_100,
192 CHARGE_80,
193 CHARGE_60
194 };
195
Sean Rhodes4d1bf7b2022-02-17 13:55:34 +0000196 if (CONFIG(EC_STARLABS_MAX_CHARGE))
197 ec_write(ECRAM_MAX_CHARGE,
198 get_ec_value_from_option("max_charge",
199 0,
200 max_charge,
201 ARRAY_SIZE(max_charge)));
Sean Rhodes296994b2021-10-14 20:58:15 +0100202
203 /*
204 * Fan Mode
205 *
206 * Setting: fan_mode
207 *
208 * Values: Quiet, Normal, Aggressive
209 * Default: Normal
210 *
211 */
212 const uint8_t fan_mode[] = {
213 FAN_NORMAL,
214 FAN_AGGRESSIVE,
215 FAN_QUIET
216 };
217
218 if (CONFIG(EC_STARLABS_FAN))
219 ec_write(ECRAM_FAN_MODE,
220 get_ec_value_from_option("fan_mode",
221 0,
222 fan_mode,
223 ARRAY_SIZE(fan_mode)));
224
225 /*
226 * Function Lock
227 *
228 * Setting: fn_lock_state
229 *
230 * Values: Locked, Unlocked
231 * Default: Locked
232 *
233 */
234 const uint8_t fn_lock_state[] = {
235 UNLOCKED,
236 LOCKED
237 };
238
239 ec_write(ECRAM_FN_LOCK_STATE,
240 get_ec_value_from_option("fn_lock_state",
241 1,
242 fn_lock_state,
243 ARRAY_SIZE(fn_lock_state)));
244
245 /*
246 * Trackpad State
247 *
248 * Setting: trackpad_state
249 *
250 * Values: Enabled, Disabled
251 * Default: Enabled
252 *
253 */
254 const uint8_t trackpad_state[] = {
255 TRACKPAD_ENABLED,
256 TRACKPAD_DISABLED
257 };
258
259 ec_write(ECRAM_TRACKPAD_STATE,
260 get_ec_value_from_option("trackpad_state",
261 0,
262 trackpad_state,
263 ARRAY_SIZE(trackpad_state)));
264
265 /*
266 * Keyboard Backlight Brightness
267 *
268 * Setting: kbl_brightness
269 *
270 * Values: Off, Low, High / Off, On
271 * Default: Low
272 *
273 */
274 const uint8_t kbl_brightness[] = {
275 KBL_ON,
276 KBL_OFF,
277 KBL_LOW,
278 KBL_HIGH
279 };
280
281 if (CONFIG(EC_STARLABS_KBL_LEVELS))
282 ec_write(ECRAM_KBL_BRIGHTNESS,
283 get_ec_value_from_option("kbl_brightness",
284 2,
285 kbl_brightness,
286 ARRAY_SIZE(kbl_brightness)));
287 else
288 ec_write(ECRAM_KBL_BRIGHTNESS,
289 get_ec_value_from_option("kbl_brightness",
290 0,
291 kbl_brightness,
292 ARRAY_SIZE(kbl_brightness)));
293
294 /*
295 * Keyboard Backlight State
296 *
297 * Setting: kbl_state
298 *
299 * Values: Off, On
300 * Default: On
301 *
302 */
303 const uint8_t kbl_state[] = {
304 KBL_DISABLED,
305 KBL_ENABLED
306 };
307
308 ec_write(ECRAM_KBL_STATE,
309 get_ec_value_from_option("kbl_state",
310 1,
311 kbl_state,
312 ARRAY_SIZE(kbl_state)));
Sean Rhodes296994b2021-10-14 20:58:15 +0100313}
314
315static struct device_operations ops = {
316 .init = merlin_init,
317 .read_resources = noop_read_resources,
318 .set_resources = noop_set_resources,
319};
320
321static struct pnp_info pnp_dev_info[] = {
322 /* Serial Port 1 (UART1) */
323 { NULL, ITE_SP1, PNP_IO0 | PNP_IRQ0, 0x0ff8, },
324 /* Serial Port 2 (UART2) */
325 { NULL, ITE_SP2, PNP_IO0 | PNP_IRQ0, 0x0ff8, },
326 /* System Wake-Up Control (SWUC) */
327 { NULL, ITE_SWUC, PNP_IO0 | PNP_IRQ0, 0xfff0, },
328 /* KBC / Mouse Interface */
329 { NULL, ITE_SWUC, PNP_IRQ0, },
330 /* KBC / Keyboard Interface */
331 { NULL, ITE_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
332 /* Consumer IR (CIR) */
333 { NULL, ITE_IR, PNP_IO0 | PNP_IRQ0, 0xfff8, },
334 /* Shared Memory / Flash Interface (SMFI) */
335 { NULL, ITE_SMFI, PNP_IO0 | PNP_IRQ0, 0xfff0, },
336 /* RTC-like Timer (RCTC) */
337 { NULL, ITE_RTCT, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IO3 | PNP_IRQ0,
338 0xfffe, 0xfffe, 0xfffe, 0xfffe, },
339 /* Power Management I/F Channel 1 (PMC1) */
340 { NULL, ITE_PMC1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
341 /* Power Management I/F Channel 2 (PMC2) */
342 { NULL, ITE_PMC2, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0, 0x07fc,
343 0x07fc, 0xfff0, },
344 /* Serial Peripheral Interface (SSPI) */
345 { NULL, ITE_SSPI, PNP_IO0 | PNP_IRQ0, 0xfff8, },
346 /* Platform Environment Control Interface (PECI) */
347 { NULL, ITE_PECI, PNP_IRQ0, 0xfff8, },
348 /* Power Management I/F Channel 3 (PMC3) */
349 { NULL, ITE_PMC3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
350 /* Power Management I/F Channel 4 (PMC4) */
351 { NULL, ITE_PMC4, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
352 /* Power Management I/F Channel 5 (PMC5) */
353 { NULL, ITE_PMC5, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
354};
355
356static void enable_dev(struct device *dev)
357{
358 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
359}
360
361struct chip_operations ec_starlabs_merlin_ops = {
362 CHIP_NAME("ITE EC")
363 .enable_dev = enable_dev
364};