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

cpcap-pwrbutton.c (3061B)


      1/**
      2 * CPCAP Power Button Input Driver
      3 *
      4 * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
      5 *
      6 * This file is subject to the terms and conditions of the GNU General
      7 * Public License. See the file "COPYING" in the main directory of this
      8 * archive for more details.
      9 *
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14 */
     15
     16#include <linux/module.h>
     17#include <linux/init.h>
     18#include <linux/kernel.h>
     19#include <linux/errno.h>
     20#include <linux/input.h>
     21#include <linux/interrupt.h>
     22#include <linux/regmap.h>
     23#include <linux/of.h>
     24#include <linux/platform_device.h>
     25#include <linux/mfd/motorola-cpcap.h>
     26
     27#define CPCAP_IRQ_ON 23
     28#define CPCAP_IRQ_ON_BITMASK (1 << (CPCAP_IRQ_ON % 16))
     29
     30struct cpcap_power_button {
     31	struct regmap *regmap;
     32	struct input_dev *idev;
     33	struct device *dev;
     34};
     35
     36static irqreturn_t powerbutton_irq(int irq, void *_button)
     37{
     38	struct cpcap_power_button *button = _button;
     39	int val;
     40
     41	val = cpcap_sense_virq(button->regmap, irq);
     42	if (val < 0) {
     43		dev_err(button->dev, "irq read failed: %d", val);
     44		return IRQ_HANDLED;
     45	}
     46
     47	pm_wakeup_event(button->dev, 0);
     48	input_report_key(button->idev, KEY_POWER, val);
     49	input_sync(button->idev);
     50
     51	return IRQ_HANDLED;
     52}
     53
     54static int cpcap_power_button_probe(struct platform_device *pdev)
     55{
     56	struct cpcap_power_button *button;
     57	int irq;
     58	int err;
     59
     60	irq = platform_get_irq(pdev, 0);
     61	if (irq < 0)
     62		return irq;
     63
     64	button = devm_kmalloc(&pdev->dev, sizeof(*button), GFP_KERNEL);
     65	if (!button)
     66		return -ENOMEM;
     67
     68	button->idev = devm_input_allocate_device(&pdev->dev);
     69	if (!button->idev)
     70		return -ENOMEM;
     71
     72	button->regmap = dev_get_regmap(pdev->dev.parent, NULL);
     73	if (!button->regmap)
     74		return -ENODEV;
     75
     76	button->dev = &pdev->dev;
     77
     78	button->idev->name = "cpcap-pwrbutton";
     79	button->idev->phys = "cpcap-pwrbutton/input0";
     80	input_set_capability(button->idev, EV_KEY, KEY_POWER);
     81
     82	err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
     83		powerbutton_irq, IRQF_ONESHOT, "cpcap_pwrbutton", button);
     84	if (err < 0) {
     85		dev_err(&pdev->dev, "IRQ request failed: %d\n", err);
     86		return err;
     87	}
     88
     89	err = input_register_device(button->idev);
     90	if (err) {
     91		dev_err(&pdev->dev, "Input register failed: %d\n", err);
     92		return err;
     93	}
     94
     95	device_init_wakeup(&pdev->dev, true);
     96
     97	return 0;
     98}
     99
    100#ifdef CONFIG_OF
    101static const struct of_device_id cpcap_pwrbutton_dt_match_table[] = {
    102	{ .compatible = "motorola,cpcap-pwrbutton" },
    103	{},
    104};
    105MODULE_DEVICE_TABLE(of, cpcap_pwrbutton_dt_match_table);
    106#endif
    107
    108static struct platform_driver cpcap_power_button_driver = {
    109	.probe		= cpcap_power_button_probe,
    110	.driver		= {
    111		.name	= "cpcap-pwrbutton",
    112		.of_match_table = of_match_ptr(cpcap_pwrbutton_dt_match_table),
    113	},
    114};
    115module_platform_driver(cpcap_power_button_driver);
    116
    117MODULE_ALIAS("platform:cpcap-pwrbutton");
    118MODULE_DESCRIPTION("CPCAP Power Button");
    119MODULE_LICENSE("GPL");
    120MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");