diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 9dc2764..2193516 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -72,6 +72,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; @@ -849,17 +851,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 void uw_charging_priority_write_state(void) @@ -960,17 +966,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; } static void uw_charging_profile_write_state(void) @@ -1156,10 +1166,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") @@ -1202,8 +1220,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; } diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 40dbc38..b000d17 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; @@ -124,21 +125,34 @@ 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\n"); + bflag = true; + } + + 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 - count = UW_EC_WAIT_CYCLES; - ec_read(UNIWILL_EC_REG_FLAGS, &tmp); - while (((tmp & (1 << UNIWILL_EC_BIT_DRDY)) == 0) && count != 0) { - msleep(1); + count = UW_EC_BUSY_WAIT_CYCLES; + ready = false; + while (!ready && count != 0) { + msleep(UW_EC_BUSY_WAIT_DELAY); ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + ready = (tmp & (1 << UNIWILL_EC_BIT_DRDY)) != 0; count -= 1; } @@ -158,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; @@ -167,23 +184,36 @@ 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"); + bflag = true; + } + + 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 - count = UW_EC_WAIT_CYCLES; - ec_read(UNIWILL_EC_REG_FLAGS, &tmp); - while (((tmp & (1 << UNIWILL_EC_BIT_DRDY)) == 0) && count != 0) { - msleep(1); + count = UW_EC_BUSY_WAIT_CYCLES; + ready = false; + while (!ready && count != 0) { + msleep(UW_EC_BUSY_WAIT_DELAY); ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + ready = (tmp & (1 << UNIWILL_EC_BIT_DRDY)) != 0; count -= 1; } @@ -201,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;