blob: dec9766b39810b753a50ec90f3fc9f8f63c0f686 [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 +000030void ec_mirror_flag(void)
31{
32 /*
33 * For the mirror flag to work, the status of the EC pin must be known
34 * at all times, which means external power. This can be either a DC
35 * charger, or PD with CCG6. PD with an ANX7447 requires configuration
36 * from the EC, so the update will interrupt this.
37 *
38 * This means we can unconditionally apply the mirror flag to devices
39 * that have CCG6, present on devices with TBT, but have a manual
40 * flag for devices without it.
41 */
Sean Rhodes7d00b7c2023-07-07 14:27:28 +010042 uint16_t ec_version = ec_get_version();
43
Sean Rhodesded5a602023-09-20 14:51:57 +010044 /* Full mirror support was added in EC 1.18 (0x0112) */
45 if (ec_version < 0x0112)
46 return;
47
Sean Rhodes0579c602023-02-16 15:00:14 +000048 if (CONFIG(EC_STARLABS_MIRROR_SUPPORT) &&
Sean Rhodese4fd5612023-07-18 11:49:19 +010049 (CONFIG(DRIVERS_INTEL_USB4_RETIMER) || get_uint_option("mirror_flag", 0)) &&
Sean Rhodes7d00b7c2023-07-07 14:27:28 +010050 (ec_version != CONFIG_EC_STARLABS_MIRROR_VERSION)) {
Sean Rhodesded5a602023-09-20 14:51:57 +010051
Sean Rhodes7d00b7c2023-07-07 14:27:28 +010052 printk(BIOS_ERR, "ITE: EC version 0x%x doesn't match coreboot version 0x%x.\n",
53 ec_version, CONFIG_EC_STARLABS_MIRROR_VERSION);
Sean Rhodesded5a602023-09-20 14:51:57 +010054
55 ec_write(ECRAM_MIRROR_FLAG, MIRROR_ENABLED);
Sean Rhodes0579c602023-02-16 15:00:14 +000056 }
57}
58
Sean Rhodes6082ee52022-03-09 08:07:30 +000059static uint16_t ec_get_chip_id(unsigned int port)
Sean Rhodes296994b2021-10-14 20:58:15 +010060{
61 return (pnp_read_index(port, ITE_CHIPID1) << 8) |
62 pnp_read_index(port, ITE_CHIPID2);
63}
64
65static void merlin_init(struct device *dev)
66{
67 if (!dev->enabled)
68 return;
69
70 /*
71 * The address/data IO port pair for the ite EC are configurable
72 * through the EC domain and are fixed by the EC's firmware blob. If
73 * the value(s) passed through the "dev" structure don't match the
74 * expected values then output severe warnings.
75 */
76 if (dev->path.pnp.port != ITE_FIXED_ADDR) {
77 printk(BIOS_ERR, "ITE: Incorrect ports defined in devicetree.cb.\n");
78 printk(BIOS_ERR, "ITE: Serious operational issues will arise.\n");
79 return;
80 }
81
Sean Rhodes6082ee52022-03-09 08:07:30 +000082 const uint16_t chip_id = ec_get_chip_id(dev->path.pnp.port);
Sean Rhodes296994b2021-10-14 20:58:15 +010083
84 if (chip_id != ITE_CHIPID_VAL) {
85 printk(BIOS_ERR, "ITE: Expected chip ID 0x%04x, but got 0x%04x instead.\n",
86 ITE_CHIPID_VAL, chip_id);
87 return;
88 }
89
Sean Rhodes0579c602023-02-16 15:00:14 +000090 ec_mirror_flag();
91
Sean Rhodes296994b2021-10-14 20:58:15 +010092 pc_keyboard_init(NO_AUX_DEVICE);
93
94 /*
95 * Restore settings from CMOS into EC RAM:
96 *
97 * kbl_timeout
98 * fn_ctrl_swap
99 * max_charge
100 * fan_mode
101 * fn_lock_state
102 * trackpad_state
103 * kbl_brightness
104 * kbl_state
105 */
106
107 /*
108 * Keyboard Backlight Timeout
109 *
110 * Setting: kbl_timeout
111 *
112 * Values: 30 Seconds, 1 Minute, 3 Minutes, 5 Minutes, Never
113 * Default: 30 Seconds
114 *
115 */
116 const uint8_t kbl_timeout[] = {
117 SEC_30,
118 MIN_1,
119 MIN_3,
120 MIN_5,
121 NEVER
122 };
123
124 ec_write(ECRAM_KBL_TIMEOUT,
125 get_ec_value_from_option("kbl_timeout",
126 0,
127 kbl_timeout,
128 ARRAY_SIZE(kbl_timeout)));
129
130 /*
131 * Fn Ctrl Reverse
132 *
133 * Setting: fn_ctrl_swap
134 *
135 * Values: Enabled, Disabled
136 * Default: Disabled
137 *
138 */
139 const uint8_t fn_ctrl_swap[] = {
140 FN_CTRL,
141 CTRL_FN
142 };
143
144 ec_write(ECRAM_FN_CTRL_REVERSE,
145 get_ec_value_from_option("fn_ctrl_swap",
Sean Rhodesc45cfad2023-04-25 22:51:57 +0100146 0,
Sean Rhodes296994b2021-10-14 20:58:15 +0100147 fn_ctrl_swap,
148 ARRAY_SIZE(fn_ctrl_swap)));
149
150 /*
151 * Maximum Charge Level
152 *
153 * Setting: max_charge
154 *
155 * Values: 60%, 80%, 100%
156 * Default: 100%
157 *
158 */
159 const uint8_t max_charge[] = {
160 CHARGE_100,
161 CHARGE_80,
162 CHARGE_60
163 };
164
Sean Rhodes4d1bf7b2022-02-17 13:55:34 +0000165 if (CONFIG(EC_STARLABS_MAX_CHARGE))
166 ec_write(ECRAM_MAX_CHARGE,
167 get_ec_value_from_option("max_charge",
168 0,
169 max_charge,
170 ARRAY_SIZE(max_charge)));
Sean Rhodes296994b2021-10-14 20:58:15 +0100171
172 /*
173 * Fan Mode
174 *
175 * Setting: fan_mode
176 *
177 * Values: Quiet, Normal, Aggressive
178 * Default: Normal
179 *
180 */
181 const uint8_t fan_mode[] = {
182 FAN_NORMAL,
183 FAN_AGGRESSIVE,
184 FAN_QUIET
185 };
186
187 if (CONFIG(EC_STARLABS_FAN))
188 ec_write(ECRAM_FAN_MODE,
189 get_ec_value_from_option("fan_mode",
190 0,
191 fan_mode,
192 ARRAY_SIZE(fan_mode)));
193
194 /*
195 * Function Lock
196 *
197 * Setting: fn_lock_state
198 *
199 * Values: Locked, Unlocked
200 * Default: Locked
201 *
202 */
203 const uint8_t fn_lock_state[] = {
204 UNLOCKED,
205 LOCKED
206 };
207
208 ec_write(ECRAM_FN_LOCK_STATE,
209 get_ec_value_from_option("fn_lock_state",
210 1,
211 fn_lock_state,
212 ARRAY_SIZE(fn_lock_state)));
213
214 /*
215 * Trackpad State
216 *
217 * Setting: trackpad_state
218 *
219 * Values: Enabled, Disabled
220 * Default: Enabled
221 *
222 */
223 const uint8_t trackpad_state[] = {
224 TRACKPAD_ENABLED,
225 TRACKPAD_DISABLED
226 };
227
228 ec_write(ECRAM_TRACKPAD_STATE,
229 get_ec_value_from_option("trackpad_state",
230 0,
231 trackpad_state,
232 ARRAY_SIZE(trackpad_state)));
233
234 /*
235 * Keyboard Backlight Brightness
236 *
237 * Setting: kbl_brightness
238 *
239 * Values: Off, Low, High / Off, On
240 * Default: Low
241 *
242 */
243 const uint8_t kbl_brightness[] = {
244 KBL_ON,
245 KBL_OFF,
246 KBL_LOW,
247 KBL_HIGH
248 };
249
250 if (CONFIG(EC_STARLABS_KBL_LEVELS))
251 ec_write(ECRAM_KBL_BRIGHTNESS,
252 get_ec_value_from_option("kbl_brightness",
253 2,
254 kbl_brightness,
255 ARRAY_SIZE(kbl_brightness)));
256 else
257 ec_write(ECRAM_KBL_BRIGHTNESS,
258 get_ec_value_from_option("kbl_brightness",
259 0,
260 kbl_brightness,
261 ARRAY_SIZE(kbl_brightness)));
262
263 /*
264 * Keyboard Backlight State
265 *
266 * Setting: kbl_state
267 *
268 * Values: Off, On
269 * Default: On
270 *
Sean Rhodescbedae12023-08-16 09:25:42 +0100271 * Note: Always enable, as the brightness level of `off` disables it.
272 *
Sean Rhodes296994b2021-10-14 20:58:15 +0100273 */
Sean Rhodes296994b2021-10-14 20:58:15 +0100274
Sean Rhodescbedae12023-08-16 09:25:42 +0100275 ec_write(ECRAM_KBL_STATE, KBL_ENABLED);
Sean Rhodes296994b2021-10-14 20:58:15 +0100276}
277
278static struct device_operations ops = {
279 .init = merlin_init,
280 .read_resources = noop_read_resources,
281 .set_resources = noop_set_resources,
282};
283
284static struct pnp_info pnp_dev_info[] = {
285 /* Serial Port 1 (UART1) */
286 { NULL, ITE_SP1, PNP_IO0 | PNP_IRQ0, 0x0ff8, },
287 /* Serial Port 2 (UART2) */
288 { NULL, ITE_SP2, PNP_IO0 | PNP_IRQ0, 0x0ff8, },
289 /* System Wake-Up Control (SWUC) */
290 { NULL, ITE_SWUC, PNP_IO0 | PNP_IRQ0, 0xfff0, },
291 /* KBC / Mouse Interface */
292 { NULL, ITE_SWUC, PNP_IRQ0, },
293 /* KBC / Keyboard Interface */
294 { NULL, ITE_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
295 /* Consumer IR (CIR) */
296 { NULL, ITE_IR, PNP_IO0 | PNP_IRQ0, 0xfff8, },
297 /* Shared Memory / Flash Interface (SMFI) */
298 { NULL, ITE_SMFI, PNP_IO0 | PNP_IRQ0, 0xfff0, },
299 /* RTC-like Timer (RCTC) */
300 { NULL, ITE_RTCT, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IO3 | PNP_IRQ0,
301 0xfffe, 0xfffe, 0xfffe, 0xfffe, },
302 /* Power Management I/F Channel 1 (PMC1) */
303 { NULL, ITE_PMC1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
304 /* Power Management I/F Channel 2 (PMC2) */
305 { NULL, ITE_PMC2, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0, 0x07fc,
306 0x07fc, 0xfff0, },
307 /* Serial Peripheral Interface (SSPI) */
308 { NULL, ITE_SSPI, PNP_IO0 | PNP_IRQ0, 0xfff8, },
309 /* Platform Environment Control Interface (PECI) */
310 { NULL, ITE_PECI, PNP_IRQ0, 0xfff8, },
311 /* Power Management I/F Channel 3 (PMC3) */
312 { NULL, ITE_PMC3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
313 /* Power Management I/F Channel 4 (PMC4) */
314 { NULL, ITE_PMC4, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
315 /* Power Management I/F Channel 5 (PMC5) */
316 { NULL, ITE_PMC5, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
317};
318
319static void enable_dev(struct device *dev)
320{
321 pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
322}
323
324struct chip_operations ec_starlabs_merlin_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +0900325 .name = "ITE EC",
Sean Rhodes296994b2021-10-14 20:58:15 +0100326 .enable_dev = enable_dev
327};