summaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-08-11 09:23:08 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-08-11 09:23:08 -0700
commit2ae08b36c06ea8df73a79f6b80ff7964e006e9e3 (patch)
tree5efdf98f3e7189f7256e97114ed6f3bcad1a7c8b /drivers/input/keyboard
parent21f9c8a13bb2a0c24d9c6b86bc0896542a28c197 (diff)
parent8bb5e7f4dcd9b9ef22a3ea25c9066a8a968f12dd (diff)
downloadlinux-stable-2ae08b36c06ea8df73a79f6b80ff7964e006e9e3.tar.gz
linux-stable-2ae08b36c06ea8df73a79f6b80ff7964e006e9e3.tar.bz2
linux-stable-2ae08b36c06ea8df73a79f6b80ff7964e006e9e3.zip
Merge tag 'input-for-v5.20-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - changes to input core to properly queue synthetic events (such as autorepeat) and to release multitouch contacts when an input device is inhibited or suspended - reworked quirk handling in i8042 driver that consolidates multiple DMI tables into one and adds several quirks for TUXEDO line of laptops - update to mt6779 keypad to better reflect organization of the hardware - changes to mtk-pmic-keys driver preparing it to handle more variants - facelift of adp5588-keys driver - improvements to iqs7222 driver - adjustments to various DT binding documents for input devices - other assorted driver fixes. * tag 'input-for-v5.20-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (54 commits) Input: adc-joystick - fix ordering in adc_joystick_probe() dt-bindings: input: ariel-pwrbutton: use spi-peripheral-props.yaml Input: deactivate MT slots when inhibiting or suspending devices Input: properly queue synthetic events dt-bindings: input: iqs7222: Use central 'linux,code' definition Input: i8042 - add dritek quirk for Acer Aspire One AO532 dt-bindings: input: gpio-keys: accept also interrupt-extended dt-bindings: input: gpio-keys: reference input.yaml and document properties dt-bindings: input: gpio-keys: enforce node names to match all properties dt-bindings: input: Convert adc-keys to DT schema dt-bindings: input: Centralize 'linux,input-type' definition dt-bindings: input: Use common 'linux,keycodes' definition dt-bindings: input: Centralize 'linux,code' definition dt-bindings: input: Increase maximum keycode value to 0x2ff Input: mt6779-keypad - implement row/column selection Input: mt6779-keypad - match hardware matrix organization Input: i8042 - add additional TUXEDO devices to i8042 quirk tables Input: goodix - switch use of acpi_gpio_get_*_resource() APIs Input: i8042 - add TUXEDO devices to i8042 quirk tables Input: i8042 - add debug output for quirks ...
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/adp5588-keys.c206
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c89
-rw-r--r--drivers/input/keyboard/mt6779-keypad.c18
-rw-r--r--drivers/input/keyboard/mtk-pmic-keys.c98
-rw-r--r--drivers/input/keyboard/omap4-keypad.c26
6 files changed, 227 insertions, 212 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4ea79db8f134..a20ee693b22b 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -795,7 +795,7 @@ config KEYBOARD_MT6779
config KEYBOARD_MTK_PMIC
tristate "MediaTek PMIC keys support"
- depends on MFD_MT6397
+ depends on MFD_MT6397 || COMPILE_TEST
help
Say Y here if you want to use the pmic keys (powerkey/homekey).
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 1592da4de336..1a1a05d7cd42 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -8,17 +8,19 @@
* Copyright (C) 2008-2010 Analog Devices Inc.
*/
-#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/workqueue.h>
-#include <linux/errno.h>
-#include <linux/pm.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/gpio/driver.h>
+#include <linux/pm.h>
#include <linux/slab.h>
+#include <linux/timekeeping.h>
#include <linux/platform_data/adp5588.h>
@@ -36,18 +38,18 @@
* asserted.
*/
#define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4)
+#define WA_DELAYED_READOUT_TIME 25
struct adp5588_kpad {
struct i2c_client *client;
struct input_dev *input;
- struct delayed_work work;
+ ktime_t irq_time;
unsigned long delay;
unsigned short keycode[ADP5588_KEYMAPSIZE];
const struct adp5588_gpi_map *gpimap;
unsigned short gpimapsize;
#ifdef CONFIG_GPIOLIB
unsigned char gpiomap[ADP5588_MAXGPIO];
- bool export_gpio;
struct gpio_chip gc;
struct mutex gpio_lock; /* Protect cached dir, dat_out */
u8 dat_out[3];
@@ -179,6 +181,21 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
return n_unused;
}
+static void adp5588_gpio_do_teardown(void *_kpad)
+{
+ struct adp5588_kpad *kpad = _kpad;
+ struct device *dev = &kpad->client->dev;
+ const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
+ const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
+ int error;
+
+ error = gpio_data->teardown(kpad->client,
+ kpad->gc.base, kpad->gc.ngpio,
+ gpio_data->context);
+ if (error)
+ dev_warn(&kpad->client->dev, "teardown failed %d\n", error);
+}
+
static int adp5588_gpio_add(struct adp5588_kpad *kpad)
{
struct device *dev = &kpad->client->dev;
@@ -195,8 +212,6 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
return 0;
}
- kpad->export_gpio = true;
-
kpad->gc.direction_input = adp5588_gpio_direction_input;
kpad->gc.direction_output = adp5588_gpio_direction_output;
kpad->gc.get = adp5588_gpio_get_value;
@@ -210,9 +225,9 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
mutex_init(&kpad->gpio_lock);
- error = gpiochip_add_data(&kpad->gc, kpad);
+ error = devm_gpiochip_add_data(dev, &kpad->gc, kpad);
if (error) {
- dev_err(dev, "gpiochip_add failed, err: %d\n", error);
+ dev_err(dev, "gpiochip_add failed: %d\n", error);
return error;
}
@@ -227,41 +242,24 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
kpad->gc.base, kpad->gc.ngpio,
gpio_data->context);
if (error)
- dev_warn(dev, "setup failed, %d\n", error);
+ dev_warn(dev, "setup failed: %d\n", error);
}
- return 0;
-}
-
-static void adp5588_gpio_remove(struct adp5588_kpad *kpad)
-{
- struct device *dev = &kpad->client->dev;
- const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
- const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
- int error;
-
- if (!kpad->export_gpio)
- return;
-
if (gpio_data->teardown) {
- error = gpio_data->teardown(kpad->client,
- kpad->gc.base, kpad->gc.ngpio,
- gpio_data->context);
+ error = devm_add_action(dev, adp5588_gpio_do_teardown, kpad);
if (error)
- dev_warn(dev, "teardown failed %d\n", error);
+ dev_warn(dev, "failed to schedule teardown: %d\n",
+ error);
}
- gpiochip_remove(&kpad->gc);
+ return 0;
}
+
#else
static inline int adp5588_gpio_add(struct adp5588_kpad *kpad)
{
return 0;
}
-
-static inline void adp5588_gpio_remove(struct adp5588_kpad *kpad)
-{
-}
#endif
static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
@@ -289,13 +287,36 @@ static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
}
}
-static void adp5588_work(struct work_struct *work)
+static irqreturn_t adp5588_hard_irq(int irq, void *handle)
{
- struct adp5588_kpad *kpad = container_of(work,
- struct adp5588_kpad, work.work);
+ struct adp5588_kpad *kpad = handle;
+
+ kpad->irq_time = ktime_get();
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t adp5588_thread_irq(int irq, void *handle)
+{
+ struct adp5588_kpad *kpad = handle;
struct i2c_client *client = kpad->client;
+ ktime_t target_time, now;
+ unsigned long delay;
int status, ev_cnt;
+ /*
+ * Readout needs to wait for at least 25ms after the notification
+ * for REVID < 4.
+ */
+ if (kpad->delay) {
+ target_time = ktime_add_ms(kpad->irq_time, kpad->delay);
+ now = ktime_get();
+ if (ktime_before(now, target_time)) {
+ delay = ktime_to_us(ktime_sub(target_time, now));
+ usleep_range(delay, delay + 1000);
+ }
+ }
+
status = adp5588_read(client, INT_STAT);
if (status & ADP5588_OVR_FLOW_INT) /* Unlikely and should never happen */
@@ -308,20 +329,8 @@ static void adp5588_work(struct work_struct *work)
input_sync(kpad->input);
}
}
- adp5588_write(client, INT_STAT, status); /* Status is W1C */
-}
-
-static irqreturn_t adp5588_irq(int irq, void *handle)
-{
- struct adp5588_kpad *kpad = handle;
- /*
- * use keventd context to read the event fifo registers
- * Schedule readout at least 25ms after notification for
- * REVID < 4
- */
-
- schedule_delayed_work(&kpad->work, kpad->delay);
+ adp5588_write(client, INT_STAT, status); /* Status is W1C */
return IRQ_HANDLED;
}
@@ -496,30 +505,27 @@ static int adp5588_probe(struct i2c_client *client,
return -EINVAL;
}
- kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
- input = input_allocate_device();
- if (!kpad || !input) {
- error = -ENOMEM;
- goto err_free_mem;
- }
+ kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL);
+ if (!kpad)
+ return -ENOMEM;
+
+ input = devm_input_allocate_device(&client->dev);
+ if (!input)
+ return -ENOMEM;
kpad->client = client;
kpad->input = input;
- INIT_DELAYED_WORK(&kpad->work, adp5588_work);
ret = adp5588_read(client, DEV_ID);
- if (ret < 0) {
- error = ret;
- goto err_free_mem;
- }
+ if (ret < 0)
+ return ret;
revid = (u8) ret & ADP5588_DEVICE_ID_MASK;
if (WA_DELAYED_READOUT_REVID(revid))
- kpad->delay = msecs_to_jiffies(30);
+ kpad->delay = msecs_to_jiffies(WA_DELAYED_READOUT_TIME);
input->name = client->name;
input->phys = "adp5588-keys/input0";
- input->dev.parent = &client->dev;
input_set_drvdata(input, kpad);
@@ -556,95 +562,63 @@ static int adp5588_probe(struct i2c_client *client,
error = input_register_device(input);
if (error) {
- dev_err(&client->dev, "unable to register input device\n");
- goto err_free_mem;
+ dev_err(&client->dev, "unable to register input device: %d\n",
+ error);
+ return error;
}
- error = request_irq(client->irq, adp5588_irq,
- IRQF_TRIGGER_FALLING,
- client->dev.driver->name, kpad);
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ adp5588_hard_irq, adp5588_thread_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->dev.driver->name, kpad);
if (error) {
- dev_err(&client->dev, "irq %d busy?\n", client->irq);
- goto err_unreg_dev;
+ dev_err(&client->dev, "failed to request irq %d: %d\n",
+ client->irq, error);
+ return error;
}
error = adp5588_setup(client);
if (error)
- goto err_free_irq;
+ return error;
if (kpad->gpimapsize)
adp5588_report_switch_state(kpad);
error = adp5588_gpio_add(kpad);
if (error)
- goto err_free_irq;
-
- device_init_wakeup(&client->dev, 1);
- i2c_set_clientdata(client, kpad);
+ return error;
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
return 0;
-
- err_free_irq:
- free_irq(client->irq, kpad);
- cancel_delayed_work_sync(&kpad->work);
- err_unreg_dev:
- input_unregister_device(input);
- input = NULL;
- err_free_mem:
- input_free_device(input);
- kfree(kpad);
-
- return error;
}
static int adp5588_remove(struct i2c_client *client)
{
- struct adp5588_kpad *kpad = i2c_get_clientdata(client);
-
adp5588_write(client, CFG, 0);
- free_irq(client->irq, kpad);
- cancel_delayed_work_sync(&kpad->work);
- input_unregister_device(kpad->input);
- adp5588_gpio_remove(kpad);
- kfree(kpad);
+ /* all resources will be freed by devm */
return 0;
}
-#ifdef CONFIG_PM
-static int adp5588_suspend(struct device *dev)
+static int __maybe_unused adp5588_suspend(struct device *dev)
{
- struct adp5588_kpad *kpad = dev_get_drvdata(dev);
- struct i2c_client *client = kpad->client;
+ struct i2c_client *client = to_i2c_client(dev);
disable_irq(client->irq);
- cancel_delayed_work_sync(&kpad->work);
-
- if (device_may_wakeup(&client->dev))
- enable_irq_wake(client->irq);
return 0;
}
-static int adp5588_resume(struct device *dev)
+static int __maybe_unused adp5588_resume(struct device *dev)
{
- struct adp5588_kpad *kpad = dev_get_drvdata(dev);
- struct i2c_client *client = kpad->client;
-
- if (device_may_wakeup(&client->dev))
- disable_irq_wake(client->irq);
+ struct i2c_client *client = to_i2c_client(dev);
enable_irq(client->irq);
return 0;
}
-static const struct dev_pm_ops adp5588_dev_pm_ops = {
- .suspend = adp5588_suspend,
- .resume = adp5588_resume,
-};
-#endif
+static SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);
static const struct i2c_device_id adp5588_id[] = {
{ "adp5588-keys", 0 },
@@ -656,9 +630,7 @@ MODULE_DEVICE_TABLE(i2c, adp5588_id);
static struct i2c_driver adp5588_driver = {
.driver = {
.name = KBUILD_MODNAME,
-#ifdef CONFIG_PM
.pm = &adp5588_dev_pm_ops,
-#endif
},
.probe = adp5588_probe,
.remove = adp5588_remove,
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index cc73a149da28..c14136b733a9 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -12,6 +12,7 @@
// expensive.
#include <linux/module.h>
+#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/input.h>
@@ -518,6 +519,50 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev,
return 0;
}
+static void cros_ec_keyb_parse_vivaldi_physmap(struct cros_ec_keyb *ckdev)
+{
+ u32 *physmap = ckdev->vdata.function_row_physmap;
+ unsigned int row, col, scancode;
+ int n_physmap;
+ int error;
+ int i;
+
+ n_physmap = device_property_count_u32(ckdev->dev,
+ "function-row-physmap");
+ if (n_physmap <= 0)
+ return;
+
+ if (n_physmap >= VIVALDI_MAX_FUNCTION_ROW_KEYS) {
+ dev_warn(ckdev->dev,
+ "only up to %d top row keys is supported (%d specified)\n",
+ VIVALDI_MAX_FUNCTION_ROW_KEYS, n_physmap);
+ n_physmap = VIVALDI_MAX_FUNCTION_ROW_KEYS;
+ }
+
+ error = device_property_read_u32_array(ckdev->dev,
+ "function-row-physmap",
+ physmap, n_physmap);
+ if (error) {
+ dev_warn(ckdev->dev,
+ "failed to parse function-row-physmap property: %d\n",
+ error);
+ return;
+ }
+
+ /*
+ * Convert (in place) from row/column encoding to matrix "scancode"
+ * used by the driver.
+ */
+ for (i = 0; i < n_physmap; i++) {
+ row = KEY_ROW(physmap[i]);
+ col = KEY_COL(physmap[i]);
+ scancode = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
+ physmap[i] = scancode;
+ }
+
+ ckdev->vdata.num_function_row_keys = n_physmap;
+}
+
/**
* cros_ec_keyb_register_matrix - Register matrix keys
*
@@ -534,11 +579,6 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
struct input_dev *idev;
const char *phys;
int err;
- struct property *prop;
- const __be32 *p;
- u32 *physmap;
- u32 key_pos;
- unsigned int row, col, scancode, n_physmap;
err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols);
if (err)
@@ -573,7 +613,7 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
idev->id.product = 0;
idev->dev.parent = dev;
- ckdev->ghost_filter = of_property_read_bool(dev->of_node,
+ ckdev->ghost_filter = device_property_read_bool(dev,
"google,needs-ghost-filter");
err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols,
@@ -589,22 +629,7 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
input_set_drvdata(idev, ckdev);
ckdev->idev = idev;
cros_ec_keyb_compute_valid_keys(ckdev);
-
- physmap = ckdev->vdata.function_row_physmap;
- n_physmap = 0;
- of_property_for_each_u32(dev->of_node, "function-row-physmap",
- prop, p, key_pos) {
- if (n_physmap == VIVALDI_MAX_FUNCTION_ROW_KEYS) {
- dev_warn(dev, "Only support up to %d top row keys\n",
- VIVALDI_MAX_FUNCTION_ROW_KEYS);
- break;
- }
- row = KEY_ROW(key_pos);
- col = KEY_COL(key_pos);
- scancode = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
- physmap[n_physmap++] = scancode;
- }
- ckdev->vdata.num_function_row_keys = n_physmap;
+ cros_ec_keyb_parse_vivaldi_physmap(ckdev);
err = input_register_device(ckdev->idev);
if (err) {
@@ -653,14 +678,19 @@ static const struct attribute_group cros_ec_keyb_attr_group = {
static int cros_ec_keyb_probe(struct platform_device *pdev)
{
- struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+ struct cros_ec_device *ec;
struct device *dev = &pdev->dev;
struct cros_ec_keyb *ckdev;
bool buttons_switches_only = device_get_match_data(dev);
int err;
- if (!dev->of_node)
- return -ENODEV;
+ /*
+ * If the parent ec device has not been probed yet, defer the probe of
+ * this keyboard/button driver until later.
+ */
+ ec = dev_get_drvdata(pdev->dev.parent);
+ if (!ec)
+ return -EPROBE_DEFER;
ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL);
if (!ckdev)
@@ -713,6 +743,14 @@ static int cros_ec_keyb_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cros_ec_keyb_acpi_match[] = {
+ { "GOOG0007", true },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_keyb_acpi_match);
+#endif
+
#ifdef CONFIG_OF
static const struct of_device_id cros_ec_keyb_of_match[] = {
{ .compatible = "google,cros-ec-keyb" },
@@ -730,6 +768,7 @@ static struct platform_driver cros_ec_keyb_driver = {
.driver = {
.name = "cros-ec-keyb",
.of_match_table = of_match_ptr(cros_ec_keyb_of_match),
+ .acpi_match_table = ACPI_PTR(cros_ec_keyb_acpi_match),
.pm = &cros_ec_keyb_pm_ops,
},
};
diff --git a/drivers/input/keyboard/mt6779-keypad.c b/drivers/input/keyboard/mt6779-keypad.c
index 2e7c9187c10f..bf447bf598fb 100644
--- a/drivers/input/keyboard/mt6779-keypad.c
+++ b/drivers/input/keyboard/mt6779-keypad.c
@@ -17,6 +17,11 @@
#define MTK_KPD_DEBOUNCE 0x0018
#define MTK_KPD_DEBOUNCE_MASK GENMASK(13, 0)
#define MTK_KPD_DEBOUNCE_MAX_MS 256
+#define MTK_KPD_SEL 0x0020
+#define MTK_KPD_SEL_COL GENMASK(15, 10)
+#define MTK_KPD_SEL_ROW GENMASK(9, 4)
+#define MTK_KPD_SEL_COLMASK(c) GENMASK((c) + 9, 10)
+#define MTK_KPD_SEL_ROWMASK(r) GENMASK((r) + 3, 4)
#define MTK_KPD_NUM_MEMS 5
#define MTK_KPD_NUM_BITS 136 /* 4*32+8 MEM5 only use 8 BITS */
@@ -42,7 +47,7 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id)
const unsigned short *keycode = keypad->input_dev->keycode;
DECLARE_BITMAP(new_state, MTK_KPD_NUM_BITS);
DECLARE_BITMAP(change, MTK_KPD_NUM_BITS);
- unsigned int bit_nr;
+ unsigned int bit_nr, key;
unsigned int row, col;
unsigned int scancode;
unsigned int row_shift = get_count_order(keypad->n_cols);
@@ -61,8 +66,10 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id)
if (bit_nr % 32 >= 16)
continue;
- row = bit_nr / 32;
- col = bit_nr % 32;
+ key = bit_nr / 32 * 16 + bit_nr % 32;
+ row = key / 9;
+ col = key % 9;
+
scancode = MATRIX_SCAN_CODE(row, col, row_shift);
/* 1: not pressed, 0: pressed */
pressed = !test_bit(bit_nr, new_state);
@@ -159,6 +166,11 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev)
regmap_write(keypad->regmap, MTK_KPD_DEBOUNCE,
(debounce * (1 << 5)) & MTK_KPD_DEBOUNCE_MASK);
+ regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_ROW,
+ MTK_KPD_SEL_ROWMASK(keypad->n_rows));
+ regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_COL,
+ MTK_KPD_SEL_COLMASK(keypad->n_cols));
+
keypad->clk = devm_clk_get(&pdev->dev, "kpd");
if (IS_ERR(keypad->clk))
return PTR_ERR(keypad->clk);
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index c31ab4368388..6404081253ea 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -18,17 +18,9 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
-#define MTK_PMIC_PWRKEY_RST_EN_MASK 0x1
-#define MTK_PMIC_PWRKEY_RST_EN_SHIFT 6
-#define MTK_PMIC_HOMEKEY_RST_EN_MASK 0x1
-#define MTK_PMIC_HOMEKEY_RST_EN_SHIFT 5
-#define MTK_PMIC_RST_DU_MASK 0x3
-#define MTK_PMIC_RST_DU_SHIFT 8
-
-#define MTK_PMIC_PWRKEY_RST \
- (MTK_PMIC_PWRKEY_RST_EN_MASK << MTK_PMIC_PWRKEY_RST_EN_SHIFT)
-#define MTK_PMIC_HOMEKEY_RST \
- (MTK_PMIC_HOMEKEY_RST_EN_MASK << MTK_PMIC_HOMEKEY_RST_EN_SHIFT)
+#define MTK_PMIC_RST_DU_MASK GENMASK(9, 8)
+#define MTK_PMIC_PWRKEY_RST BIT(6)
+#define MTK_PMIC_HOMEKEY_RST BIT(5)
#define MTK_PMIC_PWRKEY_INDEX 0
#define MTK_PMIC_HOMEKEY_INDEX 1
@@ -39,50 +31,58 @@ struct mtk_pmic_keys_regs {
u32 deb_mask;
u32 intsel_reg;
u32 intsel_mask;
+ u32 rst_en_mask;
};
#define MTK_PMIC_KEYS_REGS(_deb_reg, _deb_mask, \
- _intsel_reg, _intsel_mask) \
+ _intsel_reg, _intsel_mask, _rst_mask) \
{ \
.deb_reg = _deb_reg, \
.deb_mask = _deb_mask, \
.intsel_reg = _intsel_reg, \
.intsel_mask = _intsel_mask, \
+ .rst_en_mask = _rst_mask, \
}
struct mtk_pmic_regs {
const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT];
u32 pmic_rst_reg;
+ u32 rst_lprst_mask; /* Long-press reset timeout bitmask */
};
static const struct mtk_pmic_regs mt6397_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6397_CHRSTATUS,
- 0x8, MT6397_INT_RSV, 0x10),
+ 0x8, MT6397_INT_RSV, 0x10, MTK_PMIC_PWRKEY_RST),
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6397_OCSTATUS2,
- 0x10, MT6397_INT_RSV, 0x8),
+ 0x10, MT6397_INT_RSV, 0x8, MTK_PMIC_HOMEKEY_RST),
.pmic_rst_reg = MT6397_TOP_RST_MISC,
+ .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
};
static const struct mtk_pmic_regs mt6323_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
- 0x2, MT6323_INT_MISC_CON, 0x10),
+ 0x2, MT6323_INT_MISC_CON, 0x10, MTK_PMIC_PWRKEY_RST),
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
- 0x4, MT6323_INT_MISC_CON, 0x8),
+ 0x4, MT6323_INT_MISC_CON, 0x8, MTK_PMIC_HOMEKEY_RST),
.pmic_rst_reg = MT6323_TOP_RST_MISC,
+ .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
};
static const struct mtk_pmic_regs mt6358_regs = {
.keys_regs[MTK_PMIC_PWRKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6358_TOPSTATUS,
- 0x2, MT6358_PSC_TOP_INT_CON0, 0x5),
+ 0x2, MT6358_PSC_TOP_INT_CON0, 0x5,
+ MTK_PMIC_PWRKEY_RST),
.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
MTK_PMIC_KEYS_REGS(MT6358_TOPSTATUS,
- 0x8, MT6358_PSC_TOP_INT_CON0, 0xa),
+ 0x8, MT6358_PSC_TOP_INT_CON0, 0xa,
+ MTK_PMIC_HOMEKEY_RST),
.pmic_rst_reg = MT6358_TOP_RST_MISC,
+ .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
};
struct mtk_pmic_keys_info {
@@ -108,53 +108,49 @@ enum mtk_pmic_keys_lp_mode {
};
static void mtk_pmic_keys_lp_reset_setup(struct mtk_pmic_keys *keys,
- u32 pmic_rst_reg)
+ const struct mtk_pmic_regs *regs)
{
- int ret;
+ const struct mtk_pmic_keys_regs *kregs_home, *kregs_pwr;
u32 long_press_mode, long_press_debounce;
+ u32 value, mask;
+ int error;
+
+ kregs_home = keys->keys[MTK_PMIC_HOMEKEY_INDEX].regs;
+ kregs_pwr = keys->keys[MTK_PMIC_PWRKEY_INDEX].regs;
- ret = of_property_read_u32(keys->dev->of_node,
- "power-off-time-sec", &long_press_debounce);
- if (ret)
+ error = of_property_read_u32(keys->dev->of_node, "power-off-time-sec",
+ &long_press_debounce);
+ if (error)
long_press_debounce = 0;
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_RST_DU_MASK << MTK_PMIC_RST_DU_SHIFT,
- long_press_debounce << MTK_PMIC_RST_DU_SHIFT);
+ mask = regs->rst_lprst_mask;
+ value = long_press_debounce << (ffs(regs->rst_lprst_mask) - 1);
- ret = of_property_read_u32(keys->dev->of_node,
- "mediatek,long-press-mode", &long_press_mode);
- if (ret)
+ error = of_property_read_u32(keys->dev->of_node,
+ "mediatek,long-press-mode",
+ &long_press_mode);
+ if (error)
long_press_mode = LP_DISABLE;
switch (long_press_mode) {
- case LP_ONEKEY:
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_PWRKEY_RST,
- MTK_PMIC_PWRKEY_RST);
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_HOMEKEY_RST,
- 0);
- break;
case LP_TWOKEY:
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_PWRKEY_RST,
- MTK_PMIC_PWRKEY_RST);
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_HOMEKEY_RST,
- MTK_PMIC_HOMEKEY_RST);
- break;
+ value |= kregs_home->rst_en_mask;
+ fallthrough;
+
+ case LP_ONEKEY:
+ value |= kregs_pwr->rst_en_mask;
+ fallthrough;
+
case LP_DISABLE:
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_PWRKEY_RST,
- 0);
- regmap_update_bits(keys->regmap, pmic_rst_reg,
- MTK_PMIC_HOMEKEY_RST,
- 0);
+ mask |= kregs_home->rst_en_mask;
+ mask |= kregs_pwr->rst_en_mask;
break;
+
default:
break;
}
+
+ regmap_update_bits(keys->regmap, regs->pmic_rst_reg, mask, value);
}
static irqreturn_t mtk_pmic_keys_irq_handler_thread(int irq, void *data)
@@ -358,7 +354,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
return error;
}
- mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs->pmic_rst_reg);
+ mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs);
platform_set_drvdata(pdev, keys);
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index 8a7ce41b8c56..ee9d04a3f0d5 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -179,11 +179,9 @@ static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
int error;
u64 keys;
- error = pm_runtime_get_sync(dev);
- if (error < 0) {
- pm_runtime_put_noidle(dev);
+ error = pm_runtime_resume_and_get(dev);
+ if (error)
return IRQ_NONE;
- }
low = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
high = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
@@ -207,11 +205,9 @@ static int omap4_keypad_open(struct input_dev *input)
struct device *dev = input->dev.parent;
int error;
- error = pm_runtime_get_sync(dev);
- if (error < 0) {
- pm_runtime_put_noidle(dev);
+ error = pm_runtime_resume_and_get(dev);
+ if (error)
return error;
- }
disable_irq(keypad_data->irq);
@@ -254,9 +250,10 @@ static void omap4_keypad_close(struct input_dev *input)
struct device *dev = input->dev.parent;
int error;
- error = pm_runtime_get_sync(dev);
- if (error < 0)
- pm_runtime_put_noidle(dev);
+ error = pm_runtime_resume_and_get(dev);
+ if (error)
+ dev_err(dev, "%s: pm_runtime_resume_and_get() failed: %d\n",
+ __func__, error);
disable_irq(keypad_data->irq);
omap4_keypad_stop(keypad_data);
@@ -392,10 +389,9 @@ static int omap4_keypad_probe(struct platform_device *pdev)
* Enable clocks for the keypad module so that we can read
* revision register.
*/
- error = pm_runtime_get_sync(dev);
- if (error < 0) {
- dev_err(dev, "pm_runtime_get_sync() failed\n");
- pm_runtime_put_noidle(dev);
+ error = pm_runtime_resume_and_get(dev);
+ if (error) {
+ dev_err(dev, "pm_runtime_resume_and_get() failed\n");
return error;
}