xref: /aosp_15_r20/external/coreboot/src/ec/google/chromeec/smihandler.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <acpi/acpi_gnvs.h>
5 #include <console/console.h>
6 #include <cpu/x86/smm.h>
7 #include <ec/google/chromeec/ec.h>
8 #include <elog.h>
9 #include <halt.h>
10 #include "smm.h"
11 
chromeec_process_one_event(void)12 static int chromeec_process_one_event(void)
13 {
14 	uint8_t event = google_chromeec_get_event();
15 
16 	/* Log this event */
17 	if (event)
18 		elog_gsmi_add_event_byte(ELOG_TYPE_EC_EVENT, event);
19 
20 	switch (event) {
21 	case EC_HOST_EVENT_LID_CLOSED:
22 		printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n");
23 
24 		poweroff();
25 		break;
26 	}
27 	return !!event;
28 }
29 
chromeec_smi_process_events(void)30 void chromeec_smi_process_events(void)
31 {
32 	/* Process all pending events */
33 	while (chromeec_process_one_event())
34 		;
35 }
36 
clear_pending_events(void)37 static void clear_pending_events(void)
38 {
39 	struct ec_response_get_next_event mkbp_event;
40 
41 	while (google_chromeec_get_event() != EC_HOST_EVENT_NONE)
42 		;
43 
44 	printk(BIOS_DEBUG, "Clearing pending EC events. Error code EC_RES_UNAVAILABLE(9) is expected.\n");
45 	while (google_chromeec_get_mkbp_event(&mkbp_event) == 0)
46 		;
47 }
48 
chromeec_set_usb_charge_mode(int slp_type)49 void chromeec_set_usb_charge_mode(int slp_type)
50 {
51 	bool usb0_disable = 0, usb1_disable = 0;
52 
53 	usb_charge_mode_from_gnvs(slp_type, &usb0_disable, &usb1_disable);
54 
55 	if (usb0_disable)
56 		google_chromeec_set_usb_charge_mode(0, USB_CHARGE_MODE_DISABLED);
57 
58 	if (usb1_disable)
59 		google_chromeec_set_usb_charge_mode(1, USB_CHARGE_MODE_DISABLED);
60 }
61 
chromeec_smi_sleep(int slp_type,uint64_t s3_mask,uint64_t s5_mask)62 void chromeec_smi_sleep(int slp_type, uint64_t s3_mask, uint64_t s5_mask)
63 {
64 	if (!google_chromeec_is_uhepi_supported()) {
65 		switch (slp_type) {
66 		case ACPI_S3:
67 			/* Enable wake events */
68 			google_chromeec_set_wake_mask(s3_mask);
69 			break;
70 		case ACPI_S4:
71 		case ACPI_S5:
72 			/* Enable wake events */
73 			google_chromeec_set_wake_mask(s5_mask);
74 			break;
75 		}
76 	}
77 
78 	/* Disable SCI and SMI events */
79 	google_chromeec_set_smi_mask(0);
80 	google_chromeec_set_sci_mask(0);
81 
82 	/* Clear pending events that may trigger immediate wake */
83 	clear_pending_events();
84 }
85 
chromeec_smi_device_event_sleep(int slp_type,uint64_t s3_mask,uint64_t s5_mask)86 void chromeec_smi_device_event_sleep(int slp_type, uint64_t s3_mask,
87 				     uint64_t s5_mask)
88 {
89 	switch (slp_type) {
90 	case ACPI_S3:
91 		/* Enable device wake events */
92 		google_chromeec_set_device_enabled_events(s3_mask);
93 		break;
94 	case ACPI_S5:
95 		/* Enable device wake events */
96 		google_chromeec_set_device_enabled_events(s5_mask);
97 		break;
98 	}
99 
100 	/* Read and clear pending events that may trigger immediate wake */
101 	google_chromeec_get_device_current_events();
102 }
103 
chromeec_smi_apmc(int apmc,uint64_t sci_mask,uint64_t smi_mask)104 void chromeec_smi_apmc(int apmc, uint64_t sci_mask, uint64_t smi_mask)
105 {
106 	switch (apmc) {
107 	case APM_CNT_ACPI_ENABLE:
108 		google_chromeec_set_smi_mask(0);
109 		clear_pending_events();
110 		google_chromeec_set_sci_mask(sci_mask);
111 		break;
112 	case APM_CNT_ACPI_DISABLE:
113 		google_chromeec_set_sci_mask(0);
114 		clear_pending_events();
115 		google_chromeec_set_smi_mask(smi_mask);
116 		break;
117 	}
118 }
119