payloads/edk2: Disable the CPU Timer Lib unless supported
[coreboot.git] / src / mainboard / lenovo / t60 / smihandler.c
blob12a1e53be0b6d26fac8a7e627e52a5506106f75e
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <device/pci_ops.h>
5 #include <device/pci_def.h>
6 #include <console/console.h>
7 #include <cpu/x86/smm.h>
8 #include <soc/nvs.h>
9 #include <southbridge/intel/common/pmutil.h>
10 #include <ec/acpi/ec.h>
11 #include "dock.h"
12 #include "smi.h"
14 #define GPE_EC_SCI 12
16 #define LVTMA_BL_MOD_LEVEL 0x7af9 /* ATI Radeon backlight level */
18 static void mainboard_smi_brightness_down(void)
20 uint32_t reg32 = pci_read_config32(PCI_DEV(1, 0, 0), PCI_BASE_ADDRESS_2) & ~0xf;
21 u8 *bar = (void *)(uintptr_t)reg32;
23 /* Validate pointer before using it */
24 if (!bar || smm_points_to_smram(bar, LVTMA_BL_MOD_LEVEL + sizeof(uint8_t)))
25 return;
27 printk(BIOS_DEBUG, "bar: %p, level %02X\n", bar, *(bar+LVTMA_BL_MOD_LEVEL));
28 *(bar+LVTMA_BL_MOD_LEVEL) &= 0xf0;
29 if (*(bar+LVTMA_BL_MOD_LEVEL) > 0x10)
30 *(bar+LVTMA_BL_MOD_LEVEL) -= 0x10;
33 static void mainboard_smi_brightness_up(void)
35 uint32_t reg32 = pci_read_config32(PCI_DEV(1, 0, 0), PCI_BASE_ADDRESS_2) & ~0xf;
36 u8 *bar = (void *)(uintptr_t)reg32;
38 /* Validate pointer before using it */
39 if (!bar || smm_points_to_smram(bar, LVTMA_BL_MOD_LEVEL + sizeof(uint8_t)))
40 return;
42 printk(BIOS_DEBUG, "bar: %p, level %02X\n", bar, *(bar+LVTMA_BL_MOD_LEVEL));
43 *(bar+LVTMA_BL_MOD_LEVEL) |= 0x0f;
44 if (*(bar+LVTMA_BL_MOD_LEVEL) < 0xf0)
45 *(bar+LVTMA_BL_MOD_LEVEL) += 0x10;
48 int mainboard_io_trap_handler(int smif)
50 switch (smif) {
51 case SMI_DOCK_CONNECT:
52 /* If there's an legacy I/O module present, we're not
53 * allowed to connect the Docking LPC Bus, as both Super I/O
54 * chips are using 0x2e as base address.
56 if (legacy_io_present())
57 break;
59 if (!dock_connect()) {
60 /* set dock LED to indicate status */
61 ec_write(0x0c, 0x08);
62 ec_write(0x0c, 0x89);
63 } else {
64 /* blink dock LED to indicate failure */
65 ec_write(0x0c, 0xc8);
66 ec_write(0x0c, 0x09);
68 break;
70 case SMI_DOCK_DISCONNECT:
71 dock_disconnect();
72 ec_write(0x0c, 0x09);
73 ec_write(0x0c, 0x08);
74 break;
76 case SMI_BRIGHTNESS_UP:
77 mainboard_smi_brightness_up();
78 break;
80 case SMI_BRIGHTNESS_DOWN:
81 mainboard_smi_brightness_down();
82 break;
84 default:
85 return 0;
88 /* On success, the IO Trap Handler returns 1
89 * On failure, the IO Trap Handler returns a value != 1 */
90 return 1;
93 static void mainboard_smi_handle_ec_sci(void)
95 u8 status = inb(EC_SC);
96 u8 event;
98 if (!(status & EC_SCI_EVT))
99 return;
101 event = ec_query();
102 printk(BIOS_DEBUG, "EC event %#02x\n", event);
104 switch (event) {
105 /* brightness up */
106 case 0x14:
107 mainboard_smi_brightness_up();
108 break;
109 /* brightness down */
110 case 0x15:
111 mainboard_smi_brightness_down();
112 break;
113 /* Fn-F9 Key */
114 case 0x18:
115 /* power loss */
116 case 0x27:
117 /* undock event */
118 case 0x50:
119 mainboard_io_trap_handler(SMI_DOCK_DISCONNECT);
120 break;
121 /* dock event */
122 case 0x37:
123 mainboard_io_trap_handler(SMI_DOCK_CONNECT);
124 break;
125 default:
126 break;
130 void mainboard_smi_gpi(u32 gpi)
132 if (gpi & (1 << GPE_EC_SCI))
133 mainboard_smi_handle_ec_sci();
136 int mainboard_smi_apmc(u8 data)
138 switch (data) {
139 case APM_CNT_ACPI_ENABLE:
140 /* use 0x1600/0x1604 to prevent races with userspace */
141 ec_set_ports(0x1604, 0x1600);
142 /* route H8SCI to SCI */
143 gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SCI);
144 break;
145 case APM_CNT_ACPI_DISABLE:
146 /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't
147 provide a EC query function */
148 ec_set_ports(0x66, 0x62);
149 /* route H8SCI# to SMI */
150 gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI);
151 break;
152 default:
153 break;
155 return 0;