1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <stdint.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <console/console.h>
7 #include <delay.h>
8 #include <device/device.h>
9 #include <device/path.h>
10 #include <elog.h>
11 #include <rtc.h>
12 #include <security/vboot/vboot_common.h>
13 #include <stdlib.h>
14 #include <timer.h>
15
16 #include "ec.h"
17
18 #define CROS_EC_COMMAND_INFO const void
19 #define CROS_EC_COMMAND(h, c, v, p, ps, r, rs) \
20 google_chromeec_command(&(struct chromeec_command) { \
21 .cmd_code = (c), \
22 .cmd_version = (v), \
23 .cmd_data_in = (p), \
24 .cmd_size_in = (ps), \
25 .cmd_data_out = (r), \
26 .cmd_size_out = (rs), \
27 .cmd_dev_index = 0, \
28 })
29
30 #include "ec_cmd_api.h"
31
32 /*
33 * coreboot only supports a single platform EC, so there is no need to
34 * provide a context handle for the EC.
35 */
36 #define PLAT_EC NULL
37
38 #define INVALID_HCMD 0xFF
39
40 /*
41 * Map UHEPI masks to non UHEPI commands in order to support old EC FW
42 * which does not support UHEPI command.
43 */
44 static const struct {
45 uint8_t set_cmd;
46 uint8_t clear_cmd;
47 uint8_t get_cmd;
48 } event_map[] = {
49 [EC_HOST_EVENT_MAIN] = {
50 INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR,
51 INVALID_HCMD,
52 },
53 [EC_HOST_EVENT_B] = {
54 INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR_B,
55 EC_CMD_HOST_EVENT_GET_B,
56 },
57 [EC_HOST_EVENT_SCI_MASK] = {
58 EC_CMD_HOST_EVENT_SET_SCI_MASK, INVALID_HCMD,
59 EC_CMD_HOST_EVENT_GET_SCI_MASK,
60 },
61 [EC_HOST_EVENT_SMI_MASK] = {
62 EC_CMD_HOST_EVENT_SET_SMI_MASK, INVALID_HCMD,
63 EC_CMD_HOST_EVENT_GET_SMI_MASK,
64 },
65 [EC_HOST_EVENT_ALWAYS_REPORT_MASK] = {
66 INVALID_HCMD, INVALID_HCMD, INVALID_HCMD,
67 },
68 [EC_HOST_EVENT_ACTIVE_WAKE_MASK] = {
69 EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
70 EC_CMD_HOST_EVENT_GET_WAKE_MASK,
71 },
72 [EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX] = {
73 EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
74 EC_CMD_HOST_EVENT_GET_WAKE_MASK,
75 },
76 [EC_HOST_EVENT_LAZY_WAKE_MASK_S3] = {
77 EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
78 EC_CMD_HOST_EVENT_GET_WAKE_MASK,
79 },
80 [EC_HOST_EVENT_LAZY_WAKE_MASK_S5] = {
81 EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD,
82 EC_CMD_HOST_EVENT_GET_WAKE_MASK,
83 },
84 };
85
google_chromeec_calc_checksum(const uint8_t * data,int size)86 uint8_t google_chromeec_calc_checksum(const uint8_t *data, int size)
87 {
88 int csum;
89
90 for (csum = 0; size > 0; data++, size--)
91 csum += *data;
92 return (uint8_t)(csum & 0xff);
93 }
94
google_chromeec_kbbacklight(int percent)95 int google_chromeec_kbbacklight(int percent)
96 {
97 const struct ec_params_pwm_set_keyboard_backlight params = {
98 .percent = percent % 101,
99 };
100
101 if (ec_cmd_pwm_set_keyboard_backlight(PLAT_EC, ¶ms) != 0)
102 return -1;
103
104 return 0;
105 }
106
google_chromeec_post(uint8_t postcode)107 void google_chromeec_post(uint8_t postcode)
108 {
109 /* backlight is a percent. postcode is a uint8_t.
110 * Convert the uint8_t to %.
111 */
112 postcode = (postcode/4) + (postcode/8);
113 google_chromeec_kbbacklight(postcode);
114 }
115
116 /*
117 * Query the EC for specified mask indicating enabled events.
118 * The EC maintains separate event masks for SMI, SCI and WAKE.
119 */
google_chromeec_uhepi_cmd(uint8_t mask,uint8_t action,uint64_t * value)120 static int google_chromeec_uhepi_cmd(uint8_t mask, uint8_t action,
121 uint64_t *value)
122 {
123 int ret;
124 struct ec_params_host_event params = {
125 .action = action,
126 .mask_type = mask,
127 };
128 struct ec_response_host_event resp = {};
129
130 if (action != EC_HOST_EVENT_GET)
131 params.value = *value;
132 else
133 *value = 0;
134
135 ret = ec_cmd_host_event(PLAT_EC, ¶ms, &resp);
136
137 if (action != EC_HOST_EVENT_GET)
138 return ret;
139 if (ret == 0)
140 *value = resp.value;
141 return ret;
142 }
143
google_chromeec_handle_non_uhepi_cmd(uint8_t hcmd,uint8_t action,uint64_t * value)144 static int google_chromeec_handle_non_uhepi_cmd(uint8_t hcmd, uint8_t action,
145 uint64_t *value)
146 {
147 int ret = -1;
148 struct ec_params_host_event_mask params = {};
149 struct ec_response_host_event_mask resp = {};
150 struct chromeec_command cmd = {
151 .cmd_code = hcmd,
152 .cmd_version = 0,
153 .cmd_data_in = ¶ms,
154 .cmd_size_in = sizeof(params),
155 .cmd_data_out = &resp,
156 .cmd_size_out = sizeof(resp),
157 .cmd_dev_index = 0,
158 };
159
160 if (hcmd == INVALID_HCMD)
161 return ret;
162
163 if (action != EC_HOST_EVENT_GET)
164 params.mask = (uint32_t)*value;
165 else
166 *value = 0;
167
168 ret = google_chromeec_command(&cmd);
169
170 if (action != EC_HOST_EVENT_GET)
171 return ret;
172 if (ret == 0)
173 *value = resp.mask;
174
175 return ret;
176 }
177
google_chromeec_is_uhepi_supported(void)178 bool google_chromeec_is_uhepi_supported(void)
179 {
180 #define UHEPI_SUPPORTED 1
181 #define UHEPI_NOT_SUPPORTED 2
182
183 static int uhepi_support;
184
185 if (!uhepi_support) {
186 uhepi_support = google_chromeec_check_feature
187 (EC_FEATURE_UNIFIED_WAKE_MASKS) > 0 ? UHEPI_SUPPORTED :
188 UHEPI_NOT_SUPPORTED;
189 printk(BIOS_DEBUG, "Chrome EC: UHEPI %s\n",
190 uhepi_support == UHEPI_SUPPORTED ?
191 "supported" : "not supported");
192 }
193 return uhepi_support == UHEPI_SUPPORTED;
194 }
195
google_chromeec_get_mask(uint8_t type)196 static uint64_t google_chromeec_get_mask(uint8_t type)
197 {
198 uint64_t value = 0;
199
200 if (google_chromeec_is_uhepi_supported()) {
201 google_chromeec_uhepi_cmd(type, EC_HOST_EVENT_GET, &value);
202 } else {
203 assert(type < ARRAY_SIZE(event_map));
204 google_chromeec_handle_non_uhepi_cmd(
205 event_map[type].get_cmd,
206 EC_HOST_EVENT_GET, &value);
207 }
208 return value;
209 }
210
google_chromeec_clear_mask(uint8_t type,uint64_t mask)211 static int google_chromeec_clear_mask(uint8_t type, uint64_t mask)
212 {
213 if (google_chromeec_is_uhepi_supported())
214 return google_chromeec_uhepi_cmd(type,
215 EC_HOST_EVENT_CLEAR, &mask);
216
217 assert(type < ARRAY_SIZE(event_map));
218 return google_chromeec_handle_non_uhepi_cmd(
219 event_map[type].clear_cmd,
220 EC_HOST_EVENT_CLEAR, &mask);
221 }
222
google_chromeec_set_mask(uint8_t type,uint64_t mask)223 static int google_chromeec_set_mask(uint8_t type, uint64_t mask)
224 {
225 if (google_chromeec_is_uhepi_supported())
226 return google_chromeec_uhepi_cmd(type,
227 EC_HOST_EVENT_SET, &mask);
228
229 assert(type < ARRAY_SIZE(event_map));
230 return google_chromeec_handle_non_uhepi_cmd(
231 event_map[type].set_cmd,
232 EC_HOST_EVENT_SET, &mask);
233 }
234
google_chromeec_set_s3_lazy_wake_mask(uint64_t mask)235 static int google_chromeec_set_s3_lazy_wake_mask(uint64_t mask)
236 {
237 printk(BIOS_DEBUG, "Chrome EC: Set S3 LAZY WAKE mask to 0x%016llx\n",
238 mask);
239 return google_chromeec_set_mask
240 (EC_HOST_EVENT_LAZY_WAKE_MASK_S3, mask);
241 }
242
google_chromeec_set_s5_lazy_wake_mask(uint64_t mask)243 static int google_chromeec_set_s5_lazy_wake_mask(uint64_t mask)
244 {
245 printk(BIOS_DEBUG, "Chrome EC: Set S5 LAZY WAKE mask to 0x%016llx\n",
246 mask);
247 return google_chromeec_set_mask
248 (EC_HOST_EVENT_LAZY_WAKE_MASK_S5, mask);
249 }
250
google_chromeec_set_s0ix_lazy_wake_mask(uint64_t mask)251 static int google_chromeec_set_s0ix_lazy_wake_mask(uint64_t mask)
252 {
253 printk(BIOS_DEBUG, "Chrome EC: Set S0iX LAZY WAKE mask to 0x%016llx\n",
254 mask);
255 return google_chromeec_set_mask
256 (EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, mask);
257 }
google_chromeec_set_lazy_wake_masks(uint64_t s5_mask,uint64_t s3_mask,uint64_t s0ix_mask)258 static void google_chromeec_set_lazy_wake_masks(uint64_t s5_mask,
259 uint64_t s3_mask, uint64_t s0ix_mask)
260 {
261 if (google_chromeec_set_s5_lazy_wake_mask(s5_mask))
262 printk(BIOS_DEBUG, "Error: Set S5 LAZY WAKE mask failed\n");
263 if (google_chromeec_set_s3_lazy_wake_mask(s3_mask))
264 printk(BIOS_DEBUG, "Error: Set S3 LAZY WAKE mask failed\n");
265 /*
266 * Make sure S0Ix is supported before trying to set up the EC's
267 * S0Ix lazy wake mask.
268 */
269 if (s0ix_mask && google_chromeec_set_s0ix_lazy_wake_mask(s0ix_mask))
270 printk(BIOS_DEBUG, "Error: Set S0iX LAZY WAKE mask failed\n");
271 }
272
google_chromeec_get_events_b(void)273 uint64_t google_chromeec_get_events_b(void)
274 {
275 return google_chromeec_get_mask(EC_HOST_EVENT_B);
276 }
277
google_chromeec_clear_events_b(uint64_t mask)278 int google_chromeec_clear_events_b(uint64_t mask)
279 {
280 printk(BIOS_DEBUG,
281 "Chrome EC: clear events_b mask to 0x%016llx\n", mask);
282 return google_chromeec_clear_mask(EC_HOST_EVENT_B, mask);
283 }
284
google_chromeec_get_mkbp_event(struct ec_response_get_next_event * event)285 int google_chromeec_get_mkbp_event(struct ec_response_get_next_event *event)
286 {
287 return ec_cmd_get_next_event(PLAT_EC, event);
288 }
289
290 /* Get the current device event mask */
google_chromeec_get_device_enabled_events(void)291 uint64_t google_chromeec_get_device_enabled_events(void)
292 {
293 const struct ec_params_device_event params = {
294 .param = EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS,
295 };
296 struct ec_response_device_event resp = {};
297
298 if (ec_cmd_device_event(PLAT_EC, ¶ms, &resp) == 0)
299 return resp.event_mask;
300
301 return 0;
302 }
303
304 /* Set the current device event mask */
google_chromeec_set_device_enabled_events(uint64_t mask)305 int google_chromeec_set_device_enabled_events(uint64_t mask)
306 {
307 const struct ec_params_device_event params = {
308 .event_mask = (uint32_t)mask,
309 .param = EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS,
310 };
311 struct ec_response_device_event resp = {};
312
313 return ec_cmd_device_event(PLAT_EC, ¶ms, &resp);
314 }
315
316 /* Read and clear pending device events */
google_chromeec_get_device_current_events(void)317 uint64_t google_chromeec_get_device_current_events(void)
318 {
319 const struct ec_params_device_event params = {
320 .param = EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS,
321 };
322 struct ec_response_device_event resp = {};
323
324 if (ec_cmd_device_event(PLAT_EC, ¶ms, &resp) == 0)
325 return resp.event_mask;
326
327 return 0;
328 }
329
google_chromeec_log_device_events(uint64_t mask)330 static void google_chromeec_log_device_events(uint64_t mask)
331 {
332 uint64_t events;
333 int i;
334
335 if (!CONFIG(ELOG) || !mask)
336 return;
337
338 if (google_chromeec_check_feature(EC_FEATURE_DEVICE_EVENT) != 1)
339 return;
340
341 events = google_chromeec_get_device_current_events() & mask;
342 printk(BIOS_INFO, "EC Device Events: 0x%016llx\n", events);
343
344 for (i = 0; i < sizeof(events) * 8; i++) {
345 if (EC_DEVICE_EVENT_MASK(i) & events)
346 elog_add_event_byte(ELOG_TYPE_EC_DEVICE_EVENT, i);
347 }
348 }
349
google_chromeec_log_events(uint64_t mask)350 void google_chromeec_log_events(uint64_t mask)
351 {
352 uint64_t events;
353 int i;
354
355 if (!CONFIG(ELOG))
356 return;
357
358 events = google_chromeec_get_events_b() & mask;
359
360 /*
361 * This loop starts at 1 because the EC_HOST_EVENT_MASK macro subtracts
362 * 1 from its argument before applying the left-shift operator. This
363 * prevents a left-shift of -1 happening, and covers the entire 64-bit
364 * range of the event mask.
365 */
366 for (i = 1; i <= sizeof(events) * 8; i++) {
367 if (EC_HOST_EVENT_MASK(i) & events)
368 elog_add_event_byte(ELOG_TYPE_EC_EVENT, i);
369 }
370
371 google_chromeec_clear_events_b(events);
372 }
373
google_chromeec_events_init(const struct google_chromeec_event_info * info,bool is_s3_wakeup)374 void google_chromeec_events_init(const struct google_chromeec_event_info *info,
375 bool is_s3_wakeup)
376 {
377 if (is_s3_wakeup) {
378 google_chromeec_log_events(info->log_events |
379 info->s3_wake_events);
380
381 /* Log and clear device events that may wake the system. */
382 google_chromeec_log_device_events(info->s3_device_events);
383
384 /* Disable SMI and wake events. */
385 google_chromeec_set_smi_mask(0);
386
387 /* Restore SCI event mask. */
388 google_chromeec_set_sci_mask(info->sci_events);
389
390 } else {
391 google_chromeec_set_smi_mask(info->smi_events);
392
393 google_chromeec_log_events(info->log_events |
394 info->s5_wake_events);
395
396 if (google_chromeec_is_uhepi_supported())
397 google_chromeec_set_lazy_wake_masks
398 (info->s5_wake_events,
399 info->s3_wake_events,
400 info->s0ix_wake_events);
401 }
402
403 /* Clear wake event mask. */
404 google_chromeec_set_wake_mask(0);
405 }
406
google_chromeec_check_feature(int feature)407 int google_chromeec_check_feature(int feature)
408 {
409 struct ec_response_get_features resp = {};
410
411 if (ec_cmd_get_features(PLAT_EC, &resp) != 0)
412 return -1;
413
414 if (feature >= 8 * sizeof(resp.flags))
415 return -1;
416
417 return resp.flags[feature / 32] & EC_FEATURE_MASK_0(feature);
418 }
419
google_chromeec_get_cmd_versions(int command,uint32_t * pmask)420 int google_chromeec_get_cmd_versions(int command, uint32_t *pmask)
421 {
422 const struct ec_params_get_cmd_versions_v1 params = {
423 .cmd = command,
424 };
425 struct ec_response_get_cmd_versions resp = {};
426
427 if (ec_cmd_get_cmd_versions_v1(PLAT_EC, ¶ms, &resp) != 0)
428 return -1;
429
430 *pmask = resp.version_mask;
431 return 0;
432 }
433
google_chromeec_get_vboot_hash(uint32_t offset,struct ec_response_vboot_hash * resp)434 int google_chromeec_get_vboot_hash(uint32_t offset,
435 struct ec_response_vboot_hash *resp)
436 {
437 const struct ec_params_vboot_hash params = {
438 .cmd = EC_VBOOT_HASH_GET,
439 .offset = offset,
440 };
441
442 if (ec_cmd_vboot_hash(PLAT_EC, ¶ms, resp) != 0)
443 return -1;
444
445 return 0;
446 }
447
google_chromeec_start_vboot_hash(enum ec_vboot_hash_type hash_type,uint32_t hash_offset,struct ec_response_vboot_hash * resp)448 int google_chromeec_start_vboot_hash(enum ec_vboot_hash_type hash_type,
449 uint32_t hash_offset,
450 struct ec_response_vboot_hash *resp)
451 {
452 const struct ec_params_vboot_hash params = {
453 .cmd = EC_VBOOT_HASH_START,
454 .hash_type = hash_type,
455 .nonce_size = 0,
456 .offset = hash_offset,
457 };
458
459 if (ec_cmd_vboot_hash(PLAT_EC, ¶ms, resp) != 0)
460 return -1;
461
462 return 0;
463 }
464
google_chromeec_flash_protect(uint32_t mask,uint32_t flags,struct ec_response_flash_protect * resp)465 int google_chromeec_flash_protect(uint32_t mask, uint32_t flags,
466 struct ec_response_flash_protect *resp)
467 {
468 const struct ec_params_flash_protect params = {
469 .mask = mask,
470 .flags = flags,
471 };
472
473 if (ec_cmd_flash_protect_v1(PLAT_EC, ¶ms, resp) != 0)
474 return -1;
475
476 return 0;
477 }
478
google_chromeec_flash_region_info(enum ec_flash_region region,uint32_t * offset,uint32_t * size)479 int google_chromeec_flash_region_info(enum ec_flash_region region,
480 uint32_t *offset, uint32_t *size)
481 {
482 const struct ec_params_flash_region_info params = {
483 .region = region,
484 };
485 struct ec_response_flash_region_info resp = {};
486
487 if (ec_cmd_flash_region_info_v1(PLAT_EC, ¶ms, &resp) != 0)
488 return -1;
489
490 if (offset)
491 *offset = resp.offset;
492 if (size)
493 *size = resp.size;
494
495 return 0;
496 }
497
google_chromeec_flash_erase(uint32_t offset,uint32_t size)498 int google_chromeec_flash_erase(uint32_t offset, uint32_t size)
499 {
500 const struct ec_params_flash_erase params = {
501 .offset = offset,
502 .size = size,
503 };
504
505 if (ec_cmd_flash_erase(PLAT_EC, ¶ms) != 0)
506 return -1;
507
508 return 0;
509 }
510
google_chromeec_flash_info(struct ec_response_flash_info * info)511 int google_chromeec_flash_info(struct ec_response_flash_info *info)
512 {
513 if (ec_cmd_flash_info(PLAT_EC, info) != 0)
514 return -1;
515
516 return 0;
517 }
518
519 /*
520 * Write a block into EC flash. Expects params_data to be a buffer where
521 * the first N bytes are a struct ec_params_flash_write, and the rest of it
522 * is the data to write to flash.
523 */
google_chromeec_flash_write_block(const uint8_t * params_data,uint32_t bufsize)524 int google_chromeec_flash_write_block(const uint8_t *params_data,
525 uint32_t bufsize)
526 {
527 struct chromeec_command cmd = {
528 .cmd_code = EC_CMD_FLASH_WRITE,
529 .cmd_version = EC_VER_FLASH_WRITE,
530 .cmd_size_out = 0,
531 .cmd_data_out = NULL,
532 .cmd_size_in = bufsize,
533 .cmd_data_in = params_data,
534 .cmd_dev_index = 0,
535 };
536
537 assert(params_data);
538
539 return google_chromeec_command(&cmd);
540 }
541
542 /*
543 * EFS verification of flash.
544 */
google_chromeec_efs_verify(enum ec_flash_region region)545 int google_chromeec_efs_verify(enum ec_flash_region region)
546 {
547 struct ec_params_efs_verify params = {
548 .region = region,
549 };
550 struct chromeec_command cmd = {
551 .cmd_code = EC_CMD_EFS_VERIFY,
552 .cmd_version = 0,
553 .cmd_size_in = sizeof(params),
554 .cmd_data_in = ¶ms,
555 .cmd_size_out = 0,
556 .cmd_data_out = NULL,
557 .cmd_dev_index = 0,
558 };
559 int rv;
560
561 /* It's okay if the EC doesn't support EFS */
562 rv = google_chromeec_command(&cmd);
563 if (rv != 0 && (cmd.cmd_code == EC_RES_INVALID_COMMAND))
564 return 0;
565 else if (rv != 0)
566 return -1;
567
568 return 0;
569 }
570
google_chromeec_battery_cutoff(uint8_t flags)571 int google_chromeec_battery_cutoff(uint8_t flags)
572 {
573 const struct ec_params_battery_cutoff params = {
574 .flags = flags,
575 };
576
577 if (ec_cmd_battery_cut_off_v1(PLAT_EC, ¶ms) != 0)
578 return -1;
579
580 return 0;
581 }
582
google_chromeec_read_limit_power_request(int * limit_power)583 int google_chromeec_read_limit_power_request(int *limit_power)
584 {
585 const struct ec_params_charge_state params = {
586 .cmd = CHARGE_STATE_CMD_GET_PARAM,
587 .get_param.param = CS_PARAM_LIMIT_POWER,
588 };
589 struct ec_response_charge_state resp = {};
590 struct chromeec_command cmd = {
591 .cmd_code = EC_CMD_CHARGE_STATE,
592 .cmd_version = 0,
593 .cmd_size_in = sizeof(params),
594 .cmd_data_in = ¶ms,
595 .cmd_size_out = sizeof(resp),
596 .cmd_data_out = &resp,
597 .cmd_dev_index = 0,
598 };
599 int rv;
600
601 rv = google_chromeec_command(&cmd);
602
603 if (rv != 0 && (cmd.cmd_code == EC_RES_INVALID_COMMAND ||
604 cmd.cmd_code == EC_RES_INVALID_PARAM)) {
605 printk(BIOS_INFO, "PARAM_LIMIT_POWER not supported by EC.\n");
606 *limit_power = 0;
607 return 0;
608 } else if (rv != 0) {
609 return -1;
610 }
611
612 *limit_power = resp.get_param.value;
613
614 return 0;
615 }
616
google_chromeec_get_protocol_info(struct ec_response_get_protocol_info * resp)617 int google_chromeec_get_protocol_info(
618 struct ec_response_get_protocol_info *resp)
619 {
620 if (ec_cmd_get_protocol_info(PLAT_EC, resp))
621 return -1;
622
623 return 0;
624 }
625
google_chromeec_set_sku_id(uint32_t skuid)626 int google_chromeec_set_sku_id(uint32_t skuid)
627 {
628 const struct ec_sku_id_info params = {
629 .sku_id = skuid
630 };
631
632 if (ec_cmd_set_sku_id(PLAT_EC, ¶ms) != 0)
633 return -1;
634
635 return 0;
636 }
637
638 #if CONFIG(EC_GOOGLE_CHROMEEC_RTC)
rtc_get(struct rtc_time * time)639 int rtc_get(struct rtc_time *time)
640 {
641 struct ec_response_rtc resp = {};
642
643 if (ec_cmd_rtc_get_value(PLAT_EC, &resp) != 0)
644 return -1;
645
646 return rtc_to_tm(resp.time, time);
647 }
648 #endif
649
google_chromeec_reboot(enum ec_reboot_cmd type,uint8_t flags)650 int google_chromeec_reboot(enum ec_reboot_cmd type, uint8_t flags)
651 {
652 const struct ec_params_reboot_ec params = {
653 .cmd = type,
654 .flags = flags,
655 };
656
657 return ec_cmd_reboot_ec(PLAT_EC, ¶ms);
658 }
659
cbi_get_uint32(uint32_t * id,uint32_t tag)660 static int cbi_get_uint32(uint32_t *id, uint32_t tag)
661 {
662 struct ec_params_get_cbi params = {
663 .tag = tag,
664 };
665 uint32_t r = 0;
666 struct chromeec_command cmd = {
667 .cmd_code = EC_CMD_GET_CROS_BOARD_INFO,
668 .cmd_version = 0,
669 .cmd_data_in = ¶ms,
670 .cmd_data_out = &r,
671 .cmd_size_in = sizeof(params),
672 .cmd_size_out = sizeof(r),
673 .cmd_dev_index = 0,
674 };
675 int rv;
676
677 rv = google_chromeec_command(&cmd);
678 if (rv != 0)
679 return rv;
680
681 *id = r;
682 return 0;
683 }
684
google_chromeec_cbi_get_sku_id(uint32_t * id)685 int google_chromeec_cbi_get_sku_id(uint32_t *id)
686 {
687 return cbi_get_uint32(id, CBI_TAG_SKU_ID);
688 }
689
google_chromeec_cbi_get_fw_config(uint64_t * fw_config)690 int google_chromeec_cbi_get_fw_config(uint64_t *fw_config)
691 {
692 uint32_t config;
693
694 if (cbi_get_uint32(&config, CBI_TAG_FW_CONFIG))
695 return -1;
696
697 *fw_config = (uint64_t)config;
698 /*
699 * If SSFC is configured to be part of FW_CONFIG, add it at the most significant
700 * 32 bits.
701 */
702 if (CONFIG(EC_GOOGLE_CHROMEEC_INCLUDE_SSFC_IN_FW_CONFIG)) {
703 uint32_t ssfc;
704
705 if (!google_chromeec_cbi_get_ssfc(&ssfc))
706 *fw_config |= (uint64_t)ssfc << 32;
707 }
708 return 0;
709 }
710
google_chromeec_cbi_get_oem_id(uint32_t * id)711 int google_chromeec_cbi_get_oem_id(uint32_t *id)
712 {
713 return cbi_get_uint32(id, CBI_TAG_OEM_ID);
714 }
715
google_chromeec_cbi_get_board_version(uint32_t * version)716 int google_chromeec_cbi_get_board_version(uint32_t *version)
717 {
718 return cbi_get_uint32(version, CBI_TAG_BOARD_VERSION);
719 }
720
google_chromeec_cbi_get_ssfc(uint32_t * ssfc)721 int google_chromeec_cbi_get_ssfc(uint32_t *ssfc)
722 {
723 return cbi_get_uint32(ssfc, CBI_TAG_SSFC);
724 }
725
google_chromeec_get_ucsi_enabled(void)726 bool google_chromeec_get_ucsi_enabled(void)
727 {
728 int rv;
729
730 rv = google_chromeec_check_feature(EC_FEATURE_UCSI_PPM);
731 if (rv < 0) {
732 printk(BIOS_INFO, "Cannot check if EC_FEATURE_UCSI_PPM is available: status = %d\n", rv);
733 return false;
734 }
735
736 return rv != 0;
737 }
738
cbi_get_string(char * buf,size_t bufsize,uint32_t tag)739 static int cbi_get_string(char *buf, size_t bufsize, uint32_t tag)
740 {
741 struct ec_params_get_cbi params = {
742 .tag = tag,
743 };
744 struct chromeec_command cmd = {
745 .cmd_code = EC_CMD_GET_CROS_BOARD_INFO,
746 .cmd_version = 0,
747 .cmd_data_in = ¶ms,
748 .cmd_data_out = buf,
749 .cmd_size_in = sizeof(params),
750 .cmd_size_out = bufsize,
751 };
752 int rv;
753
754 rv = google_chromeec_command(&cmd);
755 if (rv != 0)
756 return rv;
757
758 /* Ensure NUL termination. */
759 buf[bufsize - 1] = '\0';
760
761 return 0;
762 }
763
google_chromeec_cbi_get_dram_part_num(char * buf,size_t bufsize)764 int google_chromeec_cbi_get_dram_part_num(char *buf, size_t bufsize)
765 {
766 return cbi_get_string(buf, bufsize, CBI_TAG_DRAM_PART_NUM);
767 }
768
google_chromeec_cbi_get_oem_name(char * buf,size_t bufsize)769 int google_chromeec_cbi_get_oem_name(char *buf, size_t bufsize)
770 {
771 return cbi_get_string(buf, bufsize, CBI_TAG_OEM_NAME);
772 }
773
google_chromeec_get_board_version(uint32_t * version)774 int google_chromeec_get_board_version(uint32_t *version)
775 {
776 struct ec_response_board_version resp;
777
778 if (ec_cmd_get_board_version(PLAT_EC, &resp))
779 return -1;
780
781 *version = resp.board_version;
782 return 0;
783 }
784
google_chromeec_get_sku_id(void)785 uint32_t google_chromeec_get_sku_id(void)
786 {
787 struct ec_sku_id_info resp;
788
789 if (ec_cmd_get_sku_id(PLAT_EC, &resp) != 0)
790 return 0;
791
792 return resp.sku_id;
793 }
794
google_chromeec_get_uptime_info(struct ec_response_uptime_info * resp)795 static bool google_chromeec_get_uptime_info(
796 struct ec_response_uptime_info *resp)
797 {
798 return ec_cmd_get_uptime_info(PLAT_EC, resp) == 0;
799 }
800
google_chromeec_get_ap_watchdog_flag(void)801 bool google_chromeec_get_ap_watchdog_flag(void)
802 {
803 int i;
804 struct ec_response_uptime_info resp;
805
806 if (!google_chromeec_get_uptime_info(&resp))
807 return false;
808
809 if (resp.ec_reset_flags & EC_RESET_FLAG_AP_WATCHDOG)
810 return true;
811
812 /* Find the last valid entry */
813 for (i = ARRAY_SIZE(resp.recent_ap_reset) - 1; i >= 0; i--) {
814 if (resp.recent_ap_reset[i].reset_time_ms == 0)
815 continue;
816 return (resp.recent_ap_reset[i].reset_cause ==
817 CHIPSET_RESET_AP_WATCHDOG);
818 }
819
820 return false;
821 }
822
google_chromeec_i2c_xfer(uint8_t chip,uint8_t addr,int alen,uint8_t * buffer,int len,int is_read)823 int google_chromeec_i2c_xfer(uint8_t chip, uint8_t addr, int alen,
824 uint8_t *buffer, int len, int is_read)
825 {
826 union {
827 struct ec_params_i2c_passthru p;
828 uint8_t outbuf[EC_HOST_PARAM_SIZE];
829 } params;
830 union {
831 struct ec_response_i2c_passthru r;
832 uint8_t inbuf[EC_HOST_PARAM_SIZE];
833 } response;
834 struct ec_params_i2c_passthru *p = ¶ms.p;
835 struct ec_response_i2c_passthru *r = &response.r;
836 struct ec_params_i2c_passthru_msg *msg = p->msg;
837 struct chromeec_command cmd;
838 uint8_t *pdata;
839 int read_len, write_len;
840 int size;
841 int rv;
842
843 p->port = 0;
844
845 if (alen != 1) {
846 printk(BIOS_ERR, "Unsupported address length %d\n", alen);
847 return -1;
848 }
849 if (is_read) {
850 read_len = len;
851 write_len = alen;
852 p->num_msgs = 2;
853 } else {
854 read_len = 0;
855 write_len = alen + len;
856 p->num_msgs = 1;
857 }
858
859 size = sizeof(*p) + p->num_msgs * sizeof(*msg);
860 if (size + write_len > sizeof(params)) {
861 printk(BIOS_ERR, "Params too large for buffer\n");
862 return -1;
863 }
864 if (sizeof(*r) + read_len > sizeof(response)) {
865 printk(BIOS_ERR, "Read length too big for buffer\n");
866 return -1;
867 }
868
869 /* Create a message to write the register address and optional data */
870 pdata = (uint8_t *)p + size;
871 msg->addr_flags = chip;
872 msg->len = write_len;
873 pdata[0] = addr;
874 if (!is_read)
875 memcpy(pdata + 1, buffer, len);
876 msg++;
877
878 if (read_len) {
879 msg->addr_flags = chip | EC_I2C_FLAG_READ;
880 msg->len = read_len;
881 }
882
883 cmd.cmd_code = EC_CMD_I2C_PASSTHRU;
884 cmd.cmd_version = 0;
885 cmd.cmd_data_in = p;
886 cmd.cmd_size_in = size + write_len;
887 cmd.cmd_data_out = r;
888 cmd.cmd_size_out = sizeof(*r) + read_len;
889 cmd.cmd_dev_index = 0;
890 rv = google_chromeec_command(&cmd);
891 if (rv != 0)
892 return rv;
893
894 /* Parse response */
895 if (r->i2c_status & EC_I2C_STATUS_ERROR) {
896 printk(BIOS_ERR, "Transfer failed with status=0x%x\n",
897 r->i2c_status);
898 return -1;
899 }
900
901 if (cmd.cmd_size_out < sizeof(*r) + read_len) {
902 printk(BIOS_ERR, "Truncated read response\n");
903 return -1;
904 }
905
906 if (read_len)
907 memcpy(buffer, r->data, read_len);
908
909 return 0;
910 }
911
google_chromeec_set_sci_mask(uint64_t mask)912 int google_chromeec_set_sci_mask(uint64_t mask)
913 {
914 printk(BIOS_DEBUG, "Chrome EC: Set SCI mask to 0x%016llx\n", mask);
915 return google_chromeec_set_mask(EC_HOST_EVENT_SCI_MASK, mask);
916 }
917
google_chromeec_set_smi_mask(uint64_t mask)918 int google_chromeec_set_smi_mask(uint64_t mask)
919 {
920 printk(BIOS_DEBUG, "Chrome EC: Set SMI mask to 0x%016llx\n", mask);
921 return google_chromeec_set_mask(EC_HOST_EVENT_SMI_MASK, mask);
922 }
923
google_chromeec_set_wake_mask(uint64_t mask)924 int google_chromeec_set_wake_mask(uint64_t mask)
925 {
926 printk(BIOS_DEBUG, "Chrome EC: Set WAKE mask to 0x%016llx\n", mask);
927 return google_chromeec_set_mask
928 (EC_HOST_EVENT_ACTIVE_WAKE_MASK, mask);
929 }
930
google_chromeec_get_wake_mask(void)931 uint64_t google_chromeec_get_wake_mask(void)
932 {
933 return google_chromeec_get_mask(EC_HOST_EVENT_ACTIVE_WAKE_MASK);
934 }
935
google_chromeec_set_usb_charge_mode(uint8_t port_id,enum usb_charge_mode mode)936 int google_chromeec_set_usb_charge_mode(uint8_t port_id, enum usb_charge_mode mode)
937 {
938 const struct ec_params_usb_charge_set_mode params = {
939 .usb_port_id = port_id,
940 .mode = mode,
941 };
942
943 return ec_cmd_usb_charge_set_mode(PLAT_EC, ¶ms);
944 }
945
946 /* Get charger voltage and current. Also returns type of charger */
google_chromeec_get_usb_pd_power_info(enum usb_chg_type * type,uint16_t * current_max,uint16_t * voltage_max)947 int google_chromeec_get_usb_pd_power_info(enum usb_chg_type *type,
948 uint16_t *current_max, uint16_t *voltage_max)
949 {
950 const struct ec_params_usb_pd_power_info params = {
951 .port = PD_POWER_CHARGING_PORT,
952 };
953 struct ec_response_usb_pd_power_info resp = {};
954 struct usb_chg_measures m;
955 int rv;
956
957 rv = ec_cmd_usb_pd_power_info(PLAT_EC, ¶ms, &resp);
958 if (rv != 0)
959 return rv;
960
961 /* values are given in milliAmps and milliVolts */
962 *type = resp.type;
963 m = resp.meas;
964 *voltage_max = m.voltage_max;
965 *current_max = m.current_max;
966 return 0;
967 }
968
google_chromeec_override_dedicated_charger_limit(uint16_t current_lim,uint16_t voltage_lim)969 int google_chromeec_override_dedicated_charger_limit(uint16_t current_lim,
970 uint16_t voltage_lim)
971 {
972 const struct ec_params_dedicated_charger_limit params = {
973 .current_lim = current_lim,
974 .voltage_lim = voltage_lim,
975 };
976
977 return ec_cmd_override_dedicated_charger_limit(PLAT_EC, ¶ms);
978 }
979
google_chromeec_set_usb_pd_role(uint8_t port,enum usb_pd_control_role role)980 int google_chromeec_set_usb_pd_role(uint8_t port, enum usb_pd_control_role role)
981 {
982 const struct ec_params_usb_pd_control params = {
983 .port = port,
984 .role = role,
985 .mux = USB_PD_CTRL_MUX_NO_CHANGE,
986 .swap = USB_PD_CTRL_SWAP_NONE,
987 };
988 struct ec_response_usb_pd_control resp;
989
990 return ec_cmd_usb_pd_control(PLAT_EC, ¶ms, &resp);
991 }
992
google_chromeec_hello(void)993 int google_chromeec_hello(void)
994 {
995 const struct ec_params_hello params = {
996 .in_data = 0x10203040,
997 };
998 struct ec_response_hello resp = {};
999
1000 int rv = ec_cmd_hello(PLAT_EC, ¶ms, &resp);
1001 if (rv)
1002 return -1;
1003
1004 if (resp.out_data != (params.in_data + 0x01020304))
1005 return -1;
1006
1007 return 0;
1008 }
1009
1010 /*
1011 * Convert a reset cause ID to human-readable string, providing total coverage
1012 * of the 'cause' space. The returned string points to static storage and must
1013 * not be free()ed.
1014 */
reset_cause_to_str(uint16_t cause)1015 static const char *reset_cause_to_str(uint16_t cause)
1016 {
1017 /* See also ChromiumOS EC include/chipset.h for details. */
1018 static const char * const reset_causes[] = {
1019 "(reset unknown)",
1020 "reset: board custom",
1021 "reset: ap hang detected",
1022 "reset: console command",
1023 "reset: keyboard sysreset",
1024 "reset: keyboard warm reboot",
1025 "reset: debug warm reboot",
1026 "reset: at AP's request",
1027 "reset: during EC initialization",
1028 "reset: AP watchdog",
1029 };
1030
1031 static const size_t shutdown_cause_begin = 1 << 15;
1032 static const char * const shutdown_causes[] = {
1033 "shutdown: power failure",
1034 "shutdown: during EC initialization",
1035 "shutdown: board custom",
1036 "shutdown: battery voltage startup inhibit",
1037 "shutdown: power wait asserted",
1038 "shutdown: critical battery",
1039 "shutdown: by console command",
1040 "shutdown: entering G3",
1041 "shutdown: thermal",
1042 "shutdown: power button",
1043 };
1044
1045 if (cause < ARRAY_SIZE(reset_causes))
1046 return reset_causes[cause];
1047
1048 if (cause < shutdown_cause_begin)
1049 return "(reset unknown)";
1050
1051 if (cause < shutdown_cause_begin + ARRAY_SIZE(shutdown_causes))
1052 return shutdown_causes[cause - shutdown_cause_begin];
1053
1054 return "(shutdown unknown)";
1055 }
1056
1057 /*
1058 * Copy the EC's information about resets of the AP and its own uptime for
1059 * debugging purposes.
1060 */
google_chromeec_log_uptimeinfo(void)1061 static void google_chromeec_log_uptimeinfo(void)
1062 {
1063 /* See also ec_commands.h EC_RESET_FLAG_* for details. */
1064 static const char * const reset_flag_strings[] = {
1065 "other",
1066 "reset-pin",
1067 "brownout",
1068 "power-on",
1069 "watchdog",
1070 "soft",
1071 "hibernate",
1072 "rtc-alarm",
1073 "wake-pin",
1074 "low-battery",
1075 "sysjump",
1076 "hard",
1077 "ap-off",
1078 "preserved",
1079 "usb-resume",
1080 "rdd",
1081 "rbox",
1082 "security",
1083 "ap-watchdog",
1084 };
1085 struct ec_response_uptime_info cmd_resp;
1086 int i, flag, flag_count;
1087
1088 if (!google_chromeec_get_uptime_info(&cmd_resp)) {
1089 /*
1090 * Deliberately say nothing for EC's that don't support this
1091 * command
1092 */
1093 return;
1094 }
1095
1096 printk(BIOS_DEBUG, "Google Chrome EC uptime: %d.%03d seconds\n",
1097 cmd_resp.time_since_ec_boot_ms / MSECS_PER_SEC,
1098 cmd_resp.time_since_ec_boot_ms % MSECS_PER_SEC);
1099
1100 printk(BIOS_DEBUG, "Google Chrome AP resets since EC boot: %d\n",
1101 cmd_resp.ap_resets_since_ec_boot);
1102
1103 printk(BIOS_DEBUG, "Google Chrome most recent AP reset causes:\n");
1104 for (i = 0; i != ARRAY_SIZE(cmd_resp.recent_ap_reset); ++i) {
1105 if (cmd_resp.recent_ap_reset[i].reset_time_ms == 0)
1106 continue;
1107
1108 printk(BIOS_DEBUG, "\t%d.%03d: %d %s\n",
1109 cmd_resp.recent_ap_reset[i].reset_time_ms /
1110 MSECS_PER_SEC,
1111 cmd_resp.recent_ap_reset[i].reset_time_ms %
1112 MSECS_PER_SEC,
1113 cmd_resp.recent_ap_reset[i].reset_cause,
1114 reset_cause_to_str(
1115 cmd_resp.recent_ap_reset[i].reset_cause));
1116 }
1117
1118 printk(BIOS_DEBUG, "Google Chrome EC reset flags at last EC boot: ");
1119 flag_count = 0;
1120 for (flag = 0; flag != ARRAY_SIZE(reset_flag_strings); ++flag) {
1121 if ((cmd_resp.ec_reset_flags & (1 << flag)) != 0) {
1122 if (flag_count)
1123 printk(BIOS_DEBUG, " | ");
1124 printk(BIOS_DEBUG, "%s", reset_flag_strings[flag]);
1125 flag_count++;
1126 }
1127 }
1128 printk(BIOS_DEBUG, "\n");
1129 }
1130
1131 /* Cache and retrieve the EC image type (ro or rw) */
google_chromeec_get_current_image(void)1132 enum ec_image google_chromeec_get_current_image(void)
1133 {
1134 static enum ec_image ec_image_type = EC_IMAGE_UNKNOWN;
1135
1136 if (ec_image_type != EC_IMAGE_UNKNOWN)
1137 return ec_image_type;
1138
1139 struct ec_response_get_version resp = {};
1140 int rv;
1141
1142 rv = ec_cmd_get_version(PLAT_EC, &resp);
1143
1144 if (rv != 0) {
1145 printk(BIOS_DEBUG,
1146 "Google Chrome EC: version command failed!\n");
1147 } else {
1148 printk(BIOS_DEBUG, "Google Chrome EC: version:\n");
1149 printk(BIOS_DEBUG, " ro: %s\n", resp.version_string_ro);
1150 printk(BIOS_DEBUG, " rw: %s\n", resp.version_string_rw);
1151 printk(BIOS_DEBUG, " running image: %d\n",
1152 resp.current_image);
1153 ec_image_type = resp.current_image;
1154 }
1155
1156 /* Will still be UNKNOWN if command failed */
1157 return ec_image_type;
1158 }
1159
google_chromeec_get_num_pd_ports(unsigned int * num_ports)1160 int google_chromeec_get_num_pd_ports(unsigned int *num_ports)
1161 {
1162 struct ec_response_usb_pd_ports resp = {};
1163 int rv;
1164
1165 rv = ec_cmd_usb_pd_ports(PLAT_EC, &resp);
1166 if (rv)
1167 return rv;
1168
1169 *num_ports = resp.num_ports;
1170 return 0;
1171 }
1172
google_chromeec_get_pd_port_caps(int port,struct usb_pd_port_caps * port_caps)1173 int google_chromeec_get_pd_port_caps(int port,
1174 struct usb_pd_port_caps *port_caps)
1175 {
1176 const struct ec_params_get_pd_port_caps params = {
1177 .port = port,
1178 };
1179 struct ec_response_get_pd_port_caps resp = {};
1180 int rv;
1181
1182 rv = ec_cmd_get_pd_port_caps(PLAT_EC, ¶ms, &resp);
1183 if (rv)
1184 return rv;
1185
1186 port_caps->power_role_cap = resp.pd_power_role_cap;
1187 port_caps->try_power_role_cap = resp.pd_try_power_role_cap;
1188 port_caps->data_role_cap = resp.pd_data_role_cap;
1189 port_caps->port_location = resp.pd_port_location;
1190
1191 return 0;
1192 }
1193
google_chromeec_init(void)1194 void google_chromeec_init(void)
1195 {
1196 google_chromeec_log_uptimeinfo();
1197
1198 /* Enable automatic fan control */
1199 if (CONFIG(EC_GOOGLE_CHROMEEC_AUTO_FAN_CTRL)) {
1200 ec_cmd_thermal_auto_fan_ctrl(PLAT_EC);
1201 }
1202 }
1203
google_ec_running_ro(void)1204 int google_ec_running_ro(void)
1205 {
1206 return (google_chromeec_get_current_image() == EC_IMAGE_RO);
1207 }
1208
1209 /* Returns data role and type of device connected */
google_chromeec_usb_pd_get_info(int port,bool * ufp,bool * dbg_acc,bool * active_cable,uint8_t * dp_mode)1210 static int google_chromeec_usb_pd_get_info(int port, bool *ufp, bool *dbg_acc,
1211 bool *active_cable, uint8_t *dp_mode)
1212 {
1213 const struct ec_params_usb_pd_control pd_control = {
1214 .port = port,
1215 .role = USB_PD_CTRL_ROLE_NO_CHANGE,
1216 .mux = USB_PD_CTRL_ROLE_NO_CHANGE,
1217 .swap = USB_PD_CTRL_SWAP_NONE,
1218 };
1219 struct ec_response_usb_pd_control_v2 resp = {};
1220
1221 if (ec_cmd_usb_pd_control_v2(PLAT_EC, &pd_control, &resp) < 0)
1222 return -1;
1223
1224 *ufp = !(resp.role & PD_CTRL_RESP_ROLE_DATA);
1225 *dbg_acc = (resp.cc_state == PD_CC_DFP_DEBUG_ACC);
1226 *active_cable = !!(resp.control_flags & USB_PD_CTRL_ACTIVE_CABLE);
1227 *dp_mode = resp.dp_mode;
1228
1229 return 0;
1230 }
1231
google_chromeec_typec_control_enter_dp_mode(int port)1232 int google_chromeec_typec_control_enter_dp_mode(int port)
1233 {
1234 int ret;
1235 struct usbc_mux_info mux_info;
1236
1237 if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY))
1238 return 0;
1239
1240 ret = google_chromeec_get_usbc_mux_info(port, &mux_info);
1241 if ((ret < 0) || (!mux_info.usb))
1242 return -1;
1243
1244 const struct ec_params_typec_control typec_control = {
1245 .port = port,
1246 .command = TYPEC_CONTROL_COMMAND_ENTER_MODE,
1247 .mode_to_enter = TYPEC_MODE_DP,
1248 };
1249
1250 if (ec_cmd_typec_control(PLAT_EC, &typec_control) < 0)
1251 return -1;
1252
1253 return 0;
1254 }
1255
1256 /**
1257 * Check for the current mux state in EC. Flags representing the mux state found
1258 * in ec_commands.h
1259 */
google_chromeec_usb_get_pd_mux_info(int port,uint8_t * flags)1260 int google_chromeec_usb_get_pd_mux_info(int port, uint8_t *flags)
1261 {
1262 const struct ec_params_usb_pd_mux_info req_mux = {
1263 .port = port,
1264 };
1265 struct ec_response_usb_pd_mux_info resp_mux = {};
1266
1267 if (port < 0)
1268 return -1;
1269
1270 if (ec_cmd_usb_pd_mux_info(PLAT_EC, &req_mux, &resp_mux) < 0)
1271 return -1;
1272
1273 *flags = resp_mux.flags;
1274 return 0;
1275 }
1276
1277 /*
1278 * Obtain any USB-C mux data needed for the specified port
1279 * in: physical port number of the type-c port
1280 * out: struct usbc_mux_info mux_info stores USB-C mux data
1281 * Return: 0 on success, -1 on error
1282 */
google_chromeec_get_usbc_mux_info(int port,struct usbc_mux_info * mux_info)1283 int google_chromeec_get_usbc_mux_info(int port, struct usbc_mux_info *mux_info)
1284 {
1285 uint8_t mux_flags;
1286 uint8_t dp_pin_mode;
1287 bool ufp, dbg_acc, active_cable;
1288
1289 if (google_chromeec_usb_get_pd_mux_info(port, &mux_flags) < 0) {
1290 printk(BIOS_ERR, "Port C%d: get_pd_mux_info failed\n", port);
1291 return -1;
1292 }
1293
1294 if (google_chromeec_usb_pd_get_info(port, &ufp, &dbg_acc,
1295 &active_cable, &dp_pin_mode) < 0) {
1296 printk(BIOS_ERR, "Port C%d: pd_control failed\n", port);
1297 return -1;
1298 }
1299
1300 mux_info->usb = !!(mux_flags & USB_PD_MUX_USB_ENABLED);
1301 mux_info->dp = !!(mux_flags & USB_PD_MUX_DP_ENABLED);
1302 mux_info->polarity = !!(mux_flags & USB_PD_MUX_POLARITY_INVERTED);
1303 mux_info->hpd_irq = !!(mux_flags & USB_PD_MUX_HPD_IRQ);
1304 mux_info->hpd_lvl = !!(mux_flags & USB_PD_MUX_HPD_LVL);
1305 mux_info->ufp = !!ufp;
1306 mux_info->dbg_acc = !!dbg_acc;
1307 mux_info->cable = !!active_cable;
1308 mux_info->dp_pin_mode = dp_pin_mode;
1309
1310 return 0;
1311 }
1312
1313 /**
1314 * Check if EC/TCPM is in an alternate mode or not.
1315 *
1316 * @param svid SVID of the alternate mode to check
1317 * @return 0: Not in the mode. -1: Error.
1318 * >=1: bitmask of the ports that are in the mode.
1319 */
google_chromeec_pd_get_amode(uint16_t svid)1320 static int google_chromeec_pd_get_amode(uint16_t svid)
1321 {
1322 struct ec_response_usb_pd_ports resp;
1323 int i;
1324 int ret = 0;
1325
1326 if (ec_cmd_usb_pd_ports(PLAT_EC, &resp) < 0)
1327 return -1;
1328
1329 for (i = 0; i < resp.num_ports; i++) {
1330 struct chromeec_command cmd = { };
1331 struct ec_params_usb_pd_get_mode_request params;
1332 struct ec_params_usb_pd_get_mode_response resp2;
1333 int svid_idx = 0;
1334
1335 do {
1336 /* Reset cmd in each iteration in case
1337 google_chromeec_command changes it. */
1338 params.port = i;
1339 params.svid_idx = svid_idx;
1340 cmd.cmd_code = EC_CMD_USB_PD_GET_AMODE;
1341 cmd.cmd_version = 0;
1342 cmd.cmd_data_in = ¶ms;
1343 cmd.cmd_size_in = sizeof(params);
1344 cmd.cmd_data_out = &resp2;
1345 cmd.cmd_size_out = sizeof(resp2);
1346 cmd.cmd_dev_index = 0;
1347
1348 if (google_chromeec_command(&cmd) < 0)
1349 return -1;
1350 if (resp2.svid == svid)
1351 ret |= BIT(i);
1352 svid_idx++;
1353 } while (resp2.svid);
1354 }
1355
1356 return ret;
1357 }
1358
1359 #define USB_SID_DISPLAYPORT 0xff01
1360
1361 /**
1362 * Wait for DisplayPort to be ready
1363 *
1364 * @param timeout_ms Wait aborts after <timeout_ms> ms.
1365 * @return -1: Error. 0: Timeout.
1366 * >=1: Bitmask of the ports that DP device is connected
1367 */
google_chromeec_wait_for_displayport(long timeout_ms)1368 int google_chromeec_wait_for_displayport(long timeout_ms)
1369 {
1370 struct stopwatch sw;
1371 int ret = 0;
1372
1373 if (google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) {
1374 printk(BIOS_INFO, "AP Mode Entry enabled, skip waiting for DisplayPort connection\n");
1375 return -1;
1376 }
1377
1378 printk(BIOS_INFO, "Waiting for DisplayPort\n");
1379 stopwatch_init_msecs_expire(&sw, timeout_ms);
1380 while (1) {
1381 ret = google_chromeec_pd_get_amode(USB_SID_DISPLAYPORT);
1382 if (ret > 0)
1383 break;
1384
1385 if (ret < 0) {
1386 printk(BIOS_ERR, "Can't get alternate mode!\n");
1387 return ret;
1388 }
1389
1390 if (stopwatch_expired(&sw)) {
1391 printk(BIOS_WARNING,
1392 "DisplayPort not ready after %ldms. Abort.\n",
1393 timeout_ms);
1394 return 0;
1395 }
1396 mdelay(200);
1397 }
1398 printk(BIOS_INFO, "DisplayPort ready after %lld ms\n",
1399 stopwatch_duration_msecs(&sw));
1400
1401 return ret;
1402 }
1403
1404 /**
1405 * Check for given flag in PD mux info for a port.
1406 *
1407 * @param port Type-C port number
1408 * flag Flag to check
1409 * @return 1: Flag is set. 0: Flag is not set.
1410 */
google_chromeec_check_mux_flag(int port,uint8_t flag)1411 static int google_chromeec_check_mux_flag(int port, uint8_t flag)
1412 {
1413 uint8_t mux_flags = 0;
1414 google_chromeec_usb_get_pd_mux_info(port, &mux_flags);
1415 if ((mux_flags & flag) == flag)
1416 return 1;
1417 return 0;
1418 }
1419
google_chromeec_wait_for_dp_mode_entry(int port,long timeout_ms)1420 int google_chromeec_wait_for_dp_mode_entry(int port, long timeout_ms)
1421 {
1422 struct stopwatch sw;
1423
1424 if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) {
1425 if (!google_chromeec_check_mux_flag(port, USB_PD_MUX_DP_ENABLED)) {
1426 printk(BIOS_WARNING, "DP mode entry is not ready. Abort.\n");
1427 return -1;
1428 }
1429
1430 return 0;
1431 }
1432
1433 stopwatch_init_msecs_expire(&sw, timeout_ms);
1434 while (!google_chromeec_check_mux_flag(port, USB_PD_MUX_DP_ENABLED)) {
1435 if (stopwatch_expired(&sw)) {
1436 printk(BIOS_WARNING, "DP not ready after %ldms. Abort.\n", timeout_ms);
1437 return -1;
1438 }
1439 mdelay(100);
1440 }
1441 printk(BIOS_INFO, "DP ready after %lld ms\n", stopwatch_duration_msecs(&sw));
1442
1443 return 0;
1444 }
1445
google_chromeec_wait_for_hpd(int port,long timeout_ms)1446 int google_chromeec_wait_for_hpd(int port, long timeout_ms)
1447 {
1448 struct stopwatch sw;
1449
1450 if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) {
1451 if (!google_chromeec_check_mux_flag(port, USB_PD_MUX_HPD_LVL)) {
1452 printk(BIOS_WARNING, "HPD not ready. Abort.\n");
1453 return -1;
1454 }
1455
1456 return 0;
1457 }
1458
1459 stopwatch_init_msecs_expire(&sw, timeout_ms);
1460 while (!google_chromeec_check_mux_flag(port, USB_PD_MUX_HPD_LVL)) {
1461 if (stopwatch_expired(&sw)) {
1462 printk(BIOS_WARNING, "HPD not ready after %ldms. Abort.\n", timeout_ms);
1463 return -1;
1464 }
1465 mdelay(100);
1466 }
1467 printk(BIOS_INFO, "HPD ready after %lld ms\n", stopwatch_duration_msecs(&sw));
1468
1469 return 0;
1470 }
1471
google_chromeec_get_keybd_config(struct ec_response_keybd_config * keybd)1472 int google_chromeec_get_keybd_config(struct ec_response_keybd_config *keybd)
1473 {
1474 if (ec_cmd_get_keybd_config(PLAT_EC, keybd))
1475 return -1;
1476 return 0;
1477 }
1478
google_chromeec_ap_reset(void)1479 int google_chromeec_ap_reset(void)
1480 {
1481 if (ec_cmd_ap_reset(NULL))
1482 return -1;
1483
1484 return 0;
1485 }
1486
google_chromeec_regulator_enable(uint32_t index,uint8_t enable)1487 int google_chromeec_regulator_enable(uint32_t index, uint8_t enable)
1488 {
1489 const struct ec_params_regulator_enable params = {
1490 .index = index,
1491 .enable = enable,
1492 };
1493
1494 if (ec_cmd_regulator_enable(PLAT_EC, ¶ms))
1495 return -1;
1496
1497 return 0;
1498 }
1499
google_chromeec_regulator_is_enabled(uint32_t index,uint8_t * enabled)1500 int google_chromeec_regulator_is_enabled(uint32_t index, uint8_t *enabled)
1501 {
1502 const struct ec_params_regulator_is_enabled params = {
1503 .index = index,
1504 };
1505 struct ec_response_regulator_is_enabled resp = {};
1506
1507 if (ec_cmd_regulator_is_enabled(PLAT_EC, ¶ms, &resp))
1508 return -1;
1509
1510 *enabled = resp.enabled;
1511
1512 return 0;
1513 }
1514
google_chromeec_regulator_set_voltage(uint32_t index,uint32_t min_mv,uint32_t max_mv)1515 int google_chromeec_regulator_set_voltage(uint32_t index, uint32_t min_mv,
1516 uint32_t max_mv)
1517 {
1518 const struct ec_params_regulator_set_voltage params = {
1519 .index = index,
1520 .min_mv = min_mv,
1521 .max_mv = max_mv,
1522 };
1523
1524 if (ec_cmd_regulator_set_voltage(PLAT_EC, ¶ms))
1525 return -1;
1526
1527 return 0;
1528 }
1529
google_chromeec_regulator_get_voltage(uint32_t index,uint32_t * voltage_mv)1530 int google_chromeec_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv)
1531 {
1532 const struct ec_params_regulator_get_voltage params = {
1533 .index = index,
1534 };
1535 struct ec_response_regulator_get_voltage resp = {};
1536
1537 if (ec_cmd_regulator_get_voltage(PLAT_EC, ¶ms, &resp))
1538 return -1;
1539
1540 *voltage_mv = resp.voltage_mv;
1541 return 0;
1542 }
1543
google_chromeec_clear_ec_ap_idle(void)1544 void google_chromeec_clear_ec_ap_idle(void)
1545 {
1546 /* Send EC command to clear AP_IDLE flag */
1547 if (!google_chromeec_reboot(EC_REBOOT_NO_OP, EC_REBOOT_FLAG_CLEAR_AP_IDLE |
1548 EC_REBOOT_FLAG_ON_AP_SHUTDOWN))
1549 printk(BIOS_INFO, "Successfully clear AP_IDLE flag\n");
1550 else
1551 printk(BIOS_ERR, "Failed to clear EC AP_IDLE flag\n");
1552 }
1553
google_chromeec_is_battery_present_and_above_critical_threshold(void)1554 bool google_chromeec_is_battery_present_and_above_critical_threshold(void)
1555 {
1556 struct ec_params_battery_dynamic_info params = {
1557 .index = 0,
1558 };
1559 struct ec_response_battery_dynamic_info resp;
1560
1561 if (ec_cmd_battery_get_dynamic(PLAT_EC, ¶ms, &resp) == 0) {
1562 /* Check if battery is present and LEVEL_CRITICAL is not set */
1563 if (resp.flags && !(resp.flags & EC_BATT_FLAG_LEVEL_CRITICAL))
1564 return true;
1565 }
1566
1567 return false;
1568 }
1569