xref: /aosp_15_r20/external/coreboot/src/ec/google/chromeec/ec.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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, &params) != 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, &params, &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 = &params,
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, &params, &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, &params, &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, &params, &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, &params, &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, &params, 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, &params, 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, &params, 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, &params, &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, &params) != 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 = &params,
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, &params) != 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 = &params,
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, &params) != 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, &params);
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 = &params,
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 = &params,
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 = &params.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, &params);
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, &params, &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, &params);
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, &params, &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, &params, &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, &params, &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 = &params;
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, &params))
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, &params, &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, &params))
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, &params, &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, &params, &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