From 2a3c59b06f9a1e4060484f4d38607e000dab28b2 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 13 Feb 2023 11:57:54 +0100 Subject: [PATCH 1/9] uniwill_wmi: Add missing BFLG impl. according to original wmi methods --- src/uniwill_wmi.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 40dbc38..e7ea578 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -127,10 +127,21 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re mutex_lock(&uniwill_ec_lock); + ec_read(UNIWILL_EC_REG_FLAGS, &flags); + if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { + output->dword = 0xfefefefe; + mutex_unlock(&uniwill_ec_lock); + return -EBUSY; + } + + flags |= (1 << UNIWILL_EC_BIT_BFLG); + ec_write(UNIWILL_EC_REG_FLAGS, flags); + ec_write(UNIWILL_EC_REG_LDAT, addr_low); ec_write(UNIWILL_EC_REG_HDAT, addr_high); - flags = (0 << UNIWILL_EC_BIT_DRDY) | (1 << UNIWILL_EC_BIT_RFLG); + flags &= ~(1 << UNIWILL_EC_BIT_DRDY); + flags |= (1 << UNIWILL_EC_BIT_RFLG); ec_write(UNIWILL_EC_REG_FLAGS, flags); // Wait for ready flag @@ -170,12 +181,23 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da mutex_lock(&uniwill_ec_lock); + ec_read(UNIWILL_EC_REG_FLAGS, &flags); + if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { + output->dword = 0xfefefefe; + mutex_unlock(&uniwill_ec_lock); + return -EBUSY; + } + + flags |= (1 << UNIWILL_EC_BIT_BFLG); + ec_write(UNIWILL_EC_REG_FLAGS, flags); + ec_write(UNIWILL_EC_REG_LDAT, addr_low); ec_write(UNIWILL_EC_REG_HDAT, addr_high); ec_write(UNIWILL_EC_REG_CMDL, data_low); ec_write(UNIWILL_EC_REG_CMDH, data_high); - flags = (0 << UNIWILL_EC_BIT_DRDY) | (1 << UNIWILL_EC_BIT_WFLG); + flags &= ~(1 << UNIWILL_EC_BIT_DRDY); + flags |= (1 << UNIWILL_EC_BIT_WFLG); ec_write(UNIWILL_EC_REG_FLAGS, flags); // Wait for ready flag From 230acf394012a34d8c4a967194523e9bbfc5b19d Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 13 Feb 2023 12:13:04 +0100 Subject: [PATCH 2/9] uniwill_wmi: Restructure busy wait loop to include delay before read --- src/uniwill_wmi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index e7ea578..dd5c05d 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -124,6 +124,7 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re { u32 result; u8 tmp, count, flags; + bool ready; mutex_lock(&uniwill_ec_lock); @@ -146,10 +147,11 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re // Wait for ready flag count = UW_EC_WAIT_CYCLES; - ec_read(UNIWILL_EC_REG_FLAGS, &tmp); - while (((tmp & (1 << UNIWILL_EC_BIT_DRDY)) == 0) && count != 0) { + ready = false; + while (!ready && count != 0) { msleep(1); ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + ready = (tmp & (1 << UNIWILL_EC_BIT_DRDY)) != 0; count -= 1; } @@ -178,6 +180,7 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da { u32 result = 0; u8 tmp, count, flags; + bool ready; mutex_lock(&uniwill_ec_lock); @@ -202,10 +205,11 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da // Wait for ready flag count = UW_EC_WAIT_CYCLES; - ec_read(UNIWILL_EC_REG_FLAGS, &tmp); - while (((tmp & (1 << UNIWILL_EC_BIT_DRDY)) == 0) && count != 0) { + ready = false; + while (!ready && count != 0) { msleep(1); ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + ready = (tmp & (1 << UNIWILL_EC_BIT_DRDY)) != 0; count -= 1; } From 44848558a0e5d77381cf516f8ed0d5c225c10055 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 13 Feb 2023 12:28:47 +0100 Subject: [PATCH 3/9] uniwill_wmi: Tweak busy wait delay --- src/uniwill_wmi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index dd5c05d..1c5fe65 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -36,7 +36,8 @@ #define UNIWILL_EC_BIT_CFLG 3 #define UNIWILL_EC_BIT_DRDY 7 -#define UW_EC_WAIT_CYCLES 0x50 +#define UW_EC_BUSY_WAIT_CYCLES 30 +#define UW_EC_BUSY_WAIT_DELAY 15 static bool uniwill_ec_direct = true; @@ -146,10 +147,10 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re ec_write(UNIWILL_EC_REG_FLAGS, flags); // Wait for ready flag - count = UW_EC_WAIT_CYCLES; + count = UW_EC_BUSY_WAIT_CYCLES; ready = false; while (!ready && count != 0) { - msleep(1); + msleep(UW_EC_BUSY_WAIT_DELAY); ec_read(UNIWILL_EC_REG_FLAGS, &tmp); ready = (tmp & (1 << UNIWILL_EC_BIT_DRDY)) != 0; count -= 1; @@ -204,10 +205,10 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da ec_write(UNIWILL_EC_REG_FLAGS, flags); // Wait for ready flag - count = UW_EC_WAIT_CYCLES; + count = UW_EC_BUSY_WAIT_CYCLES; ready = false; while (!ready && count != 0) { - msleep(1); + msleep(UW_EC_BUSY_WAIT_DELAY); ec_read(UNIWILL_EC_REG_FLAGS, &tmp); ready = (tmp & (1 << UNIWILL_EC_BIT_DRDY)) != 0; count -= 1; From d231df67ff398011992ebfe449e919e19a0bd923 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 13 Feb 2023 15:32:38 +0100 Subject: [PATCH 4/9] Avoid feature identification if already done --- src/tuxedo_io/tuxedo_io.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 07e0f02..4ed06d0 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -48,6 +48,7 @@ static u32 id_check_clevo; static u32 id_check_uniwill; static struct uniwill_device_features_t *uw_feats; +static bool uw_feats_loaded = false; /** * strstr version of dmi_match @@ -154,9 +155,10 @@ void uw_id_tdp(void) static u32 uniwill_identify(void) { u32 result = uniwill_get_active_interface_id(NULL) == 0 ? 1 : 0; - if (result) { + if (result && !uw_feats_loaded) { uw_feats = uniwill_get_device_features(); uw_id_tdp(); + uw_feats_loaded = true; } return result; } From 852cba45232cfb3e3f12991b3524f32d0633096a Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 14 Feb 2023 11:03:58 +0100 Subject: [PATCH 5/9] uniwill_wmi: Zero BFLG according to wmi impl. Note: weird behaviour but BFLG is always zeroed --- src/uniwill_wmi.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 1c5fe65..ac820d9 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -131,8 +131,14 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re ec_read(UNIWILL_EC_REG_FLAGS, &flags); if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { - output->dword = 0xfefefefe; + pr_debug("read: BFLG set\n"); + + // Note: weird behaviour but BFLG is always zeroed + flags &= ~(1 << UNIWILL_EC_BIT_BFLG); + ec_write(UNIWILL_EC_REG_FLAGS, flags); + mutex_unlock(&uniwill_ec_lock); + output->dword = 0xfefefefe; return -EBUSY; } @@ -187,8 +193,14 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da ec_read(UNIWILL_EC_REG_FLAGS, &flags); if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { - output->dword = 0xfefefefe; + pr_debug("write: BFLG set\n"); + + // Note: weird behaviour but BFLG is always zeroed + flags &= ~(1 << UNIWILL_EC_BIT_BFLG); + ec_write(UNIWILL_EC_REG_FLAGS, flags); + mutex_unlock(&uniwill_ec_lock); + output->dword = 0xfefefefe; return -EBUSY; } From a14e6a02984ed8d2cadf313ca8fbd5003b5b70d0 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 16 Feb 2023 17:14:33 +0100 Subject: [PATCH 6/9] Fix return values of charging id funcs --- src/uniwill_keyboard.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index c17b5cb..d86e21c 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -808,17 +808,21 @@ static int uw_has_charging_priority(bool *status) || dmi_match(DMI_PRODUCT_NAME, "A60 MUV") ; - if (not_supported_device) - return false; + if (not_supported_device) { + *status = false; + return 0; + } result = uniwill_read_ec_ram(0x0742, &data); + if (result != 0) + return -EIO; if (data & (1 << 5)) *status = true; else *status = false; - return result; + return 0; } static bool uw_charging_profile_loaded = false; @@ -865,17 +869,21 @@ static int uw_has_charging_profile(bool *status) || dmi_match(DMI_PRODUCT_NAME, "A60 MUV") ; - if (not_supported_device) - return false; + if (not_supported_device) { + *status = false; + return 0; + } result = uniwill_read_ec_ram(0x078e, &data); + if (result != 0) + return -EIO; if (data & (1 << 3)) *status = true; else *status = false; - return result; + return 0; } struct char_to_u8_t { From 67e6d3caceb16fa8891e0cb881da94507ffde199 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 16 Feb 2023 18:14:28 +0100 Subject: [PATCH 7/9] Move feats loaded check to inside get features method - Extend with checks on each IO for success --- src/tuxedo_io/tuxedo_io.c | 4 +--- src/uniwill_keyboard.h | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 4ed06d0..07e0f02 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -48,7 +48,6 @@ static u32 id_check_clevo; static u32 id_check_uniwill; static struct uniwill_device_features_t *uw_feats; -static bool uw_feats_loaded = false; /** * strstr version of dmi_match @@ -155,10 +154,9 @@ void uw_id_tdp(void) static u32 uniwill_identify(void) { u32 result = uniwill_get_active_interface_id(NULL) == 0 ? 1 : 0; - if (result && !uw_feats_loaded) { + if (result) { uw_feats = uniwill_get_device_features(); uw_id_tdp(); - uw_feats_loaded = true; } return result; } diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index d86e21c..b465ff4 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -69,6 +69,8 @@ struct kbd_led_state_uw_t { struct uniwill_device_features_t uniwill_device_features; +static bool uw_feats_loaded = false; + static u8 uniwill_kbd_bl_enable_state_on_start; static bool uniwill_kbd_bl_type_rgb_single_color = true; @@ -1086,10 +1088,18 @@ struct uniwill_device_features_t *uniwill_get_device_features(void) { struct uniwill_device_features_t *uw_feats = &uniwill_device_features; u32 status; + bool feats_loaded; + + if (uw_feats_loaded) + return uw_feats; + + feats_loaded = true; status = uniwill_read_ec_ram(0x0740, &uw_feats->model); - if (status != 0) + if (status != 0) { uw_feats->model = 0; + feats_loaded = false; + } uw_feats->uniwill_profile_v1_two_profs = false || dmi_match(DMI_BOARD_NAME, "PF5PU1G") @@ -1132,8 +1142,17 @@ struct uniwill_device_features_t *uniwill_get_device_features(void) uw_feats->uniwill_profile_v1_two_profs || uw_feats->uniwill_profile_v1_three_profs; - uw_has_charging_priority(&uw_feats->uniwill_has_charging_prio); - uw_has_charging_profile(&uw_feats->uniwill_has_charging_profile); + if (uw_has_charging_priority(&uw_feats->uniwill_has_charging_prio) != 0) + feats_loaded = false; + if (uw_has_charging_profile(&uw_feats->uniwill_has_charging_profile) != 0) + feats_loaded = false; + + if (feats_loaded) + pr_debug("feats loaded\n"); + else + pr_debug("feats not yet loaded\n"); + + uw_feats_loaded = feats_loaded; return uw_feats; } From a2a7cbb8da767e714a8370f5f75cdf20289244be Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 16 Feb 2023 18:15:47 +0100 Subject: [PATCH 8/9] Add address to BFLG debug output --- src/uniwill_wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index ac820d9..9650e59 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -131,7 +131,7 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re ec_read(UNIWILL_EC_REG_FLAGS, &flags); if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { - pr_debug("read: BFLG set\n"); + pr_debug("read: BFLG set (high: 0x%0#2x, low: %0#2x)\n", addr_high, addr_low); // Note: weird behaviour but BFLG is always zeroed flags &= ~(1 << UNIWILL_EC_BIT_BFLG); From 555a5a0424136e694680d31d91b670674d96ea3a Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 17 Feb 2023 11:49:19 +0100 Subject: [PATCH 9/9] Leave out BFLG but leave in debug for observing --- src/uniwill_wmi.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 9650e59..b000d17 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -126,20 +126,14 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re u32 result; u8 tmp, count, flags; bool ready; + bool bflag = false; mutex_lock(&uniwill_ec_lock); ec_read(UNIWILL_EC_REG_FLAGS, &flags); if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { - pr_debug("read: BFLG set (high: 0x%0#2x, low: %0#2x)\n", addr_high, addr_low); - - // Note: weird behaviour but BFLG is always zeroed - flags &= ~(1 << UNIWILL_EC_BIT_BFLG); - ec_write(UNIWILL_EC_REG_FLAGS, flags); - - mutex_unlock(&uniwill_ec_lock); - output->dword = 0xfefefefe; - return -EBUSY; + pr_debug("read: BFLG set\n"); + bflag = true; } flags |= (1 << UNIWILL_EC_BIT_BFLG); @@ -178,6 +172,9 @@ static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_re mutex_unlock(&uniwill_ec_lock); + if (bflag) + pr_debug("addr: 0x%02x%02x value: %0#4x result: %d\n", addr_high, addr_low, output->bytes.data_low, result); + // pr_debug("addr: 0x%02x%02x value: %0#4x result: %d\n", addr_high, addr_low, output->bytes.data_low, result); return result; @@ -188,20 +185,14 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da u32 result = 0; u8 tmp, count, flags; bool ready; + bool bflag = false; mutex_lock(&uniwill_ec_lock); ec_read(UNIWILL_EC_REG_FLAGS, &flags); if ((flags & (1 << UNIWILL_EC_BIT_BFLG)) > 0) { pr_debug("write: BFLG set\n"); - - // Note: weird behaviour but BFLG is always zeroed - flags &= ~(1 << UNIWILL_EC_BIT_BFLG); - ec_write(UNIWILL_EC_REG_FLAGS, flags); - - mutex_unlock(&uniwill_ec_lock); - output->dword = 0xfefefefe; - return -EBUSY; + bflag = true; } flags |= (1 << UNIWILL_EC_BIT_BFLG); @@ -240,6 +231,9 @@ static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 da ec_write(UNIWILL_EC_REG_FLAGS, 0x00); + if (bflag) + pr_debug("addr: 0x%02x%02x value: %0#4x result: %d\n", addr_high, addr_low, data_low, result); + mutex_unlock(&uniwill_ec_lock); return result;