blob: 3dc2d8a31e50a911d37262f8218acabd824d474a [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Martin Rothebace9f2018-05-26 18:56:17 -06002
3/*
4 * SMM utilities used in both SMM and normal mode
Alexandru Gagniuc599d6682014-04-17 23:33:50 -05005 */
6
Michał Żygowskif3db2ae2019-11-24 13:26:10 +01007#include <amdblocks/acpimmio.h>
Alexandru Gagniuc599d6682014-04-17 23:33:50 -05008#include <console/console.h>
9
Michał Żygowskif3db2ae2019-11-24 13:26:10 +010010#include "smi.h"
11
Alexandru Gagniuc599d6682014-04-17 23:33:50 -050012#define HUDSON_SMI_ACPI_COMMAND 75
13
14static void configure_smi(uint8_t smi_num, uint8_t mode)
15{
16 uint8_t reg32_offset, bit_offset;
17 uint32_t reg32;
18
19 /* SMI sources range from [0:149] */
20 if (smi_num > 149) {
21 printk(BIOS_WARNING, "BUG: Invalid SMI: %u\n", smi_num);
22 return;
23 }
24
25 /* 16 sources per register, 2 bits per source; registers are 4 bytes */
26 reg32_offset = (smi_num / 16) * 4;
27 bit_offset = (smi_num % 16) * 2;
28
29 reg32 = smi_read32(SMI_REG_CONTROL0 + reg32_offset);
30 reg32 &= ~(0x3 << (bit_offset));
31 reg32 |= (mode & 0x3) << bit_offset;
32 smi_write32(SMI_REG_CONTROL0 + reg32_offset, reg32);
33}
34
35/**
36 * Configure generation of interrupts for given GEVENT pin
37 *
38 * @param gevent The GEVENT pin number. Valid values are 0 thru 23
39 * @param mode The type of event this pin should generate. Note that only
40 * SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events.
41 * @param level SMI_LVL_LOW or SMI_LVL_HIGH
42 */
43void hudson_configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
44{
45 uint32_t reg32;
46 /* GEVENT pins range from [0:23] */
47 if (gevent > 23) {
48 printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
49 return;
50 }
51
52 /* SMI0 source is GEVENT0 and so on */
53 configure_smi(gevent, mode);
54
Elyes HAOUASf23cc1c2022-01-07 18:26:24 +010055 /* And set the trigger level */
Alexandru Gagniuc599d6682014-04-17 23:33:50 -050056 reg32 = smi_read32(SMI_REG_SMITRIG0);
57 reg32 &= ~(1 << gevent);
58 reg32 |= (level & 0x1) << gevent;
59 smi_write32(SMI_REG_SMITRIG0, reg32);
60}
61
62/** Disable events from given GEVENT pin */
63void hudson_disable_gevent_smi(uint8_t gevent)
64{
65 /* GEVENT pins range from [0:23] */
66 if (gevent > 23) {
67 printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
68 return;
69 }
70
71 /* SMI0 source is GEVENT0 and so on */
72 configure_smi(gevent, SMI_MODE_DISABLE);
73}
74
75/** Enable SMIs on writes to ACPI SMI command port */
76void hudson_enable_acpi_cmd_smi(void)
77{
78 configure_smi(HUDSON_SMI_ACPI_COMMAND, SMI_MODE_SMI);
79}