aboutsummaryrefslogtreecommitdiff
path: root/src/southbridge/amd/pi/hudson/smihandler.c
diff options
context:
space:
mode:
authorDave Frodin <dave.frodin@se-eng.com>2015-01-19 11:40:38 -0700
committerDave Frodin <dave.frodin@se-eng.com>2015-01-27 15:07:45 +0100
commitbc21a41e1ca045baae57f79d89aafdf682528a4b (patch)
tree217891284eb2f483f57a053b94d1f4fc6e7f94fe /src/southbridge/amd/pi/hudson/smihandler.c
parentbd1d1580d3cdbd1f438e8fb0d960102f252c6939 (diff)
southbridge/amd/pi: Rename Avalon to Hudson
To maintain consistancy with southbridge/amd/agesa/hudson rename pi/avalon to pi/hudson in advance of adding support for the base hudson southbridge. Change-Id: Icff8c4c06aae2d40cbd9e90903754735ac3510c3 Signed-off-by: Dave Frodin <dave.frodin@se-eng.com> Reviewed-on: http://review.coreboot.org/8251 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones <marc.jones@se-eng.com>
Diffstat (limited to 'src/southbridge/amd/pi/hudson/smihandler.c')
-rw-r--r--src/southbridge/amd/pi/hudson/smihandler.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/southbridge/amd/pi/hudson/smihandler.c b/src/southbridge/amd/pi/hudson/smihandler.c
new file mode 100644
index 0000000000..e762d0bb96
--- /dev/null
+++ b/src/southbridge/amd/pi/hudson/smihandler.c
@@ -0,0 +1,136 @@
+/*
+ * SMI handler for Hudson southbridges
+ *
+ * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#include "hudson.h"
+#include "smi.h"
+
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <delay.h>
+
+#define SMI_0x88_ACPI_COMMAND (1 << 11)
+
+enum smi_source {
+ SMI_SOURCE_SCI = (1 << 0),
+ SMI_SOURCE_GPE = (1 << 1),
+ SMI_SOURCE_0x84 = (1 << 2),
+ SMI_SOURCE_0x88 = (1 << 3),
+ SMI_SOURCE_IRQ_TRAP = (1 << 4),
+ SMI_SOURCE_0x90 = (1 << 5)
+};
+
+static void hudson_apmc_smi_handler(void)
+{
+ u32 reg32;
+ const uint8_t cmd = inb(ACPI_SMI_CTL_PORT);
+
+ switch (cmd) {
+ case ACPI_SMI_CMD_ENABLE:
+ reg32 = inl(ACPI_PM1_CNT_BLK);
+ reg32 |= (1 << 0); /* SCI_EN */
+ outl(reg32, ACPI_PM1_CNT_BLK);
+ break;
+ case ACPI_SMI_CMD_DISABLE:
+ reg32 = inl(ACPI_PM1_CNT_BLK);
+ reg32 &= ~(1 << 0); /* clear SCI_EN */
+ outl(ACPI_PM1_CNT_BLK, reg32);
+ break;
+ }
+
+ if (mainboard_smi_apmc)
+ mainboard_smi_apmc(cmd);
+}
+
+int southbridge_io_trap_handler(int smif)
+{
+ return 0;
+}
+
+static void process_smi_sci(void)
+{
+ const uint32_t status = smi_read32(0x10);
+
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(0x10, status);
+}
+
+static void process_gpe_smi(void)
+{
+ const uint32_t status = smi_read32(0x80);
+ const uint32_t gevent_mask = (1 << 24) - 1;
+
+ /* Only Bits [23:0] indicate GEVENT SMIs. */
+ if (status & gevent_mask) {
+ /* A GEVENT SMI occured */
+ if (mainboard_smi_gpi)
+ mainboard_smi_gpi(status & gevent_mask);
+ }
+
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(0x80, status);
+}
+
+static void process_smi_0x84(void)
+{
+ const uint32_t status = smi_read32(0x84);
+
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(0x84, status);
+}
+
+static void process_smi_0x88(void)
+{
+ const uint32_t status = smi_read32(0x88);
+
+ if (status & SMI_0x88_ACPI_COMMAND) {
+ /* Command received via ACPI SMI command port */
+ hudson_apmc_smi_handler();
+ }
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(0x88, status);
+}
+
+static void process_smi_0x8c(void)
+{
+ const uint32_t status = smi_read32(0x8c);
+
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(0x8c, status);
+}
+
+static void process_smi_0x90(void)
+{
+ const uint32_t status = smi_read32(0x90);
+
+ /* Clear events to prevent re-entering SMI if event isn't handled */
+ smi_write32(0x90, status);
+}
+
+void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save)
+{
+ const uint16_t smi_src = smi_read16(0x94);
+
+ if (smi_src & SMI_SOURCE_SCI)
+ process_smi_sci();
+ if (smi_src & SMI_SOURCE_GPE)
+ process_gpe_smi();
+ if (smi_src & SMI_SOURCE_0x84)
+ process_smi_0x84();
+ if (smi_src & SMI_SOURCE_0x88)
+ process_smi_0x88();
+ if (smi_src & SMI_SOURCE_IRQ_TRAP)
+ process_smi_0x8c();
+ if (smi_src & SMI_SOURCE_0x90)
+ process_smi_0x90();
+}
+
+void southbridge_smi_set_eos(void)
+{
+ uint32_t reg = smi_read32(SMI_REG_SMITRIG0);
+ reg |= SMITRG0_EOS;
+ smi_write32(SMI_REG_SMITRIG0, reg);
+}