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

push-switch.c (2973B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Generic push-switch framework
      4 *
      5 * Copyright (C) 2006  Paul Mundt
      6 */
      7#include <linux/init.h>
      8#include <linux/slab.h>
      9#include <linux/module.h>
     10#include <linux/interrupt.h>
     11#include <linux/platform_device.h>
     12#include <asm/push-switch.h>
     13
     14#define DRV_NAME "push-switch"
     15#define DRV_VERSION "0.1.1"
     16
     17static ssize_t switch_show(struct device *dev,
     18			   struct device_attribute *attr,
     19			   char *buf)
     20{
     21	struct push_switch_platform_info *psw_info = dev->platform_data;
     22	return sprintf(buf, "%s\n", psw_info->name);
     23}
     24static DEVICE_ATTR_RO(switch);
     25
     26static void switch_timer(struct timer_list *t)
     27{
     28	struct push_switch *psw = from_timer(psw, t, debounce);
     29
     30	schedule_work(&psw->work);
     31}
     32
     33static void switch_work_handler(struct work_struct *work)
     34{
     35	struct push_switch *psw = container_of(work, struct push_switch, work);
     36	struct platform_device *pdev = psw->pdev;
     37
     38	psw->state = 0;
     39
     40	kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE);
     41}
     42
     43static int switch_drv_probe(struct platform_device *pdev)
     44{
     45	struct push_switch_platform_info *psw_info;
     46	struct push_switch *psw;
     47	int ret, irq;
     48
     49	psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL);
     50	if (unlikely(!psw))
     51		return -ENOMEM;
     52
     53	irq = platform_get_irq(pdev, 0);
     54	if (unlikely(irq < 0)) {
     55		ret = -ENODEV;
     56		goto err;
     57	}
     58
     59	psw_info = pdev->dev.platform_data;
     60	BUG_ON(!psw_info);
     61
     62	ret = request_irq(irq, psw_info->irq_handler,
     63			  psw_info->irq_flags,
     64			  psw_info->name ? psw_info->name : DRV_NAME, pdev);
     65	if (unlikely(ret < 0))
     66		goto err;
     67
     68	if (psw_info->name) {
     69		ret = device_create_file(&pdev->dev, &dev_attr_switch);
     70		if (unlikely(ret)) {
     71			dev_err(&pdev->dev, "Failed creating device attrs\n");
     72			ret = -EINVAL;
     73			goto err_irq;
     74		}
     75	}
     76
     77	INIT_WORK(&psw->work, switch_work_handler);
     78	timer_setup(&psw->debounce, switch_timer, 0);
     79
     80	/* Workqueue API brain-damage */
     81	psw->pdev = pdev;
     82
     83	platform_set_drvdata(pdev, psw);
     84
     85	return 0;
     86
     87err_irq:
     88	free_irq(irq, pdev);
     89err:
     90	kfree(psw);
     91	return ret;
     92}
     93
     94static int switch_drv_remove(struct platform_device *pdev)
     95{
     96	struct push_switch *psw = platform_get_drvdata(pdev);
     97	struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
     98	int irq = platform_get_irq(pdev, 0);
     99
    100	if (psw_info->name)
    101		device_remove_file(&pdev->dev, &dev_attr_switch);
    102
    103	platform_set_drvdata(pdev, NULL);
    104	flush_work(&psw->work);
    105	del_timer_sync(&psw->debounce);
    106	free_irq(irq, pdev);
    107
    108	kfree(psw);
    109
    110	return 0;
    111}
    112
    113static struct platform_driver switch_driver = {
    114	.probe		= switch_drv_probe,
    115	.remove		= switch_drv_remove,
    116	.driver		= {
    117		.name	= DRV_NAME,
    118	},
    119};
    120
    121static int __init switch_init(void)
    122{
    123	printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
    124	return platform_driver_register(&switch_driver);
    125}
    126
    127static void __exit switch_exit(void)
    128{
    129	platform_driver_unregister(&switch_driver);
    130}
    131module_init(switch_init);
    132module_exit(switch_exit);
    133
    134MODULE_VERSION(DRV_VERSION);
    135MODULE_AUTHOR("Paul Mundt");
    136MODULE_LICENSE("GPL v2");