coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
smi_util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 /* SMI utilities used in both SMM and normal mode */
4 
5 #include <console/console.h>
6 #include <cpu/x86/smm.h>
7 #include <soc/southbridge.h>
8 #include <soc/smi.h>
9 #include <amdblocks/acpimmio.h>
10 #include <amdblocks/smi.h>
11 
12 void configure_smi(uint8_t smi_num, uint8_t mode)
13 {
14  uint8_t reg32_offset, bit_offset;
15  uint32_t reg32;
16 
17  if (smi_num >= NUMBER_SMITYPES) {
18  printk(BIOS_WARNING, "BUG: Invalid SMI: %u\n", smi_num);
19  return;
20  }
21 
22  /* 16 sources per register, 2 bits per source; registers are 4 bytes */
23  reg32_offset = (smi_num / 16) * 4;
24  bit_offset = (smi_num % 16) * 2;
25 
26  reg32 = smi_read32(SMI_REG_CONTROL0 + reg32_offset);
27  reg32 &= ~(0x3 << (bit_offset));
28  reg32 |= (mode & 0x3) << bit_offset;
29  smi_write32(SMI_REG_CONTROL0 + reg32_offset, reg32);
30 }
31 
32 /**
33  * Configure generation of interrupts for given GEVENT pin
34  *
35  * @param gevent The GEVENT pin number. Valid values are 0 thru 23
36  * @param mode The type of event this pin should generate. Note that only
37  * SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events.
38  * @param level SMI__SCI_LVL_LOW or SMI_SCI_LVL_HIGH
39  */
40 void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
41 {
42  uint32_t reg32;
43  /* GEVENT pins range from [0:23] */
44  if (gevent >= SMI_GEVENTS) {
45  printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
46  return;
47  }
48 
49  /* SMI0 source is GEVENT0 and so on */
50  configure_smi(gevent, mode);
51 
52  /* And set the trigger level */
54  reg32 &= ~(1 << gevent);
55  reg32 |= (level & 0x1) << gevent;
57 }
58 
59 /** Set the EOS bit and enable SMI generation from southbridge */
61 {
63  reg &= ~SMITRG0_SMIENB; /* Enable SMI generation */
64  reg |= SMITRG0_EOS; /* Set EOS bit */
66 }
67 
69 {
71  reg |= SMITRG0_EOS;
73 }
74 
75 /**
76  * Configure generation of SCIs.
77  */
78 void configure_scimap(const struct sci_source *sci)
79 {
80  uint32_t reg32;
81 
82  /* GEVENT pins range */
83  if (sci->scimap >= SCIMAPS) {
84  printk(BIOS_WARNING, "BUG: Invalid SCIMAP: %u\n",
85  sci->scimap);
86  return;
87  }
88 
89  /* GPEs range from [0:31] */
90  if (sci->gpe >= SCI_GPES) {
91  printk(BIOS_WARNING, "BUG: Invalid SCI GPE: %u\n", sci->gpe);
92  return;
93  }
94 
95  printk(BIOS_DEBUG, "SCIMAP %u maps to GPE %u (active %s, %s trigger)\n",
96  sci->scimap, sci->gpe,
97  (!!sci->direction) ? "high" : "low",
98  (!!sci->level) ? "level" : "edge");
99 
100  /* Map Gevent to SCI GPE# */
101  smi_write8(SMI_SCI_MAP(sci->scimap), sci->gpe);
102 
103  /* Set the trigger direction (high/low) */
104  reg32 = smi_read32(SMI_SCI_TRIG);
105  reg32 &= ~(1 << sci->gpe);
106  reg32 |= !!sci->direction << sci->gpe;
107  smi_write32(SMI_SCI_TRIG, reg32);
108 
109  /* Set the trigger level (edge/level) */
110  reg32 = smi_read32(SMI_SCI_LEVEL);
111  reg32 &= ~(1 << sci->gpe);
112  reg32 |= !!sci->level << sci->gpe;
113  smi_write32(SMI_SCI_LEVEL, reg32);
114 }
115 
116 void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes)
117 {
118  size_t i;
119 
120  for (i = 0; i < num_gpes; i++)
121  configure_scimap(scis + i);
122 }
123 
124 /** Disable events from given GEVENT pin */
126 {
127  /* GEVENT pins range from [0:23] */
128  if (gevent > 23) {
129  printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
130  return;
131  }
132 
133  /* SMI0 source is GEVENT0 and so on */
135 }
136 
138 {
139  return pm_read16(PM_ACPI_SMI_CMD);
140 }
141 
143 {
151 }
152 
154 {
156 }
static void smi_write32(uint8_t reg, uint32_t value)
Definition: acpimmio.h:161
static uint16_t pm_read16(uint8_t reg)
Definition: acpimmio.h:171
static uint32_t smi_read32(uint8_t reg)
Definition: acpimmio.h:146
static void smi_write8(uint8_t reg, uint8_t value)
Definition: acpimmio.h:151
#define PM_ACPI_SMI_CMD
Definition: southbridge.h:42
#define printk(level,...)
Definition: stdlib.h:16
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
#define SMITRG0_EOS
Definition: smi.h:165
#define SMI_SCI_STATUS
Definition: smi.h:17
#define SMI_SCI_TRIG
Definition: smi.h:15
#define SMI_REG_CONTROL0
Definition: smi.h:169
#define SMI_SCI_MAP(X)
Definition: smi.h:20
#define SMITRG0_SMIENB
Definition: smi.h:167
#define SMI_REG_SMITRIG0
Definition: smi.h:163
#define SCIMAPS
Definition: smi.h:9
#define SMI_REG_SMISTS1
Definition: smi.h:146
#define SMI_SCI_LEVEL
Definition: smi.h:16
#define SCI_GPES
Definition: smi.h:10
#define SMI_REG_SMISTS0
Definition: smi.h:145
#define SMI_REG_SMISTS4
Definition: smi.h:149
#define SMI_REG_SMISTS3
Definition: smi.h:148
#define SMI_REG_SMISTS2
Definition: smi.h:147
#define SMI_GEVENTS
Definition: smi.h:8
#define SMI_EVENT_STATUS
Definition: smi.h:13
#define NUMBER_SMITYPES
Definition: smi.h:11
@ SMI_MODE_DISABLE
Definition: smi.h:9
void clear_smi_sci_status(void)
Definition: smi_util.c:153
void configure_smi(uint8_t smi_num, uint8_t mode)
Definition: smi_util.c:12
void southbridge_smi_set_eos(void)
Definition: smi_util.c:68
void clear_all_smi_status(void)
Definition: smi_util.c:142
void global_smi_enable(void)
Set the EOS bit and enable SMI generation from southbridge.
Definition: smi_util.c:60
uint16_t pm_acpi_smi_cmd_port(void)
Definition: smi_util.c:137
void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
Configure generation of interrupts for given GEVENT pin.
Definition: smi_util.c:40
void configure_scimap(const struct sci_source *sci)
Configure generation of SCIs.
Definition: smi_util.c:78
void disable_gevent_smi(uint8_t gevent)
Disable events from given GEVENT pin.
Definition: smi_util.c:125
void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes)
Definition: smi_util.c:116
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
Definition: smi.h:37
uint8_t gpe
Definition: smi.h:39
uint8_t scimap
Definition: smi.h:38
uint8_t level
Definition: smi.h:41
uint8_t direction
Definition: smi.h:40