diff options
-rw-r--r-- | src/superio/nuvoton/npcd378/acpi/superio.asl | 184 | ||||
-rw-r--r-- | src/superio/nuvoton/npcd378/superio.c | 53 |
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[] = { |