ec/starlabs/merlin: persist settings via EFI options
When STARLABS_ACPI_EFI_OPTION_SMI is enabled, store and restore trackpad and keyboard backlight state across S4/S5 using the EFI variable store SMI bridge instead of CMOS. Also make the EC init paths treat CMOS as an index mapping and prefer the option backend when CMOS options are not in use. Signed-off-by: Sean Rhodes <sean@starlabs.systems> Change-Id: Ia31ac0440eba1334be48030ce7fe03dc84193ac3 Reviewed-on: https://review.coreboot.org/c/coreboot/+/91304 Reviewed-by: Matt DeVillier <matt.devillier@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
3fa3818e41
commit
9dac2b9e53
3 changed files with 246 additions and 243 deletions
|
|
@ -1,8 +1,75 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#if CONFIG(STARLABS_ACPI_EFI_OPTION_SMI)
|
||||
Field (\DNVS, ByteAcc, NoLock, Preserve)
|
||||
{
|
||||
EOCM, 32, // EFI option command
|
||||
EOID, 32, // EFI option ID
|
||||
EOVL, 32, // EFI option value
|
||||
EORS, 32, // EFI option status
|
||||
}
|
||||
|
||||
Name (EOAP, 0xE2) // STARLABS_APMC_CMD_EFI_OPTION
|
||||
|
||||
Name (EOFL, 0x1) // STARLABS_EFIOPT_ID_FN_LOCK_STATE
|
||||
Name (EOTP, 0x2) // STARLABS_EFIOPT_ID_TRACKPAD_STATE
|
||||
Name (EOKB, 0x3) // STARLABS_EFIOPT_ID_KBL_BRIGHTNESS
|
||||
Name (EOKS, 0x4) // STARLABS_EFIOPT_ID_KBL_STATE
|
||||
|
||||
Mutex (EOMX, 0x00)
|
||||
|
||||
Method (EOGT, 1, Serialized)
|
||||
{
|
||||
If (Acquire (EOMX, 1000))
|
||||
{
|
||||
Return (0xFFFFFFFF)
|
||||
}
|
||||
|
||||
Store (0x01, EOCM)
|
||||
Store (Arg0, EOID)
|
||||
Store (0x00, EORS)
|
||||
Store (EOAP, \_SB.PCI0.LPCB.EC.SMB2)
|
||||
|
||||
Store (EOVL, Local0)
|
||||
Release (EOMX)
|
||||
Return (Local0)
|
||||
}
|
||||
|
||||
Method (EOSV, 2, Serialized)
|
||||
{
|
||||
If (Acquire (EOMX, 1000))
|
||||
{
|
||||
Return (0x01)
|
||||
}
|
||||
|
||||
Store (0x02, EOCM)
|
||||
Store (Arg0, EOID)
|
||||
Store (Arg1, EOVL)
|
||||
Store (0x00, EORS)
|
||||
Store (EOAP, \_SB.PCI0.LPCB.EC.SMB2)
|
||||
|
||||
Store (EORS, Local0)
|
||||
Release (EOMX)
|
||||
Return (Local0)
|
||||
}
|
||||
#endif
|
||||
|
||||
Method (RPTS, 1, Serialized)
|
||||
{
|
||||
|
||||
#if CONFIG(STARLABS_ACPI_EFI_OPTION_SMI)
|
||||
/* Store current EC settings in UEFI variable store */
|
||||
Store (\_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.TPLE)), Local0)
|
||||
If (Local0 == 0x11)
|
||||
{
|
||||
Store (0x00, Local0)
|
||||
}
|
||||
EOSV (EOTP, Local0)
|
||||
|
||||
EOSV (EOFL, \_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.FLKE)))
|
||||
EOSV (EOKS, \_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.KLSE)))
|
||||
EOSV (EOKB, \_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.KLBE)))
|
||||
#else
|
||||
/* Store current EC settings in CMOS */
|
||||
Switch (ToInteger (\_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.TPLE))))
|
||||
{
|
||||
|
|
@ -11,20 +78,19 @@ Method (RPTS, 1, Serialized)
|
|||
// 0x22 == Disabled == 0x01
|
||||
Case (0x00)
|
||||
{
|
||||
\_SB.PCI0.LPCB.TPLC = 0x00
|
||||
Store (0x00, \_SB.PCI0.LPCB.TPLC)
|
||||
}
|
||||
Case (0x11)
|
||||
{
|
||||
\_SB.PCI0.LPCB.TPLC = 0x00
|
||||
Store (0x00, \_SB.PCI0.LPCB.TPLC)
|
||||
}
|
||||
Case (0x22)
|
||||
{
|
||||
\_SB.PCI0.LPCB.TPLC = 0x01
|
||||
Store (0x01, \_SB.PCI0.LPCB.TPLC)
|
||||
}
|
||||
}
|
||||
|
||||
\_SB.PCI0.LPCB.FLKC =
|
||||
\_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.FLKE))
|
||||
Store (\_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.FLKE)), \_SB.PCI0.LPCB.FLKC)
|
||||
|
||||
Switch (ToInteger (\_SB.PCI0.LPCB.EC.ECRD (RefOf (\_SB.PCI0.LPCB.EC.KLSE))))
|
||||
{
|
||||
|
|
@ -32,11 +98,11 @@ Method (RPTS, 1, Serialized)
|
|||
// 0xdd == Enabled == 0x01
|
||||
Case (0x00)
|
||||
{
|
||||
\_SB.PCI0.LPCB.KLSC = 0x00
|
||||
Store (0x00, \_SB.PCI0.LPCB.KLSC)
|
||||
}
|
||||
Case (0xdd)
|
||||
{
|
||||
\_SB.PCI0.LPCB.KLSC = 0x01
|
||||
Store (0x01, \_SB.PCI0.LPCB.KLSC)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,27 +114,30 @@ Method (RPTS, 1, Serialized)
|
|||
// 0xaa == High == 0x03
|
||||
Case (0xdd)
|
||||
{
|
||||
\_SB.PCI0.LPCB.KLBC = 0x00
|
||||
Store (0x00, \_SB.PCI0.LPCB.KLBC)
|
||||
}
|
||||
Case (0xcc)
|
||||
{
|
||||
\_SB.PCI0.LPCB.KLBC = 0x01
|
||||
Store (0x01, \_SB.PCI0.LPCB.KLBC)
|
||||
}
|
||||
Case (0xbb)
|
||||
{
|
||||
\_SB.PCI0.LPCB.KLBC = 0x02
|
||||
Store (0x02, \_SB.PCI0.LPCB.KLBC)
|
||||
}
|
||||
Case (0xaa)
|
||||
{
|
||||
\_SB.PCI0.LPCB.KLBC = 0x03
|
||||
Store (0x03, \_SB.PCI0.LPCB.KLBC)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable ACPI support.
|
||||
* This should always be the last action before entering a sleep state.
|
||||
*/
|
||||
\_SB.PCI0.LPCB.EC.ECWR(0x00, RefOf(\_SB.PCI0.LPCB.EC.OSFG))
|
||||
|
||||
Return (Arg0)
|
||||
}
|
||||
|
||||
Method (RWAK, 1, Serialized)
|
||||
|
|
@ -79,6 +148,51 @@ Method (RWAK, 1, Serialized)
|
|||
*/
|
||||
\_SB.PCI0.LPCB.EC.ECWR(0x01, RefOf(\_SB.PCI0.LPCB.EC.OSFG))
|
||||
|
||||
#if CONFIG(STARLABS_ACPI_EFI_OPTION_SMI)
|
||||
/* Restore EC settings from UEFI variable store */
|
||||
Store (EOGT (EOTP), Local0)
|
||||
If (Local0 == 0x22)
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0x22, RefOf(\_SB.PCI0.LPCB.EC.TPLE))
|
||||
}
|
||||
Else
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0x00, RefOf(\_SB.PCI0.LPCB.EC.TPLE))
|
||||
}
|
||||
|
||||
\_SB.PCI0.LPCB.EC.ECWR (EOGT (EOFL), RefOf(\_SB.PCI0.LPCB.EC.FLKE))
|
||||
|
||||
Store (EOGT (EOKS), Local0)
|
||||
If (Local0 == 0xdd)
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0xdd, RefOf(\_SB.PCI0.LPCB.EC.KLSE))
|
||||
}
|
||||
Else
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0x00, RefOf(\_SB.PCI0.LPCB.EC.KLSE))
|
||||
}
|
||||
|
||||
Store (EOGT (EOKB), Local0)
|
||||
Switch (ToInteger (Local0))
|
||||
{
|
||||
Case (0xdd)
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0xdd, RefOf(\_SB.PCI0.LPCB.EC.KLBE))
|
||||
}
|
||||
Case (0xcc)
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0xcc, RefOf(\_SB.PCI0.LPCB.EC.KLBE))
|
||||
}
|
||||
Case (0xbb)
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0xbb, RefOf(\_SB.PCI0.LPCB.EC.KLBE))
|
||||
}
|
||||
Case (0xaa)
|
||||
{
|
||||
\_SB.PCI0.LPCB.EC.ECWR (0xaa, RefOf(\_SB.PCI0.LPCB.EC.KLBE))
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Restore EC settings from CMOS */
|
||||
Switch (ToInteger (\_SB.PCI0.LPCB.TPLC))
|
||||
{
|
||||
|
|
@ -134,4 +248,7 @@ Method (RWAK, 1, Serialized)
|
|||
\_SB.PCI0.LPCB.EC.ECWR (0xaa, RefOf(\_SB.PCI0.LPCB.EC.KLBE))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Return (Arg0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#include "option_table.h"
|
||||
#include "ec.h"
|
||||
|
||||
#define ITE_IT5570 0x5570
|
||||
#define ITE_IT8987 0x8987
|
||||
#define ITE_IT5570 0x5570
|
||||
#define ITE_IT8987 0x8987
|
||||
|
||||
uint16_t ec_get_version(void)
|
||||
{
|
||||
|
|
@ -25,20 +25,17 @@ static uint8_t get_cmos_value(uint32_t bit, uint32_t length)
|
|||
uint32_t byte, byte_bit;
|
||||
uint8_t uchar;
|
||||
|
||||
byte = bit / 8; // find the byte where the data starts
|
||||
byte = bit / 8; // find the byte where the data starts
|
||||
byte_bit = bit % 8; // find the bit in the byte where the data starts
|
||||
|
||||
uchar = cmos_read(byte); // load the byte
|
||||
uchar >>= byte_bit; // shift the bits to byte align
|
||||
uchar >>= byte_bit; // shift the bits to byte align
|
||||
// clear unspecified bits
|
||||
return uchar & ((1U << length) - 1);
|
||||
}
|
||||
|
||||
static uint8_t get_ec_value_from_option(const char *name,
|
||||
uint32_t fallback,
|
||||
const uint8_t *lut,
|
||||
size_t lut_size,
|
||||
uint32_t cmos_start_bit,
|
||||
static uint8_t get_ec_value_from_option(const char *name, uint32_t fallback, const uint8_t *lut,
|
||||
size_t lut_size, uint32_t cmos_start_bit,
|
||||
uint32_t cmos_length)
|
||||
{
|
||||
/*
|
||||
|
|
@ -69,8 +66,7 @@ static uint8_t get_ec_value_from_option(const char *name,
|
|||
|
||||
static uint16_t ec_get_chip_id(unsigned int port)
|
||||
{
|
||||
return (pnp_read_index(port, ITE_CHIPID1) << 8) |
|
||||
pnp_read_index(port, ITE_CHIPID2);
|
||||
return (pnp_read_index(port, ITE_CHIPID1) << 8) | pnp_read_index(port, ITE_CHIPID2);
|
||||
}
|
||||
|
||||
static void merlin_init(struct device *dev)
|
||||
|
|
@ -122,21 +118,11 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 30 Seconds
|
||||
*
|
||||
*/
|
||||
const uint8_t kbl_timeout[] = {
|
||||
SEC_30,
|
||||
MIN_1,
|
||||
MIN_3,
|
||||
MIN_5,
|
||||
NEVER
|
||||
};
|
||||
const uint8_t kbl_timeout[] = {SEC_30, MIN_1, MIN_3, MIN_5, NEVER};
|
||||
|
||||
ec_write(ECRAM_KBL_TIMEOUT,
|
||||
get_ec_value_from_option("kbl_timeout",
|
||||
SEC_30,
|
||||
kbl_timeout,
|
||||
ARRAY_SIZE(kbl_timeout),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("kbl_timeout", SEC_30, kbl_timeout,
|
||||
ARRAY_SIZE(kbl_timeout), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Fn Ctrl Reverse
|
||||
|
|
@ -147,18 +133,11 @@ static void merlin_init(struct device *dev)
|
|||
* Default: Disabled
|
||||
*
|
||||
*/
|
||||
const uint8_t fn_ctrl_swap[] = {
|
||||
FN_CTRL,
|
||||
CTRL_FN
|
||||
};
|
||||
const uint8_t fn_ctrl_swap[] = {FN_CTRL, CTRL_FN};
|
||||
|
||||
ec_write(ECRAM_FN_CTRL_REVERSE,
|
||||
get_ec_value_from_option("fn_ctrl_swap",
|
||||
FN_CTRL,
|
||||
fn_ctrl_swap,
|
||||
ARRAY_SIZE(fn_ctrl_swap),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("fn_ctrl_swap", FN_CTRL, fn_ctrl_swap,
|
||||
ARRAY_SIZE(fn_ctrl_swap), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Maximum Charge Level
|
||||
|
|
@ -169,20 +148,12 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 100%
|
||||
*
|
||||
*/
|
||||
const uint8_t max_charge[] = {
|
||||
CHARGE_100,
|
||||
CHARGE_80,
|
||||
CHARGE_60
|
||||
};
|
||||
const uint8_t max_charge[] = {CHARGE_100, CHARGE_80, CHARGE_60};
|
||||
|
||||
if (CONFIG(EC_STARLABS_MAX_CHARGE))
|
||||
ec_write(ECRAM_MAX_CHARGE,
|
||||
get_ec_value_from_option("max_charge",
|
||||
CHARGE_100,
|
||||
max_charge,
|
||||
ARRAY_SIZE(max_charge),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("max_charge", CHARGE_100, max_charge,
|
||||
ARRAY_SIZE(max_charge), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Fan Mode
|
||||
|
|
@ -193,21 +164,12 @@ static void merlin_init(struct device *dev)
|
|||
* Default: Normal
|
||||
*
|
||||
*/
|
||||
const uint8_t fan_mode[] = {
|
||||
FAN_NORMAL,
|
||||
FAN_AGGRESSIVE,
|
||||
FAN_QUIET,
|
||||
FAN_DISABLED
|
||||
};
|
||||
const uint8_t fan_mode[] = {FAN_NORMAL, FAN_AGGRESSIVE, FAN_QUIET, FAN_DISABLED};
|
||||
|
||||
if (CONFIG(EC_STARLABS_FAN))
|
||||
ec_write(ECRAM_FAN_MODE,
|
||||
get_ec_value_from_option("fan_mode",
|
||||
FAN_NORMAL,
|
||||
fan_mode,
|
||||
ARRAY_SIZE(fan_mode),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("fan_mode", FAN_NORMAL, fan_mode,
|
||||
ARRAY_SIZE(fan_mode), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Function Lock
|
||||
|
|
@ -219,18 +181,13 @@ static void merlin_init(struct device *dev)
|
|||
*
|
||||
*/
|
||||
#ifdef CMOS_VLEN_fn_lock_state
|
||||
const uint8_t fn_lock_state[] = {
|
||||
UNLOCKED,
|
||||
LOCKED
|
||||
};
|
||||
const uint8_t fn_lock_state[] = {UNLOCKED, LOCKED};
|
||||
|
||||
ec_write(ECRAM_FN_LOCK_STATE,
|
||||
get_ec_value_from_option("fn_lock_state",
|
||||
UNLOCKED,
|
||||
fn_lock_state,
|
||||
ARRAY_SIZE(fn_lock_state),
|
||||
CMOS_VSTART_fn_lock_state,
|
||||
CMOS_VLEN_fn_lock_state));
|
||||
get_ec_value_from_option(
|
||||
"fn_lock_state", UNLOCKED, fn_lock_state, ARRAY_SIZE(fn_lock_state),
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VSTART_fn_lock_state : UINT_MAX,
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VLEN_fn_lock_state : UINT_MAX));
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -243,18 +200,14 @@ static void merlin_init(struct device *dev)
|
|||
*
|
||||
*/
|
||||
#ifdef CMOS_VSTART_trackpad_state
|
||||
const uint8_t trackpad_state[] = {
|
||||
TRACKPAD_ENABLED,
|
||||
TRACKPAD_DISABLED
|
||||
};
|
||||
const uint8_t trackpad_state[] = {TRACKPAD_ENABLED, TRACKPAD_DISABLED};
|
||||
|
||||
ec_write(ECRAM_TRACKPAD_STATE,
|
||||
get_ec_value_from_option("trackpad_state",
|
||||
TRACKPAD_ENABLED,
|
||||
trackpad_state,
|
||||
ARRAY_SIZE(trackpad_state),
|
||||
CMOS_VSTART_trackpad_state,
|
||||
CMOS_VLEN_trackpad_state));
|
||||
get_ec_value_from_option(
|
||||
"trackpad_state", TRACKPAD_ENABLED, trackpad_state,
|
||||
ARRAY_SIZE(trackpad_state),
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VSTART_trackpad_state : UINT_MAX,
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VLEN_trackpad_state : UINT_MAX));
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -267,24 +220,19 @@ static void merlin_init(struct device *dev)
|
|||
*
|
||||
*/
|
||||
#ifdef CMOS_VSTART_kbl_brightness
|
||||
const uint8_t kbl_brightness[] = {
|
||||
KBL_ON,
|
||||
KBL_OFF,
|
||||
KBL_LOW,
|
||||
KBL_HIGH
|
||||
};
|
||||
const uint8_t kbl_brightness[] = {KBL_ON, KBL_OFF, KBL_LOW, KBL_HIGH};
|
||||
|
||||
ec_write(ECRAM_KBL_BRIGHTNESS,
|
||||
get_ec_value_from_option("kbl_brightness",
|
||||
CONFIG(EC_STARLABS_KBL_LEVELS) ? 2 : 0,
|
||||
kbl_brightness,
|
||||
ARRAY_SIZE(kbl_brightness),
|
||||
CMOS_VSTART_kbl_brightness,
|
||||
CMOS_VLEN_kbl_brightness));
|
||||
|
||||
get_ec_value_from_option(
|
||||
"kbl_brightness",
|
||||
CONFIG(USE_OPTION_TABLE) ?
|
||||
(CONFIG(EC_STARLABS_KBL_LEVELS) ? 2 : 0) :
|
||||
(CONFIG(EC_STARLABS_KBL_LEVELS) ? KBL_LOW : KBL_ON),
|
||||
kbl_brightness, ARRAY_SIZE(kbl_brightness),
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VSTART_kbl_brightness : UINT_MAX,
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VLEN_kbl_brightness : UINT_MAX));
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard Backlight State
|
||||
*
|
||||
|
|
@ -308,20 +256,13 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 0.5C
|
||||
*
|
||||
*/
|
||||
const uint8_t charging_speed[] = {
|
||||
SPEED_1_0C,
|
||||
SPEED_0_5C,
|
||||
SPEED_0_2C
|
||||
};
|
||||
const uint8_t charging_speed[] = {SPEED_1_0C, SPEED_0_5C, SPEED_0_2C};
|
||||
|
||||
if (CONFIG(EC_STARLABS_CHARGING_SPEED))
|
||||
ec_write(ECRAM_CHARGING_SPEED,
|
||||
get_ec_value_from_option("charging_speed",
|
||||
SPEED_0_5C,
|
||||
charging_speed,
|
||||
ARRAY_SIZE(charging_speed),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("charging_speed", SPEED_0_5C, charging_speed,
|
||||
ARRAY_SIZE(charging_speed), UINT_MAX,
|
||||
UINT_MAX));
|
||||
|
||||
/*
|
||||
* Lid Switch
|
||||
|
|
@ -332,20 +273,12 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 0
|
||||
*
|
||||
*/
|
||||
const uint8_t lid_switch[] = {
|
||||
SWITCH_NORMAL,
|
||||
SWITCH_SLEEP_ONLY,
|
||||
SWITCH_DISABLED
|
||||
};
|
||||
const uint8_t lid_switch[] = {SWITCH_NORMAL, SWITCH_SLEEP_ONLY, SWITCH_DISABLED};
|
||||
|
||||
if (CONFIG(EC_STARLABS_LID_SWITCH))
|
||||
ec_write(ECRAM_LID_SWITCH,
|
||||
get_ec_value_from_option("lid_switch",
|
||||
SWITCH_NORMAL,
|
||||
lid_switch,
|
||||
ARRAY_SIZE(lid_switch),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("lid_switch", SWITCH_NORMAL, lid_switch,
|
||||
ARRAY_SIZE(lid_switch), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Power LED Brightness
|
||||
|
|
@ -356,20 +289,13 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 0
|
||||
*
|
||||
*/
|
||||
const uint8_t led_brightness[] = {
|
||||
LED_NORMAL,
|
||||
LED_REDUCED,
|
||||
LED_OFF
|
||||
};
|
||||
const uint8_t led_brightness[] = {LED_NORMAL, LED_REDUCED, LED_OFF};
|
||||
|
||||
if (CONFIG(EC_STARLABS_POWER_LED))
|
||||
ec_write(ECRAM_POWER_LED,
|
||||
get_ec_value_from_option("power_led",
|
||||
LED_NORMAL,
|
||||
led_brightness,
|
||||
ARRAY_SIZE(led_brightness),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("power_led", LED_NORMAL, led_brightness,
|
||||
ARRAY_SIZE(led_brightness), UINT_MAX,
|
||||
UINT_MAX));
|
||||
|
||||
/*
|
||||
* Charge LED Brightness
|
||||
|
|
@ -383,18 +309,15 @@ static void merlin_init(struct device *dev)
|
|||
|
||||
if (CONFIG(EC_STARLABS_CHARGE_LED))
|
||||
ec_write(ECRAM_CHARGE_LED,
|
||||
get_ec_value_from_option("charge_led",
|
||||
LED_NORMAL,
|
||||
led_brightness,
|
||||
ARRAY_SIZE(led_brightness),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("charge_led", LED_NORMAL, led_brightness,
|
||||
ARRAY_SIZE(led_brightness), UINT_MAX,
|
||||
UINT_MAX));
|
||||
}
|
||||
|
||||
static struct device_operations ops = {
|
||||
.init = merlin_init,
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
.init = merlin_init,
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
};
|
||||
|
||||
static struct pnp_info pnp_dev_info[] = {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "option_table.h"
|
||||
#include "ec.h"
|
||||
|
||||
|
||||
uint16_t ec_get_version(void)
|
||||
{
|
||||
return (ec_read(ECRAM_MAJOR_VERSION) << 8) | ec_read(ECRAM_MINOR_VERSION);
|
||||
|
|
@ -23,32 +22,43 @@ static uint8_t get_cmos_value(uint32_t bit, uint32_t length)
|
|||
uint32_t byte, byte_bit;
|
||||
uint8_t uchar;
|
||||
|
||||
byte = bit / 8; // find the byte where the data starts
|
||||
byte = bit / 8; // find the byte where the data starts
|
||||
byte_bit = bit % 8; // find the bit in the byte where the data starts
|
||||
|
||||
uchar = cmos_read(byte); // load the byte
|
||||
uchar >>= byte_bit; // shift the bits to byte align
|
||||
uchar >>= byte_bit; // shift the bits to byte align
|
||||
// clear unspecified bits
|
||||
return uchar & ((1U << length) - 1);
|
||||
}
|
||||
|
||||
static uint8_t get_ec_value_from_option(const char *name,
|
||||
uint32_t fallback,
|
||||
const uint8_t *lut,
|
||||
size_t lut_size,
|
||||
uint32_t cmos_start_bit,
|
||||
static uint8_t get_ec_value_from_option(const char *name, uint32_t fallback, const uint8_t *lut,
|
||||
size_t lut_size, uint32_t cmos_start_bit,
|
||||
uint32_t cmos_length)
|
||||
{
|
||||
unsigned int index;
|
||||
/*
|
||||
* CMOS-backed EC options store an index (see cmos.layout and ACPI
|
||||
* RPTS/RWAK mappings), while the option backend stores the EC's raw
|
||||
* values (e.g. 0xaa/0xbb/0xdd).
|
||||
*/
|
||||
if (cmos_start_bit != UINT_MAX) {
|
||||
unsigned int index = get_cmos_value(cmos_start_bit, cmos_length);
|
||||
|
||||
if (cmos_start_bit != UINT_MAX)
|
||||
index = get_cmos_value(cmos_start_bit, cmos_length);
|
||||
else
|
||||
index = get_uint_option(name, fallback);
|
||||
if (index >= lut_size)
|
||||
index = fallback;
|
||||
if (index >= lut_size)
|
||||
index = 0;
|
||||
|
||||
if (index >= lut_size)
|
||||
index = fallback;
|
||||
return lut[index];
|
||||
return lut[index];
|
||||
}
|
||||
|
||||
const uint8_t value = get_uint_option(name, fallback);
|
||||
|
||||
/* Check if the value exists in the LUT array */
|
||||
for (size_t i = 0; i < lut_size; i++)
|
||||
if (lut[i] == value)
|
||||
return value;
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static uint16_t ec_get_chip_id(unsigned int port)
|
||||
|
|
@ -77,7 +87,7 @@ static void merlin_init(struct device *dev)
|
|||
|
||||
if (chip_id != NUVOTON_CHIPID_VAL) {
|
||||
printk(BIOS_ERR, "NUVOTON: Expected chip ID 0x%04x, but got 0x%04x instead.\n",
|
||||
NUVOTON_CHIPID_VAL, chip_id);
|
||||
NUVOTON_CHIPID_VAL, chip_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -103,21 +113,11 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 30 Seconds
|
||||
*
|
||||
*/
|
||||
const uint8_t kbl_timeout[] = {
|
||||
SEC_30,
|
||||
MIN_1,
|
||||
MIN_3,
|
||||
MIN_5,
|
||||
NEVER
|
||||
};
|
||||
const uint8_t kbl_timeout[] = {SEC_30, MIN_1, MIN_3, MIN_5, NEVER};
|
||||
|
||||
ec_write(ECRAM_KBL_TIMEOUT,
|
||||
get_ec_value_from_option("kbl_timeout",
|
||||
0,
|
||||
kbl_timeout,
|
||||
ARRAY_SIZE(kbl_timeout),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("kbl_timeout", 0, kbl_timeout,
|
||||
ARRAY_SIZE(kbl_timeout), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Fn Ctrl Reverse
|
||||
|
|
@ -128,18 +128,11 @@ static void merlin_init(struct device *dev)
|
|||
* Default: Disabled
|
||||
*
|
||||
*/
|
||||
const uint8_t fn_ctrl_swap[] = {
|
||||
FN_CTRL,
|
||||
CTRL_FN
|
||||
};
|
||||
const uint8_t fn_ctrl_swap[] = {FN_CTRL, CTRL_FN};
|
||||
|
||||
ec_write(ECRAM_FN_CTRL_REVERSE,
|
||||
get_ec_value_from_option("fn_ctrl_swap",
|
||||
0,
|
||||
fn_ctrl_swap,
|
||||
ARRAY_SIZE(fn_ctrl_swap),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("fn_ctrl_swap", 0, fn_ctrl_swap,
|
||||
ARRAY_SIZE(fn_ctrl_swap), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Maximum Charge Level
|
||||
|
|
@ -150,20 +143,12 @@ static void merlin_init(struct device *dev)
|
|||
* Default: 100%
|
||||
*
|
||||
*/
|
||||
const uint8_t max_charge[] = {
|
||||
CHARGE_100,
|
||||
CHARGE_80,
|
||||
CHARGE_60
|
||||
};
|
||||
const uint8_t max_charge[] = {CHARGE_100, CHARGE_80, CHARGE_60};
|
||||
|
||||
if (CONFIG(EC_STARLABS_MAX_CHARGE))
|
||||
ec_write(ECRAM_MAX_CHARGE,
|
||||
get_ec_value_from_option("max_charge",
|
||||
0,
|
||||
max_charge,
|
||||
ARRAY_SIZE(max_charge),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("max_charge", 0, max_charge,
|
||||
ARRAY_SIZE(max_charge), UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Fan Mode
|
||||
|
|
@ -174,20 +159,12 @@ static void merlin_init(struct device *dev)
|
|||
* Default: Normal
|
||||
*
|
||||
*/
|
||||
const uint8_t fan_mode[] = {
|
||||
FAN_NORMAL,
|
||||
FAN_AGGRESSIVE,
|
||||
FAN_QUIET
|
||||
};
|
||||
const uint8_t fan_mode[] = {FAN_NORMAL, FAN_AGGRESSIVE, FAN_QUIET};
|
||||
|
||||
if (CONFIG(EC_STARLABS_FAN))
|
||||
ec_write(ECRAM_FAN_MODE,
|
||||
get_ec_value_from_option("fan_mode",
|
||||
0,
|
||||
fan_mode,
|
||||
ARRAY_SIZE(fan_mode),
|
||||
UINT_MAX,
|
||||
UINT_MAX));
|
||||
get_ec_value_from_option("fan_mode", 0, fan_mode, ARRAY_SIZE(fan_mode),
|
||||
UINT_MAX, UINT_MAX));
|
||||
|
||||
/*
|
||||
* Function Lock
|
||||
|
|
@ -199,18 +176,13 @@ static void merlin_init(struct device *dev)
|
|||
*
|
||||
*/
|
||||
#ifdef CMOS_VLEN_fn_lock_state
|
||||
const uint8_t fn_lock_state[] = {
|
||||
UNLOCKED,
|
||||
LOCKED
|
||||
};
|
||||
const uint8_t fn_lock_state[] = {UNLOCKED, LOCKED};
|
||||
|
||||
ec_write(ECRAM_FN_LOCK_STATE,
|
||||
get_ec_value_from_option("fn_lock_state",
|
||||
1,
|
||||
fn_lock_state,
|
||||
ARRAY_SIZE(fn_lock_state),
|
||||
CMOS_VSTART_fn_lock_state,
|
||||
CMOS_VLEN_fn_lock_state));
|
||||
get_ec_value_from_option(
|
||||
"fn_lock_state", 1, fn_lock_state, ARRAY_SIZE(fn_lock_state),
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VSTART_fn_lock_state : UINT_MAX,
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VLEN_fn_lock_state : UINT_MAX));
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -223,18 +195,13 @@ static void merlin_init(struct device *dev)
|
|||
*
|
||||
*/
|
||||
#ifdef CMOS_VSTART_trackpad_state
|
||||
const uint8_t trackpad_state[] = {
|
||||
TRACKPAD_ENABLED,
|
||||
TRACKPAD_DISABLED
|
||||
};
|
||||
const uint8_t trackpad_state[] = {TRACKPAD_ENABLED, TRACKPAD_DISABLED};
|
||||
|
||||
ec_write(ECRAM_TRACKPAD_STATE,
|
||||
get_ec_value_from_option("trackpad_state",
|
||||
0,
|
||||
trackpad_state,
|
||||
ARRAY_SIZE(trackpad_state),
|
||||
CMOS_VSTART_trackpad_state,
|
||||
CMOS_VLEN_trackpad_state));
|
||||
get_ec_value_from_option(
|
||||
"trackpad_state", 0, trackpad_state, ARRAY_SIZE(trackpad_state),
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VSTART_trackpad_state : UINT_MAX,
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VLEN_trackpad_state : UINT_MAX));
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -247,24 +214,20 @@ static void merlin_init(struct device *dev)
|
|||
*
|
||||
*/
|
||||
#ifdef CMOS_VSTART_kbl_brightness
|
||||
const uint8_t kbl_brightness[] = {
|
||||
KBL_ON,
|
||||
KBL_OFF,
|
||||
KBL_LOW,
|
||||
KBL_HIGH
|
||||
};
|
||||
const uint8_t kbl_brightness[] = {KBL_ON, KBL_OFF, KBL_LOW, KBL_HIGH};
|
||||
|
||||
ec_write(ECRAM_KBL_BRIGHTNESS,
|
||||
get_ec_value_from_option("kbl_brightness",
|
||||
CONFIG(EC_STARLABS_KBL_LEVELS) ? 2 : 0,
|
||||
kbl_brightness,
|
||||
ARRAY_SIZE(kbl_brightness),
|
||||
CMOS_VSTART_kbl_brightness,
|
||||
CMOS_VLEN_kbl_brightness));
|
||||
get_ec_value_from_option(
|
||||
"kbl_brightness",
|
||||
CONFIG(USE_OPTION_TABLE) ?
|
||||
(CONFIG(EC_STARLABS_KBL_LEVELS) ? 2 : 0) :
|
||||
(CONFIG(EC_STARLABS_KBL_LEVELS) ? KBL_LOW : KBL_ON),
|
||||
kbl_brightness, ARRAY_SIZE(kbl_brightness),
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VSTART_kbl_brightness : UINT_MAX,
|
||||
CONFIG(USE_OPTION_TABLE) ? CMOS_VLEN_kbl_brightness : UINT_MAX));
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard Backlight State
|
||||
*
|
||||
|
|
@ -281,9 +244,9 @@ static void merlin_init(struct device *dev)
|
|||
}
|
||||
|
||||
static struct device_operations ops = {
|
||||
.init = merlin_init,
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
.init = merlin_init,
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
};
|
||||
|
||||
static struct pnp_info pnp_dev_info[] = {
|
||||
|
|
@ -299,7 +262,7 @@ static struct pnp_info pnp_dev_info[] = {
|
|||
{ NULL, NUVOTON_PM1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
|
||||
/* Power Management I/F Channel 2 (PMC2) */
|
||||
{ NULL, NUVOTON_PM2, PNP_IO0 | PNP_IO1 | PNP_IO2 | PNP_IRQ0, 0x07fc,
|
||||
0x07fc, 0xfff0, },
|
||||
0x07fc, 0xfff0, },
|
||||
/* Power Management I/F Channel 3 (PMC3) */
|
||||
{ NULL, NUVOTON_PM3, PNP_IO0 | PNP_IO1 | PNP_IRQ0, 0x07ff, 0x07ff, },
|
||||
/* Extended Shared Memory (ESHM) */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue