ec/purism/librem-ec: Add support for Purism Librem EC
Initial commit is a clone of ec/system76/ec with string changes; Purism-specific functionality will be added in subsequent commits. Change-Id: I8c51724e6dbfe1bc09496537f9e031643f95c755 Signed-off-by: Matt DeVillier <matt.devillier@puri.sm> Reviewed-on: https://review.coreboot.org/c/coreboot/+/52390 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						parent
						
							5f20e85ff3
						
					
				
				
					commit
					7d57d561b1
				
			
							
								
								
									
										19
									
								
								src/ec/purism/librem-ec/Kconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/ec/purism/librem-ec/Kconfig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
config EC_LIBREM_EC
 | 
			
		||||
	bool
 | 
			
		||||
	help
 | 
			
		||||
	  Purism Librem EC
 | 
			
		||||
 | 
			
		||||
config EC_LIBREM_EC_BAT_THRESHOLDS
 | 
			
		||||
	depends on EC_LIBREM_EC
 | 
			
		||||
	bool
 | 
			
		||||
	default n
 | 
			
		||||
 | 
			
		||||
config EC_LIBREM_EC_COLOR_KEYBOARD
 | 
			
		||||
	depends on EC_LIBREM_EC
 | 
			
		||||
	bool
 | 
			
		||||
	default n
 | 
			
		||||
 | 
			
		||||
config EC_LIBREM_EC_OLED
 | 
			
		||||
	depends on EC_LIBREM_EC
 | 
			
		||||
	bool
 | 
			
		||||
	default n
 | 
			
		||||
							
								
								
									
										6
									
								
								src/ec/purism/librem-ec/Makefile.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/ec/purism/librem-ec/Makefile.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
ifeq ($(CONFIG_EC_LIBREM_EC),y)
 | 
			
		||||
 | 
			
		||||
all-y += librem_ec.c
 | 
			
		||||
smm-$(CONFIG_DEBUG_SMI) += librem_ec.c
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										22
									
								
								src/ec/purism/librem-ec/acpi/ac.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/ec/purism/librem-ec/acpi/ac.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
/* 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 (ACFG, One)
 | 
			
		||||
 | 
			
		||||
	Method (_PSR, 0, NotSerialized)  // _PSR: Power Source
 | 
			
		||||
	{
 | 
			
		||||
		Return (ACFG)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_STA, 0, NotSerialized)  // _STA: Status
 | 
			
		||||
	{
 | 
			
		||||
		Return (0x0F)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										170
									
								
								src/ec/purism/librem-ec/acpi/battery.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/ec/purism/librem-ec/acpi/battery.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,170 @@
 | 
			
		||||
/* 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 (BFCC, Zero)
 | 
			
		||||
	Method (_STA, 0, NotSerialized)  // _STA: Status
 | 
			
		||||
	{
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK)
 | 
			
		||||
		{
 | 
			
		||||
			If (^^PCI0.LPCB.EC0.BAT0)
 | 
			
		||||
			{
 | 
			
		||||
				Return (0x1F)
 | 
			
		||||
			}
 | 
			
		||||
			Else
 | 
			
		||||
			{
 | 
			
		||||
				Return (0x0F)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		Else
 | 
			
		||||
		{
 | 
			
		||||
			Return (0x0F)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Name (PBIF, Package (0x0D)
 | 
			
		||||
	{
 | 
			
		||||
		One, // 0 - Power Unit
 | 
			
		||||
		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
 | 
			
		||||
		0x40, // 7 - Battery Capacity Granularity 1
 | 
			
		||||
		0x40, // 8 - Battery Capacity Granularity 2
 | 
			
		||||
		" ", // 9 - Model Number
 | 
			
		||||
		" ", // 10 - Serial Number
 | 
			
		||||
		" ", // 11 - Battery Type
 | 
			
		||||
		" " // 12 - OEM Information
 | 
			
		||||
	})
 | 
			
		||||
	Method (IVBI, 0, NotSerialized)
 | 
			
		||||
	{
 | 
			
		||||
		PBIF [1] = 0xFFFFFFFF
 | 
			
		||||
		PBIF [2] = 0xFFFFFFFF
 | 
			
		||||
		PBIF [4] = 0xFFFFFFFF
 | 
			
		||||
		PBIF [9] = " "
 | 
			
		||||
		PBIF [10] = " "
 | 
			
		||||
		PBIF [11] = " "
 | 
			
		||||
		PBIF [12] = " "
 | 
			
		||||
		BFCC = Zero
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (UPBI, 0, NotSerialized)
 | 
			
		||||
	{
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.BAT0)
 | 
			
		||||
		{
 | 
			
		||||
			Local0 = (^^PCI0.LPCB.EC0.BDC0 & 0xFFFF)
 | 
			
		||||
			PBIF [1] = Local0
 | 
			
		||||
			Local0 = (^^PCI0.LPCB.EC0.BFC0 & 0xFFFF)
 | 
			
		||||
			PBIF [2] = Local0
 | 
			
		||||
			BFCC = Local0
 | 
			
		||||
			Local0 = (^^PCI0.LPCB.EC0.BDV0 & 0xFFFF)
 | 
			
		||||
			PBIF [4] = Local0
 | 
			
		||||
			Local0 = (^^PCI0.LPCB.EC0.BCW0 & 0xFFFF)
 | 
			
		||||
			PBIF [5] = Local0
 | 
			
		||||
			Local0 = (^^PCI0.LPCB.EC0.BCL0 & 0xFFFF)
 | 
			
		||||
			PBIF [6] = Local0
 | 
			
		||||
			PBIF [9] = "BAT"
 | 
			
		||||
			PBIF [10] = "0001"
 | 
			
		||||
			PBIF [11] = "LION"
 | 
			
		||||
			PBIF [12] = "Notebook"
 | 
			
		||||
		}
 | 
			
		||||
		Else
 | 
			
		||||
		{
 | 
			
		||||
			IVBI ()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_BIF, 0, NotSerialized)  // _BIF: Battery Information
 | 
			
		||||
	{
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK)
 | 
			
		||||
		{
 | 
			
		||||
			UPBI ()
 | 
			
		||||
		}
 | 
			
		||||
		Else
 | 
			
		||||
		{
 | 
			
		||||
			IVBI ()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Return (PBIF) /* \_SB_.BAT0.PBIF */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Name (PBST, Package (0x04)
 | 
			
		||||
	{
 | 
			
		||||
		Zero, // 0 - Battery state
 | 
			
		||||
		0xFFFFFFFF, // 1 - Battery present rate
 | 
			
		||||
		0xFFFFFFFF, // 2 - Battery remaining capacity
 | 
			
		||||
		0xFFFFFFFF // 3 - Battery present voltage
 | 
			
		||||
	})
 | 
			
		||||
	Method (IVBS, 0, NotSerialized)
 | 
			
		||||
	{
 | 
			
		||||
		PBST [0] = Zero
 | 
			
		||||
		PBST [1] = 0xFFFFFFFF
 | 
			
		||||
		PBST [2] = 0xFFFFFFFF
 | 
			
		||||
		PBST [3] = 0xFFFFFFFF
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (UPBS, 0, NotSerialized)
 | 
			
		||||
	{
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.BAT0)
 | 
			
		||||
		{
 | 
			
		||||
			Local0 = Zero
 | 
			
		||||
			Local1 = Zero
 | 
			
		||||
			If (^^AC.ACFG)
 | 
			
		||||
			{
 | 
			
		||||
				If (((^^PCI0.LPCB.EC0.BST0 & 0x02) == 0x02))
 | 
			
		||||
				{
 | 
			
		||||
					Local0 |= 0x02
 | 
			
		||||
					Local1 = (^^PCI0.LPCB.EC0.BPR0 & 0xFFFF)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			Else
 | 
			
		||||
			{
 | 
			
		||||
				Local0 |= One
 | 
			
		||||
				Local1 = (^^PCI0.LPCB.EC0.BPR0 & 0xFFFF)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Local7 = (Local1 & 0x8000)
 | 
			
		||||
			If ((Local7 == 0x8000))
 | 
			
		||||
			{
 | 
			
		||||
				Local1 ^= 0xFFFF
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Local2 = (^^PCI0.LPCB.EC0.BRC0 & 0xFFFF)
 | 
			
		||||
			Local3 = (^^PCI0.LPCB.EC0.BPV0 & 0xFFFF)
 | 
			
		||||
			PBST [0] = Local0
 | 
			
		||||
			PBST [1] = Local1
 | 
			
		||||
			PBST [2] = Local2
 | 
			
		||||
			PBST [3] = Local3
 | 
			
		||||
			If ((BFCC != ^^PCI0.LPCB.EC0.BFC0))
 | 
			
		||||
			{
 | 
			
		||||
				Notify (BAT0, 0x81) // Information Change
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		Else
 | 
			
		||||
		{
 | 
			
		||||
			IVBS ()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_BST, 0, NotSerialized)  // _BST: Battery Status
 | 
			
		||||
	{
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK)
 | 
			
		||||
		{
 | 
			
		||||
			UPBS ()
 | 
			
		||||
		}
 | 
			
		||||
		Else
 | 
			
		||||
		{
 | 
			
		||||
			IVBS ()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Return (PBST) /* \_SB_.BAT0.PBST */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/ec/purism/librem-ec/acpi/battery_thresholds.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/ec/purism/librem-ec/acpi/battery_thresholds.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
Field (ERAM, ByteAcc, Lock, Preserve)
 | 
			
		||||
{
 | 
			
		||||
	Offset (0xBC),
 | 
			
		||||
	BTL0,   8,      /* BAT0 charging start threshold */
 | 
			
		||||
	BTH0,   8,      /* BAT0 charging end threshold */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get battery charging threshold
 | 
			
		||||
 *
 | 
			
		||||
 * Arg0: 0: Start threshold
 | 
			
		||||
 *       1: Stop threshold
 | 
			
		||||
 */
 | 
			
		||||
Method (GBCT, 1, NotSerialized)
 | 
			
		||||
{
 | 
			
		||||
	If (Arg0 == 0) {
 | 
			
		||||
		Return (BTL0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	If (Arg0 == 1) {
 | 
			
		||||
		Return (BTH0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Return (0xFF)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set battery charging threshold
 | 
			
		||||
 *
 | 
			
		||||
 * Arg0: 0: Start threshold
 | 
			
		||||
 *       1: Stop threshold
 | 
			
		||||
 * Arg1: Percentage
 | 
			
		||||
 */
 | 
			
		||||
Method (SBCT, 2, NotSerialized)
 | 
			
		||||
{
 | 
			
		||||
	If (Arg1 <= 100) {
 | 
			
		||||
		If (Arg0 == 0) {
 | 
			
		||||
			BTL0 = Arg1
 | 
			
		||||
		}
 | 
			
		||||
		If (Arg0 == 1) {
 | 
			
		||||
			BTH0 = Arg1
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/ec/purism/librem-ec/acpi/buttons.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/ec/purism/librem-ec/acpi/buttons.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
Device (PWRB)
 | 
			
		||||
{
 | 
			
		||||
	Name (_HID, EisaId ("PNP0C0C"))
 | 
			
		||||
	Name (_PRW, Package () { EC_GPE_SWI, 3 })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Device (SLPB)
 | 
			
		||||
{
 | 
			
		||||
	Name (_HID, EisaId ("PNP0C0E"))
 | 
			
		||||
	Name (_PRW, Package () { EC_GPE_SWI, 3 })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										244
									
								
								src/ec/purism/librem-ec/acpi/ec.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								src/ec/purism/librem-ec/acpi/ec.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,244 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
Scope (\_SB) {
 | 
			
		||||
	#include "ac.asl"
 | 
			
		||||
	#include "battery.asl"
 | 
			
		||||
	#include "buttons.asl"
 | 
			
		||||
	#include "hid.asl"
 | 
			
		||||
	#include "lid.asl"
 | 
			
		||||
	#include "librem-ec.asl"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Device (\_SB.PCI0.LPCB.EC0)
 | 
			
		||||
{
 | 
			
		||||
	Name (_HID, EisaId ("PNP0C09") /* Embedded Controller Device */)  // _HID: Hardware ID
 | 
			
		||||
	Name (_GPE, EC_GPE_SCI)  // _GPE: General Purpose Events
 | 
			
		||||
	Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
 | 
			
		||||
	{
 | 
			
		||||
		IO (Decode16,
 | 
			
		||||
			0x0062,             // Range Minimum
 | 
			
		||||
			0x0062,             // Range Maximum
 | 
			
		||||
			0x00,               // Alignment
 | 
			
		||||
			0x01,               // Length
 | 
			
		||||
			)
 | 
			
		||||
		IO (Decode16,
 | 
			
		||||
			0x0066,             // Range Minimum
 | 
			
		||||
			0x0066,             // Range Maximum
 | 
			
		||||
			0x00,               // Alignment
 | 
			
		||||
			0x01,               // Length
 | 
			
		||||
			)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	#include "ec_ram.asl"
 | 
			
		||||
 | 
			
		||||
	Name (ECOK, Zero)
 | 
			
		||||
	Method (_REG, 2, Serialized)  // _REG: Region Availability
 | 
			
		||||
	{
 | 
			
		||||
		Debug = Concatenate("EC: _REG", Concatenate(ToHexString(Arg0), Concatenate(" ", ToHexString(Arg1))))
 | 
			
		||||
		If ((Arg0 == 0x03) && (Arg1 == One)) {
 | 
			
		||||
			// Enable hardware touchpad lock, airplane mode, and keyboard backlight keys
 | 
			
		||||
			ECOS = 1
 | 
			
		||||
 | 
			
		||||
			// Enable software display brightness keys
 | 
			
		||||
			WINF = 1
 | 
			
		||||
 | 
			
		||||
			// Set current AC state
 | 
			
		||||
			^^^^AC.ACFG = ADP
 | 
			
		||||
			// Update battery information and status
 | 
			
		||||
			^^^^BAT0.UPBI()
 | 
			
		||||
			^^^^BAT0.UPBS()
 | 
			
		||||
 | 
			
		||||
			// Notify of changes
 | 
			
		||||
			Notify(^^^^AC, Zero)
 | 
			
		||||
			Notify(^^^^BAT0, Zero)
 | 
			
		||||
 | 
			
		||||
			PNOT ()
 | 
			
		||||
 | 
			
		||||
			// EC is now available
 | 
			
		||||
			ECOK = Arg1
 | 
			
		||||
 | 
			
		||||
			// Reset System76 Device
 | 
			
		||||
			^^^^S76D.RSET()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Name (S3OS, Zero)
 | 
			
		||||
	Method (PTS, 1, Serialized) {
 | 
			
		||||
		Debug = Concatenate("EC: PTS: ", ToHexString(Arg0))
 | 
			
		||||
		If (ECOK) {
 | 
			
		||||
			// Save ECOS during sleep
 | 
			
		||||
			S3OS = ECOS
 | 
			
		||||
 | 
			
		||||
			// Clear wake cause
 | 
			
		||||
			WFNO = Zero
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (WAK, 1, Serialized) {
 | 
			
		||||
		Debug = Concatenate("EC: WAK: ", ToHexString(Arg0))
 | 
			
		||||
		If (ECOK) {
 | 
			
		||||
			// Restore ECOS after sleep
 | 
			
		||||
			ECOS = S3OS
 | 
			
		||||
 | 
			
		||||
			// Set current AC state
 | 
			
		||||
			^^^^AC.ACFG = ADP
 | 
			
		||||
 | 
			
		||||
			// Update battery information and status
 | 
			
		||||
			^^^^BAT0.UPBI()
 | 
			
		||||
			^^^^BAT0.UPBS()
 | 
			
		||||
 | 
			
		||||
			// Notify of changes
 | 
			
		||||
			Notify(^^^^AC, Zero)
 | 
			
		||||
			Notify(^^^^BAT0, Zero)
 | 
			
		||||
 | 
			
		||||
			// Reset System76 Device
 | 
			
		||||
			^^^^S76D.RSET()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q0A, 0, NotSerialized) // Touchpad Toggle
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Touchpad Toggle"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q0B, 0, NotSerialized) // Screen Toggle
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Screen Toggle"
 | 
			
		||||
#if CONFIG(EC_SYSTEM76_EC_OLED)
 | 
			
		||||
		Notify (^^^^S76D, 0x85)
 | 
			
		||||
#endif // CONFIG(EC_SYSTEM76_EC_OLED)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q0C, 0, NotSerialized)  // Mute
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Mute"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q0D, 0, NotSerialized) // Keyboard Backlight
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Keyboard Backlight"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q0E, 0, NotSerialized) // Volume Down
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Volume Down"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q0F, 0, NotSerialized) // Volume Up
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Volume Up"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q10, 0, NotSerialized) // Switch Video Mode
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Switch Video Mode"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q11, 0, NotSerialized) // Brightness Down
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Brightness Down"
 | 
			
		||||
		if (^^^^HIDD.HRDY) {
 | 
			
		||||
			^^^^HIDD.HPEM (20)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q12, 0, NotSerialized) // Brightness Up
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Brightness Up"
 | 
			
		||||
		if (^^^^HIDD.HRDY) {
 | 
			
		||||
			^^^^HIDD.HPEM (19)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q13, 0, NotSerialized) // Camera Toggle
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Camera Toggle"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q14, 0, NotSerialized) // Airplane Mode
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Airplane Mode"
 | 
			
		||||
		if (^^^^HIDD.HRDY) {
 | 
			
		||||
			^^^^HIDD.HPEM (8)
 | 
			
		||||
		}
 | 
			
		||||
		// TODO: hardware airplane mode
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q15, 0, NotSerialized) // Suspend Button
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Suspend Button"
 | 
			
		||||
		Notify (SLPB, 0x80)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q16, 0, NotSerialized) // AC Detect
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: AC Detect"
 | 
			
		||||
		^^^^AC.ACFG = ADP
 | 
			
		||||
		Notify (AC, 0x80) // Status Change
 | 
			
		||||
		If (BAT0)
 | 
			
		||||
		{
 | 
			
		||||
			Notify (^^^^BAT0, 0x81) // Information Change
 | 
			
		||||
			Notify (^^^^BAT0, 0x80) // Status Change
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q17, 0, NotSerialized)  // BAT0 Update
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: BAT0 Update (17)"
 | 
			
		||||
		Notify (^^^^BAT0, 0x81) // Information Change
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q19, 0, NotSerialized)  // BAT0 Update
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: BAT0 Update (19)"
 | 
			
		||||
		Notify (^^^^BAT0, 0x81) // Information Change
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q1B, 0, NotSerialized) // Lid Close
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Lid Close"
 | 
			
		||||
		Notify (LID0, 0x80)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q1C, 0, NotSerialized) // Thermal Trip
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Thermal Trip"
 | 
			
		||||
		/* TODO
 | 
			
		||||
		Notify (\_TZ.TZ0, 0x81) // Thermal Trip Point Change
 | 
			
		||||
		Notify (\_TZ.TZ0, 0x80) // Thermal Status Change
 | 
			
		||||
		*/
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q1D, 0, NotSerialized) // Power Button
 | 
			
		||||
	{
 | 
			
		||||
		Debug = "EC: Power Button"
 | 
			
		||||
		Notify (PWRB, 0x80)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_Q50, 0, NotSerialized) // Other Events
 | 
			
		||||
	{
 | 
			
		||||
		Local0 = OEM4
 | 
			
		||||
		If (Local0 == 0x8A) {
 | 
			
		||||
			Debug = "EC: White Keyboard Backlight"
 | 
			
		||||
			Notify (^^^^S76D, 0x80)
 | 
			
		||||
		} ElseIf (Local0 == 0x9F) {
 | 
			
		||||
			Debug = "EC: Color Keyboard Toggle"
 | 
			
		||||
			Notify (^^^^S76D, 0x81)
 | 
			
		||||
		} ElseIf (Local0 == 0x81) {
 | 
			
		||||
			Debug = "EC: Color Keyboard Down"
 | 
			
		||||
			Notify (^^^^S76D, 0x82)
 | 
			
		||||
		} ElseIf (Local0 == 0x82) {
 | 
			
		||||
			Debug = "EC: Color Keyboard Up"
 | 
			
		||||
			Notify (^^^^S76D, 0x83)
 | 
			
		||||
		} ElseIf (Local0 == 0x80) {
 | 
			
		||||
			Debug = "EC: Color Keyboard Color Change"
 | 
			
		||||
			Notify (^^^^S76D, 0x84)
 | 
			
		||||
		} Else {
 | 
			
		||||
			Debug = Concatenate("EC: Other: ", ToHexString(Local0))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#if CONFIG(EC_SYSTEM76_EC_BAT_THRESHOLDS)
 | 
			
		||||
	#include "battery_thresholds.asl"
 | 
			
		||||
	#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/ec/purism/librem-ec/acpi/ec_ram.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/ec/purism/librem-ec/acpi/ec_ram.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
OperationRegion (ERAM, EmbeddedControl, Zero, 0xFF)
 | 
			
		||||
Field (ERAM, ByteAcc, Lock, Preserve)
 | 
			
		||||
{
 | 
			
		||||
	Offset (0x03),
 | 
			
		||||
	LSTE, 1,	// Lid is open
 | 
			
		||||
	, 1,
 | 
			
		||||
	LWKE, 1,	// Lid wake
 | 
			
		||||
	, 5,
 | 
			
		||||
	Offset (0x07),
 | 
			
		||||
	TMP1, 8,	// CPU temperature
 | 
			
		||||
	Offset (0x10),
 | 
			
		||||
	ADP, 1,		// AC adapter connected
 | 
			
		||||
	, 1,
 | 
			
		||||
	BAT0, 1,	// Battery connected
 | 
			
		||||
	, 5,
 | 
			
		||||
	WFNO, 8,	// Wake cause (not implemented)
 | 
			
		||||
	Offset (0x16),
 | 
			
		||||
	BDC0, 32,	// Battery design capacity
 | 
			
		||||
	BFC0, 32,	// Battery full capacity
 | 
			
		||||
	Offset (0x22),
 | 
			
		||||
	BDV0, 32,	// Battery design voltage
 | 
			
		||||
	BST0, 32,	// Battery status
 | 
			
		||||
	BPR0, 32,	// Battery current
 | 
			
		||||
	BRC0, 32,	// Battery remaining capacity
 | 
			
		||||
	BPV0, 32,	// Battery voltage
 | 
			
		||||
	Offset (0x3A),
 | 
			
		||||
	BCW0, 32,
 | 
			
		||||
	BCL0, 32,
 | 
			
		||||
	Offset (0x68),
 | 
			
		||||
	ECOS, 8,	// Detected OS, 0 = no ACPI, 1 = ACPI but no driver, 2 = ACPI with driver
 | 
			
		||||
	Offset (0xC8),
 | 
			
		||||
	OEM1, 8,
 | 
			
		||||
	OEM2, 8,
 | 
			
		||||
	OEM3, 16,
 | 
			
		||||
	OEM4, 8,	// Extra SCI data
 | 
			
		||||
	Offset (0xCD),
 | 
			
		||||
	TMP2, 8,	// GPU temperature
 | 
			
		||||
	DUT1, 8,	// Fan 1 duty
 | 
			
		||||
	DUT2, 8,	// Fan 2 duty
 | 
			
		||||
	RPM1, 16,	// Fan 1 RPM
 | 
			
		||||
	RPM2, 16,	// Fan 2 RPM
 | 
			
		||||
	Offset (0xD9),
 | 
			
		||||
	AIRP, 8,	// Airplane mode LED
 | 
			
		||||
	WINF, 8,	// Enable ACPI brightness controls
 | 
			
		||||
	Offset (0xF8),
 | 
			
		||||
	FCMD, 8,
 | 
			
		||||
	FDAT, 8,
 | 
			
		||||
	FBUF, 8,
 | 
			
		||||
	FBF1, 8,
 | 
			
		||||
	FBF2, 8,
 | 
			
		||||
	FBF3, 8,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								src/ec/purism/librem-ec/acpi/hid.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/ec/purism/librem-ec/acpi/hid.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
Device (HIDD)
 | 
			
		||||
{
 | 
			
		||||
	Name (_HID, "INT33D5")
 | 
			
		||||
	Name (HBSY, Zero)
 | 
			
		||||
	Name (HIDX, Zero)
 | 
			
		||||
	Name (HRDY, Zero)
 | 
			
		||||
 | 
			
		||||
	Method (HDEM, 0, Serialized)
 | 
			
		||||
	{
 | 
			
		||||
		HBSY = Zero
 | 
			
		||||
		Return (HIDX)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (HDMM, 0, Serialized)
 | 
			
		||||
	{
 | 
			
		||||
		Return (Zero)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (HDSM, 1, Serialized)
 | 
			
		||||
	{
 | 
			
		||||
		HRDY = Arg0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (HPEM, 1, Serialized)
 | 
			
		||||
	{
 | 
			
		||||
		HBSY = One
 | 
			
		||||
		HIDX = Arg0
 | 
			
		||||
 | 
			
		||||
		Notify (HIDD, 0xC0)
 | 
			
		||||
		Local0 = Zero
 | 
			
		||||
		While ((Local0 < 0xFA) && HBSY)
 | 
			
		||||
		{
 | 
			
		||||
			Sleep (0x04)
 | 
			
		||||
			Local0++
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		If (HBSY == One)
 | 
			
		||||
		{
 | 
			
		||||
			HBSY = Zero
 | 
			
		||||
			HIDX = Zero
 | 
			
		||||
			Return (One)
 | 
			
		||||
		}
 | 
			
		||||
		Else
 | 
			
		||||
		{
 | 
			
		||||
			Return (Zero)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										162
									
								
								src/ec/purism/librem-ec/acpi/librem-ec.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/ec/purism/librem-ec/acpi/librem-ec.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
// Notifications:
 | 
			
		||||
//   0x80 - hardware backlight toggle
 | 
			
		||||
//   0x81 - backlight toggle
 | 
			
		||||
//   0x82 - backlight down
 | 
			
		||||
//   0x83 - backlight up
 | 
			
		||||
//   0x84 - backlight color change
 | 
			
		||||
//   0x85 - OLED screen toggle
 | 
			
		||||
Device (S76D) {
 | 
			
		||||
	Name (_HID, "17761776")
 | 
			
		||||
	Name (_UID, 0)
 | 
			
		||||
 | 
			
		||||
	Method (RSET, 0, Serialized) {
 | 
			
		||||
		Debug = "S76D: RSET"
 | 
			
		||||
		SAPL(0)
 | 
			
		||||
		SKBL(0)
 | 
			
		||||
#if CONFIG(EC_SYSTEM76_EC_COLOR_KEYBOARD)
 | 
			
		||||
			SKBC(0xFFFFFF)
 | 
			
		||||
#endif // CONFIG(EC_SYSTEM76_EC_COLOR_KEYBOARD)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (INIT, 0, Serialized) {
 | 
			
		||||
		Debug = "S76D: INIT"
 | 
			
		||||
		RSET()
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			// Set flags to use software control
 | 
			
		||||
			^^PCI0.LPCB.EC0.ECOS = 2
 | 
			
		||||
			Return (0)
 | 
			
		||||
		} Else {
 | 
			
		||||
			Return (1)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (FINI, 0, Serialized) {
 | 
			
		||||
		Debug = "S76D: FINI"
 | 
			
		||||
		RSET()
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			// Set flags to use hardware control
 | 
			
		||||
			^^PCI0.LPCB.EC0.ECOS = 1
 | 
			
		||||
			Return (0)
 | 
			
		||||
		} Else {
 | 
			
		||||
			Return (1)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get Airplane LED
 | 
			
		||||
	Method (GAPL, 0, Serialized) {
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			If (^^PCI0.LPCB.EC0.AIRP & 0x40) {
 | 
			
		||||
				Return (1)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		Return (0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set Airplane LED
 | 
			
		||||
	Method (SAPL, 1, Serialized) {
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			If (Arg0) {
 | 
			
		||||
				^^PCI0.LPCB.EC0.AIRP |= 0x40
 | 
			
		||||
			} Else {
 | 
			
		||||
				^^PCI0.LPCB.EC0.AIRP &= 0xBF
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if CONFIG(EC_SYSTEM76_EC_COLOR_KEYBOARD)
 | 
			
		||||
	// Set KB LED Brightness
 | 
			
		||||
	Method (SKBL, 1, Serialized) {
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			^^PCI0.LPCB.EC0.FDAT = 6
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBUF = Arg0
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBF1 = 0
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBF2 = Arg0
 | 
			
		||||
			^^PCI0.LPCB.EC0.FCMD = 0xCA
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set Keyboard Color
 | 
			
		||||
	Method (SKBC, 1, Serialized) {
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			^^PCI0.LPCB.EC0.FDAT = 0x3
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBUF = (Arg0 & 0xFF)
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBF1 = ((Arg0 >> 16) & 0xFF)
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBF2 = ((Arg0 >> 8) & 0xFF)
 | 
			
		||||
			^^PCI0.LPCB.EC0.FCMD = 0xCA
 | 
			
		||||
			Return (Arg0)
 | 
			
		||||
		} Else {
 | 
			
		||||
			Return (0)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#else // CONFIG(EC_SYSTEM76_EC_COLOR_KEYBOARD)
 | 
			
		||||
	// Get KB LED
 | 
			
		||||
	Method (GKBL, 0, Serialized) {
 | 
			
		||||
		Local0 = 0
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			^^PCI0.LPCB.EC0.FDAT = One
 | 
			
		||||
			^^PCI0.LPCB.EC0.FCMD = 0xCA
 | 
			
		||||
			Local0 = ^^PCI0.LPCB.EC0.FBUF
 | 
			
		||||
			^^PCI0.LPCB.EC0.FCMD = Zero
 | 
			
		||||
		}
 | 
			
		||||
		Return (Local0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set KB Led
 | 
			
		||||
	Method (SKBL, 1, Serialized) {
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			^^PCI0.LPCB.EC0.FDAT = Zero
 | 
			
		||||
			^^PCI0.LPCB.EC0.FBUF = Arg0
 | 
			
		||||
			^^PCI0.LPCB.EC0.FCMD = 0xCA
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif // CONFIG(EC_SYSTEM76_EC_COLOR_KEYBOARD)
 | 
			
		||||
 | 
			
		||||
	// Fan names
 | 
			
		||||
	Method (NFAN, 0, Serialized) {
 | 
			
		||||
		Return (Package() {
 | 
			
		||||
			"CPU fan",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get fan duty cycle and RPM as a single value
 | 
			
		||||
	Method (GFAN, 1, Serialized) {
 | 
			
		||||
		Local0 = 0
 | 
			
		||||
		Local1 = 0
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			If (Arg0 == 0) {
 | 
			
		||||
				Local0 = ^^PCI0.LPCB.EC0.DUT1
 | 
			
		||||
				Local1 = ^^PCI0.LPCB.EC0.RPM1
 | 
			
		||||
			} ElseIf (Arg0 == 1) {
 | 
			
		||||
				Local0 = ^^PCI0.LPCB.EC0.DUT2
 | 
			
		||||
				Local1 = ^^PCI0.LPCB.EC0.RPM2
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		If (Local1 != 0) {
 | 
			
		||||
			// 60 * (EC frequency / 120) / 2
 | 
			
		||||
			Local1 = 2156250 / Local1
 | 
			
		||||
		}
 | 
			
		||||
		Return ((Local1 << 8) | Local0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Temperature names
 | 
			
		||||
	Method (NTMP, 0, Serialized) {
 | 
			
		||||
		Return (Package() {
 | 
			
		||||
			"CPU temp",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get temperature
 | 
			
		||||
	Method (GTMP, 1, Serialized) {
 | 
			
		||||
		Local0 = 0;
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			If (Arg0 == 0) {
 | 
			
		||||
				Local0 = ^^PCI0.LPCB.EC0.TMP1
 | 
			
		||||
			} ElseIf (Arg0 == 1) {
 | 
			
		||||
				Local0 = ^^PCI0.LPCB.EC0.TMP2
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		Return (Local0)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/ec/purism/librem-ec/acpi/lid.asl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/ec/purism/librem-ec/acpi/lid.asl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
Device (LID0)
 | 
			
		||||
{
 | 
			
		||||
	Name (_HID, EisaId ("PNP0C0D"))
 | 
			
		||||
	Name (_PRW, Package () { EC_GPE_SWI, 3 })
 | 
			
		||||
 | 
			
		||||
	Method (_LID, 0, NotSerialized) {
 | 
			
		||||
		DEBUG = "LID: _LID"
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			Return (^^PCI0.LPCB.EC0.LSTE)
 | 
			
		||||
		} Else {
 | 
			
		||||
			Return (One)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Method (_PSW, 1, NotSerialized) {
 | 
			
		||||
		DEBUG = Concatenate("LID: _PSW: ", ToHexString(Arg0))
 | 
			
		||||
		If (^^PCI0.LPCB.EC0.ECOK) {
 | 
			
		||||
			^^PCI0.LPCB.EC0.LWKE = Arg0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								src/ec/purism/librem-ec/librem_ec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/ec/purism/librem-ec/librem_ec.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
#include <arch/io.h>
 | 
			
		||||
#include <console/system76_ec.h>
 | 
			
		||||
#include <timer.h>
 | 
			
		||||
 | 
			
		||||
// This is the command region for Librem EC firmware. It must be
 | 
			
		||||
// enabled for LPC in the mainboard.
 | 
			
		||||
#define LIBREM_EC_BASE 0x0E00
 | 
			
		||||
#define LIBREM_EC_SIZE 256
 | 
			
		||||
 | 
			
		||||
#define REG_CMD 0
 | 
			
		||||
#define REG_RESULT 1
 | 
			
		||||
 | 
			
		||||
// When command register is 0, command is complete
 | 
			
		||||
#define CMD_FINISHED 0
 | 
			
		||||
 | 
			
		||||
// Print command. Registers are unique for each command
 | 
			
		||||
#define CMD_PRINT 4
 | 
			
		||||
#define CMD_PRINT_REG_FLAGS 2
 | 
			
		||||
#define CMD_PRINT_REG_LEN 3
 | 
			
		||||
#define CMD_PRINT_REG_DATA 4
 | 
			
		||||
 | 
			
		||||
static inline uint8_t system76_ec_read(uint8_t addr)
 | 
			
		||||
{
 | 
			
		||||
	return inb(LIBREM_EC_BASE + (uint16_t)addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void system76_ec_write(uint8_t addr, uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
	outb(data, LIBREM_EC_BASE + (uint16_t)addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void system76_ec_init(void)
 | 
			
		||||
{
 | 
			
		||||
	// Clear entire command region
 | 
			
		||||
	for (int i = 0; i < LIBREM_EC_SIZE; i++)
 | 
			
		||||
		system76_ec_write((uint8_t)i, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void system76_ec_flush(void)
 | 
			
		||||
{
 | 
			
		||||
	system76_ec_write(REG_CMD, CMD_PRINT);
 | 
			
		||||
 | 
			
		||||
	// Wait for command completion, for up to 10 milliseconds, with a
 | 
			
		||||
	// test period of 1 microsecond
 | 
			
		||||
	wait_us(10000, system76_ec_read(REG_CMD) == CMD_FINISHED);
 | 
			
		||||
 | 
			
		||||
	system76_ec_write(CMD_PRINT_REG_LEN, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void system76_ec_print(uint8_t byte)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t len = system76_ec_read(CMD_PRINT_REG_LEN);
 | 
			
		||||
	system76_ec_write(CMD_PRINT_REG_DATA + len, byte);
 | 
			
		||||
	system76_ec_write(CMD_PRINT_REG_LEN, len + 1);
 | 
			
		||||
 | 
			
		||||
	// If we hit the end of the buffer, or were given a newline, flush
 | 
			
		||||
	if (byte == '\n' || len >= (LIBREM_EC_SIZE - CMD_PRINT_REG_DATA))
 | 
			
		||||
		system76_ec_flush();
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user