2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 * SMM utilities used in both SMM and normal mode
20 #include <console/console.h>
21 #include <soc/southbridge.h>
23 #include <amdblocks/acpimmio.h>
25 void configure_smi(uint8_t smi_num
, uint8_t mode
)
27 uint8_t reg32_offset
, bit_offset
;
30 if (smi_num
>= NUMBER_SMITYPES
) {
31 printk(BIOS_WARNING
, "BUG: Invalid SMI: %u\n", smi_num
);
35 /* 16 sources per register, 2 bits per source; registers are 4 bytes */
36 reg32_offset
= (smi_num
/ 16) * 4;
37 bit_offset
= (smi_num
% 16) * 2;
39 reg32
= smi_read32(SMI_REG_CONTROL0
+ reg32_offset
);
40 reg32
&= ~(0x3 << (bit_offset
));
41 reg32
|= (mode
& 0x3) << bit_offset
;
42 smi_write32(SMI_REG_CONTROL0
+ reg32_offset
, reg32
);
46 * Configure generation of interrupts for given GEVENT pin
48 * @param gevent The GEVENT pin number. Valid values are 0 thru 23
49 * @param mode The type of event this pin should generate. Note that only
50 * SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events.
51 * @param level SMI__SCI_LVL_LOW or SMI_SCI_LVL_HIGH
53 void configure_gevent_smi(uint8_t gevent
, uint8_t mode
, uint8_t level
)
56 /* GEVENT pins range from [0:23] */
57 if (gevent
>= SMI_GEVENTS
) {
58 printk(BIOS_WARNING
, "BUG: Invalid GEVENT: %u\n", gevent
);
62 /* SMI0 source is GEVENT0 and so on */
63 configure_smi(gevent
, mode
);
65 /* And set set the trigger level */
66 reg32
= smi_read32(SMI_REG_SMITRIG0
);
67 reg32
&= ~(1 << gevent
);
68 reg32
|= (level
& 0x1) << gevent
;
69 smi_write32(SMI_REG_SMITRIG0
, reg32
);
73 * Configure generation of SCIs.
75 void configure_scimap(const struct sci_source
*sci
)
79 /* GEVENT pins range */
80 if (sci
->scimap
>= SCIMAPS
) {
81 printk(BIOS_WARNING
, "BUG: Invalid SCIMAP: %u\n",
86 /* GPEs range from [0:31] */
87 if (sci
->gpe
>= SCI_GPES
) {
88 printk(BIOS_WARNING
, "BUG: Invalid SCI GPE: %u\n", sci
->gpe
);
92 printk(BIOS_DEBUG
, "SCIMAP %u maps to GPE %u (active %s, %s trigger)\n",
93 sci
->scimap
, sci
->gpe
,
94 (!!sci
->direction
) ? "high" : "low",
95 (!!sci
->level
) ? "level" : "edge");
97 /* Map Gevent to SCI GPE# */
98 smi_write8(SMI_SCI_MAP(sci
->scimap
), sci
->gpe
);
100 /* Set the trigger direction (high/low) */
101 reg32
= smi_read32(SMI_SCI_TRIG
);
102 reg32
&= ~(1 << sci
->gpe
);
103 reg32
|= !!sci
->direction
<< sci
->gpe
;
104 smi_write32(SMI_SCI_TRIG
, reg32
);
106 /* Set the trigger level (edge/level) */
107 reg32
= smi_read32(SMI_SCI_LEVEL
);
108 reg32
&= ~(1 << sci
->gpe
);
109 reg32
|= !!sci
->level
<< sci
->gpe
;
110 smi_write32(SMI_SCI_LEVEL
, reg32
);
113 void gpe_configure_sci(const struct sci_source
*scis
, size_t num_gpes
)
117 for (i
= 0; i
< num_gpes
; i
++)
118 configure_scimap(scis
+ i
);
121 /** Disable events from given GEVENT pin */
122 void disable_gevent_smi(uint8_t gevent
)
124 /* GEVENT pins range from [0:23] */
126 printk(BIOS_WARNING
, "BUG: Invalid GEVENT: %u\n", gevent
);
130 /* SMI0 source is GEVENT0 and so on */
131 configure_smi(gevent
, SMI_MODE_DISABLE
);
134 uint16_t pm_acpi_smi_cmd_port(void)
136 return pm_read16(PM_ACPI_SMI_CMD
);