1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <device/pci_ops.h>
5 #include <device/pci_def.h>
6 #include <console/console.h>
7 #include <cpu/x86/smm.h>
9 #include <southbridge/intel/common/pmutil.h>
10 #include <ec/acpi/ec.h>
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)))
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)))
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 static void mainboard_smi_dock_connect(void)
50 /* If there's an legacy I/O module present, we're not
51 * allowed to connect the Docking LPC Bus, as both Super I/O
52 * chips are using 0x2e as base address.
54 if (legacy_io_present())
57 if (!dock_connect()) {
58 /* set dock LED to indicate status */
62 /* blink dock LED to indicate failure */
68 static void mainboard_smi_dock_disconnect(void)
75 int mainboard_io_trap_handler(int smif
)
78 case SMI_DOCK_CONNECT
:
79 mainboard_smi_dock_connect();
82 case SMI_DOCK_DISCONNECT
:
83 mainboard_smi_dock_disconnect();
86 case SMI_BRIGHTNESS_UP
:
87 mainboard_smi_brightness_up();
90 case SMI_BRIGHTNESS_DOWN
:
91 mainboard_smi_brightness_down();
98 /* On success, the IO Trap Handler returns 1
99 * On failure, the IO Trap Handler returns a value != 1 */
103 static void mainboard_smi_handle_ec_sci(void)
105 u8 status
= inb(EC_SC
);
108 if (!(status
& EC_SCI_EVT
))
112 printk(BIOS_DEBUG
, "EC event %#02x\n", event
);
117 mainboard_smi_brightness_up();
119 /* brightness down */
121 mainboard_smi_brightness_down();
129 mainboard_smi_dock_disconnect();
133 mainboard_smi_dock_connect();
140 void mainboard_smi_gpi(u32 gpi
)
142 if (gpi
& (1 << GPE_EC_SCI
))
143 mainboard_smi_handle_ec_sci();
146 int mainboard_smi_apmc(u8 data
)
149 case APM_CNT_ACPI_ENABLE
:
150 /* use 0x1600/0x1604 to prevent races with userspace */
151 ec_set_ports(0x1604, 0x1600);
152 /* route H8SCI to SCI */
153 gpi_route_interrupt(GPE_EC_SCI
, GPI_IS_SCI
);
155 case APM_CNT_ACPI_DISABLE
:
156 /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't
157 provide a EC query function */
158 ec_set_ports(0x66, 0x62);
159 /* route H8SCI# to SMI */
160 gpi_route_interrupt(GPE_EC_SCI
, GPI_IS_SMI
);