Skip to content

Commit 2be519d

Browse files
Wer-Wolfij-intel
authored andcommitted
platform/x86: uniwill-laptop: Mark FN lock status as being volatile
It turns out that the FN lock status can be changed by the underlying hardware when the user presses a special key combination. Mark the associated register as volatile to prevent regmap from caching said value. Also add the necessary suspend/resume handling. Fixes: d050479 ("platform/x86: Add Uniwill laptop driver") Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://patch.msgid.link/20260218005101.73680-4-W_Armin@gmx.de Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
1 parent 67e7eb4 commit 2be519d

1 file changed

Lines changed: 35 additions & 4 deletions

File tree

drivers/platform/x86/uniwill/uniwill-acpi.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ struct uniwill_data {
330330
struct acpi_battery_hook hook;
331331
unsigned int last_charge_ctrl;
332332
struct mutex battery_lock; /* Protects the list of currently registered batteries */
333+
unsigned int last_status;
333334
unsigned int last_switch_status;
334335
struct mutex super_key_lock; /* Protects the toggling of the super key lock state */
335336
struct list_head batteries;
@@ -580,6 +581,7 @@ static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
580581
case EC_ADDR_SECOND_FAN_RPM_1:
581582
case EC_ADDR_SECOND_FAN_RPM_2:
582583
case EC_ADDR_BAT_ALERT:
584+
case EC_ADDR_BIOS_OEM:
583585
case EC_ADDR_PWM_1:
584586
case EC_ADDR_PWM_2:
585587
case EC_ADDR_TRIGGER:
@@ -1508,7 +1510,19 @@ static void uniwill_shutdown(struct platform_device *pdev)
15081510
regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
15091511
}
15101512

1511-
static int uniwill_suspend_keyboard(struct uniwill_data *data)
1513+
static int uniwill_suspend_fn_lock(struct uniwill_data *data)
1514+
{
1515+
if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
1516+
return 0;
1517+
1518+
/*
1519+
* The EC_ADDR_BIOS_OEM is marked as volatile, so we have to restore it
1520+
* ourselves.
1521+
*/
1522+
return regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &data->last_status);
1523+
}
1524+
1525+
static int uniwill_suspend_super_key(struct uniwill_data *data)
15121526
{
15131527
if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
15141528
return 0;
@@ -1547,7 +1561,11 @@ static int uniwill_suspend(struct device *dev)
15471561
struct uniwill_data *data = dev_get_drvdata(dev);
15481562
int ret;
15491563

1550-
ret = uniwill_suspend_keyboard(data);
1564+
ret = uniwill_suspend_fn_lock(data);
1565+
if (ret < 0)
1566+
return ret;
1567+
1568+
ret = uniwill_suspend_super_key(data);
15511569
if (ret < 0)
15521570
return ret;
15531571

@@ -1565,7 +1583,16 @@ static int uniwill_suspend(struct device *dev)
15651583
return 0;
15661584
}
15671585

1568-
static int uniwill_resume_keyboard(struct uniwill_data *data)
1586+
static int uniwill_resume_fn_lock(struct uniwill_data *data)
1587+
{
1588+
if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
1589+
return 0;
1590+
1591+
return regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS,
1592+
data->last_status);
1593+
}
1594+
1595+
static int uniwill_resume_super_key(struct uniwill_data *data)
15691596
{
15701597
unsigned int value;
15711598
int ret;
@@ -1613,7 +1640,11 @@ static int uniwill_resume(struct device *dev)
16131640
if (ret < 0)
16141641
return ret;
16151642

1616-
ret = uniwill_resume_keyboard(data);
1643+
ret = uniwill_resume_fn_lock(data);
1644+
if (ret < 0)
1645+
return ret;
1646+
1647+
ret = uniwill_resume_super_key(data);
16171648
if (ret < 0)
16181649
return ret;
16191650

0 commit comments

Comments
 (0)