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

sh_keysc.c (7916B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * SuperH KEYSC Keypad Driver
      4 *
      5 * Copyright (C) 2008 Magnus Damm
      6 *
      7 * Based on gpio_keys.c, Copyright 2005 Phil Blundell
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/interrupt.h>
     13#include <linux/irq.h>
     14#include <linux/delay.h>
     15#include <linux/platform_device.h>
     16#include <linux/input.h>
     17#include <linux/input/sh_keysc.h>
     18#include <linux/bitmap.h>
     19#include <linux/pm_runtime.h>
     20#include <linux/io.h>
     21#include <linux/slab.h>
     22
     23static const struct {
     24	unsigned char kymd, keyout, keyin;
     25} sh_keysc_mode[] = {
     26	[SH_KEYSC_MODE_1] = { 0, 6, 5 },
     27	[SH_KEYSC_MODE_2] = { 1, 5, 6 },
     28	[SH_KEYSC_MODE_3] = { 2, 4, 7 },
     29	[SH_KEYSC_MODE_4] = { 3, 6, 6 },
     30	[SH_KEYSC_MODE_5] = { 4, 6, 7 },
     31	[SH_KEYSC_MODE_6] = { 5, 8, 8 },
     32};
     33
     34struct sh_keysc_priv {
     35	void __iomem *iomem_base;
     36	DECLARE_BITMAP(last_keys, SH_KEYSC_MAXKEYS);
     37	struct input_dev *input;
     38	struct sh_keysc_info pdata;
     39};
     40
     41#define KYCR1 0
     42#define KYCR2 1
     43#define KYINDR 2
     44#define KYOUTDR 3
     45
     46#define KYCR2_IRQ_LEVEL    0x10
     47#define KYCR2_IRQ_DISABLED 0x00
     48
     49static unsigned long sh_keysc_read(struct sh_keysc_priv *p, int reg_nr)
     50{
     51	return ioread16(p->iomem_base + (reg_nr << 2));
     52}
     53
     54static void sh_keysc_write(struct sh_keysc_priv *p, int reg_nr,
     55			   unsigned long value)
     56{
     57	iowrite16(value, p->iomem_base + (reg_nr << 2));
     58}
     59
     60static void sh_keysc_level_mode(struct sh_keysc_priv *p,
     61				unsigned long keys_set)
     62{
     63	struct sh_keysc_info *pdata = &p->pdata;
     64
     65	sh_keysc_write(p, KYOUTDR, 0);
     66	sh_keysc_write(p, KYCR2, KYCR2_IRQ_LEVEL | (keys_set << 8));
     67
     68	if (pdata->kycr2_delay)
     69		udelay(pdata->kycr2_delay);
     70}
     71
     72static void sh_keysc_map_dbg(struct device *dev, unsigned long *map,
     73			     const char *str)
     74{
     75	int k;
     76
     77	for (k = 0; k < BITS_TO_LONGS(SH_KEYSC_MAXKEYS); k++)
     78		dev_dbg(dev, "%s[%d] 0x%lx\n", str, k, map[k]);
     79}
     80
     81static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
     82{
     83	struct platform_device *pdev = dev_id;
     84	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
     85	struct sh_keysc_info *pdata = &priv->pdata;
     86	int keyout_nr = sh_keysc_mode[pdata->mode].keyout;
     87	int keyin_nr = sh_keysc_mode[pdata->mode].keyin;
     88	DECLARE_BITMAP(keys, SH_KEYSC_MAXKEYS);
     89	DECLARE_BITMAP(keys0, SH_KEYSC_MAXKEYS);
     90	DECLARE_BITMAP(keys1, SH_KEYSC_MAXKEYS);
     91	unsigned char keyin_set, tmp;
     92	int i, k, n;
     93
     94	dev_dbg(&pdev->dev, "isr!\n");
     95
     96	bitmap_fill(keys1, SH_KEYSC_MAXKEYS);
     97	bitmap_zero(keys0, SH_KEYSC_MAXKEYS);
     98
     99	do {
    100		bitmap_zero(keys, SH_KEYSC_MAXKEYS);
    101		keyin_set = 0;
    102
    103		sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED);
    104
    105		for (i = 0; i < keyout_nr; i++) {
    106			n = keyin_nr * i;
    107
    108			/* drive one KEYOUT pin low, read KEYIN pins */
    109			sh_keysc_write(priv, KYOUTDR, 0xffff ^ (3 << (i * 2)));
    110			udelay(pdata->delay);
    111			tmp = sh_keysc_read(priv, KYINDR);
    112
    113			/* set bit if key press has been detected */
    114			for (k = 0; k < keyin_nr; k++) {
    115				if (tmp & (1 << k))
    116					__set_bit(n + k, keys);
    117			}
    118
    119			/* keep track of which KEYIN bits that have been set */
    120			keyin_set |= tmp ^ ((1 << keyin_nr) - 1);
    121		}
    122
    123		sh_keysc_level_mode(priv, keyin_set);
    124
    125		bitmap_complement(keys, keys, SH_KEYSC_MAXKEYS);
    126		bitmap_and(keys1, keys1, keys, SH_KEYSC_MAXKEYS);
    127		bitmap_or(keys0, keys0, keys, SH_KEYSC_MAXKEYS);
    128
    129		sh_keysc_map_dbg(&pdev->dev, keys, "keys");
    130
    131	} while (sh_keysc_read(priv, KYCR2) & 0x01);
    132
    133	sh_keysc_map_dbg(&pdev->dev, priv->last_keys, "last_keys");
    134	sh_keysc_map_dbg(&pdev->dev, keys0, "keys0");
    135	sh_keysc_map_dbg(&pdev->dev, keys1, "keys1");
    136
    137	for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
    138		k = pdata->keycodes[i];
    139		if (!k)
    140			continue;
    141
    142		if (test_bit(i, keys0) == test_bit(i, priv->last_keys))
    143			continue;
    144
    145		if (test_bit(i, keys1) || test_bit(i, keys0)) {
    146			input_event(priv->input, EV_KEY, k, 1);
    147			__set_bit(i, priv->last_keys);
    148		}
    149
    150		if (!test_bit(i, keys1)) {
    151			input_event(priv->input, EV_KEY, k, 0);
    152			__clear_bit(i, priv->last_keys);
    153		}
    154
    155	}
    156	input_sync(priv->input);
    157
    158	return IRQ_HANDLED;
    159}
    160
    161static int sh_keysc_probe(struct platform_device *pdev)
    162{
    163	struct sh_keysc_priv *priv;
    164	struct sh_keysc_info *pdata;
    165	struct resource *res;
    166	struct input_dev *input;
    167	int i;
    168	int irq, error;
    169
    170	if (!dev_get_platdata(&pdev->dev)) {
    171		dev_err(&pdev->dev, "no platform data defined\n");
    172		error = -EINVAL;
    173		goto err0;
    174	}
    175
    176	error = -ENXIO;
    177	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    178	if (res == NULL) {
    179		dev_err(&pdev->dev, "failed to get I/O memory\n");
    180		goto err0;
    181	}
    182
    183	irq = platform_get_irq(pdev, 0);
    184	if (irq < 0)
    185		goto err0;
    186
    187	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    188	if (priv == NULL) {
    189		dev_err(&pdev->dev, "failed to allocate driver data\n");
    190		error = -ENOMEM;
    191		goto err0;
    192	}
    193
    194	platform_set_drvdata(pdev, priv);
    195	memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata));
    196	pdata = &priv->pdata;
    197
    198	priv->iomem_base = ioremap(res->start, resource_size(res));
    199	if (priv->iomem_base == NULL) {
    200		dev_err(&pdev->dev, "failed to remap I/O memory\n");
    201		error = -ENXIO;
    202		goto err1;
    203	}
    204
    205	priv->input = input_allocate_device();
    206	if (!priv->input) {
    207		dev_err(&pdev->dev, "failed to allocate input device\n");
    208		error = -ENOMEM;
    209		goto err2;
    210	}
    211
    212	input = priv->input;
    213	input->evbit[0] = BIT_MASK(EV_KEY);
    214
    215	input->name = pdev->name;
    216	input->phys = "sh-keysc-keys/input0";
    217	input->dev.parent = &pdev->dev;
    218
    219	input->id.bustype = BUS_HOST;
    220	input->id.vendor = 0x0001;
    221	input->id.product = 0x0001;
    222	input->id.version = 0x0100;
    223
    224	input->keycode = pdata->keycodes;
    225	input->keycodesize = sizeof(pdata->keycodes[0]);
    226	input->keycodemax = ARRAY_SIZE(pdata->keycodes);
    227
    228	error = request_threaded_irq(irq, NULL, sh_keysc_isr, IRQF_ONESHOT,
    229				     dev_name(&pdev->dev), pdev);
    230	if (error) {
    231		dev_err(&pdev->dev, "failed to request IRQ\n");
    232		goto err3;
    233	}
    234
    235	for (i = 0; i < SH_KEYSC_MAXKEYS; i++)
    236		__set_bit(pdata->keycodes[i], input->keybit);
    237	__clear_bit(KEY_RESERVED, input->keybit);
    238
    239	error = input_register_device(input);
    240	if (error) {
    241		dev_err(&pdev->dev, "failed to register input device\n");
    242		goto err4;
    243	}
    244
    245	pm_runtime_enable(&pdev->dev);
    246	pm_runtime_get_sync(&pdev->dev);
    247
    248	sh_keysc_write(priv, KYCR1, (sh_keysc_mode[pdata->mode].kymd << 8) |
    249		       pdata->scan_timing);
    250	sh_keysc_level_mode(priv, 0);
    251
    252	device_init_wakeup(&pdev->dev, 1);
    253
    254	return 0;
    255
    256 err4:
    257	free_irq(irq, pdev);
    258 err3:
    259	input_free_device(input);
    260 err2:
    261	iounmap(priv->iomem_base);
    262 err1:
    263	kfree(priv);
    264 err0:
    265	return error;
    266}
    267
    268static int sh_keysc_remove(struct platform_device *pdev)
    269{
    270	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
    271
    272	sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED);
    273
    274	input_unregister_device(priv->input);
    275	free_irq(platform_get_irq(pdev, 0), pdev);
    276	iounmap(priv->iomem_base);
    277
    278	pm_runtime_put_sync(&pdev->dev);
    279	pm_runtime_disable(&pdev->dev);
    280
    281	kfree(priv);
    282
    283	return 0;
    284}
    285
    286#ifdef CONFIG_PM_SLEEP
    287static int sh_keysc_suspend(struct device *dev)
    288{
    289	struct platform_device *pdev = to_platform_device(dev);
    290	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
    291	int irq = platform_get_irq(pdev, 0);
    292	unsigned short value;
    293
    294	value = sh_keysc_read(priv, KYCR1);
    295
    296	if (device_may_wakeup(dev)) {
    297		sh_keysc_write(priv, KYCR1, value | 0x80);
    298		enable_irq_wake(irq);
    299	} else {
    300		sh_keysc_write(priv, KYCR1, value & ~0x80);
    301		pm_runtime_put_sync(dev);
    302	}
    303
    304	return 0;
    305}
    306
    307static int sh_keysc_resume(struct device *dev)
    308{
    309	struct platform_device *pdev = to_platform_device(dev);
    310	int irq = platform_get_irq(pdev, 0);
    311
    312	if (device_may_wakeup(dev))
    313		disable_irq_wake(irq);
    314	else
    315		pm_runtime_get_sync(dev);
    316
    317	return 0;
    318}
    319#endif
    320
    321static SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
    322			 sh_keysc_suspend, sh_keysc_resume);
    323
    324static struct platform_driver sh_keysc_device_driver = {
    325	.probe		= sh_keysc_probe,
    326	.remove		= sh_keysc_remove,
    327	.driver		= {
    328		.name	= "sh_keysc",
    329		.pm	= &sh_keysc_dev_pm_ops,
    330	}
    331};
    332module_platform_driver(sh_keysc_device_driver);
    333
    334MODULE_AUTHOR("Magnus Damm");
    335MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
    336MODULE_LICENSE("GPL");