soc/intel: Remove blank lines before '}' and after '{'
[coreboot2.git] / src / mainboard / acer / aspire_vn7_572g / smihandler.c
blob88ec10d190a564f591cf10135b30fd828c3d9ee2
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <cpu/x86/msr.h>
6 #include <cpu/x86/smm.h>
7 #include <ec/acpi/ec.h>
8 #include <soc/nvs.h>
11 * TODO: Perform RE of protocols in vendor firmware:
12 * - gEfiSmmSxDispatch2ProtocolGuid
13 * - gEfiSmmPowerButtonDispatch2ProtocolGuid
15 * However, note that first glance suggests that no handlers
16 * will be very interesting and that gEfiSmmGpiDispatch2ProtocolGuid
17 * was unused (as I recall).
19 * Also, consider gEfiSmmIoTrapDispatch2ProtocolGuid, but
20 * this is less likely.
23 /* Keep in sync with dsdt.asl; could insert into SSDT at runtime */
24 #define APM_CNT_BOARD_SMI 0xDD
26 /* Toggle TURBO_MODE_DISABLE bit in IA32_MISC_ENABLE MSR
27 when requested by EC. */
28 static void toggle_turbo_disable(uint8_t function_parameter_0)
30 if (function_parameter_0 == 1) {
31 printk(BIOS_DEBUG, "EC: Enabling Intel Turbo Mode\n");
32 msr_unset(IA32_MISC_ENABLE, 0x4000000000);
33 } else if (function_parameter_0 == 0) {
34 printk(BIOS_DEBUG, "EC: Disabling Intel Turbo Mode\n");
35 msr_set(IA32_MISC_ENABLE, 0x4000000000);
39 /* Set WiFi and BT enable bits in EC RAM. */
40 static void enable_rf_by_capability(void)
42 /* FIXME: We're not tracking (driver) 'capabilities' at the moment (must we?),
43 so we just enable WiFi and BT here. If this was tracked, then
44 bits may be cleared here */
45 uint8_t rf_register = ec_read(0x71);
46 ec_write(0x71, rf_register | 0x03);
49 /* Set OS capability bits in EC RAM. */
50 static void handle_acpi_osys(void)
52 uint8_t os_support;
54 /* TODO: Add _OSI method support to coreboot and make this work */
55 printk(BIOS_DEBUG, "GNVS.OSYS = %d\n", gnvs->unused_was_osys);
56 switch (gnvs->unused_was_osys) {
57 /* Linux */
58 case 1000:
59 os_support = 64;
60 break;
61 /* Windows versions by year */
62 case 2009:
63 os_support = 3;
64 break;
65 case 2012:
66 os_support = 4;
67 break;
68 case 2013:
69 os_support = 5;
70 break;
71 case 2015:
72 os_support = 6;
73 break;
74 /* Operating system unknown */
75 default:
76 printk(BIOS_DEBUG, "GNVS.OSYS not supported!\n");
77 printk(BIOS_DEBUG, "No capabilities!\n");
78 os_support = 0;
79 break;
82 ec_write(0x5C, os_support);
85 /* Handles EC's _REG, _PTS and _WAK methods.
86 Partially involves setting EC RAM offsets based on GNVS.OSYS - OS capabilities? */
87 static void handle_acpi_wake_event(
88 uint8_t function_parameter_0, uint8_t function_parameter_1)
90 switch (function_parameter_0) {
91 case 1:
92 printk(BIOS_DEBUG, "EC: Called for _REG method - OS initialise\n");
93 enable_rf_by_capability();
94 handle_acpi_osys();
95 // NOTE: Not handling (driver) 'capabilities'
96 break;
97 case 2:
98 printk(BIOS_DEBUG, "EC: Called for _PTS method - Entering sleep\n");
99 // NOTE: Not saving (driver) 'capabilities'
100 // NOTE: Not saving and restoring EC RAM offset 0x4F
101 break;
102 case 3:
103 printk(BIOS_DEBUG, "EC: Called for _WAK method - Sleep resume\n");
104 enable_rf_by_capability();
105 handle_acpi_osys();
106 // NOTE: Not saving and restoring EC RAM offset 0x4F
107 break;
108 default:
109 printk(BIOS_DEBUG, "function_parameter_0 is invalid!\n");
110 break;
114 /* TODO: Reverse engineer 0x80 function and implement if necessary */
115 static void ec_smi_handler(uint8_t smif)
117 uint8_t smm_data_port;
118 uint8_t function_parameter_0;
119 uint8_t function_parameter_1;
121 /* Parameters encoded onto SMI data port because PRMx NVS are not present
122 - Callers must only use 4 bits per argument
123 - _PTS and _WAK are required to call in spec-compliant way */
124 smm_data_port = inb(APM_STS);
125 function_parameter_0 = smm_data_port & ~0xF0;
126 function_parameter_1 = smm_data_port >> 4;
128 printk(BIOS_DEBUG, "Function 0x%x(0x%x, 0x%x) called\n",
129 smif, function_parameter_0, function_parameter_1);
130 switch (smif) {
131 case 0x80:
132 printk(BIOS_WARNING, "Function 0x80 is unimplemented!\n");
133 printk(BIOS_DEBUG, "Function calls offset 0 in ACER_BOOT_DEVICE_SERVICE_PROTOCOL_GUID\n");
134 break;
135 case 0x81:
136 toggle_turbo_disable(function_parameter_0);
137 break;
138 case 0x82:
139 handle_acpi_wake_event(function_parameter_0, function_parameter_1);
140 break;
141 default:
142 /* Not handled */
143 printk(BIOS_DEBUG, "Requested function is unknown!\n");
144 return;
148 * gnvs->smif:
149 * - On success, the handler returns 0
150 * - On failure, the handler returns a value != 0
152 gnvs->smif = 0;
155 int mainboard_smi_apmc(u8 data)
157 /* TODO: Continue SmmKbcDriver RE of common service registration and confirm */
158 switch (data) {
159 case APM_CNT_BOARD_SMI:
160 if (gnvs) {
161 ec_smi_handler(gnvs->smif);
163 break;
164 case APM_CNT_ACPI_ENABLE: /* Events generate SCIs for OS */
165 /* use 0x68/0x6C to prevent races with userspace */
166 ec_set_ports(0x6C, 0x68);
167 /* discard all events */
168 ec_clear_out_queue();
169 /* Tests at runtime show this re-enables charging and battery reporting */
170 send_ec_command(0xE9); /* Vendor implements using ACPI "CMDB" register" */
171 send_ec_data(0x81);
172 /* TODO: Set touchpad GPP owner to ACPI? */
173 break;
174 case APM_CNT_ACPI_DISABLE: /* Events generate SMIs for SMM */
175 /* use 0x68/0x6C to prevent races with userspace */
176 ec_set_ports(0x6C, 0x68);
177 /* discard all events */
178 ec_clear_out_queue();
179 /* Tests at runtime show this disables charging and battery reporting */
180 send_ec_command(0xE9); /* Vendor implements using ACPI "CMDB" register" */
181 send_ec_data(0x80);
182 /* TODO: Set touchpad GPP owner to GPIO? */
183 break;
184 default:
185 break;
187 return 0;