Bill XIE has uploaded this change for review.

View Change

mainboard/lenovo: Add Thinkpad Edge S220 (a.k.a E220s)

The code is based on autoport and that for s230u

Tested:
- CPU i3-2357M
- Slotted DIMM 2GiB
- Camera
- pci-e and usb2 on Mini PCI-E slot for wlan
- sata and usb2 on Mini PCI-E slot for wwan
- On board SDHCI connected to pci-e
- libgfxinit-based graphic init
- Sound
- S3
- EHCI debug
- Seabios Payload

Change-Id: I746798b13e83d1971bb7be93751a15875d16c337
Signed-off-by: Bill XIE <persmule@hardenedlinux.org>
---
M Documentation/mainboard/index.md
A Documentation/mainboard/lenovo/s220.md
A Documentation/mainboard/lenovo/s220_ready_to_flash.jpg
M src/mainboard/hp/snb_ivb_laptops/cmos.default
A src/mainboard/lenovo/s220/Kconfig
A src/mainboard/lenovo/s220/Kconfig.name
A src/mainboard/lenovo/s220/Makefile.inc
A src/mainboard/lenovo/s220/acpi/ec.asl
A src/mainboard/lenovo/s220/acpi/gpe.asl
A src/mainboard/lenovo/s220/acpi/platform.asl
A src/mainboard/lenovo/s220/acpi/superio.asl
A src/mainboard/lenovo/s220/acpi_tables.c
A src/mainboard/lenovo/s220/board_info.txt
A src/mainboard/lenovo/s220/data.vbt
A src/mainboard/lenovo/s220/devicetree.cb
A src/mainboard/lenovo/s220/dsdt.asl
A src/mainboard/lenovo/s220/early_init.c
A src/mainboard/lenovo/s220/ec.c
A src/mainboard/lenovo/s220/ec.h
A src/mainboard/lenovo/s220/gma-mainboard.ads
A src/mainboard/lenovo/s220/gpio.c
A src/mainboard/lenovo/s220/hda_verb.c
A src/mainboard/lenovo/s220/mainboard.c
A src/mainboard/lenovo/s220/smihandler.c
24 files changed, 1,269 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/71/48771/1
diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md
index 95efe55..c0976e0 100644
--- a/Documentation/mainboard/index.md
+++ b/Documentation/mainboard/index.md
@@ -103,6 +103,7 @@
- [T420](lenovo/t420.md)
- [T420 / T520 / X220 / T420s / W520 common](lenovo/Sandy_Bridge_series.md)
- [X1](lenovo/x1.md)
+- [S220](lenovo/s220.md)

### Ivy Bridge series

diff --git a/Documentation/mainboard/lenovo/s220.md b/Documentation/mainboard/lenovo/s220.md
new file mode 100644
index 0000000..2bbc22d
--- /dev/null
+++ b/Documentation/mainboard/lenovo/s220.md
@@ -0,0 +1,36 @@
+# Lenovo Edge S220 (a.k.a E220s)
+
+## Disassembly Instructions
+
+You must remove the following parts to access the SPI flash:
+
+![S220 ready to flash](s220_ready_to_flash.jpg)
+
+* Keyboard
+* Hard Drive Cover
+* Palmrest
+
+Its [Hardware Maintenance Manual](https://thinkpads.com/support/hmm/hmm_pdf/e220s_s220_hmm_en_0a60672_05.pdf) can be used as a guidance of disassembly.
+
+The vendor IFD VSCC list contains:
+- MACRONIX_MX25L6405 (0xc2, 0x2017)
+- WINBOND_NEX_W25X64 (0xef, 0x3017)
+- ATMEL_AT25DF641 (0x1f, 0x4800)
+
+The general [flashing tutorial] has more details.
+
+Tested:
+- CPU i3-2357M
+- Slotted DIMM 2GiB
+- Camera
+- pci-e and usb2 on Mini PCI-E slot for wlan
+- sata and usb2 on Mini PCI-E slot for wwan
+- On board SDHCI connected to pci-e
+- libgfxinit-based graphic init
+- Sound
+- S3
+- EHCI debug
+- Seabios Payload
+
+[flashing tutorial]: ../../flash_tutorial/ext_power.md
+
diff --git a/Documentation/mainboard/lenovo/s220_ready_to_flash.jpg b/Documentation/mainboard/lenovo/s220_ready_to_flash.jpg
new file mode 100644
index 0000000..3fbafce
--- /dev/null
+++ b/Documentation/mainboard/lenovo/s220_ready_to_flash.jpg
Binary files differ
diff --git a/src/mainboard/hp/snb_ivb_laptops/cmos.default b/src/mainboard/hp/snb_ivb_laptops/cmos.default
index ba33ddf..ad822d5 100644
--- a/src/mainboard/hp/snb_ivb_laptops/cmos.default
+++ b/src/mainboard/hp/snb_ivb_laptops/cmos.default
@@ -2,5 +2,4 @@
debug_level=Debug
power_on_after_fail=Disable
nmi=Enable
-volume=0x3
sata_mode=AHCI
diff --git a/src/mainboard/lenovo/s220/Kconfig b/src/mainboard/lenovo/s220/Kconfig
new file mode 100644
index 0000000..e909399
--- /dev/null
+++ b/src/mainboard/lenovo/s220/Kconfig
@@ -0,0 +1,59 @@
+if BOARD_LENOVO_THINKPAD_EDGE_S220
+
+config BOARD_SPECIFIC_OPTIONS
+ def_bool y
+ select BOARD_ROMSIZE_KB_4096
+ select SYSTEM_TYPE_LAPTOP
+ select NORTHBRIDGE_INTEL_SANDYBRIDGE
+ select USE_NATIVE_RAMINIT
+ select SOUTHBRIDGE_INTEL_C216
+ select EC_COMPAL_ENE932
+ select EC_ACPI
+ select NO_UART_ON_SUPERIO
+ select HAVE_ACPI_TABLES
+ select HAVE_ACPI_RESUME
+ select INTEL_INT15
+ select MAINBOARD_HAS_LIBGFXINIT
+ select GFX_GMA_PANEL_1_ON_LVDS
+ select SERIRQ_CONTINUOUS_MODE
+ select INTEL_GMA_HAVE_VBT
+
+config MAINBOARD_DIR
+ string
+ default lenovo/s220
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "ThinkPad Edge S220/E220s"
+
+config VGA_BIOS_FILE
+ string
+ default "pci8086,0116.rom"
+
+config VGA_BIOS_ID
+ string
+ default "8086,0116"
+
+config DRAM_RESET_GATE_GPIO
+ int
+ default 10
+
+config MAX_CPUS
+ int
+ default 8
+
+config USBDEBUG_HCD_INDEX
+ int
+ default 2
+
+config EC_BASE_ADDRESS
+ hex
+ default 0xff000000
+
+config PS2K_EISAID
+ default "PTL0001"
+
+config PS2M_EISAID
+ default "LEN0031"
+
+endif
diff --git a/src/mainboard/lenovo/s220/Kconfig.name b/src/mainboard/lenovo/s220/Kconfig.name
new file mode 100644
index 0000000..78a5af3
--- /dev/null
+++ b/src/mainboard/lenovo/s220/Kconfig.name
@@ -0,0 +1,2 @@
+config BOARD_LENOVO_THINKPAD_EDGE_S220
+ bool "ThinkPad Edge S220/E220s"
diff --git a/src/mainboard/lenovo/s220/Makefile.inc b/src/mainboard/lenovo/s220/Makefile.inc
new file mode 100644
index 0000000..a0a3aa1
--- /dev/null
+++ b/src/mainboard/lenovo/s220/Makefile.inc
@@ -0,0 +1,7 @@
+bootblock-y += early_init.c
+bootblock-y += gpio.c
+romstage-y += early_init.c
+romstage-y += gpio.c
+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads
+ramstage-y += ec.c
+smm-y += smihandler.c
diff --git a/src/mainboard/lenovo/s220/acpi/ec.asl b/src/mainboard/lenovo/s220/acpi/ec.asl
new file mode 100644
index 0000000..20a9096
--- /dev/null
+++ b/src/mainboard/lenovo/s220/acpi/ec.asl
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Device (EC0)
+{
+ Name (_HID, EISAID ("PNP0C09"))
+ Name (_UID, 0)
+
+ Name (_GPE, THINKPAD_EC_GPE)
+ Mutex (ECLK, 0x07)
+
+ /* EmbeddedControl should work as well, but memory mapped is faster. */
+ OperationRegion (ERAM, SystemMemory, (CONFIG_EC_BASE_ADDRESS + 0x100), 0x100)
+ Field (ERAM, ByteAcc, Lock, Preserve)
+ {
+ , 1,
+ , 1,
+ HKFA, 1, // FN lock (Hotkey / FN row toggle)
+ , 1,
+ , 1,
+ , 1,
+ , 1,
+
+ Offset(0x0c),
+ HLCL, 8, // LED control
+
+ Offset(0x46),
+ , 4,
+ ONAC, 1,
+ , 3,
+
+ Offset(0x81),
+ PAGE, 8,
+ }
+
+ /* Battery info page 0 */
+ Field (ERAM, ByteAcc, NoLock, Preserve)
+ {
+ Offset(0xA0),
+ SBRC, 16, /* Remaining capacity */
+ SBFC, 16, /* Full-charge capacity */
+ SBAE, 16,
+ SBRS, 16,
+ SBAC, 16, /* Present rate */
+ SBVO, 16, /* Present voltage */
+ SBAF, 16,
+ SBBS, 16,
+ }
+
+ /* Battery info page 1 */
+ Field (ERAM, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0xA0),
+ , 15,
+ SBCM, 1, /* Power unit (0 == mA/mAh, 1 == mW/mWh) */
+ SBMD, 16,
+ SBCC, 16,
+ }
+
+ /* Battery info page 2 */
+ Field (ERAM, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0xA0),
+ SBDC, 16, /* Design Capacity */
+ SBDV, 16, /* Design Voltage */
+ SBOM, 16,
+ SBSI, 16,
+ SBDT, 16,
+ SBSN, 16, /* Serial number */
+ }
+
+ /* Battery info page 4 */
+ Field (ERAM, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0xA0),
+ SBCH, 32, /* Type (LiON) */
+ }
+
+ /* Battery info page 5 */
+ Field (ERAM, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0xA0),
+ SBMN, 128, /* Manufacturer */
+ }
+
+ /* Battery info page 6 */
+ Field (ERAM, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0xA0),
+ SBDN, 128, /* Model */
+ }
+
+ Method (_CRS, 0, Serialized)
+ {
+ Name (ECMD, ResourceTemplate()
+ {
+ IO (Decode16, 0x62, 0x62, 0, 1)
+ IO (Decode16, 0x66, 0x66, 0, 1)
+ IO (Decode16, 0x700, 0x700, 0, 8)
+ Memory32Fixed(ReadOnly, CONFIG_EC_BASE_ADDRESS, 0x1000, FF00)
+ })
+ Return (ECMD)
+ }
+
+ /* Increase brightness hotkey */
+ Method (_Q14, 0, NotSerialized) {
+ BRIGHTNESS_UP()
+ ^HKEY.MHKQ (0x1010)
+ }
+
+ /* Decrease brightness hotkey */
+ Method (_Q15, 0, NotSerialized) {
+ BRIGHTNESS_DOWN()
+ ^HKEY.MHKQ (0x1011)
+ }
+
+ /* Video output switch hotkey */
+ Method (_Q16, 0, NotSerialized) {
+ Notify (\_SB.PCI0.GFX0, 0x82)
+ ^HKEY.MHKQ (0x1007)
+ }
+
+ Method (_Q19, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x1018)
+ }
+
+ /* Switched to AC power */
+ Method (_Q26, 0, NotSerialized)
+ {
+ Store (One, PWRS)
+ Notify (^AC, 0x80)
+ Notify (^BAT0, 0x80)
+ \PNOT ()
+ ^HKEY.MHKQ (0x6040)
+ }
+
+ /* Switched to battery power */
+ Method (_Q27, 0, NotSerialized)
+ {
+ Store (Zero, PWRS)
+ Notify (^AC, 0x80)
+ Notify (^BAT0, 0x80)
+ \PNOT ()
+ ^HKEY.MHKQ (0x6040)
+ }
+
+ /* Lid openend */
+ Method (_Q2A, 0, NotSerialized)
+ {
+ Store (One, LIDS)
+ Notify(^LID, 0x80)
+ ^HKEY.MHKQ (0x5002)
+ }
+
+ /* Lid closed */
+ Method (_Q2B, 0, NotSerialized)
+ {
+ Store (Zero, LIDS)
+ Notify(^LID, 0x80)
+ ^HKEY.MHKQ (0x5001)
+ }
+
+ /* Tablet swivel down */
+ Method (_Q35, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x60c0)
+ ^HKEY.MHKQ (0x500a)
+ }
+
+ /* Tablet swivel up */
+ Method (_Q36, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x60c0)
+ ^HKEY.MHKQ (0x5009)
+ }
+
+ /* Tablet rotate lock button */
+ Method (_Q37, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x6020)
+ }
+
+ /* Numlock pressed */
+ Method (_Q3F, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x6000)
+ }
+
+ /* RFKill status changed */
+ Method (_Q41, 0, NotSerialized) {
+ ^HKEY.MHKQ (0x7000)
+ }
+
+ /* Mute hotkey */
+ Method (_Q43, 0, NotSerialized) {
+ ^HKEY.MHKQ (0x1017)
+ }
+
+ /* Settings hotkey */
+ Method (_Q5A, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x101D)
+ }
+
+ /* Search hotkey */
+ Method (_Q5B, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x101E)
+ }
+
+ /* Scale hotkey */
+ Method (_Q5C, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x101F)
+ }
+
+ /* File hotkey */
+ Method (_Q5D, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x1020)
+ }
+
+ /* RFkill hotkey */
+ Method (_Q64, 0, NotSerialized) {
+ ^HKEY.MHKQ (0x1005)
+ }
+
+ /* Mic mute hotkey */
+ Method (_Q6A, 0, NotSerialized)
+ {
+ ^HKEY.MHKQ (0x101B)
+ }
+
+ /* FN key pressed */
+ Method (_Q70, 0, NotSerialized) { }
+
+ /* FN+Esc pressed / FN row mode switch */
+ Method (_Q74, 0, NotSerialized) {
+ XOr(One, HKFA, HKFA)
+ ^HKEY.MHKQ (0x6060)
+ }
+
+ /* Implements enough of the Lenovo hotkey device for
+ * thinkpad-acpi to work, no real support for hotkey masking */
+ Device (HKEY)
+ {
+ Name (_HID, EisaId ("LEN0068"))
+
+ Name (DHKC, Zero)
+ Name (DHKV, Zero)
+ Name (DHKN, 0xFC018070) // Hotkey mask
+ Mutex (XDHK, 0x07)
+
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+
+ Method (MHKV, 0, NotSerialized)
+ {
+ Return (0x0100) // Interface version 1.0
+ }
+
+ Method (MHKA, 0, NotSerialized) // Hotkey all mask
+ {
+ Return (0xFFFFFFFF)
+ }
+
+ Method (MHKM, 2, NotSerialized) // Set hotkey mask
+ {
+ Acquire (XDHK, 0xFFFF)
+
+ ShiftLeft (One, Decrement (Arg0), Local0)
+ If (Arg1) {
+ Or (Local0, DHKN, DHKN)
+ } Else {
+ And (Not(Local0), DHKN, DHKN)
+ }
+
+ Release (XDHK)
+ }
+
+ Method (MHKC, 1, NotSerialized) // Hotkey disable?
+ {
+ Acquire (XDHK, 0xFFFF)
+
+ Store (Arg0, DHKC)
+
+ Release (XDHK)
+ }
+
+ Method (MHKP, 0, NotSerialized) // Hotkey poll
+ {
+ Acquire (XDHK, 0xFFFF)
+
+ Store (Zero, Local0)
+
+ if (DHKV) {
+ Store (DHKV, Local0)
+ Store (Zero, DHKV)
+ }
+
+ Release (XDHK)
+
+ Return (Local0)
+ }
+
+ Method (MHKQ, 1, NotSerialized) // Send hotkey event
+ {
+ Acquire (XDHK, 0xFFFF)
+
+ Store (Arg0, DHKV)
+
+ Release (XDHK)
+
+ Notify (HKEY, 0x80) // Status Change
+ }
+ }
+
+ /* LED support for thinkpad-acpi */
+ Method (LED, 2, NotSerialized)
+ {
+ Or (Arg0, Arg1, HLCL)
+ }
+
+ Device (AC)
+ {
+ Name (_HID, "ACPI0003")
+ Name (_PCL, Package (1) { \_SB })
+
+ Method (_PSR, 0, NotSerialized)
+ {
+ Return (ONAC)
+ }
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+ }
+
+ /* Battery is H8 compatible, but requires an explicit delay */
+ #define BATTERY_PAGE_DELAY_MS 20
+ #include <ec/lenovo/h8/acpi/battery.asl>
+
+ /* LID is H8 compatible */
+ #include <ec/lenovo/h8/acpi/lid.asl>
+}
diff --git a/src/mainboard/lenovo/s220/acpi/gpe.asl b/src/mainboard/lenovo/s220/acpi/gpe.asl
new file mode 100644
index 0000000..8124ec7
--- /dev/null
+++ b/src/mainboard/lenovo/s220/acpi/gpe.asl
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Scope (_GPE)
+{
+ Name (PDET, Zero)
+ Method (PNOT, 2, Serialized) {
+ ShiftLeft (Arg0, Arg1, Local0)
+ Not( ShiftLeft (One, Arg1), Local1)
+ Or (Local0, And (Local1, PDET), PDET)
+ If (LEqual (PDET, Zero)) {
+ // Palm removed
+ \_SB.PCI0.LPCB.EC0.HKEY.MHKQ (0x60B1)
+ } Else {
+ // Palm detected
+ \_SB.PCI0.LPCB.EC0.HKEY.MHKQ (0x60B0)
+ }
+ }
+
+ Method (TINV, 2, Serialized) {
+ ShiftLeft (One, Arg1, Local0)
+ If (LEqual (Arg0, Zero)) {
+ Not (Local0, Local0)
+ And (GIV0, Local0, GIV0)
+ } Else {
+ Or (GIV0, Local0, GIV0)
+ }
+ }
+
+ /* Palm detect sensor 1 */
+ Method (_L12, 0, NotSerialized) {
+ // Invert trigger
+ TINV (GP02, 2)
+
+ PNOT (GP02, 0)
+ }
+
+ /* Palm detect sensor 2 */
+ Method (_L14, 0, NotSerialized) {
+ // Invert trigger
+ TINV (GP04, 4)
+
+ PNOT (GP04, 1)
+ }
+}
diff --git a/src/mainboard/lenovo/s220/acpi/platform.asl b/src/mainboard/lenovo/s220/acpi/platform.asl
new file mode 100644
index 0000000..149fb3a
--- /dev/null
+++ b/src/mainboard/lenovo/s220/acpi/platform.asl
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Method(_WAK,1)
+{
+ /* Turn on radios */
+ Store (One, GP33) /* WLBT_OFF_5# (To pin 5 of WiFi mPCIe) */
+ Store (One, GP36) /* WLBT_OFF_51# (To pin 51 of WiFi mPCIe) */
+ /* There also is RF_OFF# on pin 20, controlled by the EC */
+
+ Return(Package(){0,0})
+}
+
+Method(_PTS,1)
+{
+ /* Turn off radios */
+ Store (Zero, GP33) /* WLBT_OFF_5# (To pin 5 of WiFi mPCIe) */
+ Store (Zero, GP36) /* WLBT_OFF_51# (To pin 51 of WiFi mPCIe) */
+ /* There also is RF_OFF# on pin 20, controlled by the EC */
+}
+
+Scope(\_SI)
+{
+ Method(_SST, 1, NotSerialized)
+ {
+ If (LLess(Arg0, 2))
+ {
+ /* Thinkpad LED on */
+ \_SB.PCI0.LPCB.EC0.LED (Zero, 0x80)
+ }
+ Else
+ {
+ /* Thinkpad LED blinking */
+ \_SB.PCI0.LPCB.EC0.LED (Zero, 0xC0)
+ }
+ }
+}
diff --git a/src/mainboard/lenovo/s220/acpi/superio.asl b/src/mainboard/lenovo/s220/acpi/superio.asl
new file mode 100644
index 0000000..ee2eabe
--- /dev/null
+++ b/src/mainboard/lenovo/s220/acpi/superio.asl
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <drivers/pc80/pc/ps2_controller.asl>
diff --git a/src/mainboard/lenovo/s220/acpi_tables.c b/src/mainboard/lenovo/s220/acpi_tables.c
new file mode 100644
index 0000000..c85058d
--- /dev/null
+++ b/src/mainboard/lenovo/s220/acpi_tables.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <acpi/acpi_gnvs.h>
+#include <southbridge/intel/bd82x6x/nvs.h>
+
+void acpi_create_gnvs(struct global_nvs *gnvs)
+{
+ /* Disable USB ports in S3 by default */
+ gnvs->s3u0 = 0;
+ gnvs->s3u1 = 0;
+
+ /* Disable USB ports in S5 by default */
+ gnvs->s5u0 = 0;
+ gnvs->s5u1 = 0;
+
+ /* The lid is open by default. */
+ gnvs->lids = 1;
+
+ gnvs->tcrt = 100;
+ gnvs->tpsv = 90;
+}
diff --git a/src/mainboard/lenovo/s220/board_info.txt b/src/mainboard/lenovo/s220/board_info.txt
new file mode 100644
index 0000000..cdbf8b8
--- /dev/null
+++ b/src/mainboard/lenovo/s220/board_info.txt
@@ -0,0 +1,4 @@
+Category: laptop
+ROM protocol: SPI
+Flashrom support: n
+FIXME: put ROM package, ROM socketed, Release year
diff --git a/src/mainboard/lenovo/s220/data.vbt b/src/mainboard/lenovo/s220/data.vbt
new file mode 100644
index 0000000..f7882f9
--- /dev/null
+++ b/src/mainboard/lenovo/s220/data.vbt
Binary files differ
diff --git a/src/mainboard/lenovo/s220/devicetree.cb b/src/mainboard/lenovo/s220/devicetree.cb
new file mode 100644
index 0000000..22429c9
--- /dev/null
+++ b/src/mainboard/lenovo/s220/devicetree.cb
@@ -0,0 +1,84 @@
+chip northbridge/intel/sandybridge
+ register "gfx" = "GMA_STATIC_DISPLAYS(1)"
+ register "gpu_cpu_backlight" = "0x00000f55"
+ register "gpu_dp_b_hotplug" = "4"
+ register "gpu_dp_c_hotplug" = "4"
+ register "gpu_dp_d_hotplug" = "4"
+ register "gpu_panel_port_select" = "PANEL_PORT_LVDS"
+ register "gpu_panel_power_backlight_off_delay" = "2700"
+ register "gpu_panel_power_backlight_on_delay" = "3800"
+ register "gpu_panel_power_cycle_delay" = "6"
+ register "gpu_panel_power_down_delay" = "95"
+ register "gpu_panel_power_up_delay" = "300"
+ register "gpu_pch_backlight" = "0x13121312"
+ device cpu_cluster 0x0 on
+ chip cpu/intel/model_206ax # FIXME: check all registers
+ register "c1_acpower" = "1"
+ register "c1_battery" = "1"
+ register "c2_acpower" = "3"
+ register "c2_battery" = "3"
+ register "c3_acpower" = "5"
+ register "c3_battery" = "5"
+ device lapic 0x0 on
+ end
+ device lapic 0xacac off
+ end
+ end
+ end
+ device domain 0x0 on
+ subsystemid 0x17aa 0x21e4 inherit
+ device pci 00.0 on end # Host bridge Host bridge
+ device pci 01.0 off end # PEG
+ device pci 02.0 on end # iGPU
+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH
+ register "c2_latency" = "0x0065"
+ register "docking_supported" = "1"
+ register "gen1_dec" = "0x00000000"
+ register "gen2_dec" = "0x000c0701"
+ register "gen3_dec" = "0x000c0069"
+ register "gen4_dec" = "0x000c06a1"
+ register "gpi13_routing" = "2"
+ register "gpi7_routing" = "2"
+ register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }"
+ register "pcie_port_coalesce" = "1"
+ register "sata_interface_speed_support" = "0x3"
+ register "sata_port_map" = "0x19"
+ register "spi_lvscc" = "0x2005"
+ register "spi_uvscc" = "0x2005"
+ device pci 16.0 on end # Management Engine Interface 1
+ device pci 16.1 off end # Management Engine Interface 2
+ device pci 16.2 off end # Management Engine IDE-R
+ device pci 16.3 off end # Management Engine KT
+ device pci 19.0 off end # Intel Gigabit Ethernet
+ device pci 1a.0 on end # USB2 EHCI #2
+ device pci 1b.0 on end # High Definition Audio
+ device pci 1c.0 off end # PCIe Port #1
+ device pci 1c.1 on end # PCIe Port #2
+ device pci 1c.2 on end # PCIe Port #3
+ device pci 1c.3 on end # PCIe Port #4
+ device pci 1c.4 off end # PCIe Port #5
+ device pci 1c.5 off end # PCIe Port #6
+ device pci 1c.6 off end # PCIe Port #7
+ device pci 1c.7 off end # PCIe Port #8
+ device pci 1d.0 on end # USB2 EHCI #1
+ device pci 1e.0 off end # PCI bridge
+ device pci 1f.0 on end # LPC bridge
+ device pci 1f.2 on end # SATA Controller 1
+ device pci 1f.3 on # SMBus
+ subsystemid 0x17aa 0x21e4
+ chip drivers/i2c/at24rf08c # eeprom, 8 virtual devices, same chip
+ device i2c 54 on end
+ device i2c 55 on end
+ device i2c 56 on end
+ device i2c 57 on end
+ device i2c 5c on end
+ device i2c 5d on end
+ device i2c 5e on end
+ device i2c 5f on end
+ end
+ end
+ device pci 1f.5 off end # SATA Controller 2
+ device pci 1f.6 off end # Thermal
+ end
+ end
+end
diff --git a/src/mainboard/lenovo/s220/dsdt.asl b/src/mainboard/lenovo/s220/dsdt.asl
new file mode 100644
index 0000000..6d67b91
--- /dev/null
+++ b/src/mainboard/lenovo/s220/dsdt.asl
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB
+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB
+#define EC_LENOVO_H8_ME_WORKAROUND 1
+#define THINKPAD_EC_GPE 23
+
+
+#include <acpi/acpi.h>
+
+DefinitionBlock(
+ "dsdt.aml",
+ "DSDT",
+ ACPI_DSDT_REV_2,
+ OEM_ID,
+ ACPI_TABLE_CREATOR,
+ 0x20141018 /* OEM revision */
+)
+{
+ #include "acpi/platform.asl"
+ #include "acpi/gpe.asl"
+ #include <cpu/intel/common/acpi/cpu.asl>
+ #include <southbridge/intel/common/acpi/platform.asl>
+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl>
+ #include <southbridge/intel/common/acpi/sleepstates.asl>
+
+ Device (\_SB.PCI0)
+ {
+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl>
+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl>
+ #include <southbridge/intel/bd82x6x/acpi/pch.asl>
+ }
+}
diff --git a/src/mainboard/lenovo/s220/early_init.c b/src/mainboard/lenovo/s220/early_init.c
new file mode 100644
index 0000000..e04b4df
--- /dev/null
+++ b/src/mainboard/lenovo/s220/early_init.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+/* FIXME: Check if all includes are needed. */
+
+#include <stdint.h>
+#include <string.h>
+#include <timestamp.h>
+#include <arch/byteorder.h>
+#include <device/mmio.h>
+#include <device/pci_ops.h>
+#include <device/pnp_ops.h>
+#include <console/console.h>
+#include <bootblock_common.h>
+#include <northbridge/intel/sandybridge/sandybridge.h>
+#include <northbridge/intel/sandybridge/raminit_native.h>
+#include <southbridge/intel/bd82x6x/pch.h>
+#include <southbridge/intel/common/gpio.h>
+#include "ec.h"
+
+const struct southbridge_usb_port mainboard_usb_ports[] = {
+ { 1, 1, 0 },
+ { 1, 1, 0 },
+ { 0, 1, 1 },
+ { 0, 1, 1 },
+ { 1, 0, 2 },
+ { 1, 0, 2 },
+ { 0, 0, 3 },
+ { 0, 0, 3 },
+ { 1, 1, 4 },
+ { 1, 1, 4 },
+ { 0, 0, 5 },
+ { 0, 0, 5 },
+ { 1, 0, 6 },
+ { 1, 0, 6 },
+};
+
+void bootblock_mainboard_early_init(void)
+{
+ /* Memory map KB9012 EC registers */
+ pci_write_config32(PCH_LPC_DEV, LGMR,
+ CONFIG_EC_BASE_ADDRESS | 1);
+ pci_write_config16(PCH_LPC_DEV, BIOS_DEC_EN1, 0xffc0);
+
+ /* Enable external USB port power. */
+ if (CONFIG(USBDEBUG))
+ ec_mm_set_bit(0x3b, 4);
+}
+
+/* FIXME: Put proper SPD map here. */
+void mainboard_get_spd(spd_raw_data *spd, bool id_only)
+{
+ read_spd(&spd[0], 0x50, id_only);
+ read_spd(&spd[1], 0x52, id_only);
+ read_spd(&spd[2], 0x51, id_only);
+ read_spd(&spd[3], 0x53, id_only);
+}
diff --git a/src/mainboard/lenovo/s220/ec.c b/src/mainboard/lenovo/s220/ec.c
new file mode 100644
index 0000000..285a8d5
--- /dev/null
+++ b/src/mainboard/lenovo/s220/ec.c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include "ec.h"
+#include <ec/compal/ene932/ec.h>
+
+/* The keyboard matrix tells the EC how the keyboard is wired internally */
+static void set_keyboard_matrix_us(void)
+{
+ ec_kbc_write_cmd(0x59);
+ ec_kbc_write_ib(0xE5);
+}
+
+/* Tell EC to operate in APM mode. Events generate SMIs instead of SCIs */
+static void enter_apm_mode(void)
+{
+ ec_kbc_write_cmd(0x59);
+ ec_kbc_write_ib(0xE9);
+}
+
+void lenovo_s230u_ec_init(void)
+{
+ set_keyboard_matrix_us();
+
+ /*
+ * The EC has a special "blinking Caps Lock LED" mode which it normally
+ * enters when it believes the OS is not responding. It occasionally
+ * disables battery charging when in this mode, although other
+ * functionality is unaffected. Although the EC starts in APM mode by
+ * default, it only leaves the "blinking Caps Lock LED" mode after
+ * receiving the following command.
+ */
+ enter_apm_mode();
+
+ /* Enable external USB port power. */
+ ec_mm_set_bit(0x3b, 4);
+}
diff --git a/src/mainboard/lenovo/s220/ec.h b/src/mainboard/lenovo/s220/ec.h
new file mode 100644
index 0000000..273f58b
--- /dev/null
+++ b/src/mainboard/lenovo/s220/ec.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _MAINBOARD_LENOVO_S230U_EC_H
+#define _MAINBOARD_LENOVO_S230U_EC_H
+
+void lenovo_s230u_ec_init(void);
+
+#define ECMM(x) (*((volatile u8 *)(CONFIG_EC_BASE_ADDRESS + x)))
+#define ec_mm_read(addr) (ECMM(0x100 + addr))
+#define ec_mm_write(addr, data) (ECMM(0x100 + addr) = data)
+#define ec_mm_set_bit(addr, bit) (ECMM(0x100 + addr) |= 1 << bit)
+#define ec_mm_clr_bit(addr, bit) (ECMM(0x100 + addr) &= ~(1 << bit))
+
+#endif /* _MAINBOARD_LENOVO_S230U_EC_H */
diff --git a/src/mainboard/lenovo/s220/gma-mainboard.ads b/src/mainboard/lenovo/s220/gma-mainboard.ads
new file mode 100644
index 0000000..03e6a55
--- /dev/null
+++ b/src/mainboard/lenovo/s220/gma-mainboard.ads
@@ -0,0 +1,18 @@
+-- SPDX-License-Identifier: GPL-2.0-or-later
+-- This file is part of the coreboot project.
+
+with HW.GFX.GMA;
+with HW.GFX.GMA.Display_Probing;
+
+use HW.GFX.GMA;
+use HW.GFX.GMA.Display_Probing;
+
+private package GMA.Mainboard is
+
+ ports : constant Port_List :=
+ (HDMI1,
+ Analog,
+ LVDS,
+ others => Disabled);
+
+end GMA.Mainboard;
diff --git a/src/mainboard/lenovo/s220/gpio.c b/src/mainboard/lenovo/s220/gpio.c
new file mode 100644
index 0000000..ea8a906
--- /dev/null
+++ b/src/mainboard/lenovo/s220/gpio.c
@@ -0,0 +1,258 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <southbridge/intel/common/gpio.h>
+
+static const struct pch_gpio_set1 pch_gpio_set1_mode = {
+ .gpio0 = GPIO_MODE_GPIO,
+ .gpio1 = GPIO_MODE_GPIO,
+ .gpio2 = GPIO_MODE_GPIO,
+ .gpio3 = GPIO_MODE_GPIO,
+ .gpio4 = GPIO_MODE_GPIO,
+ .gpio5 = GPIO_MODE_GPIO,
+ .gpio6 = GPIO_MODE_GPIO,
+ .gpio7 = GPIO_MODE_GPIO,
+ .gpio8 = GPIO_MODE_GPIO,
+ .gpio9 = GPIO_MODE_NATIVE,
+ .gpio10 = GPIO_MODE_GPIO,
+ .gpio11 = GPIO_MODE_GPIO,
+ .gpio12 = GPIO_MODE_GPIO,
+ .gpio13 = GPIO_MODE_GPIO,
+ .gpio14 = GPIO_MODE_GPIO,
+ .gpio15 = GPIO_MODE_GPIO,
+ .gpio16 = GPIO_MODE_NATIVE,
+ .gpio17 = GPIO_MODE_GPIO,
+ .gpio18 = GPIO_MODE_NATIVE,
+ .gpio19 = GPIO_MODE_NATIVE,
+ .gpio20 = GPIO_MODE_NATIVE,
+ .gpio21 = GPIO_MODE_GPIO,
+ .gpio22 = GPIO_MODE_GPIO,
+ .gpio23 = GPIO_MODE_GPIO,
+ .gpio24 = GPIO_MODE_GPIO,
+ .gpio25 = GPIO_MODE_NATIVE,
+ .gpio26 = GPIO_MODE_GPIO,
+ .gpio27 = GPIO_MODE_GPIO,
+ .gpio28 = GPIO_MODE_GPIO,
+ .gpio29 = GPIO_MODE_GPIO,
+ .gpio30 = GPIO_MODE_GPIO,
+ .gpio31 = GPIO_MODE_NATIVE,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_direction = {
+ .gpio0 = GPIO_DIR_OUTPUT,
+ .gpio1 = GPIO_DIR_INPUT,
+ .gpio2 = GPIO_DIR_OUTPUT,
+ .gpio3 = GPIO_DIR_INPUT,
+ .gpio4 = GPIO_DIR_OUTPUT,
+ .gpio5 = GPIO_DIR_OUTPUT,
+ .gpio6 = GPIO_DIR_OUTPUT,
+ .gpio7 = GPIO_DIR_INPUT,
+ .gpio8 = GPIO_DIR_INPUT,
+ .gpio10 = GPIO_DIR_OUTPUT,
+ .gpio11 = GPIO_DIR_INPUT,
+ .gpio12 = GPIO_DIR_OUTPUT,
+ .gpio13 = GPIO_DIR_OUTPUT,
+ .gpio14 = GPIO_DIR_OUTPUT,
+ .gpio15 = GPIO_DIR_OUTPUT,
+ .gpio17 = GPIO_DIR_INPUT,
+ .gpio21 = GPIO_DIR_OUTPUT,
+ .gpio22 = GPIO_DIR_OUTPUT,
+ .gpio23 = GPIO_DIR_OUTPUT,
+ .gpio24 = GPIO_DIR_OUTPUT,
+ .gpio26 = GPIO_DIR_OUTPUT,
+ .gpio27 = GPIO_DIR_INPUT,
+ .gpio28 = GPIO_DIR_OUTPUT,
+ .gpio29 = GPIO_DIR_OUTPUT,
+ .gpio30 = GPIO_DIR_OUTPUT,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_level = {
+ .gpio0 = GPIO_LEVEL_HIGH,
+ .gpio2 = GPIO_LEVEL_HIGH,
+ .gpio4 = GPIO_LEVEL_HIGH,
+ .gpio5 = GPIO_LEVEL_HIGH,
+ .gpio6 = GPIO_LEVEL_HIGH,
+ .gpio10 = GPIO_LEVEL_HIGH,
+ .gpio12 = GPIO_LEVEL_HIGH,
+ .gpio13 = GPIO_LEVEL_HIGH,
+ .gpio14 = GPIO_LEVEL_HIGH,
+ .gpio15 = GPIO_LEVEL_HIGH,
+ .gpio21 = GPIO_LEVEL_LOW,
+ .gpio22 = GPIO_LEVEL_HIGH,
+ .gpio23 = GPIO_LEVEL_HIGH,
+ .gpio24 = GPIO_LEVEL_LOW,
+ .gpio26 = GPIO_LEVEL_HIGH,
+ .gpio28 = GPIO_LEVEL_HIGH,
+ .gpio29 = GPIO_LEVEL_HIGH,
+ .gpio30 = GPIO_LEVEL_LOW,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_reset = {
+ .gpio24 = GPIO_RESET_RSMRST,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_invert = {
+ .gpio1 = GPIO_INVERT,
+ .gpio3 = GPIO_INVERT,
+ .gpio7 = GPIO_INVERT,
+ .gpio8 = GPIO_INVERT,
+ .gpio11 = GPIO_INVERT,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_blink = {
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_mode = {
+ .gpio32 = GPIO_MODE_NATIVE,
+ .gpio33 = GPIO_MODE_GPIO,
+ .gpio34 = GPIO_MODE_GPIO,
+ .gpio35 = GPIO_MODE_GPIO,
+ .gpio36 = GPIO_MODE_NATIVE,
+ .gpio37 = GPIO_MODE_NATIVE,
+ .gpio38 = GPIO_MODE_GPIO,
+ .gpio39 = GPIO_MODE_GPIO,
+ .gpio40 = GPIO_MODE_GPIO,
+ .gpio41 = GPIO_MODE_GPIO,
+ .gpio42 = GPIO_MODE_GPIO,
+ .gpio43 = GPIO_MODE_GPIO,
+ .gpio44 = GPIO_MODE_GPIO,
+ .gpio45 = GPIO_MODE_GPIO,
+ .gpio46 = GPIO_MODE_GPIO,
+ .gpio47 = GPIO_MODE_NATIVE,
+ .gpio48 = GPIO_MODE_GPIO,
+ .gpio49 = GPIO_MODE_GPIO,
+ .gpio50 = GPIO_MODE_GPIO,
+ .gpio51 = GPIO_MODE_GPIO,
+ .gpio52 = GPIO_MODE_GPIO,
+ .gpio53 = GPIO_MODE_GPIO,
+ .gpio54 = GPIO_MODE_GPIO,
+ .gpio55 = GPIO_MODE_GPIO,
+ .gpio56 = GPIO_MODE_GPIO,
+ .gpio57 = GPIO_MODE_GPIO,
+ .gpio58 = GPIO_MODE_NATIVE,
+ .gpio59 = GPIO_MODE_NATIVE,
+ .gpio60 = GPIO_MODE_GPIO,
+ .gpio61 = GPIO_MODE_GPIO,
+ .gpio62 = GPIO_MODE_NATIVE,
+ .gpio63 = GPIO_MODE_NATIVE,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_direction = {
+ .gpio33 = GPIO_DIR_OUTPUT,
+ .gpio34 = GPIO_DIR_OUTPUT,
+ .gpio35 = GPIO_DIR_OUTPUT,
+ .gpio38 = GPIO_DIR_INPUT,
+ .gpio39 = GPIO_DIR_OUTPUT,
+ .gpio40 = GPIO_DIR_OUTPUT,
+ .gpio41 = GPIO_DIR_OUTPUT,
+ .gpio42 = GPIO_DIR_OUTPUT,
+ .gpio43 = GPIO_DIR_OUTPUT,
+ .gpio44 = GPIO_DIR_OUTPUT,
+ .gpio45 = GPIO_DIR_OUTPUT,
+ .gpio46 = GPIO_DIR_OUTPUT,
+ .gpio48 = GPIO_DIR_OUTPUT,
+ .gpio49 = GPIO_DIR_OUTPUT,
+ .gpio50 = GPIO_DIR_OUTPUT,
+ .gpio51 = GPIO_DIR_OUTPUT,
+ .gpio52 = GPIO_DIR_OUTPUT,
+ .gpio53 = GPIO_DIR_OUTPUT,
+ .gpio54 = GPIO_DIR_OUTPUT,
+ .gpio55 = GPIO_DIR_OUTPUT,
+ .gpio56 = GPIO_DIR_OUTPUT,
+ .gpio57 = GPIO_DIR_OUTPUT,
+ .gpio60 = GPIO_DIR_OUTPUT,
+ .gpio61 = GPIO_DIR_OUTPUT,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_level = {
+ .gpio33 = GPIO_LEVEL_HIGH,
+ .gpio34 = GPIO_LEVEL_HIGH,
+ .gpio35 = GPIO_LEVEL_HIGH,
+ .gpio39 = GPIO_LEVEL_HIGH,
+ .gpio40 = GPIO_LEVEL_HIGH,
+ .gpio41 = GPIO_LEVEL_HIGH,
+ .gpio42 = GPIO_LEVEL_HIGH,
+ .gpio43 = GPIO_LEVEL_HIGH,
+ .gpio44 = GPIO_LEVEL_HIGH,
+ .gpio45 = GPIO_LEVEL_HIGH,
+ .gpio46 = GPIO_LEVEL_HIGH,
+ .gpio48 = GPIO_LEVEL_HIGH,
+ .gpio49 = GPIO_LEVEL_HIGH,
+ .gpio50 = GPIO_LEVEL_LOW,
+ .gpio51 = GPIO_LEVEL_HIGH,
+ .gpio52 = GPIO_LEVEL_HIGH,
+ .gpio53 = GPIO_LEVEL_HIGH,
+ .gpio54 = GPIO_LEVEL_LOW,
+ .gpio55 = GPIO_LEVEL_HIGH,
+ .gpio56 = GPIO_LEVEL_HIGH,
+ .gpio57 = GPIO_LEVEL_HIGH,
+ .gpio60 = GPIO_LEVEL_HIGH,
+ .gpio61 = GPIO_LEVEL_HIGH,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_reset = {
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_mode = {
+ .gpio64 = GPIO_MODE_GPIO,
+ .gpio65 = GPIO_MODE_GPIO,
+ .gpio66 = GPIO_MODE_GPIO,
+ .gpio67 = GPIO_MODE_GPIO,
+ .gpio68 = GPIO_MODE_GPIO,
+ .gpio69 = GPIO_MODE_GPIO,
+ .gpio70 = GPIO_MODE_GPIO,
+ .gpio71 = GPIO_MODE_GPIO,
+ .gpio72 = GPIO_MODE_GPIO,
+ .gpio73 = GPIO_MODE_GPIO,
+ .gpio74 = GPIO_MODE_GPIO,
+ .gpio75 = GPIO_MODE_NATIVE,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_direction = {
+ .gpio64 = GPIO_DIR_OUTPUT,
+ .gpio65 = GPIO_DIR_OUTPUT,
+ .gpio66 = GPIO_DIR_OUTPUT,
+ .gpio67 = GPIO_DIR_INPUT,
+ .gpio68 = GPIO_DIR_INPUT,
+ .gpio69 = GPIO_DIR_INPUT,
+ .gpio70 = GPIO_DIR_INPUT,
+ .gpio71 = GPIO_DIR_INPUT,
+ .gpio72 = GPIO_DIR_OUTPUT,
+ .gpio73 = GPIO_DIR_OUTPUT,
+ .gpio74 = GPIO_DIR_OUTPUT,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_level = {
+ .gpio64 = GPIO_LEVEL_HIGH,
+ .gpio65 = GPIO_LEVEL_HIGH,
+ .gpio66 = GPIO_LEVEL_HIGH,
+ .gpio72 = GPIO_LEVEL_HIGH,
+ .gpio73 = GPIO_LEVEL_HIGH,
+ .gpio74 = GPIO_LEVEL_HIGH,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_reset = {
+};
+
+const struct pch_gpio_map mainboard_gpio_map = {
+ .set1 = {
+ .mode = &pch_gpio_set1_mode,
+ .direction = &pch_gpio_set1_direction,
+ .level = &pch_gpio_set1_level,
+ .blink = &pch_gpio_set1_blink,
+ .invert = &pch_gpio_set1_invert,
+ .reset = &pch_gpio_set1_reset,
+ },
+ .set2 = {
+ .mode = &pch_gpio_set2_mode,
+ .direction = &pch_gpio_set2_direction,
+ .level = &pch_gpio_set2_level,
+ .reset = &pch_gpio_set2_reset,
+ },
+ .set3 = {
+ .mode = &pch_gpio_set3_mode,
+ .direction = &pch_gpio_set3_direction,
+ .level = &pch_gpio_set3_level,
+ .reset = &pch_gpio_set3_reset,
+ },
+};
diff --git a/src/mainboard/lenovo/s220/hda_verb.c b/src/mainboard/lenovo/s220/hda_verb.c
new file mode 100644
index 0000000..0bb7e02
--- /dev/null
+++ b/src/mainboard/lenovo/s220/hda_verb.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <device/azalia_device.h>
+
+const u32 cim_verb_data[] = {
+ 0x14f1506e, /* Codec Vendor / Device ID: Conexant */
+ 0x17aa21e4, /* Subsystem ID */
+ 11, /* Number of 4 dword sets */
+ AZALIA_SUBVENDOR(0, 0x17aa21e4),
+ AZALIA_PIN_CFG(0, 0x19, 0x04211040),
+ AZALIA_PIN_CFG(0, 0x1a, 0x40f001f0),
+ AZALIA_PIN_CFG(0, 0x1b, 0x04a11060),
+ AZALIA_PIN_CFG(0, 0x1c, 0x40f001f0),
+ AZALIA_PIN_CFG(0, 0x1d, 0x40f001f0),
+ AZALIA_PIN_CFG(0, 0x1e, 0x40f001f0),
+ AZALIA_PIN_CFG(0, 0x1f, 0x90170110),
+ AZALIA_PIN_CFG(0, 0x20, 0x40f001f0),
+ AZALIA_PIN_CFG(0, 0x22, 0x40f001f0),
+ AZALIA_PIN_CFG(0, 0x23, 0x90a60170),
+
+ 0x80862805, /* Codec Vendor / Device ID: Intel */
+ 0x17aa21e4, /* Subsystem ID */
+ 4, /* Number of 4 dword sets */
+ AZALIA_SUBVENDOR(3, 0x17aa21e4),
+ AZALIA_PIN_CFG(3, 0x05, 0x18560010),
+ AZALIA_PIN_CFG(3, 0x06, 0x58560020),
+ AZALIA_PIN_CFG(3, 0x07, 0x58560030),
+
+};
+
+const u32 pc_beep_verbs[0] = {};
+
+AZALIA_ARRAY_SIZES;
diff --git a/src/mainboard/lenovo/s220/mainboard.c b/src/mainboard/lenovo/s220/mainboard.c
new file mode 100644
index 0000000..7f2c7fd
--- /dev/null
+++ b/src/mainboard/lenovo/s220/mainboard.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/device.h>
+#include <console/console.h>
+#include <drivers/intel/gma/int15.h>
+#include <ec/acpi/ec.h>
+#include <southbridge/intel/common/gpio.h>
+#include <string.h>
+#include <smbios.h>
+#include "ec.h"
+
+#include <acpi/acpi.h>
+
+static u8 mainboard_fill_ec_version(char *buf, u8 buf_len)
+{
+ u8 i, c;
+ char str[16 + 1]; /* 16 ASCII chars + \0 */
+
+ /* Build ID */
+ for (i = 0; i < 8; i++) {
+ c = ec_mm_read(0xf0 + i);
+ if (c < 0x20 || c > 0x7f) {
+ i = snprintf(str, sizeof(str), "*INVALID");
+ break;
+ }
+ str[i] = c;
+ }
+
+ i = MIN(buf_len, i);
+ memcpy(buf, str, i);
+
+ return i;
+}
+
+static void mainboard_smbios_strings(
+ struct device *dev, struct smbios_type11 *t)
+{
+ char tpec[] = "IBM ThinkPad Embedded Controller -[ ]-";
+ u16 fwvh, fwvl;
+
+ mainboard_fill_ec_version(tpec + 35, 17);
+ t->count = smbios_add_string(t->eos, tpec);
+
+ /* Apparently byteswapped compared to H8 */
+ fwvh = ec_mm_read(0xe8);
+ fwvl = ec_mm_read(0xe9);
+
+ printk(BIOS_INFO, "EC Firmware ID %.54s, Version %d.%d%d%c\n", tpec,
+ fwvh >> 4, fwvh & 0x0f, fwvl >> 4, 0x41 + (fwvl & 0xf));
+}
+
+static void mainboard_enable(struct device *dev)
+{
+ dev->ops->get_smbios_strings = mainboard_smbios_strings,
+
+ install_intel_vga_int15_handler(
+ GMA_INT15_ACTIVE_LFP_INT_LVDS,
+ GMA_INT15_PANEL_FIT_DEFAULT,
+ GMA_INT15_BOOT_DISPLAY_DEFAULT,
+ 0);
+
+ if (!acpi_is_wakeup_s3())
+ lenovo_s230u_ec_init();
+}
+
+struct chip_operations mainboard_ops = {
+ .enable_dev = mainboard_enable,
+};
diff --git a/src/mainboard/lenovo/s220/smihandler.c b/src/mainboard/lenovo/s220/smihandler.c
new file mode 100644
index 0000000..62bba44
--- /dev/null
+++ b/src/mainboard/lenovo/s220/smihandler.c
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <ec/acpi/ec.h>
+#include <ec/compal/ene932/ec.h>
+#include <southbridge/intel/bd82x6x/pch.h>
+#include <southbridge/intel/common/pmutil.h>
+
+#include "ec.h"
+
+#define GPE_PALMDET1 2
+#define GPE_PALMDET2 4
+#define GPE_EC_SCI 7
+#define GPE_EC_SMI 8
+/* FIXME: check this */
+#define GPE_EC_WAKE 13
+
+enum sleep_states {
+ S0 = 0,
+ S1 = 1,
+ S3 = 3,
+ S4 = 4,
+ S5 = 5,
+};
+
+enum ec_smi_event {
+ EC_SMI_EVENT_IDLE = 0x80,
+ EC_SMI_BATTERY_LOW = 0xb3,
+};
+
+/* Tell EC to operate in APM mode. Events generate SMIs instead of SCIs. */
+static void ec_enter_apm_mode(void)
+{
+ ec_kbc_write_cmd(0x59);
+ ec_kbc_write_ib(0xE9);
+}
+/* Tell EC to operate in ACPI mode, thus generating SCIs on events, not SMIs. */
+static void ec_enter_acpi_mode(void)
+{
+ ec_kbc_write_cmd(0x59);
+ ec_kbc_write_ib(0xE8);
+}
+
+static uint8_t ec_get_smi_event(void)
+{
+ ec_kbc_write_cmd(0x56);
+ return ec_kbc_read_ob();
+}
+
+static void ec_process_smi(uint8_t src)
+{
+ /*
+ * Reading the SMI source satisfies the EC in terms of responding to
+ * the event, regardless of whether we take an action or not.
+ */
+
+ printk(BIOS_DEBUG, "Unhandled EC_SMI event 0x%x\n", src);
+}
+
+static void handle_ec_smi(void)
+{
+ uint8_t src;
+
+ while ((src = ec_get_smi_event()) != EC_SMI_EVENT_IDLE)
+ ec_process_smi(src);
+}
+
+void mainboard_smi_gpi(u32 gpi_sts)
+{
+ if (gpi_sts & (1 << GPE_EC_SMI))
+ handle_ec_smi();
+}
+
+int mainboard_smi_apmc(u8 data)
+{
+ printk(BIOS_INFO, "mainboard_smi_apmc(%02x)\n", data);
+
+ switch (data) {
+ case APM_CNT_ACPI_ENABLE:
+ printk(BIOS_DEBUG, "Enable ACPI mode\n");
+ ec_enter_acpi_mode();
+ gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SCI);
+ gpi_route_interrupt(GPE_PALMDET1, GPI_IS_SCI);
+ gpi_route_interrupt(GPE_PALMDET2, GPI_IS_SCI);
+ break;
+ case APM_CNT_ACPI_DISABLE:
+ printk(BIOS_DEBUG, "Disable ACPI mode\n");
+ ec_enter_apm_mode();
+ gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI);
+ break;
+ default:
+ printk(BIOS_DEBUG, "Unhandled ACPI command: 0x%x\n", data);
+ }
+ return 0;
+}
+
+void mainboard_smi_sleep(u8 slp_typ)
+{
+ if (slp_typ == S3) {
+ u8 ec_wake = ec_read(0x32);
+ /* If EC wake events are enabled, enable wake on EC WAKE GPE. */
+ if (ec_wake & 0x14)
+ gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
+ }
+}

To view, visit change 48771. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I746798b13e83d1971bb7be93751a15875d16c337
Gerrit-Change-Number: 48771
Gerrit-PatchSet: 1
Gerrit-Owner: Bill XIE <persmule@hardenedlinux.org>
Gerrit-MessageType: newchange