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

omap4-keypad.c (12873B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * OMAP4 Keypad Driver
      4 *
      5 * Copyright (C) 2010 Texas Instruments
      6 *
      7 * Author: Abraham Arce <x0066660@ti.com>
      8 * Initial Code: Syed Rafiuddin <rafiuddin.syed@ti.com>
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/interrupt.h>
     13#include <linux/platform_device.h>
     14#include <linux/errno.h>
     15#include <linux/io.h>
     16#include <linux/of.h>
     17#include <linux/input.h>
     18#include <linux/input/matrix_keypad.h>
     19#include <linux/slab.h>
     20#include <linux/pm_runtime.h>
     21#include <linux/pm_wakeirq.h>
     22
     23/* OMAP4 registers */
     24#define OMAP4_KBD_REVISION		0x00
     25#define OMAP4_KBD_SYSCONFIG		0x10
     26#define OMAP4_KBD_SYSSTATUS		0x14
     27#define OMAP4_KBD_IRQSTATUS		0x18
     28#define OMAP4_KBD_IRQENABLE		0x1C
     29#define OMAP4_KBD_WAKEUPENABLE		0x20
     30#define OMAP4_KBD_PENDING		0x24
     31#define OMAP4_KBD_CTRL			0x28
     32#define OMAP4_KBD_DEBOUNCINGTIME	0x2C
     33#define OMAP4_KBD_LONGKEYTIME		0x30
     34#define OMAP4_KBD_TIMEOUT		0x34
     35#define OMAP4_KBD_STATEMACHINE		0x38
     36#define OMAP4_KBD_ROWINPUTS		0x3C
     37#define OMAP4_KBD_COLUMNOUTPUTS		0x40
     38#define OMAP4_KBD_FULLCODE31_0		0x44
     39#define OMAP4_KBD_FULLCODE63_32		0x48
     40
     41/* OMAP4 bit definitions */
     42#define OMAP4_DEF_IRQENABLE_EVENTEN	BIT(0)
     43#define OMAP4_DEF_IRQENABLE_LONGKEY	BIT(1)
     44#define OMAP4_DEF_WUP_EVENT_ENA		BIT(0)
     45#define OMAP4_DEF_WUP_LONG_KEY_ENA	BIT(1)
     46#define OMAP4_DEF_CTRL_NOSOFTMODE	BIT(1)
     47#define OMAP4_DEF_CTRL_PTV_SHIFT	2
     48
     49/* OMAP4 values */
     50#define OMAP4_VAL_IRQDISABLE		0x0
     51
     52/*
     53 * Errata i689: If a key is released for a time shorter than debounce time,
     54 * the keyboard will idle and never detect the key release. The workaround
     55 * is to use at least a 12ms debounce time. See omap5432 TRM chapter
     56 * "26.4.6.2 Keyboard Controller Timer" for more information.
     57 */
     58#define OMAP4_KEYPAD_PTV_DIV_128        0x6
     59#define OMAP4_KEYPAD_DEBOUNCINGTIME_MS(dbms, ptv)     \
     60	((((dbms) * 1000) / ((1 << ((ptv) + 1)) * (1000000 / 32768))) - 1)
     61#define OMAP4_VAL_DEBOUNCINGTIME_16MS					\
     62	OMAP4_KEYPAD_DEBOUNCINGTIME_MS(16, OMAP4_KEYPAD_PTV_DIV_128)
     63#define OMAP4_KEYPAD_AUTOIDLE_MS	50	/* Approximate measured time */
     64#define OMAP4_KEYPAD_IDLE_CHECK_MS	(OMAP4_KEYPAD_AUTOIDLE_MS / 2)
     65
     66enum {
     67	KBD_REVISION_OMAP4 = 0,
     68	KBD_REVISION_OMAP5,
     69};
     70
     71struct omap4_keypad {
     72	struct input_dev *input;
     73
     74	void __iomem *base;
     75	unsigned int irq;
     76	struct mutex lock;		/* for key scan */
     77
     78	unsigned int rows;
     79	unsigned int cols;
     80	u32 reg_offset;
     81	u32 irqreg_offset;
     82	unsigned int row_shift;
     83	bool no_autorepeat;
     84	u64 keys;
     85	unsigned short *keymap;
     86};
     87
     88static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
     89{
     90	return __raw_readl(keypad_data->base +
     91				keypad_data->reg_offset + offset);
     92}
     93
     94static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
     95{
     96	__raw_writel(value,
     97		     keypad_data->base + keypad_data->reg_offset + offset);
     98}
     99
    100static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
    101{
    102	return __raw_readl(keypad_data->base +
    103				keypad_data->irqreg_offset + offset);
    104}
    105
    106static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
    107			     u32 offset, u32 value)
    108{
    109	__raw_writel(value,
    110		     keypad_data->base + keypad_data->irqreg_offset + offset);
    111}
    112
    113static int omap4_keypad_report_keys(struct omap4_keypad *keypad_data,
    114				    u64 keys, bool down)
    115{
    116	struct input_dev *input_dev = keypad_data->input;
    117	unsigned int col, row, code;
    118	DECLARE_BITMAP(mask, 64);
    119	unsigned long bit;
    120	int events = 0;
    121
    122	bitmap_from_u64(mask, keys);
    123
    124	for_each_set_bit(bit, mask, keypad_data->rows * BITS_PER_BYTE) {
    125		row = bit / BITS_PER_BYTE;
    126		col = bit % BITS_PER_BYTE;
    127		code = MATRIX_SCAN_CODE(row, col, keypad_data->row_shift);
    128
    129		input_event(input_dev, EV_MSC, MSC_SCAN, code);
    130		input_report_key(input_dev, keypad_data->keymap[code], down);
    131
    132		events++;
    133	}
    134
    135	if (events)
    136		input_sync(input_dev);
    137
    138	return events;
    139}
    140
    141static void omap4_keypad_scan_keys(struct omap4_keypad *keypad_data, u64 keys)
    142{
    143	u64 changed;
    144
    145	mutex_lock(&keypad_data->lock);
    146
    147	changed = keys ^ keypad_data->keys;
    148
    149	/*
    150	 * Report key up events separately and first. This matters in case we
    151	 * lost key-up interrupt and just now catching up.
    152	 */
    153	omap4_keypad_report_keys(keypad_data, changed & ~keys, false);
    154
    155	/* Report key down events */
    156	omap4_keypad_report_keys(keypad_data, changed & keys, true);
    157
    158	keypad_data->keys = keys;
    159
    160	mutex_unlock(&keypad_data->lock);
    161}
    162
    163/* Interrupt handlers */
    164static irqreturn_t omap4_keypad_irq_handler(int irq, void *dev_id)
    165{
    166	struct omap4_keypad *keypad_data = dev_id;
    167
    168	if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS))
    169		return IRQ_WAKE_THREAD;
    170
    171	return IRQ_NONE;
    172}
    173
    174static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
    175{
    176	struct omap4_keypad *keypad_data = dev_id;
    177	struct device *dev = keypad_data->input->dev.parent;
    178	u32 low, high;
    179	int error;
    180	u64 keys;
    181
    182	error = pm_runtime_get_sync(dev);
    183	if (error < 0) {
    184		pm_runtime_put_noidle(dev);
    185		return IRQ_NONE;
    186	}
    187
    188	low = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
    189	high = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
    190	keys = low | (u64)high << 32;
    191
    192	omap4_keypad_scan_keys(keypad_data, keys);
    193
    194	/* clear pending interrupts */
    195	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
    196			 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
    197
    198	pm_runtime_mark_last_busy(dev);
    199	pm_runtime_put_autosuspend(dev);
    200
    201	return IRQ_HANDLED;
    202}
    203
    204static int omap4_keypad_open(struct input_dev *input)
    205{
    206	struct omap4_keypad *keypad_data = input_get_drvdata(input);
    207	struct device *dev = input->dev.parent;
    208	int error;
    209
    210	error = pm_runtime_get_sync(dev);
    211	if (error < 0) {
    212		pm_runtime_put_noidle(dev);
    213		return error;
    214	}
    215
    216	disable_irq(keypad_data->irq);
    217
    218	kbd_writel(keypad_data, OMAP4_KBD_CTRL,
    219			OMAP4_DEF_CTRL_NOSOFTMODE |
    220			(OMAP4_KEYPAD_PTV_DIV_128 << OMAP4_DEF_CTRL_PTV_SHIFT));
    221	kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
    222			OMAP4_VAL_DEBOUNCINGTIME_16MS);
    223	/* clear pending interrupts */
    224	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
    225			 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
    226	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
    227			OMAP4_DEF_IRQENABLE_EVENTEN);
    228	kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
    229			OMAP4_DEF_WUP_EVENT_ENA);
    230
    231	enable_irq(keypad_data->irq);
    232
    233	pm_runtime_mark_last_busy(dev);
    234	pm_runtime_put_autosuspend(dev);
    235
    236	return 0;
    237}
    238
    239static void omap4_keypad_stop(struct omap4_keypad *keypad_data)
    240{
    241	/* Disable interrupts and wake-up events */
    242	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
    243			 OMAP4_VAL_IRQDISABLE);
    244	kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 0);
    245
    246	/* clear pending interrupts */
    247	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
    248			 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
    249}
    250
    251static void omap4_keypad_close(struct input_dev *input)
    252{
    253	struct omap4_keypad *keypad_data = input_get_drvdata(input);
    254	struct device *dev = input->dev.parent;
    255	int error;
    256
    257	error = pm_runtime_get_sync(dev);
    258	if (error < 0)
    259		pm_runtime_put_noidle(dev);
    260
    261	disable_irq(keypad_data->irq);
    262	omap4_keypad_stop(keypad_data);
    263	enable_irq(keypad_data->irq);
    264
    265	pm_runtime_mark_last_busy(dev);
    266	pm_runtime_put_autosuspend(dev);
    267}
    268
    269static int omap4_keypad_parse_dt(struct device *dev,
    270				 struct omap4_keypad *keypad_data)
    271{
    272	struct device_node *np = dev->of_node;
    273	int err;
    274
    275	err = matrix_keypad_parse_properties(dev, &keypad_data->rows,
    276					     &keypad_data->cols);
    277	if (err)
    278		return err;
    279
    280	if (of_get_property(np, "linux,input-no-autorepeat", NULL))
    281		keypad_data->no_autorepeat = true;
    282
    283	return 0;
    284}
    285
    286static int omap4_keypad_check_revision(struct device *dev,
    287				       struct omap4_keypad *keypad_data)
    288{
    289	unsigned int rev;
    290
    291	rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
    292	rev &= 0x03 << 30;
    293	rev >>= 30;
    294	switch (rev) {
    295	case KBD_REVISION_OMAP4:
    296		keypad_data->reg_offset = 0x00;
    297		keypad_data->irqreg_offset = 0x00;
    298		break;
    299	case KBD_REVISION_OMAP5:
    300		keypad_data->reg_offset = 0x10;
    301		keypad_data->irqreg_offset = 0x0c;
    302		break;
    303	default:
    304		dev_err(dev, "Keypad reports unsupported revision %d", rev);
    305		return -EINVAL;
    306	}
    307
    308	return 0;
    309}
    310
    311/*
    312 * Errata ID i689 "1.32 Keyboard Key Up Event Can Be Missed".
    313 * Interrupt may not happen for key-up events. We must clear stuck
    314 * key-up events after the keyboard hardware has auto-idled.
    315 */
    316static int __maybe_unused omap4_keypad_runtime_suspend(struct device *dev)
    317{
    318	struct platform_device *pdev = to_platform_device(dev);
    319	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
    320	u32 active;
    321
    322	active = kbd_readl(keypad_data, OMAP4_KBD_STATEMACHINE);
    323	if (active) {
    324		pm_runtime_mark_last_busy(dev);
    325		return -EBUSY;
    326	}
    327
    328	omap4_keypad_scan_keys(keypad_data, 0);
    329
    330	return 0;
    331}
    332
    333static const struct dev_pm_ops omap4_keypad_pm_ops = {
    334	SET_RUNTIME_PM_OPS(omap4_keypad_runtime_suspend, NULL, NULL)
    335};
    336
    337static void omap4_disable_pm(void *d)
    338{
    339	pm_runtime_dont_use_autosuspend(d);
    340	pm_runtime_disable(d);
    341}
    342
    343static int omap4_keypad_probe(struct platform_device *pdev)
    344{
    345	struct device *dev = &pdev->dev;
    346	struct omap4_keypad *keypad_data;
    347	struct input_dev *input_dev;
    348	struct resource *res;
    349	unsigned int max_keys;
    350	int irq;
    351	int error;
    352
    353	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    354	if (!res) {
    355		dev_err(&pdev->dev, "no base address specified\n");
    356		return -EINVAL;
    357	}
    358
    359	irq = platform_get_irq(pdev, 0);
    360	if (irq < 0)
    361		return irq;
    362
    363	keypad_data = devm_kzalloc(dev, sizeof(*keypad_data), GFP_KERNEL);
    364	if (!keypad_data) {
    365		dev_err(dev, "keypad_data memory allocation failed\n");
    366		return -ENOMEM;
    367	}
    368
    369	keypad_data->irq = irq;
    370	mutex_init(&keypad_data->lock);
    371	platform_set_drvdata(pdev, keypad_data);
    372
    373	error = omap4_keypad_parse_dt(dev, keypad_data);
    374	if (error)
    375		return error;
    376
    377	keypad_data->base = devm_ioremap_resource(dev, res);
    378	if (IS_ERR(keypad_data->base))
    379		return PTR_ERR(keypad_data->base);
    380
    381	pm_runtime_use_autosuspend(dev);
    382	pm_runtime_set_autosuspend_delay(dev, OMAP4_KEYPAD_IDLE_CHECK_MS);
    383	pm_runtime_enable(dev);
    384
    385	error = devm_add_action_or_reset(dev, omap4_disable_pm, dev);
    386	if (error) {
    387		dev_err(dev, "unable to register cleanup action\n");
    388		return error;
    389	}
    390
    391	/*
    392	 * Enable clocks for the keypad module so that we can read
    393	 * revision register.
    394	 */
    395	error = pm_runtime_get_sync(dev);
    396	if (error < 0) {
    397		dev_err(dev, "pm_runtime_get_sync() failed\n");
    398		pm_runtime_put_noidle(dev);
    399		return error;
    400	}
    401
    402	error = omap4_keypad_check_revision(dev, keypad_data);
    403	if (!error) {
    404		/* Ensure device does not raise interrupts */
    405		omap4_keypad_stop(keypad_data);
    406	}
    407
    408	pm_runtime_mark_last_busy(dev);
    409	pm_runtime_put_autosuspend(dev);
    410	if (error)
    411		return error;
    412
    413	/* input device allocation */
    414	keypad_data->input = input_dev = devm_input_allocate_device(dev);
    415	if (!input_dev)
    416		return -ENOMEM;
    417
    418	input_dev->name = pdev->name;
    419	input_dev->id.bustype = BUS_HOST;
    420	input_dev->id.vendor = 0x0001;
    421	input_dev->id.product = 0x0001;
    422	input_dev->id.version = 0x0001;
    423
    424	input_dev->open = omap4_keypad_open;
    425	input_dev->close = omap4_keypad_close;
    426
    427	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
    428	if (!keypad_data->no_autorepeat)
    429		__set_bit(EV_REP, input_dev->evbit);
    430
    431	input_set_drvdata(input_dev, keypad_data);
    432
    433	keypad_data->row_shift = get_count_order(keypad_data->cols);
    434	max_keys = keypad_data->rows << keypad_data->row_shift;
    435	keypad_data->keymap = devm_kcalloc(dev,
    436					   max_keys,
    437					   sizeof(keypad_data->keymap[0]),
    438					   GFP_KERNEL);
    439	if (!keypad_data->keymap) {
    440		dev_err(dev, "Not enough memory for keymap\n");
    441		return -ENOMEM;
    442	}
    443
    444	error = matrix_keypad_build_keymap(NULL, NULL,
    445					   keypad_data->rows, keypad_data->cols,
    446					   keypad_data->keymap, input_dev);
    447	if (error) {
    448		dev_err(dev, "failed to build keymap\n");
    449		return error;
    450	}
    451
    452	error = devm_request_threaded_irq(dev, keypad_data->irq,
    453					  omap4_keypad_irq_handler,
    454					  omap4_keypad_irq_thread_fn,
    455					  IRQF_ONESHOT,
    456					  "omap4-keypad", keypad_data);
    457	if (error) {
    458		dev_err(dev, "failed to register interrupt\n");
    459		return error;
    460	}
    461
    462	error = input_register_device(keypad_data->input);
    463	if (error) {
    464		dev_err(dev, "failed to register input device\n");
    465		return error;
    466	}
    467
    468	device_init_wakeup(dev, true);
    469	error = dev_pm_set_wake_irq(dev, keypad_data->irq);
    470	if (error)
    471		dev_warn(dev, "failed to set up wakeup irq: %d\n", error);
    472
    473	return 0;
    474}
    475
    476static int omap4_keypad_remove(struct platform_device *pdev)
    477{
    478	dev_pm_clear_wake_irq(&pdev->dev);
    479
    480	return 0;
    481}
    482
    483static const struct of_device_id omap_keypad_dt_match[] = {
    484	{ .compatible = "ti,omap4-keypad" },
    485	{},
    486};
    487MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
    488
    489static struct platform_driver omap4_keypad_driver = {
    490	.probe		= omap4_keypad_probe,
    491	.remove		= omap4_keypad_remove,
    492	.driver		= {
    493		.name	= "omap4-keypad",
    494		.of_match_table = omap_keypad_dt_match,
    495		.pm = &omap4_keypad_pm_ops,
    496	},
    497};
    498module_platform_driver(omap4_keypad_driver);
    499
    500MODULE_AUTHOR("Texas Instruments");
    501MODULE_DESCRIPTION("OMAP4 Keypad Driver");
    502MODULE_LICENSE("GPL");
    503MODULE_ALIAS("platform:omap4-keypad");