diff options
Diffstat (limited to 'drivers/input/keyboard/imx_keypad.c')
| -rw-r--r-- | drivers/input/keyboard/imx_keypad.c | 90 |
1 files changed, 40 insertions, 50 deletions
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 2165f3dd328b..069c1d6376e1 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -1,16 +1,13 @@ -/* - * Driver for the IMX keypad port. - * Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Driver for the IMX keypad port. +// Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/input.h> #include <linux/input/matrix_keypad.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -184,9 +181,10 @@ static void imx_keypad_fire_events(struct imx_keypad *keypad, /* * imx_keypad_check_for_events is the timer handler. */ -static void imx_keypad_check_for_events(unsigned long data) +static void imx_keypad_check_for_events(struct timer_list *t) { - struct imx_keypad *keypad = (struct imx_keypad *) data; + struct imx_keypad *keypad = timer_container_of(keypad, t, + check_matrix_timer); unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS]; unsigned short reg_val; bool state_changed, is_zero_matrix; @@ -373,7 +371,7 @@ static void imx_keypad_close(struct input_dev *dev) /* Mark keypad as being inactive */ keypad->enabled = false; synchronize_irq(keypad->irq); - del_timer_sync(&keypad->check_matrix_timer); + timer_delete_sync(&keypad->check_matrix_timer); imx_keypad_inhibit(keypad); @@ -412,33 +410,21 @@ open_err: return -EIO; } -#ifdef CONFIG_OF static const struct of_device_id imx_keypad_of_match[] = { { .compatible = "fsl,imx21-kpp", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_keypad_of_match); -#endif static int imx_keypad_probe(struct platform_device *pdev) { - const struct matrix_keymap_data *keymap_data = - dev_get_platdata(&pdev->dev); struct imx_keypad *keypad; struct input_dev *input_dev; - struct resource *res; int irq, error, i, row, col; - if (!keymap_data && !pdev->dev.of_node) { - dev_err(&pdev->dev, "no keymap defined\n"); - return -EINVAL; - } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq defined in platform data\n"); + if (irq < 0) return irq; - } input_dev = devm_input_allocate_device(&pdev->dev); if (!input_dev) { @@ -456,11 +442,10 @@ static int imx_keypad_probe(struct platform_device *pdev) keypad->irq = irq; keypad->stable_count = 0; - setup_timer(&keypad->check_matrix_timer, - imx_keypad_check_for_events, (unsigned long) keypad); + timer_setup(&keypad->check_matrix_timer, + imx_keypad_check_for_events, 0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res); + keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(keypad->mmio_base)) return PTR_ERR(keypad->mmio_base); @@ -477,7 +462,7 @@ static int imx_keypad_probe(struct platform_device *pdev) input_dev->open = imx_keypad_open; input_dev->close = imx_keypad_close; - error = matrix_keypad_build_keymap(keymap_data, NULL, + error = matrix_keypad_build_keymap(NULL, NULL, MAX_MATRIX_KEY_ROWS, MAX_MATRIX_KEY_COLS, keypad->keycodes, input_dev); @@ -530,57 +515,62 @@ static int imx_keypad_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused imx_kbd_suspend(struct device *dev) +static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input_dev; + unsigned short reg_val = readw(kbd->mmio_base + KPSR); - /* imx kbd can wake up system even clock is disabled */ - mutex_lock(&input_dev->mutex); - - if (input_dev->users) - clk_disable_unprepare(kbd->clk); + scoped_guard(mutex, &input_dev->mutex) { + /* imx kbd can wake up system even clock is disabled */ + if (input_device_enabled(input_dev)) + clk_disable_unprepare(kbd->clk); + } - mutex_unlock(&input_dev->mutex); + if (device_may_wakeup(&pdev->dev)) { + if (reg_val & KBD_STAT_KPKD) + reg_val |= KBD_STAT_KRIE; + if (reg_val & KBD_STAT_KPKR) + reg_val |= KBD_STAT_KDIE; + writew(reg_val, kbd->mmio_base + KPSR); - if (device_may_wakeup(&pdev->dev)) enable_irq_wake(kbd->irq); + } return 0; } -static int __maybe_unused imx_kbd_resume(struct device *dev) +static int __maybe_unused imx_kbd_noirq_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input_dev; - int ret = 0; + int error; if (device_may_wakeup(&pdev->dev)) disable_irq_wake(kbd->irq); - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); - if (input_dev->users) { - ret = clk_prepare_enable(kbd->clk); - if (ret) - goto err_clk; + if (input_device_enabled(input_dev)) { + error = clk_prepare_enable(kbd->clk); + if (error) + return error; } -err_clk: - mutex_unlock(&input_dev->mutex); - - return ret; + return 0; } -static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume); +static const struct dev_pm_ops imx_kbd_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume) +}; static struct platform_driver imx_keypad_driver = { .driver = { .name = "imx-keypad", .pm = &imx_kbd_pm_ops, - .of_match_table = of_match_ptr(imx_keypad_of_match), + .of_match_table = imx_keypad_of_match, }, .probe = imx_keypad_probe, }; |
