blob: f3c34e51f089184458baedcebd2506fef0954d81 [file] [log] [blame]
Angel Pons89ab2502020-04-03 01:22:28 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Sven Schnelled8129f92011-04-20 09:12:17 +00002
3#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Patrick Rudolph9f8f1152020-05-06 11:58:45 +02005#include <device/pci_def.h>
Sven Schnelled8129f92011-04-20 09:12:17 +00006#include <console/console.h>
7#include <cpu/x86/smm.h>
Kyösti Mälkki661ad462020-12-29 06:26:21 +02008#include <soc/nvs.h>
Arthur Heymans31312b22018-04-10 12:56:19 +02009#include <southbridge/intel/common/pmutil.h>
Sven Schnelled8129f92011-04-20 09:12:17 +000010#include <ec/acpi/ec.h>
11#include "dock.h"
12#include "smi.h"
13
Kyösti Mälkki189f3ba2014-12-29 11:32:27 +020014#define GPE_EC_SCI 12
15
Sven Schnelle61cd5bf2011-06-23 19:12:25 +020016#define LVTMA_BL_MOD_LEVEL 0x7af9 /* ATI Radeon backlight level */
Sven Schnelled8129f92011-04-20 09:12:17 +000017
Sven Schnelle61cd5bf2011-06-23 19:12:25 +020018static void mainboard_smi_brightness_down(void)
19{
Patrick Rudolph9f8f1152020-05-06 11:58:45 +020020 uint32_t reg32 = pci_read_config32(PCI_DEV(1, 0, 0), PCI_BASE_ADDRESS_2) & ~0xf;
21 u8 *bar = (void *)(uintptr_t)reg32;
22
23 /* Validate pointer before using it */
24 if (!bar || smm_points_to_smram(bar, LVTMA_BL_MOD_LEVEL + sizeof(uint8_t)))
25 return;
26
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;
Sven Schnelle61cd5bf2011-06-23 19:12:25 +020031}
32
33static void mainboard_smi_brightness_up(void)
34{
Patrick Rudolph9f8f1152020-05-06 11:58:45 +020035 uint32_t reg32 = pci_read_config32(PCI_DEV(1, 0, 0), PCI_BASE_ADDRESS_2) & ~0xf;
36 u8 *bar = (void *)(uintptr_t)reg32;
37
38 /* Validate pointer before using it */
39 if (!bar || smm_points_to_smram(bar, LVTMA_BL_MOD_LEVEL + sizeof(uint8_t)))
40 return;
41
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;
Sven Schnelled8129f92011-04-20 09:12:17 +000046}
47
Kyösti Mälkki791f7a42022-12-02 17:59:35 +020048static void mainboard_smi_dock_connect(void)
49{
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.
53 */
54 if (legacy_io_present())
55 return;
56
57 if (!dock_connect()) {
58 /* set dock LED to indicate status */
59 ec_write(0x0c, 0x08);
60 ec_write(0x0c, 0x89);
61 } else {
62 /* blink dock LED to indicate failure */
63 ec_write(0x0c, 0xc8);
64 ec_write(0x0c, 0x09);
65 }
66}
67
68static void mainboard_smi_dock_disconnect(void)
69{
70 dock_disconnect();
71 ec_write(0x0c, 0x09);
72 ec_write(0x0c, 0x08);
73}
74
Sven Schnelled8129f92011-04-20 09:12:17 +000075int mainboard_io_trap_handler(int smif)
76{
Sven Schnelled8129f92011-04-20 09:12:17 +000077 switch (smif) {
78 case SMI_DOCK_CONNECT:
Kyösti Mälkki791f7a42022-12-02 17:59:35 +020079 mainboard_smi_dock_connect();
Sven Schnelled8129f92011-04-20 09:12:17 +000080 break;
81
82 case SMI_DOCK_DISCONNECT:
Kyösti Mälkki791f7a42022-12-02 17:59:35 +020083 mainboard_smi_dock_disconnect();
Sven Schnelled8129f92011-04-20 09:12:17 +000084 break;
85
Sven Schnelle61cd5bf2011-06-23 19:12:25 +020086 case SMI_BRIGHTNESS_UP:
87 mainboard_smi_brightness_up();
88 break;
89
90 case SMI_BRIGHTNESS_DOWN:
91 mainboard_smi_brightness_down();
92 break;
93
Sven Schnelled8129f92011-04-20 09:12:17 +000094 default:
Sven Schnelle0f9cd432011-06-12 16:55:56 +020095 return 0;
Sven Schnelled8129f92011-04-20 09:12:17 +000096 }
97
Sven Schnelle0f9cd432011-06-12 16:55:56 +020098 /* On success, the IO Trap Handler returns 1
99 * On failure, the IO Trap Handler returns a value != 1 */
100 return 1;
Sven Schnelled8129f92011-04-20 09:12:17 +0000101}
102
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200103static void mainboard_smi_handle_ec_sci(void)
104{
105 u8 status = inb(EC_SC);
106 u8 event;
107
108 if (!(status & EC_SCI_EVT))
109 return;
110
111 event = ec_query();
Paul Menzel56642932020-07-19 09:42:53 +0200112 printk(BIOS_DEBUG, "EC event %#02x\n", event);
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200113
Elyes HAOUAS0ce41f12018-11-13 10:03:31 +0100114 switch (event) {
Felix Singerdf98b812023-12-08 10:52:34 +0100115 /* brightness up */
116 case 0x14:
117 mainboard_smi_brightness_up();
118 break;
119 /* brightness down */
120 case 0x15:
121 mainboard_smi_brightness_down();
122 break;
123 /* Fn-F9 Key */
124 case 0x18:
125 /* power loss */
126 case 0x27:
127 /* undock event */
128 case 0x50:
129 mainboard_smi_dock_disconnect();
130 break;
131 /* dock event */
132 case 0x37:
133 mainboard_smi_dock_connect();
134 break;
135 default:
136 break;
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200137 }
138}
139
Duncan Laurie0edc2242013-04-29 15:04:30 -0700140void mainboard_smi_gpi(u32 gpi)
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200141{
Kyösti Mälkki189f3ba2014-12-29 11:32:27 +0200142 if (gpi & (1 << GPE_EC_SCI))
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200143 mainboard_smi_handle_ec_sci();
144}
145
Stefan Reinauerbf34e942012-04-27 00:44:04 +0200146int mainboard_smi_apmc(u8 data)
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200147{
Elyes HAOUAS0ce41f12018-11-13 10:03:31 +0100148 switch (data) {
Felix Singerdf98b812023-12-08 10:52:34 +0100149 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);
154 break;
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);
161 break;
162 default:
163 break;
Sven Schnelle61cd5bf2011-06-23 19:12:25 +0200164 }
165 return 0;
166}