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