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

nomadik-ske-keypad.c (10876B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) ST-Ericsson SA 2010
      4 *
      5 * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
      6 * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
      7 *
      8 * Keypad controller driver for the SKE (Scroll Key Encoder) module used in
      9 * the Nomadik 8815 and Ux500 platforms.
     10 */
     11
     12#include <linux/platform_device.h>
     13#include <linux/interrupt.h>
     14#include <linux/spinlock.h>
     15#include <linux/io.h>
     16#include <linux/delay.h>
     17#include <linux/input.h>
     18#include <linux/slab.h>
     19#include <linux/clk.h>
     20#include <linux/module.h>
     21
     22#include <linux/platform_data/keypad-nomadik-ske.h>
     23
     24/* SKE_CR bits */
     25#define SKE_KPMLT	(0x1 << 6)
     26#define SKE_KPCN	(0x7 << 3)
     27#define SKE_KPASEN	(0x1 << 2)
     28#define SKE_KPASON	(0x1 << 7)
     29
     30/* SKE_IMSC bits */
     31#define SKE_KPIMA	(0x1 << 2)
     32
     33/* SKE_ICR bits */
     34#define SKE_KPICS	(0x1 << 3)
     35#define SKE_KPICA	(0x1 << 2)
     36
     37/* SKE_RIS bits */
     38#define SKE_KPRISA	(0x1 << 2)
     39
     40#define SKE_KEYPAD_ROW_SHIFT	3
     41#define SKE_KPD_NUM_ROWS	8
     42#define SKE_KPD_NUM_COLS	8
     43
     44/* keypad auto scan registers */
     45#define SKE_ASR0	0x20
     46#define SKE_ASR1	0x24
     47#define SKE_ASR2	0x28
     48#define SKE_ASR3	0x2C
     49
     50#define SKE_NUM_ASRX_REGISTERS	(4)
     51#define	KEY_PRESSED_DELAY	10
     52
     53/**
     54 * struct ske_keypad  - data structure used by keypad driver
     55 * @irq:	irq no
     56 * @reg_base:	ske registers base address
     57 * @input:	pointer to input device object
     58 * @board:	keypad platform device
     59 * @keymap:	matrix scan code table for keycodes
     60 * @clk:	clock structure pointer
     61 * @pclk:	clock structure pointer
     62 * @ske_keypad_lock: spinlock protecting the keypad read/writes
     63 */
     64struct ske_keypad {
     65	int irq;
     66	void __iomem *reg_base;
     67	struct input_dev *input;
     68	const struct ske_keypad_platform_data *board;
     69	unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS];
     70	struct clk *clk;
     71	struct clk *pclk;
     72	spinlock_t ske_keypad_lock;
     73};
     74
     75static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
     76		u8 mask, u8 data)
     77{
     78	u32 ret;
     79
     80	spin_lock(&keypad->ske_keypad_lock);
     81
     82	ret = readl(keypad->reg_base + addr);
     83	ret &= ~mask;
     84	ret |= data;
     85	writel(ret, keypad->reg_base + addr);
     86
     87	spin_unlock(&keypad->ske_keypad_lock);
     88}
     89
     90/*
     91 * ske_keypad_chip_init: init keypad controller configuration
     92 *
     93 * Enable Multi key press detection, auto scan mode
     94 */
     95static int __init ske_keypad_chip_init(struct ske_keypad *keypad)
     96{
     97	u32 value;
     98	int timeout = keypad->board->debounce_ms;
     99
    100	/* check SKE_RIS to be 0 */
    101	while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
    102		cpu_relax();
    103
    104	if (timeout == -1)
    105		return -EINVAL;
    106
    107	/*
    108	 * set debounce value
    109	 * keypad dbounce is configured in DBCR[15:8]
    110	 * dbounce value in steps of 32/32.768 ms
    111	 */
    112	spin_lock(&keypad->ske_keypad_lock);
    113	value = readl(keypad->reg_base + SKE_DBCR);
    114	value = value & 0xff;
    115	value |= ((keypad->board->debounce_ms * 32000)/32768) << 8;
    116	writel(value, keypad->reg_base + SKE_DBCR);
    117	spin_unlock(&keypad->ske_keypad_lock);
    118
    119	/* enable multi key detection */
    120	ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT);
    121
    122	/*
    123	 * set up the number of columns
    124	 * KPCN[5:3] defines no. of keypad columns to be auto scanned
    125	 */
    126	value = (keypad->board->kcol - 1) << 3;
    127	ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value);
    128
    129	/* clear keypad interrupt for auto(and pending SW) scans */
    130	ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS);
    131
    132	/* un-mask keypad interrupts */
    133	ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
    134
    135	/* enable automatic scan */
    136	ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN);
    137
    138	return 0;
    139}
    140
    141static void ske_keypad_report(struct ske_keypad *keypad, u8 status, int col)
    142{
    143	int row = 0, code, pos;
    144	struct input_dev *input = keypad->input;
    145	u32 ske_ris;
    146	int key_pressed;
    147	int num_of_rows;
    148
    149	/* find out the row */
    150	num_of_rows = hweight8(status);
    151	do {
    152		pos = __ffs(status);
    153		row = pos;
    154		status &= ~(1 << pos);
    155
    156		code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT);
    157		ske_ris = readl(keypad->reg_base + SKE_RIS);
    158		key_pressed = ske_ris & SKE_KPRISA;
    159
    160		input_event(input, EV_MSC, MSC_SCAN, code);
    161		input_report_key(input, keypad->keymap[code], key_pressed);
    162		input_sync(input);
    163		num_of_rows--;
    164	} while (num_of_rows);
    165}
    166
    167static void ske_keypad_read_data(struct ske_keypad *keypad)
    168{
    169	u8 status;
    170	int col = 0;
    171	int ske_asr, i;
    172
    173	/*
    174	 * Read the auto scan registers
    175	 *
    176	 * Each SKE_ASRx (x=0 to x=3) contains two row values.
    177	 * lower byte contains row value for column 2*x,
    178	 * upper byte contains row value for column 2*x + 1
    179	 */
    180	for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) {
    181		ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i));
    182		if (!ske_asr)
    183			continue;
    184
    185		/* now that ASRx is zero, find out the coloumn x and row y */
    186		status = ske_asr & 0xff;
    187		if (status) {
    188			col = i * 2;
    189			ske_keypad_report(keypad, status, col);
    190		}
    191		status = (ske_asr & 0xff00) >> 8;
    192		if (status) {
    193			col = (i * 2) + 1;
    194			ske_keypad_report(keypad, status, col);
    195		}
    196	}
    197}
    198
    199static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
    200{
    201	struct ske_keypad *keypad = dev_id;
    202	int timeout = keypad->board->debounce_ms;
    203
    204	/* disable auto scan interrupt; mask the interrupt generated */
    205	ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
    206	ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA);
    207
    208	while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --timeout)
    209		cpu_relax();
    210
    211	/* SKEx registers are stable and can be read */
    212	ske_keypad_read_data(keypad);
    213
    214	/* wait until raw interrupt is clear */
    215	while ((readl(keypad->reg_base + SKE_RIS)) && --timeout)
    216		msleep(KEY_PRESSED_DELAY);
    217
    218	/* enable auto scan interrupts */
    219	ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
    220
    221	return IRQ_HANDLED;
    222}
    223
    224static int __init ske_keypad_probe(struct platform_device *pdev)
    225{
    226	const struct ske_keypad_platform_data *plat =
    227			dev_get_platdata(&pdev->dev);
    228	struct ske_keypad *keypad;
    229	struct input_dev *input;
    230	struct resource *res;
    231	int irq;
    232	int error;
    233
    234	if (!plat) {
    235		dev_err(&pdev->dev, "invalid keypad platform data\n");
    236		return -EINVAL;
    237	}
    238
    239	irq = platform_get_irq(pdev, 0);
    240	if (irq < 0)
    241		return -EINVAL;
    242
    243	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    244	if (!res) {
    245		dev_err(&pdev->dev, "missing platform resources\n");
    246		return -EINVAL;
    247	}
    248
    249	keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL);
    250	input = input_allocate_device();
    251	if (!keypad || !input) {
    252		dev_err(&pdev->dev, "failed to allocate keypad memory\n");
    253		error = -ENOMEM;
    254		goto err_free_mem;
    255	}
    256
    257	keypad->irq = irq;
    258	keypad->board = plat;
    259	keypad->input = input;
    260	spin_lock_init(&keypad->ske_keypad_lock);
    261
    262	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
    263		dev_err(&pdev->dev, "failed to request I/O memory\n");
    264		error = -EBUSY;
    265		goto err_free_mem;
    266	}
    267
    268	keypad->reg_base = ioremap(res->start, resource_size(res));
    269	if (!keypad->reg_base) {
    270		dev_err(&pdev->dev, "failed to remap I/O memory\n");
    271		error = -ENXIO;
    272		goto err_free_mem_region;
    273	}
    274
    275	keypad->pclk = clk_get(&pdev->dev, "apb_pclk");
    276	if (IS_ERR(keypad->pclk)) {
    277		dev_err(&pdev->dev, "failed to get pclk\n");
    278		error = PTR_ERR(keypad->pclk);
    279		goto err_iounmap;
    280	}
    281
    282	keypad->clk = clk_get(&pdev->dev, NULL);
    283	if (IS_ERR(keypad->clk)) {
    284		dev_err(&pdev->dev, "failed to get clk\n");
    285		error = PTR_ERR(keypad->clk);
    286		goto err_pclk;
    287	}
    288
    289	input->id.bustype = BUS_HOST;
    290	input->name = "ux500-ske-keypad";
    291	input->dev.parent = &pdev->dev;
    292
    293	error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
    294					   SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS,
    295					   keypad->keymap, input);
    296	if (error) {
    297		dev_err(&pdev->dev, "Failed to build keymap\n");
    298		goto err_clk;
    299	}
    300
    301	input_set_capability(input, EV_MSC, MSC_SCAN);
    302	if (!plat->no_autorepeat)
    303		__set_bit(EV_REP, input->evbit);
    304
    305	error = clk_prepare_enable(keypad->pclk);
    306	if (error) {
    307		dev_err(&pdev->dev, "Failed to prepare/enable pclk\n");
    308		goto err_clk;
    309	}
    310
    311	error = clk_prepare_enable(keypad->clk);
    312	if (error) {
    313		dev_err(&pdev->dev, "Failed to prepare/enable clk\n");
    314		goto err_pclk_disable;
    315	}
    316
    317
    318	/* go through board initialization helpers */
    319	if (keypad->board->init)
    320		keypad->board->init();
    321
    322	error = ske_keypad_chip_init(keypad);
    323	if (error) {
    324		dev_err(&pdev->dev, "unable to init keypad hardware\n");
    325		goto err_clk_disable;
    326	}
    327
    328	error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq,
    329				     IRQF_ONESHOT, "ske-keypad", keypad);
    330	if (error) {
    331		dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
    332		goto err_clk_disable;
    333	}
    334
    335	error = input_register_device(input);
    336	if (error) {
    337		dev_err(&pdev->dev,
    338				"unable to register input device: %d\n", error);
    339		goto err_free_irq;
    340	}
    341
    342	if (plat->wakeup_enable)
    343		device_init_wakeup(&pdev->dev, true);
    344
    345	platform_set_drvdata(pdev, keypad);
    346
    347	return 0;
    348
    349err_free_irq:
    350	free_irq(keypad->irq, keypad);
    351err_clk_disable:
    352	clk_disable_unprepare(keypad->clk);
    353err_pclk_disable:
    354	clk_disable_unprepare(keypad->pclk);
    355err_clk:
    356	clk_put(keypad->clk);
    357err_pclk:
    358	clk_put(keypad->pclk);
    359err_iounmap:
    360	iounmap(keypad->reg_base);
    361err_free_mem_region:
    362	release_mem_region(res->start, resource_size(res));
    363err_free_mem:
    364	input_free_device(input);
    365	kfree(keypad);
    366	return error;
    367}
    368
    369static int ske_keypad_remove(struct platform_device *pdev)
    370{
    371	struct ske_keypad *keypad = platform_get_drvdata(pdev);
    372	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    373
    374	free_irq(keypad->irq, keypad);
    375
    376	input_unregister_device(keypad->input);
    377
    378	clk_disable_unprepare(keypad->clk);
    379	clk_put(keypad->clk);
    380
    381	if (keypad->board->exit)
    382		keypad->board->exit();
    383
    384	iounmap(keypad->reg_base);
    385	release_mem_region(res->start, resource_size(res));
    386	kfree(keypad);
    387
    388	return 0;
    389}
    390
    391#ifdef CONFIG_PM_SLEEP
    392static int ske_keypad_suspend(struct device *dev)
    393{
    394	struct platform_device *pdev = to_platform_device(dev);
    395	struct ske_keypad *keypad = platform_get_drvdata(pdev);
    396	int irq = platform_get_irq(pdev, 0);
    397
    398	if (device_may_wakeup(dev))
    399		enable_irq_wake(irq);
    400	else
    401		ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
    402
    403	return 0;
    404}
    405
    406static int ske_keypad_resume(struct device *dev)
    407{
    408	struct platform_device *pdev = to_platform_device(dev);
    409	struct ske_keypad *keypad = platform_get_drvdata(pdev);
    410	int irq = platform_get_irq(pdev, 0);
    411
    412	if (device_may_wakeup(dev))
    413		disable_irq_wake(irq);
    414	else
    415		ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
    416
    417	return 0;
    418}
    419#endif
    420
    421static SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops,
    422			 ske_keypad_suspend, ske_keypad_resume);
    423
    424static struct platform_driver ske_keypad_driver = {
    425	.driver = {
    426		.name = "nmk-ske-keypad",
    427		.pm = &ske_keypad_dev_pm_ops,
    428	},
    429	.remove = ske_keypad_remove,
    430};
    431
    432module_platform_driver_probe(ske_keypad_driver, ske_keypad_probe);
    433
    434MODULE_LICENSE("GPL v2");
    435MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
    436MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver");
    437MODULE_ALIAS("platform:nomadik-ske-keypad");