coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
smihandler.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
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>
10 #include <ec/acpi/ec.h>
11 #include "dock.h"
12 #include "smi.h"
13 
14 #define GPE_EC_SCI 12
15 
16 #define LVTMA_BL_MOD_LEVEL 0x7af9 /* ATI Radeon backlight level */
17 
19 {
20  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;
31 }
32 
33 static void mainboard_smi_brightness_up(void)
34 {
35  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;
46 }
47 
49 {
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.
55  */
56  if (legacy_io_present())
57  break;
58 
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);
67  }
68  break;
69 
72  ec_write(0x0c, 0x09);
73  ec_write(0x0c, 0x08);
74  break;
75 
76  case SMI_BRIGHTNESS_UP:
78  break;
79 
82  break;
83 
84  default:
85  return 0;
86  }
87 
88  /* On success, the IO Trap Handler returns 1
89  * On failure, the IO Trap Handler returns a value != 1 */
90  return 1;
91 }
92 
93 static void mainboard_smi_handle_ec_sci(void)
94 {
95  u8 status = inb(EC_SC);
96  u8 event;
97 
98  if (!(status & EC_SCI_EVT))
99  return;
100 
101  event = ec_query();
102  printk(BIOS_DEBUG, "EC event %#02x\n", event);
103 
104  switch (event) {
105  /* brightness up */
106  case 0x14:
108  break;
109  /* brightness down */
110  case 0x15:
112  break;
113  /* Fn-F9 Key */
114  case 0x18:
115  /* power loss */
116  case 0x27:
117  /* undock event */
118  case 0x50:
120  break;
121  /* dock event */
122  case 0x37:
124  break;
125  default:
126  break;
127  }
128 }
129 
131 {
132  if (gpi & (1 << GPE_EC_SCI))
134 }
135 
137 {
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 */
144  break;
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 */
151  break;
152  default:
153  break;
154  }
155  return 0;
156 }
#define printk(level,...)
Definition: stdlib.h:16
int __weak mainboard_smi_apmc(u8 data)
Definition: smihandler.c:209
void __weak mainboard_smi_gpi(u32 gpi_sts)
Definition: smihandler.c:208
int __weak mainboard_io_trap_handler(int smif)
Definition: smihandler.c:206
u8 inb(u16 port)
u8 ec_query(void)
Definition: ec.c:127
void ec_set_ports(u16 cmd_reg, u16 data_reg)
Definition: ec.c:143
int ec_write(u8 addr, u8 data)
Definition: ec.c:115
#define EC_SC
Definition: ec.h:9
#define EC_SCI_EVT
Definition: ec.h:13
static bool smm_points_to_smram(const void *ptr, const size_t len)
Definition: smm.h:118
#define APM_CNT_ACPI_DISABLE
Definition: smm.h:21
#define APM_CNT_ACPI_ENABLE
Definition: smm.h:22
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define GPI_IS_SMI
Definition: smihandler.c:34
#define GPI_IS_SCI
Definition: smihandler.c:35
#define SMI_BRIGHTNESS_UP
Definition: smi.h:8
#define SMI_DOCK_DISCONNECT
Definition: smi.h:7
#define SMI_BRIGHTNESS_DOWN
Definition: smi.h:9
#define SMI_DOCK_CONNECT
Definition: smi.h:6
#define LVTMA_BL_MOD_LEVEL
Definition: smihandler.c:16
static void mainboard_smi_handle_ec_sci(void)
Definition: smihandler.c:93
static void mainboard_smi_brightness_up(void)
Definition: smihandler.c:33
static void mainboard_smi_brightness_down(void)
Definition: smihandler.c:18
#define GPE_EC_SCI
Definition: smihandler.c:14
#define PCI_BASE_ADDRESS_2
Definition: pci_def.h:65
#define PCI_DEV(SEGBUS, DEV, FN)
Definition: pci_type.h:14
void gpi_route_interrupt(u8 gpi, u8 mode)
Definition: smihandler.c:25
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
void dock_connect(void)
Definition: dock.c:215
void dock_disconnect(void)
Definition: dock.c:234
int legacy_io_present(void)
Definition: dock.c:206