summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/superio/nuvoton/npcd378/acpi/superio.asl184
-rw-r--r--src/superio/nuvoton/npcd378/superio.c53
2 files changed, 229 insertions, 8 deletions
diff --git a/src/superio/nuvoton/npcd378/acpi/superio.asl b/src/superio/nuvoton/npcd378/acpi/superio.asl
index 963704e0ae..a4813e334c 100644
--- a/src/superio/nuvoton/npcd378/acpi/superio.asl
+++ b/src/superio/nuvoton/npcd378/acpi/superio.asl
@@ -78,14 +78,6 @@ Device(SUPERIO_DEV) {
PNP_IRQ1, 8, /* Second IRQ */
}
- Method (_CRS)
- {
- /* Announce the used I/O ports to the OS */
- Return (ResourceTemplate () {
- IO (Decode16, SUPERIO_PNP_BASE, SUPERIO_PNP_BASE, 0x01, 0x02)
- })
- }
-
#undef PNP_ENTER_MAGIC_1ST
#undef PNP_ENTER_MAGIC_2ND
#undef PNP_ENTER_MAGIC_3RD
@@ -165,4 +157,180 @@ Device(SUPERIO_DEV) {
#define SUPERIO_PNP_IO0 0x08, 0x08
#include <superio/acpi/pnp_generic.asl>
#endif
+
+ // generated by SSDT
+ External(SWB, IntObj)
+ External(SWL, IntObj)
+ OperationRegion (SWCR, SystemIO, SWB, SWL)
+ Field (SWCR, ByteAcc, NoLock, Preserve)
+ {
+ LEDC, 8,
+ SWCC, 8
+ }
+
+ // generated by SSDT
+ External(RNB, IntObj)
+ External(RNL, IntObj)
+ OperationRegion (RNTR, SystemIO, RNB, RNL)
+ Field (RNTR, ByteAcc, NoLock, Preserve)
+ {
+ GPES, 8,
+ GPEE, 8,
+ Offset (0x08),
+ GPS0, 8,
+ GPS1, 8,
+ GPS2, 8,
+ GPS3, 8,
+ GPE0, 8,
+ GPE1, 8,
+ GPE2, 8,
+ GPE3, 8
+ }
+
+ Name (MSFG, One)
+ Name (KBFG, One)
+ Name (PMFG, Zero) // Wake event backup
+
+ Method (_CRS, 0, Serialized)
+ {
+ Name (CRS, ResourceTemplate ()
+ {
+ FixedIO (SUPERIO_PNP_BASE, 0x02)
+ // filled below
+ FixedIO (0, 0, CRS1)
+ FixedIO (0, 0, CRS2)
+ })
+
+ CreateWordField (CRS, CRS1._BAS, TMP1)
+ Store(SWB, TMP1)
+ CreateByteField (CRS, CRS1._LEN, TMP2)
+ Store(SWL, TMP2)
+
+ CreateWordField (CRS, CRS2._BAS, TMP3)
+ Store(RNB, TMP3)
+ CreateByteField (CRS, CRS2._LEN, TMP4)
+ Store(RNL, TMP4)
+
+ /* Announce the used I/O ports to the OS */
+ Return (CRS)
+ }
+
+#ifdef SUPERIO_SHOW_KBC
+
+#if defined(SUPERIO_KBC_LDN)
+#define _PS2_KB SUPERIO_ID(KBD, SUPERIO_KBC_LDN)
+#else
+#define _PS2_KB PS2K
+#endif
+ Scope (_PS2_KB)
+ {
+ Method (_PSW, 1, NotSerialized)
+ {
+ KBFG = Arg0
+ }
+
+ Method (_PRW, 0, NotSerialized)
+ {
+ Return (Package (0x02) {0x08, 0x03})
+ }
+ }
+
+#if defined(SUPERIO_KBC_PS2M)
+#define _PS2_M SUPERIO_ID(PS2, SUPERIO_KBC_PS2M)
+#elif defined(SUPERIO_KBC_PS2LDN)
+#define _PS2_M SUPERIO_ID(PS2, SUPERIO_KBC_PS2LDN)
+#else
+#define _PS2_M PS2M
+#endif
+ Scope (_PS2_M)
+ {
+ Method (_PSW, 1, NotSerialized)
+ {
+ MSFG = Arg0
+ }
+
+ Method (_PRW, 0, NotSerialized)
+ {
+ Return (Package (0x02) {0x08, 0x03})
+ }
+ }
+
+ Method (SIOH, 0, NotSerialized)
+ {
+ If ((PMFG & 0xE8))
+ {
+ Notify (_PS2_KB, 0x02)
+ }
+
+ If ((PMFG & 0x10))
+ {
+ Notify (_PS2_M, 0x02)
+ }
+ }
+#else
+ Method (SIOH, 0, NotSerialized)
+ {
+ }
+#endif
+
+ /* SuperIO sleep method */
+ Method (SIOS, 1, NotSerialized)
+ {
+ If ((0x05 != Arg0))
+ {
+ /* Set PS/2 powerstate in S3 */
+ If (KBFG)
+ {
+ GPE2 |= 0xE8
+ }
+ Else
+ {
+ GPE2 &= 0x17
+ }
+
+ If (MSFG)
+ {
+ GPE2 |= 0x10
+ }
+ Else
+ {
+ GPE2 &= 0xEF
+ }
+
+ /* Enable wake on GPE */
+ GPEE = One
+ If ((0x03 == Arg0))
+ {
+ /* green LED fading */
+ Local1 = LEDC
+ Local1 &= 0xE0
+ LEDC = (Local1 | 0x1C)
+ Local1 = SWCC
+ Local1 &= 0xBF
+ SWCC = (Local1 | 0x40)
+ }
+ }
+
+ GPE0 = 0x10
+ GPE1 = 0x20
+ }
+
+ /* SuperIO wake method */
+ Method (SIOW, 1, NotSerialized)
+ {
+ /* Store wake status */
+ PMFG = GPS2
+
+ /* Disable wake on GPE */
+ GPEE = Zero
+ GPE0 = Zero
+ GPE1 = Zero
+
+ /* green LED normal */
+ Local1 = LEDC
+ Local1 &= 0xE0
+ LEDC = (Local1 | 0x1E)
+ Local1 = SWCC
+ SWCC = (Local1 & 0xBF)
+ }
}
diff --git a/src/superio/nuvoton/npcd378/superio.c b/src/superio/nuvoton/npcd378/superio.c
index e80d083bb2..1802193033 100644
--- a/src/superio/nuvoton/npcd378/superio.c
+++ b/src/superio/nuvoton/npcd378/superio.c
@@ -25,6 +25,8 @@
#include <pc80/keyboard.h>
#include <stdlib.h>
#include <superio/conf_mode.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
#include "npcd378.h"
@@ -101,6 +103,53 @@ static void npcd378_init(struct device *dev)
}
}
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+static void npcd378_ssdt(struct device *dev)
+{
+ struct resource *res;
+
+ const char *scope = acpi_device_path(dev);
+ if (!scope) {
+ printk(BIOS_ERR, "%s: Missing ACPI scope\n", dev_path(dev));
+ return;
+ }
+
+ switch (dev->path.pnp.device) {
+ case NPCD378_PWR: {
+ res = find_resource(dev, PNP_IDX_IO0);
+ if (!res || !res->base) {
+ printk(BIOS_ERR, "NPCD378: LDN%u IOBASE not set.\n",
+ NPCD378_PWR);
+ break;
+ }
+
+ acpigen_write_scope(scope);
+ acpigen_write_name_integer("SWB", res->base);
+ acpigen_write_name_integer("SWL", res->size);
+ acpigen_pop_len(); /* pop scope */
+
+ res = find_resource(dev, PNP_IDX_IO1);
+ if (!res || !res->base) {
+ printk(BIOS_ERR, "NPCD378: LDN%u IOBASE2 not set.\n",
+ NPCD378_PWR);
+ break;
+ }
+
+ acpigen_write_scope(scope);
+ acpigen_write_name_integer("RNB", res->base);
+ acpigen_write_name_integer("RNL", res->size);
+ acpigen_pop_len(); /* pop scope */
+ break;
+ }
+ }
+}
+
+static const char *npcd378_acpi_name(const struct device *dev)
+{
+ return "SIO0";
+}
+#endif
+
static struct device_operations ops = {
.read_resources = pnp_read_resources,
.set_resources = pnp_set_resources,
@@ -108,6 +157,10 @@ static struct device_operations ops = {
.enable = pnp_alt_enable,
.init = npcd378_init,
.ops_pnp_mode = &pnp_conf_mode_8787_aa,
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ .acpi_fill_ssdt_generator = npcd378_ssdt,
+ .acpi_name = npcd378_acpi_name,
+#endif
};
static struct pnp_info pnp_dev_info[] = {