cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ep93xx_keypad.c (8334B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Driver for the Cirrus EP93xx matrix keypad controller.
      4 *
      5 * Copyright (c) 2008 H Hartley Sweeten <hsweeten@visionengravers.com>
      6 *
      7 * Based on the pxa27x matrix keypad controller by Rodolfo Giometti.
      8 *
      9 * NOTE:
     10 *
     11 * The 3-key reset is triggered by pressing the 3 keys in
     12 * Row 0, Columns 2, 4, and 7 at the same time.  This action can
     13 * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag.
     14 *
     15 * Normal operation for the matrix does not autorepeat the key press.
     16 * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT
     17 * flag.
     18 */
     19
     20#include <linux/bits.h>
     21#include <linux/module.h>
     22#include <linux/platform_device.h>
     23#include <linux/interrupt.h>
     24#include <linux/clk.h>
     25#include <linux/io.h>
     26#include <linux/input/matrix_keypad.h>
     27#include <linux/slab.h>
     28#include <linux/soc/cirrus/ep93xx.h>
     29#include <linux/platform_data/keypad-ep93xx.h>
     30#include <linux/pm_wakeirq.h>
     31
     32/*
     33 * Keypad Interface Register offsets
     34 */
     35#define KEY_INIT		0x00	/* Key Scan Initialization register */
     36#define KEY_DIAG		0x04	/* Key Scan Diagnostic register */
     37#define KEY_REG			0x08	/* Key Value Capture register */
     38
     39/* Key Scan Initialization Register bit defines */
     40#define KEY_INIT_DBNC_MASK	GENMASK(23, 16)
     41#define KEY_INIT_DBNC_SHIFT	16
     42#define KEY_INIT_DIS3KY		BIT(15)
     43#define KEY_INIT_DIAG		BIT(14)
     44#define KEY_INIT_BACK		BIT(13)
     45#define KEY_INIT_T2		BIT(12)
     46#define KEY_INIT_PRSCL_MASK	GENMASK(9, 0)
     47#define KEY_INIT_PRSCL_SHIFT	0
     48
     49/* Key Scan Diagnostic Register bit defines */
     50#define KEY_DIAG_MASK		GENMASK(5, 0)
     51#define KEY_DIAG_SHIFT		0
     52
     53/* Key Value Capture Register bit defines */
     54#define KEY_REG_K		BIT(15)
     55#define KEY_REG_INT		BIT(14)
     56#define KEY_REG_2KEYS		BIT(13)
     57#define KEY_REG_1KEY		BIT(12)
     58#define KEY_REG_KEY2_MASK	GENMASK(11, 6)
     59#define KEY_REG_KEY2_SHIFT	6
     60#define KEY_REG_KEY1_MASK	GENMASK(5, 0)
     61#define KEY_REG_KEY1_SHIFT	0
     62
     63#define EP93XX_MATRIX_SIZE	(EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
     64
     65struct ep93xx_keypad {
     66	struct ep93xx_keypad_platform_data *pdata;
     67	struct input_dev *input_dev;
     68	struct clk *clk;
     69
     70	void __iomem *mmio_base;
     71
     72	unsigned short keycodes[EP93XX_MATRIX_SIZE];
     73
     74	int key1;
     75	int key2;
     76
     77	int irq;
     78
     79	bool enabled;
     80};
     81
     82static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
     83{
     84	struct ep93xx_keypad *keypad = dev_id;
     85	struct input_dev *input_dev = keypad->input_dev;
     86	unsigned int status;
     87	int keycode, key1, key2;
     88
     89	status = __raw_readl(keypad->mmio_base + KEY_REG);
     90
     91	keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
     92	key1 = keypad->keycodes[keycode];
     93
     94	keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
     95	key2 = keypad->keycodes[keycode];
     96
     97	if (status & KEY_REG_2KEYS) {
     98		if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
     99			input_report_key(input_dev, keypad->key1, 0);
    100
    101		if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2)
    102			input_report_key(input_dev, keypad->key2, 0);
    103
    104		input_report_key(input_dev, key1, 1);
    105		input_report_key(input_dev, key2, 1);
    106
    107		keypad->key1 = key1;
    108		keypad->key2 = key2;
    109
    110	} else if (status & KEY_REG_1KEY) {
    111		if (keypad->key1 && key1 != keypad->key1)
    112			input_report_key(input_dev, keypad->key1, 0);
    113
    114		if (keypad->key2 && key1 != keypad->key2)
    115			input_report_key(input_dev, keypad->key2, 0);
    116
    117		input_report_key(input_dev, key1, 1);
    118
    119		keypad->key1 = key1;
    120		keypad->key2 = 0;
    121
    122	} else {
    123		input_report_key(input_dev, keypad->key1, 0);
    124		input_report_key(input_dev, keypad->key2, 0);
    125
    126		keypad->key1 = keypad->key2 = 0;
    127	}
    128	input_sync(input_dev);
    129
    130	return IRQ_HANDLED;
    131}
    132
    133static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
    134{
    135	struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
    136	unsigned int val = 0;
    137
    138	clk_set_rate(keypad->clk, pdata->clk_rate);
    139
    140	if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
    141		val |= KEY_INIT_DIS3KY;
    142	if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE)
    143		val |= KEY_INIT_DIAG;
    144	if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE)
    145		val |= KEY_INIT_BACK;
    146	if (pdata->flags & EP93XX_KEYPAD_TEST_MODE)
    147		val |= KEY_INIT_T2;
    148
    149	val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK);
    150
    151	val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
    152
    153	__raw_writel(val, keypad->mmio_base + KEY_INIT);
    154}
    155
    156static int ep93xx_keypad_open(struct input_dev *pdev)
    157{
    158	struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
    159
    160	if (!keypad->enabled) {
    161		ep93xx_keypad_config(keypad);
    162		clk_prepare_enable(keypad->clk);
    163		keypad->enabled = true;
    164	}
    165
    166	return 0;
    167}
    168
    169static void ep93xx_keypad_close(struct input_dev *pdev)
    170{
    171	struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
    172
    173	if (keypad->enabled) {
    174		clk_disable_unprepare(keypad->clk);
    175		keypad->enabled = false;
    176	}
    177}
    178
    179
    180static int __maybe_unused ep93xx_keypad_suspend(struct device *dev)
    181{
    182	struct platform_device *pdev = to_platform_device(dev);
    183	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
    184	struct input_dev *input_dev = keypad->input_dev;
    185
    186	mutex_lock(&input_dev->mutex);
    187
    188	if (keypad->enabled) {
    189		clk_disable(keypad->clk);
    190		keypad->enabled = false;
    191	}
    192
    193	mutex_unlock(&input_dev->mutex);
    194
    195	return 0;
    196}
    197
    198static int __maybe_unused ep93xx_keypad_resume(struct device *dev)
    199{
    200	struct platform_device *pdev = to_platform_device(dev);
    201	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
    202	struct input_dev *input_dev = keypad->input_dev;
    203
    204	mutex_lock(&input_dev->mutex);
    205
    206	if (input_device_enabled(input_dev)) {
    207		if (!keypad->enabled) {
    208			ep93xx_keypad_config(keypad);
    209			clk_enable(keypad->clk);
    210			keypad->enabled = true;
    211		}
    212	}
    213
    214	mutex_unlock(&input_dev->mutex);
    215
    216	return 0;
    217}
    218
    219static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
    220			 ep93xx_keypad_suspend, ep93xx_keypad_resume);
    221
    222static void ep93xx_keypad_release_gpio_action(void *_pdev)
    223{
    224	struct platform_device *pdev = _pdev;
    225
    226	ep93xx_keypad_release_gpio(pdev);
    227}
    228
    229static int ep93xx_keypad_probe(struct platform_device *pdev)
    230{
    231	struct ep93xx_keypad *keypad;
    232	const struct matrix_keymap_data *keymap_data;
    233	struct input_dev *input_dev;
    234	int err;
    235
    236	keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
    237	if (!keypad)
    238		return -ENOMEM;
    239
    240	keypad->pdata = dev_get_platdata(&pdev->dev);
    241	if (!keypad->pdata)
    242		return -EINVAL;
    243
    244	keymap_data = keypad->pdata->keymap_data;
    245	if (!keymap_data)
    246		return -EINVAL;
    247
    248	keypad->irq = platform_get_irq(pdev, 0);
    249	if (keypad->irq < 0)
    250		return keypad->irq;
    251
    252	keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
    253	if (IS_ERR(keypad->mmio_base))
    254		return PTR_ERR(keypad->mmio_base);
    255
    256	err = ep93xx_keypad_acquire_gpio(pdev);
    257	if (err)
    258		return err;
    259
    260	err = devm_add_action_or_reset(&pdev->dev,
    261				       ep93xx_keypad_release_gpio_action, pdev);
    262	if (err)
    263		return err;
    264
    265	keypad->clk = devm_clk_get(&pdev->dev, NULL);
    266	if (IS_ERR(keypad->clk))
    267		return PTR_ERR(keypad->clk);
    268
    269	input_dev = devm_input_allocate_device(&pdev->dev);
    270	if (!input_dev)
    271		return -ENOMEM;
    272
    273	keypad->input_dev = input_dev;
    274
    275	input_dev->name = pdev->name;
    276	input_dev->id.bustype = BUS_HOST;
    277	input_dev->open = ep93xx_keypad_open;
    278	input_dev->close = ep93xx_keypad_close;
    279
    280	err = matrix_keypad_build_keymap(keymap_data, NULL,
    281					 EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
    282					 keypad->keycodes, input_dev);
    283	if (err)
    284		return err;
    285
    286	if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
    287		__set_bit(EV_REP, input_dev->evbit);
    288	input_set_drvdata(input_dev, keypad);
    289
    290	err = devm_request_irq(&pdev->dev, keypad->irq,
    291			       ep93xx_keypad_irq_handler,
    292			       0, pdev->name, keypad);
    293	if (err)
    294		return err;
    295
    296	err = input_register_device(input_dev);
    297	if (err)
    298		return err;
    299
    300	platform_set_drvdata(pdev, keypad);
    301
    302	device_init_wakeup(&pdev->dev, 1);
    303	err = dev_pm_set_wake_irq(&pdev->dev, keypad->irq);
    304	if (err)
    305		dev_warn(&pdev->dev, "failed to set up wakeup irq: %d\n", err);
    306
    307	return 0;
    308}
    309
    310static int ep93xx_keypad_remove(struct platform_device *pdev)
    311{
    312	dev_pm_clear_wake_irq(&pdev->dev);
    313
    314	return 0;
    315}
    316
    317static struct platform_driver ep93xx_keypad_driver = {
    318	.driver		= {
    319		.name	= "ep93xx-keypad",
    320		.pm	= &ep93xx_keypad_pm_ops,
    321	},
    322	.probe		= ep93xx_keypad_probe,
    323	.remove		= ep93xx_keypad_remove,
    324};
    325module_platform_driver(ep93xx_keypad_driver);
    326
    327MODULE_LICENSE("GPL");
    328MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
    329MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
    330MODULE_ALIAS("platform:ep93xx-keypad");