1 /* SPDX-License-Identifier: GPL-2.0-only */
6 #include <console/console.h>
8 #include <device/device.h>
9 #include <device/path.h>
12 #include <security/vboot/vboot_common.h>
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) { \
24 .cmd_size_in = (ps), \
25 .cmd_data_out = (r), \
26 .cmd_size_out = (rs), \
30 #include "ec_cmd_api.h"
33 * coreboot only supports a single platform EC, so there is no need to
34 * provide a context handle for the EC.
38 #define INVALID_HCMD 0xFF
41 * Map UHEPI masks to non UHEPI commands in order to support old EC FW
42 * which does not support UHEPI command.
49 [EC_HOST_EVENT_MAIN
] = {
50 INVALID_HCMD
, EC_CMD_HOST_EVENT_CLEAR
,
54 INVALID_HCMD
, EC_CMD_HOST_EVENT_CLEAR_B
,
55 EC_CMD_HOST_EVENT_GET_B
,
57 [EC_HOST_EVENT_SCI_MASK
] = {
58 EC_CMD_HOST_EVENT_SET_SCI_MASK
, INVALID_HCMD
,
59 EC_CMD_HOST_EVENT_GET_SCI_MASK
,
61 [EC_HOST_EVENT_SMI_MASK
] = {
62 EC_CMD_HOST_EVENT_SET_SMI_MASK
, INVALID_HCMD
,
63 EC_CMD_HOST_EVENT_GET_SMI_MASK
,
65 [EC_HOST_EVENT_ALWAYS_REPORT_MASK
] = {
66 INVALID_HCMD
, INVALID_HCMD
, INVALID_HCMD
,
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
,
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
,
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
,
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
,
86 uint8_t google_chromeec_calc_checksum(const uint8_t *data
, int size
)
90 for (csum
= 0; size
> 0; data
++, size
--)
92 return (uint8_t)(csum
& 0xff);
95 int google_chromeec_kbbacklight(int percent
)
97 const struct ec_params_pwm_set_keyboard_backlight params
= {
98 .percent
= percent
% 101,
101 if (ec_cmd_pwm_set_keyboard_backlight(PLAT_EC
, ¶ms
) != 0)
107 void google_chromeec_post(uint8_t postcode
)
109 /* backlight is a percent. postcode is a uint8_t.
110 * Convert the uint8_t to %.
112 postcode
= (postcode
/4) + (postcode
/8);
113 google_chromeec_kbbacklight(postcode
);
117 * Query the EC for specified mask indicating enabled events.
118 * The EC maintains separate event masks for SMI, SCI and WAKE.
120 static int google_chromeec_uhepi_cmd(uint8_t mask
, uint8_t action
,
124 struct ec_params_host_event params
= {
128 struct ec_response_host_event resp
= {};
130 if (action
!= EC_HOST_EVENT_GET
)
131 params
.value
= *value
;
135 ret
= ec_cmd_host_event(PLAT_EC
, ¶ms
, &resp
);
137 if (action
!= EC_HOST_EVENT_GET
)
144 static int google_chromeec_handle_non_uhepi_cmd(uint8_t hcmd
, uint8_t action
,
148 struct ec_params_host_event_mask params
= {};
149 struct ec_response_host_event_mask resp
= {};
150 struct chromeec_command cmd
= {
153 .cmd_data_in
= ¶ms
,
154 .cmd_size_in
= sizeof(params
),
155 .cmd_data_out
= &resp
,
156 .cmd_size_out
= sizeof(resp
),
160 if (hcmd
== INVALID_HCMD
)
163 if (action
!= EC_HOST_EVENT_GET
)
164 params
.mask
= (uint32_t)*value
;
168 ret
= google_chromeec_command(&cmd
);
170 if (action
!= EC_HOST_EVENT_GET
)
178 bool google_chromeec_is_uhepi_supported(void)
180 #define UHEPI_SUPPORTED 1
181 #define UHEPI_NOT_SUPPORTED 2
183 static int uhepi_support
;
185 if (!uhepi_support
) {
186 uhepi_support
= google_chromeec_check_feature
187 (EC_FEATURE_UNIFIED_WAKE_MASKS
) > 0 ? UHEPI_SUPPORTED
:
189 printk(BIOS_DEBUG
, "Chrome EC: UHEPI %s\n",
190 uhepi_support
== UHEPI_SUPPORTED
?
191 "supported" : "not supported");
193 return uhepi_support
== UHEPI_SUPPORTED
;
196 static uint64_t google_chromeec_get_mask(uint8_t type
)
200 if (google_chromeec_is_uhepi_supported()) {
201 google_chromeec_uhepi_cmd(type
, EC_HOST_EVENT_GET
, &value
);
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
);
211 static int google_chromeec_clear_mask(uint8_t type
, uint64_t mask
)
213 if (google_chromeec_is_uhepi_supported())
214 return google_chromeec_uhepi_cmd(type
,
215 EC_HOST_EVENT_CLEAR
, &mask
);
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
);
223 static int google_chromeec_set_mask(uint8_t type
, uint64_t mask
)
225 if (google_chromeec_is_uhepi_supported())
226 return google_chromeec_uhepi_cmd(type
,
227 EC_HOST_EVENT_SET
, &mask
);
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
);
235 static int google_chromeec_set_s3_lazy_wake_mask(uint64_t mask
)
237 printk(BIOS_DEBUG
, "Chrome EC: Set S3 LAZY WAKE mask to 0x%016llx\n",
239 return google_chromeec_set_mask
240 (EC_HOST_EVENT_LAZY_WAKE_MASK_S3
, mask
);
243 static int google_chromeec_set_s5_lazy_wake_mask(uint64_t mask
)
245 printk(BIOS_DEBUG
, "Chrome EC: Set S5 LAZY WAKE mask to 0x%016llx\n",
247 return google_chromeec_set_mask
248 (EC_HOST_EVENT_LAZY_WAKE_MASK_S5
, mask
);
251 static int google_chromeec_set_s0ix_lazy_wake_mask(uint64_t mask
)
253 printk(BIOS_DEBUG
, "Chrome EC: Set S0iX LAZY WAKE mask to 0x%016llx\n",
255 return google_chromeec_set_mask
256 (EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX
, mask
);
258 static void google_chromeec_set_lazy_wake_masks(uint64_t s5_mask
,
259 uint64_t s3_mask
, uint64_t s0ix_mask
)
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");
266 * Make sure S0Ix is supported before trying to set up the EC's
267 * S0Ix lazy wake mask.
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");
273 uint64_t google_chromeec_get_events_b(void)
275 return google_chromeec_get_mask(EC_HOST_EVENT_B
);
278 int google_chromeec_clear_events_b(uint64_t mask
)
281 "Chrome EC: clear events_b mask to 0x%016llx\n", mask
);
282 return google_chromeec_clear_mask(EC_HOST_EVENT_B
, mask
);
285 int google_chromeec_get_mkbp_event(struct ec_response_get_next_event
*event
)
287 return ec_cmd_get_next_event(PLAT_EC
, event
);
290 /* Get the current device event mask */
291 uint64_t google_chromeec_get_device_enabled_events(void)
293 const struct ec_params_device_event params
= {
294 .param
= EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS
,
296 struct ec_response_device_event resp
= {};
298 if (ec_cmd_device_event(PLAT_EC
, ¶ms
, &resp
) == 0)
299 return resp
.event_mask
;
304 /* Set the current device event mask */
305 int google_chromeec_set_device_enabled_events(uint64_t mask
)
307 const struct ec_params_device_event params
= {
308 .event_mask
= (uint32_t)mask
,
309 .param
= EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS
,
311 struct ec_response_device_event resp
= {};
313 return ec_cmd_device_event(PLAT_EC
, ¶ms
, &resp
);
316 /* Read and clear pending device events */
317 uint64_t google_chromeec_get_device_current_events(void)
319 const struct ec_params_device_event params
= {
320 .param
= EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS
,
322 struct ec_response_device_event resp
= {};
324 if (ec_cmd_device_event(PLAT_EC
, ¶ms
, &resp
) == 0)
325 return resp
.event_mask
;
330 static void google_chromeec_log_device_events(uint64_t mask
)
335 if (!CONFIG(ELOG
) || !mask
)
338 if (google_chromeec_check_feature(EC_FEATURE_DEVICE_EVENT
) != 1)
341 events
= google_chromeec_get_device_current_events() & mask
;
342 printk(BIOS_INFO
, "EC Device Events: 0x%016llx\n", events
);
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
);
350 void google_chromeec_log_events(uint64_t mask
)
358 events
= google_chromeec_get_events_b() & mask
;
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.
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
);
371 google_chromeec_clear_events_b(events
);
374 void google_chromeec_events_init(const struct google_chromeec_event_info
*info
,
378 google_chromeec_log_events(info
->log_events
|
379 info
->s3_wake_events
);
381 /* Log and clear device events that may wake the system. */
382 google_chromeec_log_device_events(info
->s3_device_events
);
384 /* Disable SMI and wake events. */
385 google_chromeec_set_smi_mask(0);
387 /* Restore SCI event mask. */
388 google_chromeec_set_sci_mask(info
->sci_events
);
391 google_chromeec_set_smi_mask(info
->smi_events
);
393 google_chromeec_log_events(info
->log_events
|
394 info
->s5_wake_events
);
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
);
403 /* Clear wake event mask. */
404 google_chromeec_set_wake_mask(0);
407 int google_chromeec_check_feature(int feature
)
409 struct ec_response_get_features resp
= {};
411 if (ec_cmd_get_features(PLAT_EC
, &resp
) != 0)
414 if (feature
>= 8 * sizeof(resp
.flags
))
417 return resp
.flags
[feature
/ 32] & EC_FEATURE_MASK_0(feature
);
420 int google_chromeec_get_cmd_versions(int command
, uint32_t *pmask
)
422 const struct ec_params_get_cmd_versions_v1 params
= {
425 struct ec_response_get_cmd_versions resp
= {};
427 if (ec_cmd_get_cmd_versions_v1(PLAT_EC
, ¶ms
, &resp
) != 0)
430 *pmask
= resp
.version_mask
;
434 int google_chromeec_get_vboot_hash(uint32_t offset
,
435 struct ec_response_vboot_hash
*resp
)
437 const struct ec_params_vboot_hash params
= {
438 .cmd
= EC_VBOOT_HASH_GET
,
442 if (ec_cmd_vboot_hash(PLAT_EC
, ¶ms
, resp
) != 0)
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
)
452 const struct ec_params_vboot_hash params
= {
453 .cmd
= EC_VBOOT_HASH_START
,
454 .hash_type
= hash_type
,
456 .offset
= hash_offset
,
459 if (ec_cmd_vboot_hash(PLAT_EC
, ¶ms
, resp
) != 0)
465 int google_chromeec_flash_protect(uint32_t mask
, uint32_t flags
,
466 struct ec_response_flash_protect
*resp
)
468 const struct ec_params_flash_protect params
= {
473 if (ec_cmd_flash_protect_v1(PLAT_EC
, ¶ms
, resp
) != 0)
479 int google_chromeec_flash_region_info(enum ec_flash_region region
,
480 uint32_t *offset
, uint32_t *size
)
482 const struct ec_params_flash_region_info params
= {
485 struct ec_response_flash_region_info resp
= {};
487 if (ec_cmd_flash_region_info_v1(PLAT_EC
, ¶ms
, &resp
) != 0)
491 *offset
= resp
.offset
;
498 int google_chromeec_flash_erase(uint32_t offset
, uint32_t size
)
500 const struct ec_params_flash_erase params
= {
505 if (ec_cmd_flash_erase(PLAT_EC
, ¶ms
) != 0)
511 int google_chromeec_flash_info(struct ec_response_flash_info
*info
)
513 if (ec_cmd_flash_info(PLAT_EC
, info
) != 0)
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.
524 int google_chromeec_flash_write_block(const uint8_t *params_data
,
527 struct chromeec_command cmd
= {
528 .cmd_code
= EC_CMD_FLASH_WRITE
,
529 .cmd_version
= EC_VER_FLASH_WRITE
,
531 .cmd_data_out
= NULL
,
532 .cmd_size_in
= bufsize
,
533 .cmd_data_in
= params_data
,
539 return google_chromeec_command(&cmd
);
543 * EFS verification of flash.
545 int google_chromeec_efs_verify(enum ec_flash_region region
)
547 struct ec_params_efs_verify params
= {
550 struct chromeec_command cmd
= {
551 .cmd_code
= EC_CMD_EFS_VERIFY
,
553 .cmd_size_in
= sizeof(params
),
554 .cmd_data_in
= ¶ms
,
556 .cmd_data_out
= NULL
,
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
))
571 int google_chromeec_battery_cutoff(uint8_t flags
)
573 const struct ec_params_battery_cutoff params
= {
577 if (ec_cmd_battery_cut_off_v1(PLAT_EC
, ¶ms
) != 0)
583 int google_chromeec_read_limit_power_request(int *limit_power
)
585 const struct ec_params_charge_state params
= {
586 .cmd
= CHARGE_STATE_CMD_GET_PARAM
,
587 .get_param
.param
= CS_PARAM_LIMIT_POWER
,
589 struct ec_response_charge_state resp
= {};
590 struct chromeec_command cmd
= {
591 .cmd_code
= EC_CMD_CHARGE_STATE
,
593 .cmd_size_in
= sizeof(params
),
594 .cmd_data_in
= ¶ms
,
595 .cmd_size_out
= sizeof(resp
),
596 .cmd_data_out
= &resp
,
601 rv
= google_chromeec_command(&cmd
);
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");
608 } else if (rv
!= 0) {
612 *limit_power
= resp
.get_param
.value
;
617 int google_chromeec_get_protocol_info(
618 struct ec_response_get_protocol_info
*resp
)
620 if (ec_cmd_get_protocol_info(PLAT_EC
, resp
))
626 int google_chromeec_set_sku_id(uint32_t skuid
)
628 const struct ec_sku_id_info params
= {
632 if (ec_cmd_set_sku_id(PLAT_EC
, ¶ms
) != 0)
638 #if CONFIG(EC_GOOGLE_CHROMEEC_RTC)
639 int rtc_get(struct rtc_time
*time
)
641 struct ec_response_rtc resp
= {};
643 if (ec_cmd_rtc_get_value(PLAT_EC
, &resp
) != 0)
646 return rtc_to_tm(resp
.time
, time
);
650 int google_chromeec_reboot(enum ec_reboot_cmd type
, uint8_t flags
)
652 const struct ec_params_reboot_ec params
= {
657 return ec_cmd_reboot_ec(PLAT_EC
, ¶ms
);
660 static int cbi_get_uint32(uint32_t *id
, uint32_t tag
)
662 struct ec_params_get_cbi params
= {
666 struct chromeec_command cmd
= {
667 .cmd_code
= EC_CMD_GET_CROS_BOARD_INFO
,
669 .cmd_data_in
= ¶ms
,
671 .cmd_size_in
= sizeof(params
),
672 .cmd_size_out
= sizeof(r
),
677 rv
= google_chromeec_command(&cmd
);
685 int google_chromeec_cbi_get_sku_id(uint32_t *id
)
687 return cbi_get_uint32(id
, CBI_TAG_SKU_ID
);
690 int google_chromeec_cbi_get_fw_config(uint64_t *fw_config
)
694 if (cbi_get_uint32(&config
, CBI_TAG_FW_CONFIG
))
697 *fw_config
= (uint64_t)config
;
699 * If SSFC is configured to be part of FW_CONFIG, add it at the most significant
702 if (CONFIG(EC_GOOGLE_CHROMEEC_INCLUDE_SSFC_IN_FW_CONFIG
)) {
705 if (!google_chromeec_cbi_get_ssfc(&ssfc
))
706 *fw_config
|= (uint64_t)ssfc
<< 32;
711 int google_chromeec_cbi_get_oem_id(uint32_t *id
)
713 return cbi_get_uint32(id
, CBI_TAG_OEM_ID
);
716 int google_chromeec_cbi_get_board_version(uint32_t *version
)
718 return cbi_get_uint32(version
, CBI_TAG_BOARD_VERSION
);
721 int google_chromeec_cbi_get_ssfc(uint32_t *ssfc
)
723 return cbi_get_uint32(ssfc
, CBI_TAG_SSFC
);
726 bool google_chromeec_get_ucsi_enabled(void)
730 rv
= google_chromeec_check_feature(EC_FEATURE_UCSI_PPM
);
732 printk(BIOS_INFO
, "Cannot check if EC_FEATURE_UCSI_PPM is available: status = %d\n", rv
);
739 static int cbi_get_string(char *buf
, size_t bufsize
, uint32_t tag
)
741 struct ec_params_get_cbi params
= {
744 struct chromeec_command cmd
= {
745 .cmd_code
= EC_CMD_GET_CROS_BOARD_INFO
,
747 .cmd_data_in
= ¶ms
,
749 .cmd_size_in
= sizeof(params
),
750 .cmd_size_out
= bufsize
,
754 rv
= google_chromeec_command(&cmd
);
758 /* Ensure NUL termination. */
759 buf
[bufsize
- 1] = '\0';
764 int google_chromeec_cbi_get_dram_part_num(char *buf
, size_t bufsize
)
766 return cbi_get_string(buf
, bufsize
, CBI_TAG_DRAM_PART_NUM
);
769 int google_chromeec_cbi_get_oem_name(char *buf
, size_t bufsize
)
771 return cbi_get_string(buf
, bufsize
, CBI_TAG_OEM_NAME
);
774 int google_chromeec_get_board_version(uint32_t *version
)
776 struct ec_response_board_version resp
;
778 if (ec_cmd_get_board_version(PLAT_EC
, &resp
))
781 *version
= resp
.board_version
;
785 uint32_t google_chromeec_get_sku_id(void)
787 struct ec_sku_id_info resp
;
789 if (ec_cmd_get_sku_id(PLAT_EC
, &resp
) != 0)
795 static bool google_chromeec_get_uptime_info(
796 struct ec_response_uptime_info
*resp
)
798 return ec_cmd_get_uptime_info(PLAT_EC
, resp
) == 0;
801 bool google_chromeec_get_ap_watchdog_flag(void)
804 struct ec_response_uptime_info resp
;
806 if (!google_chromeec_get_uptime_info(&resp
))
809 if (resp
.ec_reset_flags
& EC_RESET_FLAG_AP_WATCHDOG
)
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)
816 return (resp
.recent_ap_reset
[i
].reset_cause
==
817 CHIPSET_RESET_AP_WATCHDOG
);
823 int google_chromeec_i2c_xfer(uint8_t chip
, uint8_t addr
, int alen
,
824 uint8_t *buffer
, int len
, int is_read
)
827 struct ec_params_i2c_passthru p
;
828 uint8_t outbuf
[EC_HOST_PARAM_SIZE
];
831 struct ec_response_i2c_passthru r
;
832 uint8_t inbuf
[EC_HOST_PARAM_SIZE
];
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
;
839 int read_len
, write_len
;
846 printk(BIOS_ERR
, "Unsupported address length %d\n", alen
);
855 write_len
= alen
+ len
;
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");
864 if (sizeof(*r
) + read_len
> sizeof(response
)) {
865 printk(BIOS_ERR
, "Read length too big for buffer\n");
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
;
875 memcpy(pdata
+ 1, buffer
, len
);
879 msg
->addr_flags
= chip
| EC_I2C_FLAG_READ
;
883 cmd
.cmd_code
= EC_CMD_I2C_PASSTHRU
;
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
);
895 if (r
->i2c_status
& EC_I2C_STATUS_ERROR
) {
896 printk(BIOS_ERR
, "Transfer failed with status=0x%x\n",
901 if (cmd
.cmd_size_out
< sizeof(*r
) + read_len
) {
902 printk(BIOS_ERR
, "Truncated read response\n");
907 memcpy(buffer
, r
->data
, read_len
);
912 int google_chromeec_set_sci_mask(uint64_t mask
)
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
);
918 int google_chromeec_set_smi_mask(uint64_t mask
)
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
);
924 int google_chromeec_set_wake_mask(uint64_t mask
)
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
);
931 uint64_t google_chromeec_get_wake_mask(void)
933 return google_chromeec_get_mask(EC_HOST_EVENT_ACTIVE_WAKE_MASK
);
936 int google_chromeec_set_usb_charge_mode(uint8_t port_id
, enum usb_charge_mode mode
)
938 const struct ec_params_usb_charge_set_mode params
= {
939 .usb_port_id
= port_id
,
943 return ec_cmd_usb_charge_set_mode(PLAT_EC
, ¶ms
);
946 /* Get charger voltage and current. Also returns type of charger */
947 int google_chromeec_get_usb_pd_power_info(enum usb_chg_type
*type
,
948 uint16_t *current_max
, uint16_t *voltage_max
)
950 const struct ec_params_usb_pd_power_info params
= {
951 .port
= PD_POWER_CHARGING_PORT
,
953 struct ec_response_usb_pd_power_info resp
= {};
954 struct usb_chg_measures m
;
957 rv
= ec_cmd_usb_pd_power_info(PLAT_EC
, ¶ms
, &resp
);
961 /* values are given in milliAmps and milliVolts */
964 *voltage_max
= m
.voltage_max
;
965 *current_max
= m
.current_max
;
970 * This API checks the current status of the USB-C port and returns
971 * whether a USB Power Delivery (PD) charger is currently connected.
973 bool google_chromeec_is_usb_pd_attached(void)
975 const struct ec_params_usb_pd_power_info params
= {
976 .port
= PD_POWER_CHARGING_PORT
,
978 struct ec_response_usb_pd_power_info resp
= {};
981 rv
= ec_cmd_usb_pd_power_info(PLAT_EC
, ¶ms
, &resp
);
985 return resp
.type
== USB_CHG_TYPE_PD
;
988 /* This API checks if charger is present. */
989 bool google_chromeec_is_charger_present(void)
991 struct ec_params_battery_dynamic_info params
= {
994 struct ec_response_battery_dynamic_info resp
;
996 if (ec_cmd_battery_get_dynamic(PLAT_EC
, ¶ms
, &resp
) == 0) {
997 /* Check if AC charger is present */
998 if (resp
.flags
& EC_BATT_FLAG_AC_PRESENT
)
1006 * Using below scenarios to conclude if device has a barrel charger attached.
1007 * +-----------+-----------------+------------------+---------------------------------+
1008 * | Scenarios | Charger Present | USB-C PD Present | Conclusion: Barrel Present ? |
1009 * +-----------+-----------------+------------------+---------------------------------+
1010 * | #1 | Yes | Yes | Non Conclusive (comments below) |
1011 * | #2 | No | Yes | Not possible |
1012 * | #3 | Yes | No | Must be barrel charger |
1013 * | #4 | No | No | Barrel not present |
1014 * +-----------+-----------------+------------------+---------------------------------+
1016 bool google_chromeec_is_barrel_charger_present(void)
1019 * If both the barrel charger and USB-C PD are connected, the barrel charger takes
1020 * precedence over USB-C PD. This means google_chromeec_is_usb_pd_attached()
1021 * will return false in such a scenario.
1023 * This behavior allows us to reliably detect the presence of a barrel
1024 * charger, even when a USB-C PD charger is also connected.
1026 return google_chromeec_is_charger_present() && !google_chromeec_is_usb_pd_attached();
1029 int google_chromeec_override_dedicated_charger_limit(uint16_t current_lim
,
1030 uint16_t voltage_lim
)
1032 const struct ec_params_dedicated_charger_limit params
= {
1033 .current_lim
= current_lim
,
1034 .voltage_lim
= voltage_lim
,
1037 return ec_cmd_override_dedicated_charger_limit(PLAT_EC
, ¶ms
);
1040 int google_chromeec_set_usb_pd_role(uint8_t port
, enum usb_pd_control_role role
)
1042 const struct ec_params_usb_pd_control params
= {
1045 .mux
= USB_PD_CTRL_MUX_NO_CHANGE
,
1046 .swap
= USB_PD_CTRL_SWAP_NONE
,
1048 struct ec_response_usb_pd_control resp
;
1050 return ec_cmd_usb_pd_control(PLAT_EC
, ¶ms
, &resp
);
1053 int google_chromeec_hello(void)
1055 const struct ec_params_hello params
= {
1056 .in_data
= 0x10203040,
1058 struct ec_response_hello resp
= {};
1060 int rv
= ec_cmd_hello(PLAT_EC
, ¶ms
, &resp
);
1064 if (resp
.out_data
!= (params
.in_data
+ 0x01020304))
1071 * Convert a reset cause ID to human-readable string, providing total coverage
1072 * of the 'cause' space. The returned string points to static storage and must
1075 static const char *reset_cause_to_str(uint16_t cause
)
1077 /* See also ChromiumOS EC include/chipset.h for details. */
1078 static const char * const reset_causes
[] = {
1080 "reset: board custom",
1081 "reset: ap hang detected",
1082 "reset: console command",
1083 "reset: keyboard sysreset",
1084 "reset: keyboard warm reboot",
1085 "reset: debug warm reboot",
1086 "reset: at AP's request",
1087 "reset: during EC initialization",
1088 "reset: AP watchdog",
1091 static const size_t shutdown_cause_begin
= 1 << 15;
1092 static const char * const shutdown_causes
[] = {
1093 "shutdown: power failure",
1094 "shutdown: during EC initialization",
1095 "shutdown: board custom",
1096 "shutdown: battery voltage startup inhibit",
1097 "shutdown: power wait asserted",
1098 "shutdown: critical battery",
1099 "shutdown: by console command",
1100 "shutdown: entering G3",
1101 "shutdown: thermal",
1102 "shutdown: power button",
1105 if (cause
< ARRAY_SIZE(reset_causes
))
1106 return reset_causes
[cause
];
1108 if (cause
< shutdown_cause_begin
)
1109 return "(reset unknown)";
1111 if (cause
< shutdown_cause_begin
+ ARRAY_SIZE(shutdown_causes
))
1112 return shutdown_causes
[cause
- shutdown_cause_begin
];
1114 return "(shutdown unknown)";
1118 * Copy the EC's information about resets of the AP and its own uptime for
1119 * debugging purposes.
1121 static void google_chromeec_log_uptimeinfo(void)
1123 /* See also ec_commands.h EC_RESET_FLAG_* for details. */
1124 static const char * const reset_flag_strings
[] = {
1145 struct ec_response_uptime_info cmd_resp
;
1146 int i
, flag
, flag_count
;
1148 if (!google_chromeec_get_uptime_info(&cmd_resp
)) {
1150 * Deliberately say nothing for EC's that don't support this
1156 printk(BIOS_DEBUG
, "Google Chrome EC uptime: %d.%03d seconds\n",
1157 cmd_resp
.time_since_ec_boot_ms
/ MSECS_PER_SEC
,
1158 cmd_resp
.time_since_ec_boot_ms
% MSECS_PER_SEC
);
1160 printk(BIOS_DEBUG
, "Google Chrome AP resets since EC boot: %d\n",
1161 cmd_resp
.ap_resets_since_ec_boot
);
1163 printk(BIOS_DEBUG
, "Google Chrome most recent AP reset causes:\n");
1164 for (i
= 0; i
!= ARRAY_SIZE(cmd_resp
.recent_ap_reset
); ++i
) {
1165 if (cmd_resp
.recent_ap_reset
[i
].reset_time_ms
== 0)
1168 printk(BIOS_DEBUG
, "\t%d.%03d: %d %s\n",
1169 cmd_resp
.recent_ap_reset
[i
].reset_time_ms
/
1171 cmd_resp
.recent_ap_reset
[i
].reset_time_ms
%
1173 cmd_resp
.recent_ap_reset
[i
].reset_cause
,
1175 cmd_resp
.recent_ap_reset
[i
].reset_cause
));
1178 printk(BIOS_DEBUG
, "Google Chrome EC reset flags at last EC boot: ");
1180 for (flag
= 0; flag
!= ARRAY_SIZE(reset_flag_strings
); ++flag
) {
1181 if ((cmd_resp
.ec_reset_flags
& (1 << flag
)) != 0) {
1183 printk(BIOS_DEBUG
, " | ");
1184 printk(BIOS_DEBUG
, "%s", reset_flag_strings
[flag
]);
1188 printk(BIOS_DEBUG
, "\n");
1191 /* Cache and retrieve the EC image type (ro or rw) */
1192 enum ec_image
google_chromeec_get_current_image(void)
1194 static enum ec_image ec_image_type
= EC_IMAGE_UNKNOWN
;
1196 if (ec_image_type
!= EC_IMAGE_UNKNOWN
)
1197 return ec_image_type
;
1199 struct ec_response_get_version resp
= {};
1202 rv
= ec_cmd_get_version(PLAT_EC
, &resp
);
1206 "Google Chrome EC: version command failed!\n");
1208 printk(BIOS_DEBUG
, "Google Chrome EC: version:\n");
1209 printk(BIOS_DEBUG
, " ro: %s\n", resp
.version_string_ro
);
1210 printk(BIOS_DEBUG
, " rw: %s\n", resp
.version_string_rw
);
1211 printk(BIOS_DEBUG
, " running image: %d\n",
1212 resp
.current_image
);
1213 ec_image_type
= resp
.current_image
;
1216 /* Will still be UNKNOWN if command failed */
1217 return ec_image_type
;
1220 int google_chromeec_get_num_pd_ports(unsigned int *num_ports
)
1222 struct ec_response_usb_pd_ports resp
= {};
1225 rv
= ec_cmd_usb_pd_ports(PLAT_EC
, &resp
);
1229 *num_ports
= resp
.num_ports
;
1233 int google_chromeec_get_pd_chip_info(int port
, int renew
,
1234 struct ec_response_pd_chip_info
*r
)
1236 const struct ec_params_pd_chip_info p
= {
1241 return ec_cmd_pd_chip_info(PLAT_EC
, &p
, r
);
1244 int google_chromeec_get_pd_port_caps(int port
,
1245 struct usb_pd_port_caps
*port_caps
)
1247 const struct ec_params_get_pd_port_caps params
= {
1250 struct ec_response_get_pd_port_caps resp
= {};
1253 rv
= ec_cmd_get_pd_port_caps(PLAT_EC
, ¶ms
, &resp
);
1257 port_caps
->power_role_cap
= resp
.pd_power_role_cap
;
1258 port_caps
->try_power_role_cap
= resp
.pd_try_power_role_cap
;
1259 port_caps
->data_role_cap
= resp
.pd_data_role_cap
;
1260 port_caps
->port_location
= resp
.pd_port_location
;
1265 void google_chromeec_init(void)
1267 google_chromeec_log_uptimeinfo();
1269 /* Enable automatic fan control */
1270 if (CONFIG(EC_GOOGLE_CHROMEEC_AUTO_FAN_CTRL
)) {
1271 ec_cmd_thermal_auto_fan_ctrl(PLAT_EC
);
1275 int google_ec_running_ro(void)
1277 return (google_chromeec_get_current_image() == EC_IMAGE_RO
);
1280 /* Returns data role and type of device connected */
1281 static int google_chromeec_usb_pd_get_info(int port
, bool *ufp
, bool *dbg_acc
,
1282 bool *active_cable
, uint8_t *dp_mode
)
1284 const struct ec_params_usb_pd_control pd_control
= {
1286 .role
= USB_PD_CTRL_ROLE_NO_CHANGE
,
1287 .mux
= USB_PD_CTRL_ROLE_NO_CHANGE
,
1288 .swap
= USB_PD_CTRL_SWAP_NONE
,
1290 struct ec_response_usb_pd_control_v2 resp
= {};
1292 if (ec_cmd_usb_pd_control_v2(PLAT_EC
, &pd_control
, &resp
) < 0)
1295 *ufp
= !(resp
.role
& PD_CTRL_RESP_ROLE_DATA
);
1296 *dbg_acc
= (resp
.cc_state
== PD_CC_DFP_DEBUG_ACC
);
1297 *active_cable
= !!(resp
.control_flags
& USB_PD_CTRL_ACTIVE_CABLE
);
1298 *dp_mode
= resp
.dp_mode
;
1303 int google_chromeec_typec_control_enter_dp_mode(int port
)
1306 struct usbc_mux_info mux_info
;
1308 if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY
))
1311 ret
= google_chromeec_get_usbc_mux_info(port
, &mux_info
);
1312 if ((ret
< 0) || (!mux_info
.usb
))
1315 const struct ec_params_typec_control typec_control
= {
1317 .command
= TYPEC_CONTROL_COMMAND_ENTER_MODE
,
1318 .mode_to_enter
= TYPEC_MODE_DP
,
1321 if (ec_cmd_typec_control(PLAT_EC
, &typec_control
) < 0)
1328 * Check for the current mux state in EC. Flags representing the mux state found
1331 int google_chromeec_usb_get_pd_mux_info(int port
, uint8_t *flags
)
1333 const struct ec_params_usb_pd_mux_info req_mux
= {
1336 struct ec_response_usb_pd_mux_info resp_mux
= {};
1341 if (ec_cmd_usb_pd_mux_info(PLAT_EC
, &req_mux
, &resp_mux
) < 0)
1344 *flags
= resp_mux
.flags
;
1349 * Obtain any USB-C mux data needed for the specified port
1350 * in: physical port number of the type-c port
1351 * out: struct usbc_mux_info mux_info stores USB-C mux data
1352 * Return: 0 on success, -1 on error
1354 int google_chromeec_get_usbc_mux_info(int port
, struct usbc_mux_info
*mux_info
)
1357 uint8_t dp_pin_mode
;
1358 bool ufp
, dbg_acc
, active_cable
;
1360 if (google_chromeec_usb_get_pd_mux_info(port
, &mux_flags
) < 0) {
1361 printk(BIOS_ERR
, "Port C%d: get_pd_mux_info failed\n", port
);
1365 if (google_chromeec_usb_pd_get_info(port
, &ufp
, &dbg_acc
,
1366 &active_cable
, &dp_pin_mode
) < 0) {
1367 printk(BIOS_ERR
, "Port C%d: pd_control failed\n", port
);
1371 mux_info
->usb
= !!(mux_flags
& USB_PD_MUX_USB_ENABLED
);
1372 mux_info
->dp
= !!(mux_flags
& USB_PD_MUX_DP_ENABLED
);
1373 mux_info
->polarity
= !!(mux_flags
& USB_PD_MUX_POLARITY_INVERTED
);
1374 mux_info
->hpd_irq
= !!(mux_flags
& USB_PD_MUX_HPD_IRQ
);
1375 mux_info
->hpd_lvl
= !!(mux_flags
& USB_PD_MUX_HPD_LVL
);
1376 mux_info
->ufp
= !!ufp
;
1377 mux_info
->dbg_acc
= !!dbg_acc
;
1378 mux_info
->cable
= !!active_cable
;
1379 mux_info
->dp_pin_mode
= dp_pin_mode
;
1385 * Check if EC/TCPM is in an alternate mode or not.
1387 * @param svid SVID of the alternate mode to check
1388 * @return 0: Not in the mode. -1: Error.
1389 * >=1: bitmask of the ports that are in the mode.
1391 static int google_chromeec_pd_get_amode(uint16_t svid
)
1393 struct ec_response_usb_pd_ports resp
;
1397 if (ec_cmd_usb_pd_ports(PLAT_EC
, &resp
) < 0)
1400 for (i
= 0; i
< resp
.num_ports
; i
++) {
1401 struct chromeec_command cmd
= { };
1402 struct ec_params_usb_pd_get_mode_request params
;
1403 struct ec_params_usb_pd_get_mode_response resp2
;
1407 /* Reset cmd in each iteration in case
1408 google_chromeec_command changes it. */
1410 params
.svid_idx
= svid_idx
;
1411 cmd
.cmd_code
= EC_CMD_USB_PD_GET_AMODE
;
1412 cmd
.cmd_version
= 0;
1413 cmd
.cmd_data_in
= ¶ms
;
1414 cmd
.cmd_size_in
= sizeof(params
);
1415 cmd
.cmd_data_out
= &resp2
;
1416 cmd
.cmd_size_out
= sizeof(resp2
);
1417 cmd
.cmd_dev_index
= 0;
1419 if (google_chromeec_command(&cmd
) < 0)
1421 if (resp2
.svid
== svid
)
1424 } while (resp2
.svid
);
1430 #define USB_SID_DISPLAYPORT 0xff01
1433 * Wait for DisplayPort to be ready
1435 * @param timeout_ms Wait aborts after <timeout_ms> ms.
1436 * @return -1: Error. 0: Timeout.
1437 * >=1: Bitmask of the ports that DP device is connected
1439 int google_chromeec_wait_for_displayport(long timeout_ms
)
1441 struct stopwatch sw
;
1444 if (google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY
)) {
1445 printk(BIOS_INFO
, "AP Mode Entry enabled, skip waiting for DisplayPort connection\n");
1449 printk(BIOS_INFO
, "Waiting for DisplayPort\n");
1450 stopwatch_init_msecs_expire(&sw
, timeout_ms
);
1452 ret
= google_chromeec_pd_get_amode(USB_SID_DISPLAYPORT
);
1457 printk(BIOS_ERR
, "Can't get alternate mode!\n");
1461 if (stopwatch_expired(&sw
)) {
1462 printk(BIOS_WARNING
,
1463 "DisplayPort not ready after %ldms. Abort.\n",
1469 printk(BIOS_INFO
, "DisplayPort ready after %lld ms\n",
1470 stopwatch_duration_msecs(&sw
));
1476 * Check for given flag in PD mux info for a port.
1478 * @param port Type-C port number
1479 * flag Flag to check
1480 * @return 1: Flag is set. 0: Flag is not set.
1482 static int google_chromeec_check_mux_flag(int port
, uint8_t flag
)
1484 uint8_t mux_flags
= 0;
1485 google_chromeec_usb_get_pd_mux_info(port
, &mux_flags
);
1486 if ((mux_flags
& flag
) == flag
)
1491 int google_chromeec_wait_for_dp_mode_entry(int port
, long timeout_ms
)
1493 struct stopwatch sw
;
1495 if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY
)) {
1496 if (!google_chromeec_check_mux_flag(port
, USB_PD_MUX_DP_ENABLED
)) {
1497 printk(BIOS_WARNING
, "DP mode entry is not ready. Abort.\n");
1504 stopwatch_init_msecs_expire(&sw
, timeout_ms
);
1505 while (!google_chromeec_check_mux_flag(port
, USB_PD_MUX_DP_ENABLED
)) {
1506 if (stopwatch_expired(&sw
)) {
1507 printk(BIOS_WARNING
, "DP not ready after %ldms. Abort.\n", timeout_ms
);
1512 printk(BIOS_INFO
, "DP ready after %lld ms\n", stopwatch_duration_msecs(&sw
));
1517 int google_chromeec_wait_for_hpd(int port
, long timeout_ms
)
1519 struct stopwatch sw
;
1521 if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY
)) {
1522 if (!google_chromeec_check_mux_flag(port
, USB_PD_MUX_HPD_LVL
)) {
1523 printk(BIOS_WARNING
, "HPD not ready. Abort.\n");
1530 stopwatch_init_msecs_expire(&sw
, timeout_ms
);
1531 while (!google_chromeec_check_mux_flag(port
, USB_PD_MUX_HPD_LVL
)) {
1532 if (stopwatch_expired(&sw
)) {
1533 printk(BIOS_WARNING
, "HPD not ready after %ldms. Abort.\n", timeout_ms
);
1538 printk(BIOS_INFO
, "HPD ready after %lld ms\n", stopwatch_duration_msecs(&sw
));
1543 int google_chromeec_get_keybd_config(struct ec_response_keybd_config
*keybd
)
1545 if (ec_cmd_get_keybd_config(PLAT_EC
, keybd
))
1550 int google_chromeec_ap_reset(void)
1552 if (ec_cmd_ap_reset(NULL
))
1558 int google_chromeec_regulator_enable(uint32_t index
, uint8_t enable
)
1560 const struct ec_params_regulator_enable params
= {
1565 if (ec_cmd_regulator_enable(PLAT_EC
, ¶ms
))
1571 int google_chromeec_regulator_is_enabled(uint32_t index
, uint8_t *enabled
)
1573 const struct ec_params_regulator_is_enabled params
= {
1576 struct ec_response_regulator_is_enabled resp
= {};
1578 if (ec_cmd_regulator_is_enabled(PLAT_EC
, ¶ms
, &resp
))
1581 *enabled
= resp
.enabled
;
1586 int google_chromeec_regulator_set_voltage(uint32_t index
, uint32_t min_mv
,
1589 const struct ec_params_regulator_set_voltage params
= {
1595 if (ec_cmd_regulator_set_voltage(PLAT_EC
, ¶ms
))
1601 int google_chromeec_regulator_get_voltage(uint32_t index
, uint32_t *voltage_mv
)
1603 const struct ec_params_regulator_get_voltage params
= {
1606 struct ec_response_regulator_get_voltage resp
= {};
1608 if (ec_cmd_regulator_get_voltage(PLAT_EC
, ¶ms
, &resp
))
1611 *voltage_mv
= resp
.voltage_mv
;
1615 void google_chromeec_clear_ec_ap_idle(void)
1617 /* Send EC command to clear AP_IDLE flag */
1618 if (!google_chromeec_reboot(EC_REBOOT_NO_OP
, EC_REBOOT_FLAG_CLEAR_AP_IDLE
|
1619 EC_REBOOT_FLAG_ON_AP_SHUTDOWN
))
1620 printk(BIOS_INFO
, "Successfully clear AP_IDLE flag\n");
1622 printk(BIOS_ERR
, "Failed to clear EC AP_IDLE flag\n");
1625 bool google_chromeec_is_battery_present_and_above_critical_threshold(void)
1627 struct ec_params_battery_dynamic_info params
= {
1630 struct ec_response_battery_dynamic_info resp
;
1632 if (ec_cmd_battery_get_dynamic(PLAT_EC
, ¶ms
, &resp
) == 0) {
1633 /* Check if battery is present and LEVEL_CRITICAL is not set */
1634 if (resp
.flags
&& !(resp
.flags
& EC_BATT_FLAG_LEVEL_CRITICAL
))
1641 bool google_chromeec_is_below_critical_threshold(void)
1643 struct ec_params_battery_dynamic_info params
= {
1646 struct ec_response_battery_dynamic_info resp
;
1648 if (ec_cmd_battery_get_dynamic(PLAT_EC
, ¶ms
, &resp
) == 0) {
1649 /* Check if battery LEVEL_CRITICAL is set */
1650 if (resp
.flags
& EC_BATT_FLAG_LEVEL_CRITICAL
)
1657 bool google_chromeec_is_battery_present(void)
1659 struct ec_params_battery_dynamic_info params
= {
1662 struct ec_response_battery_dynamic_info resp
;
1664 if (ec_cmd_battery_get_dynamic(PLAT_EC
, ¶ms
, &resp
) == 0) {
1665 /* Check if battery is present */
1666 if (resp
.flags
& EC_BATT_FLAG_BATT_PRESENT
)