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

sgi_btns.c (2880B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  SGI Volume Button interface driver
      4 *
      5 *  Copyright (C) 2008  Thomas Bogendoerfer <tsbogend@alpha.franken.de>
      6 */
      7#include <linux/input.h>
      8#include <linux/ioport.h>
      9#include <linux/module.h>
     10#include <linux/platform_device.h>
     11#include <linux/slab.h>
     12
     13#ifdef CONFIG_SGI_IP22
     14#include <asm/sgi/ioc.h>
     15
     16static inline u8 button_status(void)
     17{
     18	u8 status;
     19
     20	status = readb(&sgioc->panel) ^ 0xa0;
     21	return ((status & 0x80) >> 6) | ((status & 0x20) >> 5);
     22}
     23#endif
     24
     25#ifdef CONFIG_SGI_IP32
     26#include <asm/ip32/mace.h>
     27
     28static inline u8 button_status(void)
     29{
     30	u64 status;
     31
     32	status = readq(&mace->perif.audio.control);
     33	writeq(status & ~(3U << 23), &mace->perif.audio.control);
     34
     35	return (status >> 23) & 3;
     36}
     37#endif
     38
     39#define BUTTONS_POLL_INTERVAL	30	/* msec */
     40#define BUTTONS_COUNT_THRESHOLD	3
     41
     42static const unsigned short sgi_map[] = {
     43	KEY_VOLUMEDOWN,
     44	KEY_VOLUMEUP
     45};
     46
     47struct buttons_dev {
     48	unsigned short keymap[ARRAY_SIZE(sgi_map)];
     49	int count[ARRAY_SIZE(sgi_map)];
     50};
     51
     52static void handle_buttons(struct input_dev *input)
     53{
     54	struct buttons_dev *bdev = input_get_drvdata(input);
     55	u8 status;
     56	int i;
     57
     58	status = button_status();
     59
     60	for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
     61		if (status & (1U << i)) {
     62			if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
     63				input_event(input, EV_MSC, MSC_SCAN, i);
     64				input_report_key(input, bdev->keymap[i], 1);
     65				input_sync(input);
     66			}
     67		} else {
     68			if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
     69				input_event(input, EV_MSC, MSC_SCAN, i);
     70				input_report_key(input, bdev->keymap[i], 0);
     71				input_sync(input);
     72			}
     73			bdev->count[i] = 0;
     74		}
     75	}
     76}
     77
     78static int sgi_buttons_probe(struct platform_device *pdev)
     79{
     80	struct buttons_dev *bdev;
     81	struct input_dev *input;
     82	int error, i;
     83
     84	bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
     85	if (!bdev)
     86		return -ENOMEM;
     87
     88	input = devm_input_allocate_device(&pdev->dev);
     89	if (!input)
     90		return -ENOMEM;
     91
     92	memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
     93
     94	input_set_drvdata(input, bdev);
     95
     96	input->name = "SGI buttons";
     97	input->phys = "sgi/input0";
     98	input->id.bustype = BUS_HOST;
     99
    100	input->keycode = bdev->keymap;
    101	input->keycodemax = ARRAY_SIZE(bdev->keymap);
    102	input->keycodesize = sizeof(unsigned short);
    103
    104	input_set_capability(input, EV_MSC, MSC_SCAN);
    105	__set_bit(EV_KEY, input->evbit);
    106	for (i = 0; i < ARRAY_SIZE(sgi_map); i++)
    107		__set_bit(bdev->keymap[i], input->keybit);
    108	__clear_bit(KEY_RESERVED, input->keybit);
    109
    110	error = input_setup_polling(input, handle_buttons);
    111	if (error)
    112		return error;
    113
    114	input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
    115
    116	error = input_register_device(input);
    117	if (error)
    118		return error;
    119
    120	return 0;
    121}
    122
    123static struct platform_driver sgi_buttons_driver = {
    124	.probe	= sgi_buttons_probe,
    125	.driver	= {
    126		.name	= "sgibtns",
    127	},
    128};
    129module_platform_driver(sgi_buttons_driver);
    130
    131MODULE_LICENSE("GPL");