blob: 8b88c06de3f1f1e748fcebf0562ff216267b11a3 [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 * SMI handler for Hudson southbridges
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +03005 */
6
Michał Żygowskif3db2ae2019-11-24 13:26:10 +01007#include <amdblocks/acpimmio.h>
Kyösti Mälkkibdaec072019-03-02 23:18:29 +02008#include <arch/io.h>
Elyes HAOUASbf0970e2019-03-21 11:10:03 +01009#include <cpu/x86/smm.h>
10
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030011#include "hudson.h"
12#include "smi.h"
13
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030014#define SMI_0x88_ACPI_COMMAND (1 << 11)
15
16enum smi_source {
17 SMI_SOURCE_SCI = (1 << 0),
18 SMI_SOURCE_GPE = (1 << 1),
19 SMI_SOURCE_0x84 = (1 << 2),
20 SMI_SOURCE_0x88 = (1 << 3),
21 SMI_SOURCE_IRQ_TRAP = (1 << 4),
22 SMI_SOURCE_0x90 = (1 << 5)
23};
24
25static void hudson_apmc_smi_handler(void)
26{
27 u32 reg32;
Felix Held1b558eb2024-01-08 17:10:37 +010028 const uint8_t cmd = apm_get_apmc();
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030029
30 switch (cmd) {
Felix Held74beb5d2024-01-08 17:02:23 +010031 case APM_CNT_ACPI_ENABLE:
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030032 reg32 = inl(ACPI_PM1_CNT_BLK);
33 reg32 |= (1 << 0); /* SCI_EN */
34 outl(reg32, ACPI_PM1_CNT_BLK);
35 break;
Felix Held74beb5d2024-01-08 17:02:23 +010036 case APM_CNT_ACPI_DISABLE:
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030037 reg32 = inl(ACPI_PM1_CNT_BLK);
38 reg32 &= ~(1 << 0); /* clear SCI_EN */
39 outl(ACPI_PM1_CNT_BLK, reg32);
40 break;
41 }
42
Kyösti Mälkki48b3dbc2014-12-29 19:36:50 +020043 mainboard_smi_apmc(cmd);
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030044}
45
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030046static void process_smi_sci(void)
47{
48 const uint32_t status = smi_read32(0x10);
49
50 /* Clear events to prevent re-entering SMI if event isn't handled */
51 smi_write32(0x10, status);
52}
53
54static void process_gpe_smi(void)
55{
56 const uint32_t status = smi_read32(0x80);
57 const uint32_t gevent_mask = (1 << 24) - 1;
58
59 /* Only Bits [23:0] indicate GEVENT SMIs. */
60 if (status & gevent_mask) {
Martin Roth2ed0aa22016-01-05 20:58:58 -070061 /* A GEVENT SMI occurred */
Kyösti Mälkki48b3dbc2014-12-29 19:36:50 +020062 mainboard_smi_gpi(status & gevent_mask);
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +030063 }
64
65 /* Clear events to prevent re-entering SMI if event isn't handled */
66 smi_write32(0x80, status);
67}
68
69static void process_smi_0x84(void)
70{
71 const uint32_t status = smi_read32(0x84);
72
73 /* Clear events to prevent re-entering SMI if event isn't handled */
74 smi_write32(0x84, status);
75}
76
77static void process_smi_0x88(void)
78{
79 const uint32_t status = smi_read32(0x88);
80
81 if (status & SMI_0x88_ACPI_COMMAND) {
82 /* Command received via ACPI SMI command port */
83 hudson_apmc_smi_handler();
84 }
85 /* Clear events to prevent re-entering SMI if event isn't handled */
86 smi_write32(0x88, status);
87}
88
89static void process_smi_0x8c(void)
90{
91 const uint32_t status = smi_read32(0x8c);
92
93 /* Clear events to prevent re-entering SMI if event isn't handled */
94 smi_write32(0x8c, status);
95}
96
97static void process_smi_0x90(void)
98{
99 const uint32_t status = smi_read32(0x90);
100
101 /* Clear events to prevent re-entering SMI if event isn't handled */
102 smi_write32(0x90, status);
103}
104
Kyösti Mälkki1ef039b2019-08-10 15:32:03 +0300105void southbridge_smi_handler(void)
Kyösti Mälkkie8b4da22014-10-21 18:22:32 +0300106{
107 const uint16_t smi_src = smi_read16(0x94);
108
109 if (smi_src & SMI_SOURCE_SCI)
110 process_smi_sci();
111 if (smi_src & SMI_SOURCE_GPE)
112 process_gpe_smi();
113 if (smi_src & SMI_SOURCE_0x84)
114 process_smi_0x84();
115 if (smi_src & SMI_SOURCE_0x88)
116 process_smi_0x88();
117 if (smi_src & SMI_SOURCE_IRQ_TRAP)
118 process_smi_0x8c();
119 if (smi_src & SMI_SOURCE_0x90)
120 process_smi_0x90();
121}
122
123void southbridge_smi_set_eos(void)
124{
125 uint32_t reg = smi_read32(SMI_REG_SMITRIG0);
126 reg |= SMITRG0_EOS;
127 smi_write32(SMI_REG_SMITRIG0, reg);
128}