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

imx_keypad.c (16039B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Driver for the IMX keypad port.
      4// Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
      5
      6#include <linux/clk.h>
      7#include <linux/delay.h>
      8#include <linux/device.h>
      9#include <linux/err.h>
     10#include <linux/input/matrix_keypad.h>
     11#include <linux/interrupt.h>
     12#include <linux/io.h>
     13#include <linux/jiffies.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/of.h>
     17#include <linux/platform_device.h>
     18#include <linux/slab.h>
     19#include <linux/timer.h>
     20
     21/*
     22 * Keypad Controller registers (halfword)
     23 */
     24#define KPCR		0x00 /* Keypad Control Register */
     25
     26#define KPSR		0x02 /* Keypad Status Register */
     27#define KBD_STAT_KPKD	(0x1 << 0) /* Key Press Interrupt Status bit (w1c) */
     28#define KBD_STAT_KPKR	(0x1 << 1) /* Key Release Interrupt Status bit (w1c) */
     29#define KBD_STAT_KDSC	(0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/
     30#define KBD_STAT_KRSS	(0x1 << 3) /* Key Release Synch Status bit (w1c)*/
     31#define KBD_STAT_KDIE	(0x1 << 8) /* Key Depress Interrupt Enable Status bit */
     32#define KBD_STAT_KRIE	(0x1 << 9) /* Key Release Interrupt Enable */
     33#define KBD_STAT_KPPEN	(0x1 << 10) /* Keypad Clock Enable */
     34
     35#define KDDR		0x04 /* Keypad Data Direction Register */
     36#define KPDR		0x06 /* Keypad Data Register */
     37
     38#define MAX_MATRIX_KEY_ROWS	8
     39#define MAX_MATRIX_KEY_COLS	8
     40#define MATRIX_ROW_SHIFT	3
     41
     42#define MAX_MATRIX_KEY_NUM	(MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
     43
     44struct imx_keypad {
     45
     46	struct clk *clk;
     47	struct input_dev *input_dev;
     48	void __iomem *mmio_base;
     49
     50	int			irq;
     51	struct timer_list	check_matrix_timer;
     52
     53	/*
     54	 * The matrix is stable only if no changes are detected after
     55	 * IMX_KEYPAD_SCANS_FOR_STABILITY scans
     56	 */
     57#define IMX_KEYPAD_SCANS_FOR_STABILITY 3
     58	int			stable_count;
     59
     60	bool			enabled;
     61
     62	/* Masks for enabled rows/cols */
     63	unsigned short		rows_en_mask;
     64	unsigned short		cols_en_mask;
     65
     66	unsigned short		keycodes[MAX_MATRIX_KEY_NUM];
     67
     68	/*
     69	 * Matrix states:
     70	 * -stable: achieved after a complete debounce process.
     71	 * -unstable: used in the debouncing process.
     72	 */
     73	unsigned short		matrix_stable_state[MAX_MATRIX_KEY_COLS];
     74	unsigned short		matrix_unstable_state[MAX_MATRIX_KEY_COLS];
     75};
     76
     77/* Scan the matrix and return the new state in *matrix_volatile_state. */
     78static void imx_keypad_scan_matrix(struct imx_keypad *keypad,
     79				  unsigned short *matrix_volatile_state)
     80{
     81	int col;
     82	unsigned short reg_val;
     83
     84	for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
     85		if ((keypad->cols_en_mask & (1 << col)) == 0)
     86			continue;
     87		/*
     88		 * Discharge keypad capacitance:
     89		 * 2. write 1s on column data.
     90		 * 3. configure columns as totem-pole to discharge capacitance.
     91		 * 4. configure columns as open-drain.
     92		 */
     93		reg_val = readw(keypad->mmio_base + KPDR);
     94		reg_val |= 0xff00;
     95		writew(reg_val, keypad->mmio_base + KPDR);
     96
     97		reg_val = readw(keypad->mmio_base + KPCR);
     98		reg_val &= ~((keypad->cols_en_mask & 0xff) << 8);
     99		writew(reg_val, keypad->mmio_base + KPCR);
    100
    101		udelay(2);
    102
    103		reg_val = readw(keypad->mmio_base + KPCR);
    104		reg_val |= (keypad->cols_en_mask & 0xff) << 8;
    105		writew(reg_val, keypad->mmio_base + KPCR);
    106
    107		/*
    108		 * 5. Write a single column to 0, others to 1.
    109		 * 6. Sample row inputs and save data.
    110		 * 7. Repeat steps 2 - 6 for remaining columns.
    111		 */
    112		reg_val = readw(keypad->mmio_base + KPDR);
    113		reg_val &= ~(1 << (8 + col));
    114		writew(reg_val, keypad->mmio_base + KPDR);
    115
    116		/*
    117		 * Delay added to avoid propagating the 0 from column to row
    118		 * when scanning.
    119		 */
    120		udelay(5);
    121
    122		/*
    123		 * 1s in matrix_volatile_state[col] means key pressures
    124		 * throw data from non enabled rows.
    125		 */
    126		reg_val = readw(keypad->mmio_base + KPDR);
    127		matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask;
    128	}
    129
    130	/*
    131	 * Return in standby mode:
    132	 * 9. write 0s to columns
    133	 */
    134	reg_val = readw(keypad->mmio_base + KPDR);
    135	reg_val &= 0x00ff;
    136	writew(reg_val, keypad->mmio_base + KPDR);
    137}
    138
    139/*
    140 * Compare the new matrix state (volatile) with the stable one stored in
    141 * keypad->matrix_stable_state and fire events if changes are detected.
    142 */
    143static void imx_keypad_fire_events(struct imx_keypad *keypad,
    144				   unsigned short *matrix_volatile_state)
    145{
    146	struct input_dev *input_dev = keypad->input_dev;
    147	int row, col;
    148
    149	for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
    150		unsigned short bits_changed;
    151		int code;
    152
    153		if ((keypad->cols_en_mask & (1 << col)) == 0)
    154			continue; /* Column is not enabled */
    155
    156		bits_changed = keypad->matrix_stable_state[col] ^
    157						matrix_volatile_state[col];
    158
    159		if (bits_changed == 0)
    160			continue; /* Column does not contain changes */
    161
    162		for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
    163			if ((keypad->rows_en_mask & (1 << row)) == 0)
    164				continue; /* Row is not enabled */
    165			if ((bits_changed & (1 << row)) == 0)
    166				continue; /* Row does not contain changes */
    167
    168			code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
    169			input_event(input_dev, EV_MSC, MSC_SCAN, code);
    170			input_report_key(input_dev, keypad->keycodes[code],
    171				matrix_volatile_state[col] & (1 << row));
    172			dev_dbg(&input_dev->dev, "Event code: %d, val: %d",
    173				keypad->keycodes[code],
    174				matrix_volatile_state[col] & (1 << row));
    175		}
    176	}
    177	input_sync(input_dev);
    178}
    179
    180/*
    181 * imx_keypad_check_for_events is the timer handler.
    182 */
    183static void imx_keypad_check_for_events(struct timer_list *t)
    184{
    185	struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer);
    186	unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
    187	unsigned short reg_val;
    188	bool state_changed, is_zero_matrix;
    189	int i;
    190
    191	memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state));
    192
    193	imx_keypad_scan_matrix(keypad, matrix_volatile_state);
    194
    195	state_changed = false;
    196	for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
    197		if ((keypad->cols_en_mask & (1 << i)) == 0)
    198			continue;
    199
    200		if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) {
    201			state_changed = true;
    202			break;
    203		}
    204	}
    205
    206	/*
    207	 * If the matrix state is changed from the previous scan
    208	 *   (Re)Begin the debouncing process, saving the new state in
    209	 *    keypad->matrix_unstable_state.
    210	 * else
    211	 *   Increase the count of number of scans with a stable state.
    212	 */
    213	if (state_changed) {
    214		memcpy(keypad->matrix_unstable_state, matrix_volatile_state,
    215			sizeof(matrix_volatile_state));
    216		keypad->stable_count = 0;
    217	} else
    218		keypad->stable_count++;
    219
    220	/*
    221	 * If the matrix is not as stable as we want reschedule scan
    222	 * in the near future.
    223	 */
    224	if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) {
    225		mod_timer(&keypad->check_matrix_timer,
    226			  jiffies + msecs_to_jiffies(10));
    227		return;
    228	}
    229
    230	/*
    231	 * If the matrix state is stable, fire the events and save the new
    232	 * stable state. Note, if the matrix is kept stable for longer
    233	 * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all
    234	 * events have already been generated.
    235	 */
    236	if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) {
    237		imx_keypad_fire_events(keypad, matrix_volatile_state);
    238
    239		memcpy(keypad->matrix_stable_state, matrix_volatile_state,
    240			sizeof(matrix_volatile_state));
    241	}
    242
    243	is_zero_matrix = true;
    244	for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
    245		if (matrix_volatile_state[i] != 0) {
    246			is_zero_matrix = false;
    247			break;
    248		}
    249	}
    250
    251
    252	if (is_zero_matrix) {
    253		/*
    254		 * All keys have been released. Enable only the KDI
    255		 * interrupt for future key presses (clear the KDI
    256		 * status bit and its sync chain before that).
    257		 */
    258		reg_val = readw(keypad->mmio_base + KPSR);
    259		reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC;
    260		writew(reg_val, keypad->mmio_base + KPSR);
    261
    262		reg_val = readw(keypad->mmio_base + KPSR);
    263		reg_val |= KBD_STAT_KDIE;
    264		reg_val &= ~KBD_STAT_KRIE;
    265		writew(reg_val, keypad->mmio_base + KPSR);
    266	} else {
    267		/*
    268		 * Some keys are still pressed. Schedule a rescan in
    269		 * attempt to detect multiple key presses and enable
    270		 * the KRI interrupt to react quickly to key release
    271		 * event.
    272		 */
    273		mod_timer(&keypad->check_matrix_timer,
    274			  jiffies + msecs_to_jiffies(60));
    275
    276		reg_val = readw(keypad->mmio_base + KPSR);
    277		reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS;
    278		writew(reg_val, keypad->mmio_base + KPSR);
    279
    280		reg_val = readw(keypad->mmio_base + KPSR);
    281		reg_val |= KBD_STAT_KRIE;
    282		reg_val &= ~KBD_STAT_KDIE;
    283		writew(reg_val, keypad->mmio_base + KPSR);
    284	}
    285}
    286
    287static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id)
    288{
    289	struct imx_keypad *keypad = dev_id;
    290	unsigned short reg_val;
    291
    292	reg_val = readw(keypad->mmio_base + KPSR);
    293
    294	/* Disable both interrupt types */
    295	reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
    296	/* Clear interrupts status bits */
    297	reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
    298	writew(reg_val, keypad->mmio_base + KPSR);
    299
    300	if (keypad->enabled) {
    301		/* The matrix is supposed to be changed */
    302		keypad->stable_count = 0;
    303
    304		/* Schedule the scanning procedure near in the future */
    305		mod_timer(&keypad->check_matrix_timer,
    306			  jiffies + msecs_to_jiffies(2));
    307	}
    308
    309	return IRQ_HANDLED;
    310}
    311
    312static void imx_keypad_config(struct imx_keypad *keypad)
    313{
    314	unsigned short reg_val;
    315
    316	/*
    317	 * Include enabled rows in interrupt generation (KPCR[7:0])
    318	 * Configure keypad columns as open-drain (KPCR[15:8])
    319	 */
    320	reg_val = readw(keypad->mmio_base + KPCR);
    321	reg_val |= keypad->rows_en_mask & 0xff;		/* rows */
    322	reg_val |= (keypad->cols_en_mask & 0xff) << 8;	/* cols */
    323	writew(reg_val, keypad->mmio_base + KPCR);
    324
    325	/* Write 0's to KPDR[15:8] (Colums) */
    326	reg_val = readw(keypad->mmio_base + KPDR);
    327	reg_val &= 0x00ff;
    328	writew(reg_val, keypad->mmio_base + KPDR);
    329
    330	/* Configure columns as output, rows as input (KDDR[15:0]) */
    331	writew(0xff00, keypad->mmio_base + KDDR);
    332
    333	/*
    334	 * Clear Key Depress and Key Release status bit.
    335	 * Clear both synchronizer chain.
    336	 */
    337	reg_val = readw(keypad->mmio_base + KPSR);
    338	reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD |
    339		   KBD_STAT_KDSC | KBD_STAT_KRSS;
    340	writew(reg_val, keypad->mmio_base + KPSR);
    341
    342	/* Enable KDI and disable KRI (avoid false release events). */
    343	reg_val |= KBD_STAT_KDIE;
    344	reg_val &= ~KBD_STAT_KRIE;
    345	writew(reg_val, keypad->mmio_base + KPSR);
    346}
    347
    348static void imx_keypad_inhibit(struct imx_keypad *keypad)
    349{
    350	unsigned short reg_val;
    351
    352	/* Inhibit KDI and KRI interrupts. */
    353	reg_val = readw(keypad->mmio_base + KPSR);
    354	reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
    355	reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
    356	writew(reg_val, keypad->mmio_base + KPSR);
    357
    358	/* Colums as open drain and disable all rows */
    359	reg_val = (keypad->cols_en_mask & 0xff) << 8;
    360	writew(reg_val, keypad->mmio_base + KPCR);
    361}
    362
    363static void imx_keypad_close(struct input_dev *dev)
    364{
    365	struct imx_keypad *keypad = input_get_drvdata(dev);
    366
    367	dev_dbg(&dev->dev, ">%s\n", __func__);
    368
    369	/* Mark keypad as being inactive */
    370	keypad->enabled = false;
    371	synchronize_irq(keypad->irq);
    372	del_timer_sync(&keypad->check_matrix_timer);
    373
    374	imx_keypad_inhibit(keypad);
    375
    376	/* Disable clock unit */
    377	clk_disable_unprepare(keypad->clk);
    378}
    379
    380static int imx_keypad_open(struct input_dev *dev)
    381{
    382	struct imx_keypad *keypad = input_get_drvdata(dev);
    383	int error;
    384
    385	dev_dbg(&dev->dev, ">%s\n", __func__);
    386
    387	/* Enable the kpp clock */
    388	error = clk_prepare_enable(keypad->clk);
    389	if (error)
    390		return error;
    391
    392	/* We became active from now */
    393	keypad->enabled = true;
    394
    395	imx_keypad_config(keypad);
    396
    397	/* Sanity control, not all the rows must be actived now. */
    398	if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) {
    399		dev_err(&dev->dev,
    400			"too many keys pressed, control pins initialisation\n");
    401		goto open_err;
    402	}
    403
    404	return 0;
    405
    406open_err:
    407	imx_keypad_close(dev);
    408	return -EIO;
    409}
    410
    411static const struct of_device_id imx_keypad_of_match[] = {
    412	{ .compatible = "fsl,imx21-kpp", },
    413	{ /* sentinel */ }
    414};
    415MODULE_DEVICE_TABLE(of, imx_keypad_of_match);
    416
    417static int imx_keypad_probe(struct platform_device *pdev)
    418{
    419	struct imx_keypad *keypad;
    420	struct input_dev *input_dev;
    421	int irq, error, i, row, col;
    422
    423	irq = platform_get_irq(pdev, 0);
    424	if (irq < 0)
    425		return irq;
    426
    427	input_dev = devm_input_allocate_device(&pdev->dev);
    428	if (!input_dev) {
    429		dev_err(&pdev->dev, "failed to allocate the input device\n");
    430		return -ENOMEM;
    431	}
    432
    433	keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
    434	if (!keypad) {
    435		dev_err(&pdev->dev, "not enough memory for driver data\n");
    436		return -ENOMEM;
    437	}
    438
    439	keypad->input_dev = input_dev;
    440	keypad->irq = irq;
    441	keypad->stable_count = 0;
    442
    443	timer_setup(&keypad->check_matrix_timer,
    444		    imx_keypad_check_for_events, 0);
    445
    446	keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
    447	if (IS_ERR(keypad->mmio_base))
    448		return PTR_ERR(keypad->mmio_base);
    449
    450	keypad->clk = devm_clk_get(&pdev->dev, NULL);
    451	if (IS_ERR(keypad->clk)) {
    452		dev_err(&pdev->dev, "failed to get keypad clock\n");
    453		return PTR_ERR(keypad->clk);
    454	}
    455
    456	/* Init the Input device */
    457	input_dev->name = pdev->name;
    458	input_dev->id.bustype = BUS_HOST;
    459	input_dev->dev.parent = &pdev->dev;
    460	input_dev->open = imx_keypad_open;
    461	input_dev->close = imx_keypad_close;
    462
    463	error = matrix_keypad_build_keymap(NULL, NULL,
    464					   MAX_MATRIX_KEY_ROWS,
    465					   MAX_MATRIX_KEY_COLS,
    466					   keypad->keycodes, input_dev);
    467	if (error) {
    468		dev_err(&pdev->dev, "failed to build keymap\n");
    469		return error;
    470	}
    471
    472	/* Search for rows and cols enabled */
    473	for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
    474		for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
    475			i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
    476			if (keypad->keycodes[i] != KEY_RESERVED) {
    477				keypad->rows_en_mask |= 1 << row;
    478				keypad->cols_en_mask |= 1 << col;
    479			}
    480		}
    481	}
    482	dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
    483	dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
    484
    485	__set_bit(EV_REP, input_dev->evbit);
    486	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
    487	input_set_drvdata(input_dev, keypad);
    488
    489	/* Ensure that the keypad will stay dormant until opened */
    490	error = clk_prepare_enable(keypad->clk);
    491	if (error)
    492		return error;
    493	imx_keypad_inhibit(keypad);
    494	clk_disable_unprepare(keypad->clk);
    495
    496	error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0,
    497			    pdev->name, keypad);
    498	if (error) {
    499		dev_err(&pdev->dev, "failed to request IRQ\n");
    500		return error;
    501	}
    502
    503	/* Register the input device */
    504	error = input_register_device(input_dev);
    505	if (error) {
    506		dev_err(&pdev->dev, "failed to register input device\n");
    507		return error;
    508	}
    509
    510	platform_set_drvdata(pdev, keypad);
    511	device_init_wakeup(&pdev->dev, 1);
    512
    513	return 0;
    514}
    515
    516static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
    517{
    518	struct platform_device *pdev = to_platform_device(dev);
    519	struct imx_keypad *kbd = platform_get_drvdata(pdev);
    520	struct input_dev *input_dev = kbd->input_dev;
    521	unsigned short reg_val = readw(kbd->mmio_base + KPSR);
    522
    523	/* imx kbd can wake up system even clock is disabled */
    524	mutex_lock(&input_dev->mutex);
    525
    526	if (input_device_enabled(input_dev))
    527		clk_disable_unprepare(kbd->clk);
    528
    529	mutex_unlock(&input_dev->mutex);
    530
    531	if (device_may_wakeup(&pdev->dev)) {
    532		if (reg_val & KBD_STAT_KPKD)
    533			reg_val |= KBD_STAT_KRIE;
    534		if (reg_val & KBD_STAT_KPKR)
    535			reg_val |= KBD_STAT_KDIE;
    536		writew(reg_val, kbd->mmio_base + KPSR);
    537
    538		enable_irq_wake(kbd->irq);
    539	}
    540
    541	return 0;
    542}
    543
    544static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
    545{
    546	struct platform_device *pdev = to_platform_device(dev);
    547	struct imx_keypad *kbd = platform_get_drvdata(pdev);
    548	struct input_dev *input_dev = kbd->input_dev;
    549	int ret = 0;
    550
    551	if (device_may_wakeup(&pdev->dev))
    552		disable_irq_wake(kbd->irq);
    553
    554	mutex_lock(&input_dev->mutex);
    555
    556	if (input_device_enabled(input_dev)) {
    557		ret = clk_prepare_enable(kbd->clk);
    558		if (ret)
    559			goto err_clk;
    560	}
    561
    562err_clk:
    563	mutex_unlock(&input_dev->mutex);
    564
    565	return ret;
    566}
    567
    568static const struct dev_pm_ops imx_kbd_pm_ops = {
    569	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume)
    570};
    571
    572static struct platform_driver imx_keypad_driver = {
    573	.driver		= {
    574		.name	= "imx-keypad",
    575		.pm	= &imx_kbd_pm_ops,
    576		.of_match_table = imx_keypad_of_match,
    577	},
    578	.probe		= imx_keypad_probe,
    579};
    580module_platform_driver(imx_keypad_driver);
    581
    582MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
    583MODULE_DESCRIPTION("IMX Keypad Port Driver");
    584MODULE_LICENSE("GPL v2");
    585MODULE_ALIAS("platform:imx-keypad");