mb/purism/librem_jsl: Add support for Librem 11

This adds support for the Librem 11 tablet, using the ME 13.50.15.1436
binary from the original BIOS (version 28.D8.E1.021) and FSP binaries
from a Jasper Lake Chromebook.

The following features were tested with PureOS:
* Audio (speakers, microphone, headset jack)
* Cameras
* Display
* Touchscreen and pen
* Keyboard cover, with tablet/laptop mode switch indicated via ACPI
* Power and volume buttons
* USB-C ports (USB 2/3, DP alt mode, PD charging)
* SD card reader
* WLAN
* Bluetooth
* NVMe SSD (socketed)
* Battery state information from EC
* Accelerometer

A UART is accessible with soldering via test points on the mainboard,
documented in the mainboard Kconfig with a toggle to enable it for
coreboot logging.

Change-Id: I545994889ddfb41f56de09b3a42840bccbd7c4aa
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/78343
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
This commit is contained in:
Jonathon Hall 2023-09-14 14:41:20 -04:00 committed by Matt DeVillier
parent 24502f4cb0
commit a86704aa10
20 changed files with 1171 additions and 0 deletions

View file

@ -0,0 +1,82 @@
config BOARD_PURISM_BASEBOARD_LIBREM_JSL
def_bool n
select BOARD_ROMSIZE_KB_16384
select DRIVERS_GENERIC_CBFS_SERIAL
select DRIVERS_USB_ACPI
select DRIVERS_I2C_GENERIC
select DRIVERS_I2C_HID
select EC_ACPI
select HAVE_ACPI_RESUME
select HAVE_ACPI_TABLES
select HAVE_SPD_IN_CBFS
select INTEL_GMA_HAVE_VBT
select NO_UART_ON_SUPERIO
select SOC_INTEL_COMMON_BLOCK_HDA_VERB
select SOC_INTEL_JASPERLAKE
select SYSTEM_TYPE_DETACHABLE
select USE_LEGACY_8254_TIMER
config BOARD_PURISM_LIBREM_11
select BOARD_PURISM_BASEBOARD_LIBREM_JSL
if BOARD_PURISM_BASEBOARD_LIBREM_JSL
config MAINBOARD_DIR
default "purism/librem_jsl"
config MAINBOARD_FAMILY
string
default "Librem 11" if BOARD_PURISM_BASEBOARD_LIBREM_JSL
config MAINBOARD_PART_NUMBER
default "Librem 11" if BOARD_PURISM_BASEBOARD_LIBREM_JSL
config MAX_CPUS
int
default 4
config CBFS_SIZE
default 0x700000 if BOARD_PURISM_BASEBOARD_LIBREM_JSL
config DIMM_MAX
default 2
config DIMM_SPD_SIZE
default 512
config VGA_BIOS_ID
string
default "8086,4e61" if BOARD_PURISM_BASEBOARD_LIBREM_JSL
config NO_POST
default y
config INTEL_GMA_VBT_FILE
default "src/mainboard/purism/librem_jsl/data.vbt"
config ENABLE_UART2
bool "Enable UART2 debug output"
default n
select INTEL_LPSS_UART_FOR_CONSOLE
help
Enable UART2 for debug output.
This UART can be used for boot logging by coreboot and payloads.
For Linux, boot with `console=uart,mmio32,0xfe032000,115200n8`.
(0xfe032000 is CONSOLE_UART_BASE_ADDRESS for Jasper Lake.) Blacklist
intel_lpss_pci so it does not reconfigure the UART.
Soldering is required to access these signals. On the reverse side of
the board, there are two test points directly underneath the SoC (the
only two test points between the heatsink screw holes). The pad
nearest the M.2 socket is TX, the other is RX. The signals are 3.3V
(do NOT connect directly to an RS-232 serial port).
config UART_FOR_CONSOLE
default 2 if ENABLE_UART2
config FSP_TEMP_RAM_SIZE
default 0x28000
endif

View file

@ -0,0 +1,2 @@
config BOARD_PURISM_LIBREM_11
bool "Librem 11"

View file

@ -0,0 +1,6 @@
## SPDX-License-Identifier: GPL-2.0-only
bootblock-y += bootblock.c
ramstage-y += ramstage.c
ramstage-y += hda_verb.c
SPD_SOURCES += isocon8gb

View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only */
Device (AC)
{
Name (_HID, "ACPI0003" /* Power Source Device */) // _HID: Hardware ID
Name (_PCL, Package (0x01) // _PCL: Power Consumer List
{
_SB
})
Name (ACEX, One)
Method (_PSR, 0, NotSerialized) // _PSR: Power Source
{
Printf ("AC: _PSR: %o", ACEX)
Return (ACEX)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
}

View file

@ -0,0 +1,136 @@
/* SPDX-License-Identifier: GPL-2.0-only */
Device (BAT0)
{
Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */) // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (_PCL, Package (0x01) // _PCL: Power Consumer List
{
_SB
})
Name (BTEX, Zero)
// Test if EC0 is ready, and if it is, if the battery is present
Method (BTOK, 0, NotSerialized)
{
If (^^ECOK) {
If (BTEX) {
Return (One)
}
}
Return (Zero)
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (BTOK ()) {
Printf ("BAT0: _STA: present")
Return (0x1F)
}
Printf ("BAT0: _STA: not present")
Return (0x0F)
}
Name (PBIF, Package (0x0D) // Persistent battery information
{
One, // 0 - Power Unit - mA/mAh
0xFFFFFFFF, // 1 - Design Capacity
0xFFFFFFFF, // 2 - Last Full Charge Capacity
One, // 3 - Battery Technology
0xFFFFFFFF, // 4 - Design Voltage
Zero, // 5 - Design Capacity of Warning
Zero, // 6 - Design Capacity of Low
Zero, // 7 - Battery Capacity Granularity 1
Zero, // 8 - Battery Capacity Granularity 2
"", // 9 - Model Number
"", // 10 - Serial Number
"", // 11 - Battery Type
"" // 12 - OEM Information
})
Method (IVBI, 0, NotSerialized) // Set invalid battery information
{
PBIF [1] = 0xFFFFFFFF
PBIF [2] = 0xFFFFFFFF
PBIF [5] = Zero
PBIF [6] = Zero
PBIF [7] = Zero
PBIF [8] = Zero
PBIF [9] = ""
PBIF [10] = ""
PBIF [11] = ""
}
Method (UPBI, 0, Serialized) // Update battery information
{
If (BTOK ()) {
Local0 = ^^BTDC // design cap
Local1 = ^^BTFC // last full capacity
// Design capacity
PBIF [1] = Local0
// Last full charge capacity
PBIF [2] = Local1
// Warn/low capacities - 15% and 10% of design capacity
PBIF [5] = Local1 * 15 / 100
PBIF [6] = Local1 * 10 / 100
// Granularity is 1% of design capacity
PBIF [7] = Local0 / 100
PBIF [8] = Local0 / 100
PBIF [9] = "BAT"
PBIF [10] = "0001"
PBIF [11] = "LION"
}
Else {
IVBI ()
}
}
Method (_BIF, 0, NotSerialized) // _BIF: Battery Information
{
UPBI ()
Return (PBIF)
}
Name (PBST, Package (0x04) // Persistent battery state
{
Zero, // 0 - Battery state
0xFFFFFFFF, // 1 - Battery present rate
0xFFFFFFFF, // 2 - Battery remaining capacity
0xFFFFFFFF // 3 - Battery present voltage
})
Method (IVBS, 0, NotSerialized) // Invalid battery state
{
PBST [0] = Zero
PBST [1] = 0xFFFFFFFF
PBST [2] = 0xFFFFFFFF
PBST [3] = 0xFFFFFFFF
}
Method (UPBS, 0, Serialized)
{
If (BTOK ()) {
// Status flags - 3 bits; this EC does not report the
// charge limiting state
PBST [0] = ^^BTST
// Present rate
PBST [1] = ^^BTCR
// Remaining capacity
PBST [2] = ^^BTRC
// Present voltage
PBST [3] = ^^BTVT
}
Else {
IVBS ()
}
}
Method (_BST, 0, NotSerialized) // _BST: Battery Status
{
UPBS ()
Return (PBST)
}
}

View file

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
Device (PWRB)
{
Name (_HID, EisaId ("PNP0C0C"))
Name (_PRW, Package () { EC_GPE_SWI, 3 })
}

View file

@ -0,0 +1,121 @@
/* SPDX-License-Identifier: GPL-2.0-only */
Device (EC0)
{
Name (_HID, EisaId ("PNP0C09"))
Name (_UID, 0)
Name (_GPE, EC_GPE_SWI)
Name (ECOK, Zero)
Name (_CRS, ResourceTemplate () {
IO (Decode16, 0x62, 0x62, 0, 1)
IO (Decode16, 0x66, 0x66, 0, 1)
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
OperationRegion (ERAM, EmbeddedControl, Zero, 0xFF)
Field (ERAM, ByteAcc, Lock, Preserve)
{
Offset (0x7F),
LSTE, 1, /* lid state */
, 7,
ACEX, 1, /* AC adapter present */
BTEX, 1, /* battery present */
, 6,
Offset (0x84),
BTDC, 16, /* battery design capacity - mAh */
BTFV, 16, /* battery last full voltage - mV */
BTFC, 16, /* battery last full capacity - mAh */
Offset (0x8C),
BTST, 3, /* battery state */
, 5,
BTCR, 16, /* battery present current - mA */
BTRC, 16, /* battery remaining capacity - mAh */
BTVT, 16, /* battery present voltage - mV */
Offset (0xA3),
DSPO, 8, /* Display off - write 1 to power off display */
BCST, 8, /* battery charge start threshold - % */
BCET, 8, /* battery charge end threshold - % */
}
#include "button.asl"
#include "ac.asl"
#include "battery.asl"
#include "vbtn.asl"
Method (PTS, 1, Serialized) {
Printf ("EC: PTS: %o", ToHexString(Arg0))
If (ECOK) {
// Power off display
DSPO = One
}
}
Method (WAK, 1, Serialized) {
Printf ("EC: WAK: %o", ToHexString(Arg0))
If (ECOK) {
DSPO = Zero
^AC.ACEX = ACEX
Notify(BAT0, Zero)
Notify(AC, Zero)
}
}
Method (_Q54, 0, NotSerialized) // Power button press
{
Printf ("EC: _Q54: power button press")
Notify (PWRB, 0x80)
}
Method (_Q0A, 0, NotSerialized) // Charger plugged or unplugged
{
Printf ("EC: _Q0A: charger state changed")
If (ECOK) {
^AC.ACEX = ACEX
}
Notify(BAT0, 0x81) // Information change
Notify(AC, 0x80) // Status change
}
Method (_Q0B, 0, NotSerialized) // Battery status change
{
Printf ("EC: _Q0B: battery state changed")
Notify(BAT0, 0x81) // Information change
Notify(BAT0, 0x80) // Status change
}
/* There is a lid/cover sensor, but it is not reliable with a soft cover. */
Method (_Q0C, 0, NotSerialized) // Cover closed
{
Printf ("EC: _Q0C: cover closed")
}
Method (_Q0D, 0, NotSerialized) // Cover opened
{
Printf ("EC: _Q0D: cover opened")
}
Method (_REG, 2, Serialized) // _REG: Region Availability
{
Printf ("EC: _REG: %o, %o", Arg0, Arg1)
If ((Arg0 == 0x03) && (Arg1 == One)) {
// EC is now available
ECOK = One
// Set current AC and battery state
^AC.ACEX = ACEX
^BAT0.BTEX = BTEX
// Notify of changes
Notify(AC, Zero)
Notify(BAT0, Zero)
Printf ("EC is ready; BTEX=%o, ACEX=%o", BTEX, ACEX)
}
}
}

View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
Scope (_GPE)
{
/*
* Keyboard dock connector sense. This is GPP_D4, which would seem to
* be _L34 for GPE0_DW1, but there is an additional 10h offset for some
* reason, even if GPP_D is assigned to DW0 or DW2 instead.
*/
Method (_L44, 0, NotSerialized) {
Printf ("GPE _L44");
\_SB.PCI0.LPCB.EC0.VBTN.NTFY ()
}
}

View file

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#define EC_GPE_SWI 0x6E /* eSPI SCI */
Scope (\_SB.PCI0.LPCB)
{
#include "ec.asl"
}

View file

@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0-only */
Name (FLAP, 0x40) /* Flag indicating device is in laptop mode */
/* Virtual events */
Name (VTBL, 0xcc) /* Tablet Mode */
Name (VLAP, 0xcd) /* Laptop Mode */
Device (VBTN)
{
Name (_HID, "INT33D6")
Name (_UID, 1)
Name (_DDN, "Intel Virtual Button Driver")
/*
* This method is called at driver probe time and must exist or
* the driver will not load.
*/
Method (VBDL)
{
}
/*
* This method returns flags indicating tablet and dock modes.
* It is called at driver probe time so the OS knows what the
* state of the device is at boot.
*/
Method (VGBS)
{
Local0 = 0
If (CKLP ()) {
Local0 |= ^^FLAP
}
Return (Local0)
}
Method (_STA, 0)
{
Return (0xF)
}
Method (CKLP, 0)
{
/* 120 = GPP_D4 */
If (\_SB.PCI0.GRXS (120)) {
Printf ("VBTN: tablet mode")
Return (0) /* Tablet mode */
} Else {
Printf ("VBTN: laptop mode")
Return (1) /* Laptop mode */
}
}
Method (NTFY, 0)
{
/* Notify the new state */
If (CKLP ()) {
Notify (^^VBTN, ^^VLAP)
} Else {
Notify (^^VBTN, ^^VTBL)
}
}
}

View file

@ -0,0 +1,8 @@
Vendor name: Purism
Board name: Librem Jasper Lake baseboard
Category: misc
Release year: 2023
ROM package: SOIC-8
ROM protocol: SPI
ROM socketed: n
Flashrom support: y

View file

@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h>
#include <console/console.h>
#include <delay.h>
#include <device/pci_ops.h>
#include <ec/acpi/ec.h>
#include <gpio.h>
#include <soc/pci_devs.h>
static const struct pad_config early_gpio_table[] = {
PAD_CFG_NF(GPP_C20, NONE, DEEP, NF1), /* UART2_RXD */
PAD_CFG_NF(GPP_C21, NONE, DEEP, NF1), /* UART2_TXD */
};
void bootblock_mainboard_early_init(void)
{
gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table));
}
void bootblock_mainboard_init(void)
{
/*
* Ensure the panel is powered on. ACPI _PTS disables it, if the system
* is powered up again we need to turn it on.
*/
ec_write(0xa3, 0);
}

Binary file not shown.

View file

@ -0,0 +1,184 @@
chip soc/intel/jasperlake
register "eist_enable" = "1"
register "s0ix_enable" = "0"
register "SaGv" = "SaGv_Enabled"
register "AcousticNoiseMitigation" = "1"
register "FastPkgCRampDisable" = "1"
register "SlowSlewRate" = "3"
# TCC limit of 60 C (passively cooled tablet)
register "tcc_offset" = "40"
register "power_limits_config[JSL_N5100_6W_CORE]" = "{
.tdp_pl1_override = 5,
.tdp_pl2_override = 12,
}"
register "pmc_gpe0_dw0" = "PMC_GPP_F"
register "pmc_gpe0_dw1" = "PMC_GPP_D"
register "pmc_gpe0_dw2" = "PMC_GPD"
register "SkipCpuReplacementCheck" = "1"
device cpu_cluster 0 on end
register "SerialIoI2cMode" = "{
[PchSerialIoIndexI2C0] = PchSerialIoDisabled,
[PchSerialIoIndexI2C1] = PchSerialIoDisabled,
[PchSerialIoIndexI2C2] = PchSerialIoPci,
[PchSerialIoIndexI2C3] = PchSerialIoPci,
[PchSerialIoIndexI2C4] = PchSerialIoDisabled,
[PchSerialIoIndexI2C5] = PchSerialIoDisabled,
}"
register "SerialIoUartMode[2]" = "PchSerialIoSkipInit"
# Audio related configurations
register "PchHdaDspEnable" = "1"
register "PchHdaAudioLinkHdaEnable" = "1"
device domain 0 on
device pci 00.0 on end # Host Bridge
device pci 02.0 on end # Integrated Graphics Device
device pci 04.0 on end # SA Thermal device
device pci 05.0 on end # IPU
device pci 09.0 off end # Intel Trace Hub
device pci 12.6 off end # GSPI 2
device pci 14.0 on # USB xHCI
register "usb2_ports[0]" = "USB2_PORT_MID(OC_SKIP)" # Fingerprint reader
register "usb2_ports[1]" = "USB2_PORT_MID(OC_SKIP)" # microSD
register "usb2_ports[2]" = "USB2_PORT_MID(OC_SKIP)" # Type-C 1
register "usb2_ports[3]" = "USB2_PORT_MID(OC_SKIP)" # Type-C 2
register "usb2_ports[4]" = "USB2_PORT_EMPTY"
register "usb2_ports[5]" = "USB2_PORT_MID(OC_SKIP)" # Internal hub - front and rear cameras
register "usb2_ports[6]" = "USB2_PORT_MID(OC_SKIP)" # Dock pogo pins
register "usb2_ports[7]" = "USB2_PORT_MID(OC_SKIP)" # WLAN module
register "usb3_ports[0]" = "USB3_PORT_DEFAULT(OC_SKIP)" # Type-C Port 2
register "usb3_ports[1]" = "USB3_PORT_DEFAULT(OC_SKIP)" # Type-C Port 1
chip drivers/usb/acpi
register "desc" = ""Root Hub""
register "type" = "UPC_TYPE_HUB"
device usb 0.0 on
chip drivers/usb/acpi
register "desc" = ""Fingerprint Reader""
register "type" = "UPC_TYPE_INTERNAL"
device usb 2.0 on end
end
chip drivers/usb/acpi
register "desc" = ""microSD Card Reader""
register "type" = "UPC_TYPE_INTERNAL"
device usb 2.1 on end
end
chip drivers/usb/acpi
register "desc" = ""Type-C Port 1""
register "type" = "UPC_TYPE_C_USB2_SS_SWITCH"
register "group" = "ACPI_PLD_GROUP(0, 0)"
device usb 2.2 on end
end
chip drivers/usb/acpi
register "desc" = ""Type-C Port 2""
register "type" = "UPC_TYPE_C_USB2_SS_SWITCH"
register "group" = "ACPI_PLD_GROUP(0, 1)"
device usb 2.3 on end
end
chip drivers/usb/acpi
register "desc" = ""Cameras""
register "type" = "UPC_TYPE_INTERNAL"
device usb 2.5 on end
end
chip drivers/usb/acpi
register "desc" = ""Keyboard Dock""
register "type" = "UPC_TYPE_PROPRIETARY"
device usb 2.6 on end
end
chip drivers/usb/acpi
register "desc" = ""Bluetooth""
register "type" = "UPC_TYPE_INTERNAL"
device usb 2.7 on end
end
chip drivers/usb/acpi
register "desc" = ""Type-C Port 2""
register "type" = "UPC_TYPE_C_USB2_SS_SWITCH"
register "group" = "ACPI_PLD_GROUP(0, 1)"
device usb 3.0 on end
end
chip drivers/usb/acpi
register "desc" = ""Type-C Port 1""
register "type" = "UPC_TYPE_C_USB2_SS_SWITCH"
register "group" = "ACPI_PLD_GROUP(0, 0)"
device usb 3.1 on end
end
end
end
end
device pci 14.1 off end # USB xDCI (OTG)
device pci 14.2 on end # PMC SRAM
device pci 14.3 on # CNVi wifi
chip drivers/wifi/generic
device generic 0 on end
end
end
device pci 14.5 off end # SD card
device pci 15.0 off end # I2C 0
device pci 15.1 off end # I2C 1
device pci 15.2 on # I2C 2
chip drivers/i2c/hid
register "generic.hid" = ""GXTP7380""
register "generic.cid" = ""PNP0C50""
register "generic.desc" = ""Touchscreen""
register "generic.irq_gpio" = "ACPI_GPIO_IRQ_LEVEL_LOW(GPP_C12)"
register "generic.reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_D6)"
register "hid_desc_reg_offset" = "1"
device i2c 5d on end
end
end
device pci 15.3 on # I2C 3
chip drivers/i2c/generic
register "hid" = ""MXC6655""
register "cid" = ""MXC6655""
register "desc" = ""Accelerometer""
register "irq_gpio" = "ACPI_GPIO_IRQ_LEVEL_LOW(GPP_E1)"
device i2c 15 on end
end
end
device pci 16.0 off end # HECI 1
device pci 16.1 off end # HECI 2
device pci 16.4 off end # HECI 3
device pci 16.5 off end # HECI 4
device pci 17.0 off end # SATA
device pci 19.0 on end # I2C 4
device pci 19.1 off end # I2C 5
device pci 19.2 off end # UART 2
device pci 1a.0 off end # eMMC
device pci 1c.0 off end # PCI Express Root Port 1
device pci 1c.1 off end # PCI Express Root Port 2
device pci 1c.2 on # PCI Express Root Port 3 - M.2 M-key, PCIe only
register "PcieRpEnable[2]" = "true"
register "PcieClkSrcUsage[0]" = "2"
register "PcieClkSrcClkReq[0]" = "0"
smbios_slot_desc "SlotTypeM2Socket3" "SlotLengthOther" "M.2/M 2280" "SlotDataBusWidth2X"
end
device pci 1c.3 off end # PCI Express Root Port 4
device pci 1c.4 off end # PCI Express Root Port 5
device pci 1c.5 off end # PCI Express Root Port 6
device pci 1c.6 off end # PCI Express Root Port 7
device pci 1c.7 off end # PCI Express Root Port 8
device pci 1e.0 off end # UART 0
device pci 1e.1 off end # UART 1
device pci 1e.2 off end # GSPI 0
device pci 1e.3 off end # GSPI 1
device pci 1f.0 on end # eSPI Interface
device pci 1f.1 off end # P2SB
device pci 1f.2 hidden end # Power Management Controller
device pci 1f.3 on end # Intel HDA/cAVS
device pci 1f.4 off end # SMBus
device pci 1f.5 on end # PCH SPI
device pci 1f.7 off end # Intel Trace Hub
end
end

View file

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpi.h>
DefinitionBlock(
"dsdt.aml",
"DSDT",
ACPI_DSDT_REV_2,
OEM_ID,
ACPI_TABLE_CREATOR,
0x20110725
)
{
#include <acpi/dsdt_top.asl>
#include <soc/intel/common/block/acpi/acpi/platform.asl>
#include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
#include <cpu/intel/common/acpi/cpu.asl>
Device (\_SB.PCI0)
{
#include <soc/intel/common/block/acpi/acpi/northbridge.asl>
#include <soc/intel/jasperlake/acpi/southbridge.asl>
// The volume keys are implemented by the EC as a PS/2 keyboard
#include <drivers/pc80/pc/ps2_keyboard.asl>
}
#include "acpi/mainboard.asl"
#include "acpi/gpe.asl"
#include <southbridge/intel/common/acpi/sleepstates.asl>
}

View file

@ -0,0 +1,285 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef CFG_GPIO_H
#define CFG_GPIO_H
#include <gpio.h>
static const struct pad_config gpio_table[] = {
/* ------- GPIO Community 1 ------- */
/* ------- GPIO Group GPP_G ------- */
PAD_NC(GPP_G0, NONE), /* GPIO */
PAD_NC(GPP_G1, NONE), /* GPIO */
PAD_NC(GPP_G2, NONE), /* GPIO */
PAD_NC(GPP_G3, NONE), /* GPIO */
PAD_NC(GPP_G4, NONE), /* GPIO */
PAD_NC(GPP_G5, NONE), /* GPIO */
PAD_NC(GPP_G6, NONE), /* GPIO */
PAD_NC(GPP_G7, NONE), /* GPIO */
/* ------- GPIO Community 2 ------- */
/* ------- GPIO Group HVMOS ------- */
/* ------- GPIO Group GPP_E ------- */
PAD_NC(GPP_E0, NONE), /* GPIO */
/* GPP_E1 - ACCL_1_INT_N */
PAD_CFG_GPI_TRIG_OWN(GPP_E1, NONE, PLTRST, OFF, DRIVER), /* GPIO */
PAD_NC(GPP_E2, NONE), /* GPIO */
PAD_NC(GPP_E3, NONE), /* GPIO */
PAD_NC(GPP_E4, NONE), /* GPIO */
PAD_NC(GPP_E5, NONE), /* GPIO */
PAD_NC(GPP_E6, NONE), /* GPIO */
PAD_NC(GPP_E7, NONE), /* GPIO */
/* GPP_E8 - UART_BT_WAKE_N */
//PAD_CFG_GPI_SCI(GPP_E8, NONE, DEEP, LEVEL, INVERT), /* GPIO */
PAD_NC(GPP_E8, NONE),
PAD_NC(GPP_E9, NONE), /* GPIO */
PAD_NC(GPP_E10, NONE), /* GPIO */
PAD_NC(GPP_E11, NONE), /* GPIO */
PAD_NC(GPP_E12, NONE), /* GPIO */
PAD_NC(GPP_E13, NONE), /* GPIO */
PAD_NC(GPP_E14, NONE), /* GPIO */
PAD_NC(GPP_E15, NONE), /* GPIO */
PAD_NC(GPP_E16, NONE), /* GPIO */
PAD_NC(GPP_E17, NONE), /* GPIO */
PAD_NC(GPP_E18, NONE), /* GPIO */
PAD_NC(GPP_E19, NONE), /* GPIO */
PAD_CFG_NF(GPP_E20, NONE, DEEP, NF1), /* CNV_BRI_DT */
PAD_CFG_NF(GPP_E21, UP_20K, DEEP, NF1), /* CNV_BRI_RSP */
PAD_CFG_NF(GPP_E22, NONE, DEEP, NF1), /* CNV_RGI_DT */
PAD_CFG_NF(GPP_E23, UP_20K, DEEP, NF1), /* CNV_RGI_RSP */
/* ------- GPIO Community 4 ------- */
/* ------- GPIO Group GPD ------- */
PAD_CFG_NF(GPD0, NONE, RSMRST, NF1), /* GPIO_BATLOWB */
PAD_CFG_NF(GPD1, NATIVE, RSMRST, NF1), /* GPIO_ACPRESENT */
/* GPD2 - SMC_WAKE_SCI_N */
PAD_CFG_GPI_SCI(GPD2, NONE, DEEP, LEVEL, INVERT), /* GPIO */
PAD_CFG_NF(GPD3, UP_20K, RSMRST, NF1), /* GPIO_PWRBTNB */
PAD_CFG_NF(GPD4, NONE, RSMRST, NF1), /* GPIO_SLP_S3B */
PAD_CFG_NF(GPD5, NONE, RSMRST, NF1), /* GPIO_SLP_S4B */
PAD_CFG_NF(GPD6, NONE, DEEP, NF1), /* GPIO_SLP_AB */
PAD_NC(GPD7, NONE), /* GPIO */
PAD_CFG_NF(GPD8, NONE, RSMRST, NF1), /* GPIO_SUSCLK */
PAD_CFG_NF(GPD9, NONE, DEEP, NF1), /* GPIO_SLP_WLANB */
PAD_CFG_NF(GPD10, NONE, DEEP, NF1), /* GPIO_SLP_S5B */
/* ------- GPIO Community 5 ------- */
/* ------- GPIO Group GPP_H ------- */
/* GPP_H0 - FPS_INT_N */
PAD_CFG_GPI_APIC(GPP_H0, NONE, PLTRST, LEVEL, INVERT), /* GPIO */
PAD_NC(GPP_H1, NONE), /* GPIO */
PAD_CFG_NF(GPP_H2, NONE, DEEP, NF3), /* MODEM_CLKREQ */
PAD_NC(GPP_H3, NONE), /* GPIO */
PAD_CFG_NF(GPP_H4, NONE, DEEP, NF1), /* I2C2_SDA */
PAD_CFG_NF(GPP_H5, NONE, DEEP, NF1), /* I2C2_SCL */
PAD_CFG_NF(GPP_H6, NONE, DEEP, NF1), /* I2C3_SDA */
PAD_CFG_NF(GPP_H7, NONE, DEEP, NF1), /* I2C3_SCL */
PAD_NC(GPP_H8, NONE), /* GPIO */
PAD_NC(GPP_H9, NONE), /* GPIO */
PAD_NC(GPP_H10, NONE), /* GPIO */
PAD_NC(GPP_H11, NONE), /* GPIO */
PAD_CFG_NF(GPP_H12, NONE, DEEP, NF2), /* CNV_RF_RESETB */
PAD_NC(GPP_H13, NONE), /* GPIO */
PAD_NC(GPP_H14, NONE), /* GPIO */
PAD_NC(GPP_H15, NONE), /* GPIO */
/* GPP_H16 - FPS_RST_N */
PAD_CFG_GPO(GPP_H16, 1, PLTRST), /* GPIO */
PAD_NC(GPP_H17, NONE), /* GPIO */
PAD_NC(GPP_H18, NONE), /* GPIO */
PAD_NC(GPP_H19, NONE), /* GPIO */
PAD_NC(GPP_H20, NONE), /* GPIO */
PAD_NC(GPP_H21, NONE), /* GPIO */
PAD_NC(GPP_H22, NONE), /* GPIO */
PAD_NC(GPP_H23, NONE), /* GPIO */
/* ------- GPIO Group GPP_D ------- */
PAD_NC(GPP_D0, NONE), /* GPIO */
PAD_NC(GPP_D1, NONE), /* GPIO */
/* GPP_D2 - EC_SMI_N */
PAD_CFG_GPI_SMI(GPP_D2, NONE, PLTRST, LEVEL, INVERT), /* GPIO */
PAD_NC(GPP_D3, NONE), /* GPIO */
/* GPP_D4 - GPIO_DK (keyboard dock sense) */
PAD_CFG_GPI_SCI(GPP_D4, NONE, DEEP, EDGE_BOTH, NONE), /* GPIO */
/* GPP_D5 - SSD_RST_N (NVMe PERESET#) */
PAD_CFG_GPO(GPP_D5, 1, PLTRST), /* GPIO */
/* GPP_D6 - TCH_PNL_RST_N */
PAD_CFG_GPO(GPP_D6, 1, PLTRST), /* GPIO */
PAD_NC(GPP_D7, NONE), /* GPIO */
PAD_NC(GPP_D8, NONE), /* GPIO */
PAD_NC(GPP_D9, NONE), /* GPIO */
PAD_NC(GPP_D10, NONE), /* GPIO */
PAD_NC(GPP_D11, NONE), /* GPIO */
PAD_NC(GPP_D12, NONE), /* GPIO */
PAD_NC(GPP_D13, NONE), /* GPIO */
PAD_NC(GPP_D14, NONE), /* GPIO */
PAD_NC(GPP_D15, NONE), /* GPIO */
PAD_NC(GPP_D16, NONE), /* GPIO */
PAD_NC(GPP_D17, NONE), /* GPIO */
PAD_NC(GPP_D18, NONE), /* GPIO */
PAD_NC(GPP_D19, NONE), /* GPIO */
PAD_NC(GPP_D20, NONE), /* GPIO */
PAD_NC(GPP_D21, NONE), /* GPIO */
PAD_NC(GPP_D22, NONE), /* GPIO */
PAD_NC(GPP_D23, NONE), /* GPIO */
/* ------- GPIO Group VGPIO5 ------- */
PAD_NC(VGPIO_0, NONE), /* GPIO */
PAD_NC(VGPIO_3, NONE), /* GPIO */
PAD_NC(VGPIO_4, NONE), /* GPIO */
PAD_NC(VGPIO_5, NONE), /* GPIO */
PAD_NC(VGPIO_6, NONE), /* GPIO */
PAD_NC(VGPIO_7, NONE), /* GPIO */
PAD_NC(VGPIO_8, NONE), /* GPIO */
PAD_NC(VGPIO_9, NONE), /* GPIO */
PAD_NC(VGPIO_10, NONE), /* GPIO */
PAD_NC(VGPIO_11, NONE), /* GPIO */
PAD_NC(VGPIO_12, NONE), /* GPIO */
PAD_NC(VGPIO_13, NONE), /* GPIO */
PAD_NC(VGPIO_18, NONE), /* GPIO */
PAD_NC(VGPIO_19, NONE), /* GPIO */
PAD_NC(VGPIO_20, NONE), /* GPIO */
PAD_NC(VGPIO_21, NONE), /* GPIO */
PAD_NC(VGPIO_22, NONE), /* GPIO */
PAD_NC(VGPIO_23, NONE), /* GPIO */
PAD_NC(VGPIO_24, NONE), /* GPIO */
PAD_NC(VGPIO_25, NONE), /* GPIO */
PAD_NC(VGPIO_30, NONE), /* GPIO */
PAD_NC(VGPIO_31, NONE), /* GPIO */
PAD_NC(VGPIO_32, NONE), /* GPIO */
PAD_NC(VGPIO_33, NONE), /* GPIO */
PAD_NC(VGPIO_34, NONE), /* GPIO */
PAD_NC(VGPIO_35, NONE), /* GPIO */
PAD_NC(VGPIO_36, NONE), /* GPIO */
PAD_NC(VGPIO_37, NONE), /* GPIO */
PAD_NC(VGPIO_39, NONE), /* GPIO */
/* ------- GPIO Group GPP_C ------- */
PAD_NC(GPP_C0, NONE), /* GPIO */
PAD_NC(GPP_C1, NONE), /* GPIO */
PAD_NC(GPP_C2, NONE), /* GPIO */
PAD_NC(GPP_C3, NONE), /* GPIO */
PAD_NC(GPP_C4, NONE), /* GPIO */
PAD_NC(GPP_C5, NONE), /* GPIO */
PAD_NC(GPP_C6, NONE), /* GPIO */
PAD_NC(GPP_C7, NONE), /* GPIO */
PAD_CFG_GPO(GPP_C8, 1, PLTRST), /* GPIO */
PAD_NC(GPP_C9, NONE), /* GPIO */
PAD_NC(GPP_C10, NONE), /* GPIO */
PAD_NC(GPP_C11, NONE), /* GPIO */
/* GPP_C12 - TCH_PNL_INT_N */
PAD_CFG_GPI_TRIG_OWN(GPP_C12, NONE, PLTRST, EDGE_SINGLE, DRIVER), /* GPIO */
PAD_NC(GPP_C13, NONE), /* GPIO */
PAD_NC(GPP_C14, NONE), /* GPIO */
PAD_NC(GPP_C15, NONE), /* GPIO */
PAD_NC(GPP_C16, NONE), /* GPIO */
PAD_NC(GPP_C17, NONE), /* GPIO */
PAD_NC(GPP_C18, NONE), /* GPIO */
PAD_NC(GPP_C19, NONE), /* GPIO */
/* GPP_C20, GPP_C21 configured in bootblock for UART2 */
PAD_NC(GPP_C22, NONE), /* GPIO */
PAD_NC(GPP_C23, NONE), /* GPIO */
/* ------- GPIO Community 6 ------- */
/* ------- GPIO Group GPP_F ------- */
PAD_NC(GPP_F0, NONE), /* GPIO */
PAD_NC(GPP_F1, NONE), /* GPIO */
PAD_NC(GPP_F2, NONE), /* GPIO */
PAD_NC(GPP_F3, NONE), /* GPIO */
PAD_NC(GPP_F4, NONE), /* GPIO */
PAD_NC(GPP_F5, NONE), /* GPIO */
PAD_NC(GPP_F6, NONE), /* GPIO */
PAD_NC(GPP_F7, NONE), /* GPIO */
PAD_NC(GPP_F8, NONE), /* GPIO */
PAD_NC(GPP_F9, NONE), /* GPIO */
PAD_NC(GPP_F10, NONE), /* GPIO */
PAD_NC(GPP_F11, NONE), /* GPIO */
PAD_NC(GPP_F12, NONE), /* GPIO */
PAD_NC(GPP_F13, NONE), /* GPIO */
PAD_NC(GPP_F14, NONE), /* GPIO */
PAD_NC(GPP_F15, NONE), /* GPIO */
PAD_NC(GPP_F16, NONE), /* GPIO */
PAD_NC(GPP_F17, NONE), /* GPIO */
PAD_NC(GPP_F18, NONE), /* GPIO */
PAD_NC(GPP_F19, NONE), /* GPIO */
/* ------- GPIO Group GPP_SPI ------- */
/* ------- GPIO Group GPP_B ------- */
PAD_CFG_NF(GPP_B0, NONE, DEEP, NF1), /* GPIO_CORE_VID0 */
PAD_CFG_NF(GPP_B1, NONE, DEEP, NF1), /* GPIO_CORE_VID1 */
PAD_NC(GPP_B2, NONE), /* GPIO */
PAD_NC(GPP_B3, NONE), /* GPIO */
PAD_NC(GPP_B4, NONE), /* GPIO */
PAD_CFG_NF(GPP_B5, NONE, DEEP, NF1), /* PCIE_CLKREQ0B */
PAD_CFG_NF(GPP_B6, NONE, DEEP, NF1), /* PCIE_CLKREQ1B */
PAD_NC(GPP_B7, NONE), /* GPIO */
PAD_NC(GPP_B8, NONE), /* GPIO */
PAD_NC(GPP_B9, NONE), /* GPIO */
PAD_NC(GPP_B10, NONE), /* GPIO */
PAD_NC(GPP_B11, NONE), /* GPIO */
PAD_CFG_NF(GPP_B12, NONE, DEEP, NF1), /* GPIO_SLP_S0B */
PAD_CFG_NF(GPP_B13, NONE, DEEP, NF1), /* GPIO_PLTRSTB */
PAD_NC(GPP_B14, NONE), /* GPIO */
PAD_NC(GPP_B15, NONE), /* GPIO */
PAD_NC(GPP_B16, NONE), /* GPIO */
/* GPP_B17 - PCIE_WLAN_RST_N_R */
PAD_CFG_GPO(GPP_B17, 1, PLTRST), /* GPIO */
PAD_NC(GPP_B18, NONE), /* GPIO */
PAD_CFG_NF(GPP_B19, NONE, DEEP, NF1), /* GSPI1_CS0B */
PAD_CFG_NF(GPP_B20, NONE, DEEP, NF1), /* GSPI1_CLK */
PAD_CFG_NF(GPP_B21, NONE, DEEP, NF1), /* GSPI1_MISO */
PAD_CFG_NF(GPP_B22, NONE, DEEP, NF1), /* GSPI1_MOSI */
PAD_CFG_NF(GPP_B23, NONE, DEEP, NF1), /* DDI2_HPD */
/* ------- GPIO Group GPP_A ------- */
PAD_CFG_NF(GPP_A0, UP_20K, DEEP, NF1), /* ESPI_IO_0 */
PAD_CFG_NF(GPP_A1, UP_20K, DEEP, NF1), /* ESPI_IO_1 */
PAD_CFG_NF(GPP_A2, UP_20K, DEEP, NF1), /* ESPI_IO_2 */
PAD_CFG_NF(GPP_A3, UP_20K, DEEP, NF1), /* ESPI_IO_3 */
PAD_CFG_NF(GPP_A4, UP_20K, DEEP, NF1), /* ESPI_CSB */
PAD_CFG_NF(GPP_A5, DN_20K, DEEP, NF1), /* ESPI_CLK */
PAD_CFG_NF(GPP_A6, NONE, DEEP, NF1), /* ESPI_RESETB */
PAD_NC(GPP_A7, NONE), /* GPIO */
PAD_NC(GPP_A8, NONE), /* GPIO */
PAD_NC(GPP_A9, NONE), /* GPIO */
PAD_NC(GPP_A10, NONE), /* GPIO */
PAD_NC(GPP_A11, NONE), /* GPIO */
PAD_NC(GPP_A12, NONE), /* GPIO */
PAD_NC(GPP_A13, NONE), /* GPIO */
PAD_NC(GPP_A14, NONE), /* GPIO */
PAD_NC(GPP_A15, NONE), /* GPIO */
PAD_CFG_NF(GPP_A16, NONE, DEEP, NF1), /* DDI1_HPD */
PAD_CFG_NF(GPP_A17, NONE, DEEP, NF1), /* DDI0_HPD */
PAD_NC(GPP_A18, NONE), /* GPIO */
/* GPP_A19 - WWAN_DISABLE_3P3_N (actually for WLAN despite name) */
PAD_CFG_GPO(GPP_A19, 1, PLTRST), /* GPIO */
/* ------- GPIO Group GPP_S ------- */
PAD_NC(GPP_S0, NONE), /* GPIO */
PAD_NC(GPP_S1, NONE), /* GPIO */
PAD_NC(GPP_S2, NONE), /* GPIO */
PAD_NC(GPP_S3, NONE), /* GPIO */
PAD_NC(GPP_S4, NONE), /* GPIO */
PAD_NC(GPP_S5, NONE), /* GPIO */
PAD_NC(GPP_S6, NONE), /* GPIO */
PAD_NC(GPP_S7, NONE), /* GPIO */
/* ------- GPIO Group GPP_R ------- */
PAD_CFG_NF(GPP_R0, NONE, DEEP, NF1), /* HDA_BCLK */
PAD_CFG_NF(GPP_R1, NATIVE, DEEP, NF1), /* HDA_SYNC */
PAD_CFG_NF(GPP_R2, NATIVE, DEEP, NF1), /* HDA_SD0 */
PAD_CFG_NF(GPP_R3, NATIVE, DEEP, NF1), /* HDA_SDI0 */
PAD_CFG_NF(GPP_R4, NONE, DEEP, NF1), /* HDA_RSTB */
PAD_NC(GPP_R5, NONE), /* GPIO */
PAD_NC(GPP_R6, NONE), /* GPIO */
PAD_NC(GPP_R7, NONE), /* GPIO */
};
#endif /* CFG_GPIO_H */

View file

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/azalia_device.h>
const u32 cim_verb_data[] = {
0x10ec0269, /* Codec Vendor/Device ID: Realtek ALC269 */
0x10ec0269, /* Subsystem ID */
16, /* Number of entries */
AZALIA_RESET(0x1),
AZALIA_SUBVENDOR(0, 0x10ec0269),
AZALIA_PIN_CFG(0, 0x12, 0x90a60130), /* DMIC */
AZALIA_PIN_CFG(0, 0x14, 0x90170110), /* FRONT */
AZALIA_PIN_CFG(0, 0x17, 0x40000000), /* N/C */
AZALIA_PIN_CFG(0, 0x18, 0x04a11020), /* MIC1 */
AZALIA_PIN_CFG(0, 0x19, 0x411111f0), /* N/C */
AZALIA_PIN_CFG(0, 0x1a, 0x411111f0), /* N/C */
AZALIA_PIN_CFG(0, 0x1b, 0x411111f0), /* N/C */
AZALIA_PIN_CFG(0, 0x1d, 0x40e38105), /* BEEP */
AZALIA_PIN_CFG(0, 0x1e, 0x411111f0), /* N/C */
AZALIA_PIN_CFG(0, 0x21, 0x0421101f), /* HP-OUT */
/* EQ */
0x02050011,
0x02040710,
0x02050012,
0x02041901,
0x0205000D,
0x02044440,
0x02050007,
0x02040040,
0x02050002,
0x0204AAB8,
0x02050008,
0x02040300,
0x02050017,
0x020400AF,
0x02050005,
0x020400C0,
0x8086281a, /* Codec Vendor/Device ID: Intel Jasper Lake HDMI */
0x80860101, /* Subsystem ID */
6, /* Number of entries */
AZALIA_SUBVENDOR(2, 0x80860101),
AZALIA_PIN_CFG(2, 0x04, 0x18560010),
AZALIA_PIN_CFG(2, 0x06, 0x18560010),
AZALIA_PIN_CFG(2, 0x08, 0x18560010),
AZALIA_PIN_CFG(2, 0x0a, 0x18560010),
AZALIA_PIN_CFG(2, 0x0b, 0x18560010),
};
const u32 pc_beep_verbs[] = {};
AZALIA_ARRAY_SIZES;

View file

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <soc/ramstage.h>
#include <acpi/acpigen_ps2_keybd.h>
#include "gpio.h"
void mainboard_silicon_init_params(FSP_S_CONFIG *supd)
{
}
static void mainboard_fill_ssdt(const struct device *dev)
{
/*
* Librem 11's PS/2 keyboard has only two keys - volume up and volume
* down.
*/
enum ps2_action_key ps2_action_keys[2] = {
PS2_KEY_VOL_DOWN,
PS2_KEY_VOL_UP
};
acpigen_ps2_keyboard_dsd("_SB.PCI0.PS2K", ARRAY_SIZE(ps2_action_keys),
ps2_action_keys, false, false, false, false);
}
static void mainboard_init(void *chip_info)
{
gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
}
static void mainboard_enable(struct device *dev)
{
dev->ops->acpi_fill_ssdt = mainboard_fill_ssdt;
}
struct chip_operations mainboard_ops = {
.init = mainboard_init,
.enable_dev = mainboard_enable,
};

View file

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <gpio.h>
#include <memory_info.h>
#include <soc/meminit.h>
#include <soc/romstage.h>
#include <device/pci_ops.h>
#include <console/console.h>
static const struct mb_cfg board_mem_cfg = {
.dq_map[DDR_CH0] = {
{0x0f, 0xf0},
{0x0f, 0xf0},
{0xff, 0x00},
{0x00, 0x00},
{0x00, 0x00},
{0x00, 0x00}
},
.dq_map[DDR_CH1] = {
{0x0f, 0xf0},
{0x0f, 0xf0},
{0xff, 0x00},
{0x00, 0x00},
{0x00, 0x00},
{0x00, 0x00}
},
.dqs_map[DDR_CH0] = {0, 3, 2, 1, 5, 7, 4, 6},
.dqs_map[DDR_CH1] = {3, 1, 2, 0, 4, 7, 6, 5},
/* Enable Early Command Training */
.ect = 1,
/* User Board Type */
.UserBd = BOARD_TYPE_ULT_ULX,
};
void mainboard_memory_init_params(FSPM_UPD *memupd)
{
const struct spd_info spd_info = {
.read_type = READ_SPD_CBFS,
.spd_spec.spd_index = 0,
};
memcfg_init(&memupd->FspmConfig, &board_mem_cfg, &spd_info, false);
}

View file

@ -0,0 +1,32 @@
23 11 11 0e 16 29 b8 08 00 40 00 00 02 62 00 00
00 00 05 0f 92 54 01 00 8a 00 90 a8 90 c0 08 60
04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 92 00 a7
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 20 00 00 00 4d 54 35 33 44 35 31
32 4d 36 34 44 34 52 51 2d 30 34 36 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00