superio/nuvoton/npcd378: Switch to superio/common

Replace DSDT ACPI code and DSDT injection with a SSDT only solution.

The current implementation shows some issues on current Linux, which
might be due to external ACPI objects, which are then injected into
DSDT or the fact that those objects only use 3 characters.

Replace all the DSDT code with an SSDT generator.

Tested on HP Z220:
Boots into Linux with no ACPI errors. The SSDT can be disassembled.

Change-Id: I41616d9bf320fd2b4d8495892b8190cd2a2d057f
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/38862
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
Patrick Rudolph 2020-02-12 15:23:05 +01:00 committed by Felix Held
parent 56626cf5d8
commit e1498ce6da
9 changed files with 533 additions and 571 deletions

View File

@ -15,6 +15,7 @@
Method(_WAK, 1, NotSerialized)
{
// Generated by SSDT
\_SB.PCI0.LPCB.SIO0.SIOW (Arg0)
Return(Package(){0,0})
@ -22,5 +23,6 @@ Method(_WAK, 1, NotSerialized)
Method(_PTS, 1, NotSerialized)
{
// Generated by SSDT
\_SB.PCI0.LPCB.SIO0.SIOS (Arg0)
}

View File

@ -13,24 +13,10 @@
* GNU General Public License for more details.
*/
#undef SUPERIO_DEV
#undef SUPERIO_PNP_BASE
#define SUPERIO_DEV SIO0
#define SUPERIO_PNP_BASE 0x2e
#define SUPERIO_SHOW_SP2
#define SUPERIO_SHOW_KBC
#include <superio/nuvoton/npcd378/acpi/superio.asl>
Scope (\_GPE)
{
Method (_L08, 0, NotSerialized)
{
\_SB.PCI0.LPCB.SIO0.SIOH ()
}
Method (_L0D, 0, NotSerialized)
{
Notify (\_SB.PCI0.EHC1, 0x02)

View File

@ -75,100 +75,104 @@ chip northbridge/intel/sandybridge
device pci 1d.0 on end # USB2 EHCI #1
device pci 1e.0 on end # PCI bridge
device pci 1f.0 on # LPC bridge PCI-LPC bridge
chip superio/nuvoton/npcd378
device pnp 2e.0 off end # Floppy
device pnp 2e.1 on # Parallel port
# global
chip superio/common
device pnp 2e.ff on # passes SIO base addr to SSDT gen
chip superio/nuvoton/npcd378
device pnp 2e.0 off end # Floppy
device pnp 2e.1 on # Parallel port
# global
# serialice: Vendor writes:
irq 0x14 = 0x9c
irq 0x1c = 0xa8
irq 0x1d = 0x08
irq 0x22 = 0x3f
irq 0x1a = 0xb0
# dumped from superiotool:
irq 0x1b = 0x1e
irq 0x27 = 0x04
irq 0x2a = 0x00
irq 0x2d = 0x01
# parallel port
io 0x60 = 0x378
irq 0x70 = 0x07
drq 0x74 = 0x01
end
device pnp 2e.2 off # COM1
io 0x60 = 0x2f8
irq 0x70 = 3
end
device pnp 2e.3 on # COM2, IR
io 0x60 = 0x3f8
irq 0x70 = 4
end
device pnp 2e.4 on # LED control
io 0x60 = 0x600
# IOBASE[0h] = bit0 LED red / green
# IOBASE[0h] = bit1-4 LED PWM duty cycle
# IOBASE[1h] = bit6 SWCC
# serialice: Vendor writes:
irq 0x14 = 0x9c
irq 0x1c = 0xa8
irq 0x1d = 0x08
irq 0x22 = 0x3f
irq 0x1a = 0xb0
# dumped from superiotool:
irq 0x1b = 0x1e
irq 0x27 = 0x08
irq 0x2a = 0x20
irq 0x2d = 0x01
# parallel port
io 0x60 = 0x378
irq 0x70 = 0x07
drq 0x74 = 0x01
end
device pnp 2e.2 off # COM1
io 0x60 = 0x2f8
irq 0x70 = 3
end
device pnp 2e.3 on # COM2, IR
io 0x60 = 0x3f8
irq 0x70 = 4
end
device pnp 2e.4 on # LED control
io 0x60 = 0x600
# IOBASE[0h] = bit0 LED red / green
# IOBASE[0h] = bit1-4 LED PWM duty cycle
# IOBASE[1h] = bit6 SWCC
io 0x62 = 0x610
# IOBASE [0h] = GPES
# IOBASE [1h] = GPEE
# IOBASE [4h:7h] = 32bit upcounter at 1Mhz
# IOBASE [8h:bh] = GPS
# IOBASE [ch:fh] = GPE
end
device pnp 2e.5 on # Mouse
irq 0x70 = 0xc
end
device pnp 2e.6 on # Keyboard
io 0x60 = 0x0060
io 0x62 = 0x0064
irq 0x70 = 0x01
# serialice: Vendor writes:
drq 0xf0 = 0x40
end
device pnp 2e.7 on # WDT ?
io 0x60 = 0x620
end
device pnp 2e.8 on # HWM
io 0x60 = 0x800
# IOBASE[0h:feh] HWM page
# IOBASE[ffh] bit0-bit3 page selector
io 0x62 = 0x610
# IOBASE [0h] = GPES
# IOBASE [1h] = GPEE
# IOBASE [4h:7h] = 32bit upcounter at 1Mhz
# IOBASE [8h:bh] = GPS
# IOBASE [ch:fh] = GPE
end
device pnp 2e.5 on # Mouse
irq 0x70 = 0xc
end
device pnp 2e.6 on # Keyboard
io 0x60 = 0x0060
io 0x62 = 0x0064
irq 0x70 = 0x01
# serialice: Vendor writes:
drq 0xf0 = 0x40
end
device pnp 2e.7 on # WDT ?
io 0x60 = 0x620
end
device pnp 2e.8 on # HWM
io 0x60 = 0x800
# IOBASE[0h:feh] HWM page
# IOBASE[ffh] bit0-bit3 page selector
drq 0xf0 = 0x20
drq 0xf1 = 0x01
drq 0xf2 = 0x40
drq 0xf3 = 0x01
drq 0xf0 = 0x20
drq 0xf1 = 0x01
drq 0xf2 = 0x40
drq 0xf3 = 0x01
drq 0xf4 = 0x66
drq 0xf5 = 0x67
drq 0xf6 = 0x66
drq 0xf7 = 0x01
end
device pnp 2e.f on # GPIO OD ?
drq 0xf1 = 0x97
drq 0xf2 = 0x01
drq 0xf5 = 0x08
drq 0xfe = 0x80
end
device pnp 2e.15 on # BUS ?
io 0x60 = 0x0680
io 0x62 = 0x0690
end
device pnp 2e.1c on # Suspend Control ?
io 0x60 = 0x640
# writing to IOBASE[5h]
# 0x0: Power off
# 0x9: Power off and bricked until CMOS battery removed
end
device pnp 2e.1e on # GPIO ?
io 0x60 = 0x660
drq 0xf4 = 0x01
# skip the following, as it
# looks like remapped registers
#drq 0xf5 = 0x06
#drq 0xf6 = 0x60
#drq 0xfe = 0x03
drq 0xf4 = 0x66
drq 0xf5 = 0x67
drq 0xf6 = 0x66
drq 0xf7 = 0x01
end
device pnp 2e.f on # GPIO OD ?
drq 0xf1 = 0x97
drq 0xf2 = 0x01
drq 0xf5 = 0x08
drq 0xfe = 0x80
end
device pnp 2e.15 on # BUS ?
io 0x60 = 0x0680
io 0x62 = 0x0690
end
device pnp 2e.1c on # Suspend Control ?
io 0x60 = 0x640
# writing to IOBASE[5h]
# 0x0: Power off
# 0x9: Power off and bricked until CMOS battery removed
end
device pnp 2e.1e on # GPIO ?
io 0x60 = 0x660
drq 0xf4 = 0x01
# skip the following, as it
# looks like remapped registers
#drq 0xf5 = 0x06
#drq 0xf6 = 0x60
#drq 0xfe = 0x03
end
end
end
end
chip drivers/pc80/tpm

View File

@ -15,6 +15,7 @@
Method(_WAK, 1, NotSerialized)
{
// Generated by SSDT
\_SB.PCI0.LPCB.SIO0.SIOW (Arg0)
Return(Package(){0,0})
@ -22,5 +23,6 @@ Method(_WAK, 1, NotSerialized)
Method(_PTS, 1, NotSerialized)
{
// Generated by SSDT
\_SB.PCI0.LPCB.SIO0.SIOS (Arg0)
}

View File

@ -13,24 +13,10 @@
* GNU General Public License for more details.
*/
#undef SUPERIO_DEV
#undef SUPERIO_PNP_BASE
#define SUPERIO_DEV SIO0
#define SUPERIO_PNP_BASE 0x2e
#define SUPERIO_SHOW_SP2
#define SUPERIO_SHOW_KBC
#include <superio/nuvoton/npcd378/acpi/superio.asl>
Scope (\_GPE)
{
Method (_L08, 0, NotSerialized)
{
\_SB.PCI0.LPCB.SIO0.SIOH ()
}
Method (_L0D, 0, NotSerialized)
{
Notify (\_SB.PCI0.EHC1, 0x02)

View File

@ -76,100 +76,104 @@ chip northbridge/intel/sandybridge
device pci 1d.0 on end # USB2 EHCI #1
device pci 1e.0 on end # PCI bridge
device pci 1f.0 on # LPC bridge PCI-LPC bridge
chip superio/nuvoton/npcd378
device pnp 2e.0 off end # Floppy
device pnp 2e.1 on # Parallel port
# global
chip superio/common
device pnp 2e.ff on # passes SIO base addr to SSDT gen
chip superio/nuvoton/npcd378
device pnp 2e.0 off end # Floppy
device pnp 2e.1 on # Parallel port
# global
# serialice: Vendor writes:
irq 0x14 = 0x9c
irq 0x1c = 0xa8
irq 0x1d = 0x08
irq 0x22 = 0x3f
irq 0x1a = 0xb0
# dumped from superiotool:
irq 0x1b = 0x1e
irq 0x27 = 0x08
irq 0x2a = 0x20
irq 0x2d = 0x01
# parallel port
io 0x60 = 0x378
irq 0x70 = 0x07
drq 0x74 = 0x01
end
device pnp 2e.2 off # COM1
io 0x60 = 0x2f8
irq 0x70 = 3
end
device pnp 2e.3 on # COM2, IR
io 0x60 = 0x3f8
irq 0x70 = 4
end
device pnp 2e.4 on # LED control
io 0x60 = 0x600
# IOBASE[0h] = bit0 LED red / green
# IOBASE[0h] = bit1-4 LED PWM duty cycle
# IOBASE[1h] = bit6 SWCC
# serialice: Vendor writes:
irq 0x14 = 0x9c
irq 0x1c = 0xa8
irq 0x1d = 0x08
irq 0x22 = 0x3f
irq 0x1a = 0xb0
# dumped from superiotool:
irq 0x1b = 0x1e
irq 0x27 = 0x08
irq 0x2a = 0x20
irq 0x2d = 0x01
# parallel port
io 0x60 = 0x378
irq 0x70 = 0x07
drq 0x74 = 0x01
end
device pnp 2e.2 off # COM1
io 0x60 = 0x2f8
irq 0x70 = 3
end
device pnp 2e.3 on # COM2, IR
io 0x60 = 0x3f8
irq 0x70 = 4
end
device pnp 2e.4 on # LED control
io 0x60 = 0x600
# IOBASE[0h] = bit0 LED red / green
# IOBASE[0h] = bit1-4 LED PWM duty cycle
# IOBASE[1h] = bit6 SWCC
io 0x62 = 0x610
# IOBASE [0h] = GPES
# IOBASE [1h] = GPEE
# IOBASE [4h:7h] = 32bit upcounter at 1Mhz
# IOBASE [8h:bh] = GPS
# IOBASE [ch:fh] = GPE
end
device pnp 2e.5 on # Mouse
irq 0x70 = 0xc
end
device pnp 2e.6 on # Keyboard
io 0x60 = 0x0060
io 0x62 = 0x0064
irq 0x70 = 0x01
# serialice: Vendor writes:
drq 0xf0 = 0x40
end
device pnp 2e.7 on # WDT ?
io 0x60 = 0x620
end
device pnp 2e.8 on # HWM
io 0x60 = 0x800
# IOBASE[0h:feh] HWM page
# IOBASE[ffh] bit0-bit3 page selector
io 0x62 = 0x610
# IOBASE [0h] = GPES
# IOBASE [1h] = GPEE
# IOBASE [4h:7h] = 32bit upcounter at 1Mhz
# IOBASE [8h:bh] = GPS
# IOBASE [ch:fh] = GPE
end
device pnp 2e.5 on # Mouse
irq 0x70 = 0xc
end
device pnp 2e.6 on # Keyboard
io 0x60 = 0x0060
io 0x62 = 0x0064
irq 0x70 = 0x01
# serialice: Vendor writes:
drq 0xf0 = 0x40
end
device pnp 2e.7 on # WDT ?
io 0x60 = 0x620
end
device pnp 2e.8 on # HWM
io 0x60 = 0x800
# IOBASE[0h:feh] HWM page
# IOBASE[ffh] bit0-bit3 page selector
drq 0xf0 = 0x20
drq 0xf1 = 0x01
drq 0xf2 = 0x40
drq 0xf3 = 0x01
drq 0xf0 = 0x20
drq 0xf1 = 0x01
drq 0xf2 = 0x40
drq 0xf3 = 0x01
drq 0xf4 = 0x66
drq 0xf5 = 0x67
drq 0xf6 = 0x66
drq 0xf7 = 0x01
end
device pnp 2e.f on # GPIO OD ?
drq 0xf1 = 0x97
drq 0xf2 = 0x01
drq 0xf5 = 0x08
drq 0xfe = 0x80
end
device pnp 2e.15 on # BUS ?
io 0x60 = 0x0680
io 0x62 = 0x0690
end
device pnp 2e.1c on # Suspend Control ?
io 0x60 = 0x640
# writing to IOBASE[5h]
# 0x0: Power off
# 0x9: Power off and bricked until CMOS battery removed
end
device pnp 2e.1e on # GPIO ?
io 0x60 = 0x660
drq 0xf4 = 0x01
# skip the following, as it
# looks like remapped registers
#drq 0xf5 = 0x06
#drq 0xf6 = 0x60
#drq 0xfe = 0x03
drq 0xf4 = 0x66
drq 0xf5 = 0x67
drq 0xf6 = 0x66
drq 0xf7 = 0x01
end
device pnp 2e.f on # GPIO OD ?
drq 0xf1 = 0x97
drq 0xf2 = 0x01
drq 0xf5 = 0x08
drq 0xfe = 0x80
end
device pnp 2e.15 on # BUS ?
io 0x60 = 0x0680
io 0x62 = 0x0690
end
device pnp 2e.1c on # Suspend Control ?
io 0x60 = 0x640
# writing to IOBASE[5h]
# 0x0: Power off
# 0x9: Power off and bricked until CMOS battery removed
end
device pnp 2e.1e on # GPIO ?
io 0x60 = 0x660
drq 0xf4 = 0x01
# skip the following, as it
# looks like remapped registers
#drq 0xf5 = 0x06
#drq 0xf6 = 0x60
#drq 0xfe = 0x03
end
end
end
end
chip drivers/pc80/tpm

View File

@ -2,3 +2,5 @@
# This file is part of the coreboot project.
ramstage-$(CONFIG_SUPERIO_NUVOTON_NPCD378) += superio.c
ramstage-$(CONFIG_SUPERIO_NUVOTON_NPCD378) += ../../common/ssdt.c
ramstage-$(CONFIG_SUPERIO_NUVOTON_NPCD378) += ../../common/generic.c

View File

@ -1,321 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */
/*
* Include this file into a mainboard's DSDT _SB device tree and it will
* expose the NPCD378 SuperIO and some of its functionality.
*
* It allows the change of IO ports, IRQs and DMA settings on logical
* devices, disabling and reenabling logical devices.
*
* LDN State
* 0x2 SP1 Implemented, untested
* 0x5 KBCK Implemented, untested
*/
#undef SUPERIO_CHIP_NAME
#define SUPERIO_CHIP_NAME NPCD378
#include <superio/acpi/pnp.asl>
#undef PNP_DEFAULT_PSC
#define PNP_DEFAULT_PSC Return (0) /* no power management */
Device(SUPERIO_DEV) {
Name (_HID, EisaId("PNP0A05"))
Name (_STR, Unicode("Nuvoton NPCD378 Super I/O"))
Name (_UID, SUPERIO_UID(SUPERIO_DEV,))
/* SuperIO configuration ports */
OperationRegion (CREG, SystemIO, SUPERIO_PNP_BASE, 0x02)
Field (CREG, ByteAcc, NoLock, Preserve)
{
PNP_ADDR_REG, 8,
PNP_DATA_REG, 8,
}
IndexField (PNP_ADDR_REG, PNP_DATA_REG, ByteAcc, NoLock, Preserve)
{
Offset (0x07),
PNP_LOGICAL_DEVICE, 8, /* Logical device selector */
Offset (0x30),
PNP_DEVICE_ACTIVE, 1, /* Logical device activation */
ACT1, 1, /* Logical device activation */
ACT2, 1, /* Logical device activation */
ACT3, 1, /* Logical device activation */
ACT4, 1, /* Logical device activation */
ACT5, 1, /* Logical device activation */
ACT6, 1, /* Logical device activation */
ACT7, 1, /* Logical device activation */
Offset (0x60),
PNP_IO0_HIGH_BYTE, 8, /* First I/O port base - high byte */
PNP_IO0_LOW_BYTE, 8, /* First I/O port base - low byte */
Offset (0x62),
PNP_IO1_HIGH_BYTE, 8, /* Second I/O port base - high byte */
PNP_IO1_LOW_BYTE, 8, /* Second I/O port base - low byte */
Offset (0x64),
PNP_IO2_HIGH_BYTE, 8, /* Third I/O port base - high byte */
PNP_IO2_LOW_BYTE, 8, /* Third I/O port base - low byte */
Offset (0x70),
PNP_IRQ0, 8, /* First IRQ */
Offset (0x72),
PNP_IRQ1, 8, /* Second IRQ */
}
#undef PNP_ENTER_MAGIC_1ST
#undef PNP_ENTER_MAGIC_2ND
#undef PNP_ENTER_MAGIC_3RD
#undef PNP_ENTER_MAGIC_4TH
#undef PNP_EXIT_MAGIC_1ST
#undef PNP_EXIT_SPECIAL_REG
#undef PNP_EXIT_SPECIAL_VAL
#define PNP_ENTER_MAGIC_1ST 0x87
#define PNP_ENTER_MAGIC_2ND 0x87
#define PNP_EXIT_MAGIC_1ST 0xaa
#include <superio/acpi/pnp_config.asl>
#ifdef SUPERIO_SHOW_LPT
#undef SUPERIO_PNP_HID
#undef SUPERIO_PNP_LDN
#undef SUPERIO_PNP_DDN
#undef SUPERIO_PNP_PM_REG
#undef SUPERIO_PNP_PM_VAL
#undef SUPERIO_PNP_PM_LDN
#undef SUPERIO_PNP_IO0
#undef SUPERIO_PNP_IO1
#undef SUPERIO_PNP_IRQ0
#undef SUPERIO_PNP_IRQ1
#undef SUPERIO_PNP_DMA
#undef PNP_DEVICE_ACTIVE
#define PNP_DEVICE_ACTIVE ACT3
#define SUPERIO_PNP_LDN 1
#define SUPERIO_PNP_IO0 0x08, 0x08
#include <superio/acpi/pnp_generic.asl>
#endif
#ifdef SUPERIO_SHOW_SP1
#undef SUPERIO_UART_LDN
#undef SUPERIO_UART_DDN
#undef SUPERIO_UART_PM_REG
#undef SUPERIO_UART_PM_VAL
#undef SUPERIO_UART_PM_LDN
#define SUPERIO_UART_LDN 2
#include <superio/acpi/pnp_uart.asl>
#endif
#ifdef SUPERIO_SHOW_SP2
#undef SUPERIO_UART_LDN
#undef SUPERIO_UART_DDN
#undef SUPERIO_UART_PM_REG
#undef SUPERIO_UART_PM_VAL
#undef SUPERIO_UART_PM_LDN
#define SUPERIO_UART_LDN 3
#include <superio/acpi/pnp_uart.asl>
#endif
#ifdef SUPERIO_SHOW_KBC
#undef SUPERIO_KBC_LDN
#undef SUPERIO_KBC_PS2M
#undef SUPERIO_KBC_PS2LDN
#define SUPERIO_KBC_PS2LDN 5
#define SUPERIO_KBC_LDN 6
#include <superio/acpi/pnp_kbc.asl>
#endif
#ifdef SUPERIO_SHOW_GPIO
#undef SUPERIO_PNP_HID
#undef SUPERIO_PNP_LDN
#undef SUPERIO_PNP_DDN
#undef SUPERIO_PNP_PM_REG
#undef SUPERIO_PNP_PM_VAL
#undef SUPERIO_PNP_PM_LDN
#undef SUPERIO_PNP_IO0
#undef SUPERIO_PNP_IO1
#undef SUPERIO_PNP_IO2
#undef SUPERIO_PNP_IRQ0
#undef SUPERIO_PNP_IRQ1
#undef SUPERIO_PNP_DMA
#undef PNP_DEVICE_ACTIVE
#define PNP_DEVICE_ACTIVE ACT3
#define SUPERIO_PNP_LDN 8
#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)
}
}
External (\_SB.PCI0.LPCB.SIO0, DeviceObj)
External (\_SB.PCI0.LPCB.SIO0.SIOS, MethodObj)
External (\_SB.PCI0.LPCB.SIO0.SIOW, MethodObj)

View File

@ -10,6 +10,8 @@
#include <superio/conf_mode.h>
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <superio/common/ssdt.h>
#include <stdlib.h>
#include "npcd378.h"
@ -87,62 +89,351 @@ static void npcd378_init(struct device *dev)
}
#if CONFIG(HAVE_ACPI_TABLES)
static void npcd378_ssdt(struct device *dev)
/* Provide ACPI HIDs for generic Super I/O SSDT */
static const char *npcd378_acpi_hid(const struct device *dev)
{
struct resource *res;
/* Sanity checks */
if (dev->path.type != DEVICE_PATH_PNP)
return NULL;
if (dev->path.pnp.port == 0)
return NULL;
if ((dev->path.pnp.device & 0xff) > NPCD378_GPIOA)
return NULL;
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;
}
switch (dev->path.pnp.device & 0xff) {
case NPCD378_FDC:
return ACPI_HID_FDC;
case NPCD378_PP:
return ACPI_HID_LPT;
case NPCD378_SP1: /* fallthrough */
case NPCD378_SP2:
return ACPI_HID_COM;
case NPCD378_AUX:
return ACPI_HID_MOUSE;
case NPCD378_KBC:
return ACPI_HID_KEYBOARD;
default:
return ACPI_HID_PNP;
}
}
static const char *npcd378_acpi_name(const struct device *dev)
static void npcd378_ssdt_aux(struct device *dev)
{
return "SIO0";
/* Scope */
acpigen_write_scope(acpi_device_path(dev));
acpigen_write_method("_PSW", 1);
acpigen_write_store();
acpigen_emit_byte(ARG0_OP);
acpigen_emit_namestring("^^MSFG");
acpigen_pop_len(); /* Pop Method */
acpigen_write_PRW(8, 3);
acpigen_pop_len(); /* Pop Scope */
}
static void npcd378_ssdt_kbc(struct device *dev)
{
/* Scope */
acpigen_write_scope(acpi_device_path(dev));
acpigen_write_method("_PSW", 1);
acpigen_write_store();
acpigen_emit_byte(ARG0_OP);
acpigen_emit_namestring("^^KBFG");
acpigen_pop_len(); /* Pop Method */
acpigen_write_PRW(8, 3);
acpigen_pop_len(); /* Pop Scope */
}
static void npcd378_ssdt_pwr(struct device *dev)
{
const char *name = acpi_device_path(dev);
const char *scope = acpi_device_scope(dev);
char *tmp_name;
/* Scope */
acpigen_write_scope(name);
acpigen_emit_ext_op(OPREGION_OP);
acpigen_emit_namestring("SWCR");
acpigen_emit_byte(SYSTEMIO);
acpigen_emit_namestring("IO0B");
acpigen_emit_namestring("IO0S");
struct fieldlist l1[] = {
FIELDLIST_OFFSET(0),
FIELDLIST_NAMESTR("LEDC", 8),
FIELDLIST_NAMESTR("SWCC", 8),
};
acpigen_write_field("SWCR", l1, ARRAY_SIZE(l1), FIELD_BYTEACC |
FIELD_NOLOCK | FIELD_PRESERVE);
acpigen_emit_ext_op(OPREGION_OP);
acpigen_emit_namestring("RNTR");
acpigen_emit_byte(SYSTEMIO);
acpigen_emit_namestring("IO1B");
acpigen_emit_namestring("IO1S");
struct fieldlist l2[] = {
FIELDLIST_OFFSET(0),
FIELDLIST_NAMESTR("GPES", 8),
FIELDLIST_NAMESTR("GPEE", 8),
FIELDLIST_OFFSET(8),
FIELDLIST_NAMESTR("GPS0", 8),
FIELDLIST_NAMESTR("GPS1", 8),
FIELDLIST_NAMESTR("GPS2", 8),
FIELDLIST_NAMESTR("GPS3", 8),
FIELDLIST_NAMESTR("GPE0", 8),
FIELDLIST_NAMESTR("GPE1", 8),
FIELDLIST_NAMESTR("GPE2", 8),
FIELDLIST_NAMESTR("GPE3", 8),
};
acpigen_write_field("RNTR", l2, ARRAY_SIZE(l2), FIELD_BYTEACC |
FIELD_NOLOCK | FIELD_PRESERVE);
/* Method (SIOW, 1, NotSerialized) */
acpigen_write_method("SIOW", 1);
acpigen_write_store();
acpigen_emit_namestring("^GPS2");
acpigen_emit_namestring("^^PMFG");
acpigen_write_store();
acpigen_emit_byte(ZERO_OP);
acpigen_emit_namestring("^GPEE");
acpigen_write_store();
acpigen_emit_byte(ZERO_OP);
acpigen_emit_namestring("^GPE0");
acpigen_write_store();
acpigen_emit_byte(ZERO_OP);
acpigen_emit_namestring("^GPE1");
acpigen_emit_byte(AND_OP);
acpigen_emit_namestring("^LEDC");
acpigen_write_integer(0xE0);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(OR_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_integer(0x1E);
acpigen_emit_namestring("^LEDC");
acpigen_emit_byte(AND_OP);
acpigen_emit_namestring("^SWCC");
acpigen_write_integer(0xBF);
acpigen_emit_namestring("^SWCC");
acpigen_pop_len(); /* SIOW method */
/* Method (SIOS, 1, NotSerialized) */
acpigen_write_method("SIOS", 1);
acpigen_write_if();
acpigen_emit_byte(LNOT_OP);
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_byte(ARG0_OP);
acpigen_write_integer(5);
acpigen_write_if();
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_namestring("^^KBFG");
acpigen_emit_byte(ONE_OP);
acpigen_emit_byte(OR_OP);
acpigen_emit_namestring("^GPE2");
acpigen_write_integer(0xE8);
acpigen_emit_namestring("^GPE2");
acpigen_pop_len(); /* Pop If */
acpigen_write_else();
acpigen_emit_byte(AND_OP);
acpigen_emit_namestring("^GPE2");
acpigen_write_integer(0x17);
acpigen_emit_namestring("^GPE2");
acpigen_pop_len(); /* Pop Else */
acpigen_write_if();
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_namestring("^^MSFG");
acpigen_emit_byte(ONE_OP);
acpigen_emit_byte(OR_OP);
acpigen_emit_namestring("^GPE2");
acpigen_write_integer(0x10);
acpigen_emit_namestring("^GPE2");
acpigen_pop_len(); /* Pop If */
acpigen_write_else();
acpigen_emit_byte(AND_OP);
acpigen_emit_namestring("^GPE2");
acpigen_write_integer(0xEF);
acpigen_emit_namestring("^GPE2");
acpigen_pop_len(); /* Pop Else */
/* Enable wake on GPE */
acpigen_write_store();
acpigen_emit_byte(ONE_OP);
acpigen_emit_namestring("^GPEE");
acpigen_write_if();
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_byte(ARG0_OP);
acpigen_write_integer(3);
acpigen_emit_byte(AND_OP);
acpigen_emit_namestring("^LEDC");
acpigen_write_integer(0xE0);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(OR_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_integer(0x1C);
acpigen_emit_namestring("^LEDC");
acpigen_emit_byte(AND_OP);
acpigen_emit_namestring("^SWCC");
acpigen_write_integer(0xBF);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(OR_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_integer(0x40);
acpigen_emit_namestring("^SWCC");
acpigen_pop_len(); /* Pop If */
acpigen_pop_len(); /* Pop If */
acpigen_write_store();
acpigen_write_integer(0x10);
acpigen_emit_namestring("^GPE0");
acpigen_write_store();
acpigen_write_integer(0x20);
acpigen_emit_namestring("^GPE1");
acpigen_pop_len(); /* Pop SIOS method */
acpigen_pop_len(); /* Pop Scope */
/* Inject into parent: */
acpigen_write_scope(acpi_device_scope(dev));
acpigen_write_name_integer("MSFG", 1);
acpigen_write_name_integer("KBFG", 1);
acpigen_write_name_integer("PMFG", 0);
/* DSDT must call SIOW on _WAK */
/* Method (SIOW, 1, NotSerialized) */
acpigen_write_method("SIOW", 1);
acpigen_emit_byte(RETURN_OP);
tmp_name = strconcat(name, ".SIOW");
acpigen_emit_namestring(tmp_name);
free(tmp_name);
acpigen_emit_byte(ARG0_OP);
acpigen_pop_len();
/* DSDT must call SIOS on _PTS */
/* Method (SIOS, 1, NotSerialized) */
acpigen_write_method("SIOS", 1);
acpigen_emit_byte(RETURN_OP);
tmp_name = strconcat(name, ".SIOS");
acpigen_emit_namestring(tmp_name);
free(tmp_name);
acpigen_emit_byte(ARG0_OP);
acpigen_pop_len(); /* Pop Method */
acpigen_pop_len(); /* Scope */
acpigen_write_scope("\\_GPE");
/* Method (SIOH, 0, NotSerialized) */
acpigen_write_method("_L08", 0);
acpigen_emit_byte(AND_OP);
tmp_name = strconcat(scope, ".PMFG");
acpigen_emit_namestring(tmp_name);
free(tmp_name);
acpigen_write_integer(0xE8);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_if();
acpigen_emit_byte(LGREATER_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(ZERO_OP);
acpigen_emit_byte(NOTIFY_OP);
tmp_name = strconcat(scope, ".L060");
acpigen_emit_namestring(tmp_name);
free(tmp_name);
acpigen_write_integer(2);
acpigen_pop_len(); /* Pop If */
acpigen_emit_byte(AND_OP);
tmp_name = strconcat(scope, ".PMFG");
acpigen_emit_namestring(tmp_name);
free(tmp_name);
acpigen_write_integer(0x10);
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_if();
acpigen_emit_byte(LGREATER_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(ZERO_OP);
acpigen_emit_byte(NOTIFY_OP);
tmp_name = strconcat(scope, ".L050");
acpigen_emit_namestring(tmp_name);
free(tmp_name);
acpigen_write_integer(2);
acpigen_pop_len(); /* Pop If */
acpigen_pop_len(); /* Pop Method */
acpigen_pop_len(); /* Scope */
}
static void npcd378_fill_ssdt_generator(struct device *dev)
{
superio_common_fill_ssdt_generator(dev);
switch (dev->path.pnp.device) {
case NPCD378_PWR:
npcd378_ssdt_pwr(dev);
break;
case NPCD378_AUX:
npcd378_ssdt_aux(dev);
break;
case NPCD378_KBC:
npcd378_ssdt_kbc(dev);
break;
}
}
#endif
static struct device_operations ops = {
.read_resources = pnp_read_resources,
.set_resources = pnp_set_resources,
.enable_resources = pnp_enable_resources,
.enable = pnp_alt_enable,
.init = npcd378_init,
.ops_pnp_mode = &pnp_conf_mode_8787_aa,
.read_resources = pnp_read_resources,
.set_resources = pnp_set_resources,
.enable_resources = pnp_enable_resources,
.enable = pnp_alt_enable,
.init = npcd378_init,
.ops_pnp_mode = &pnp_conf_mode_8787_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_fill_ssdt_generator = npcd378_ssdt,
.acpi_name = npcd378_acpi_name,
.acpi_fill_ssdt_generator = npcd378_fill_ssdt_generator,
.acpi_name = superio_common_ldn_acpi_name,
.acpi_hid = npcd378_acpi_hid,
#endif
};