1 // SPDX-License-Identifier: GPL-2.0
3 * Generic push-switch framework
5 * Copyright (C) 2006 Paul Mundt
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>
14 #define DRV_NAME "push-switch"
15 #define DRV_VERSION "0.1.1"
17 static ssize_t
switch_show(struct device
*dev
,
18 struct device_attribute
*attr
,
21 struct push_switch_platform_info
*psw_info
= dev
->platform_data
;
22 return sprintf(buf
, "%s\n", psw_info
->name
);
24 static DEVICE_ATTR_RO(switch);
26 static void switch_timer(struct timer_list
*t
)
28 struct push_switch
*psw
= from_timer(psw
, t
, debounce
);
30 schedule_work(&psw
->work
);
33 static void switch_work_handler(struct work_struct
*work
)
35 struct push_switch
*psw
= container_of(work
, struct push_switch
, work
);
36 struct platform_device
*pdev
= psw
->pdev
;
40 kobject_uevent(&pdev
->dev
.kobj
, KOBJ_CHANGE
);
43 static int switch_drv_probe(struct platform_device
*pdev
)
45 struct push_switch_platform_info
*psw_info
;
46 struct push_switch
*psw
;
49 psw
= kzalloc(sizeof(struct push_switch
), GFP_KERNEL
);
53 irq
= platform_get_irq(pdev
, 0);
54 if (unlikely(irq
< 0)) {
59 psw_info
= pdev
->dev
.platform_data
;
62 ret
= request_irq(irq
, psw_info
->irq_handler
,
64 psw_info
->name
? psw_info
->name
: DRV_NAME
, pdev
);
65 if (unlikely(ret
< 0))
69 ret
= device_create_file(&pdev
->dev
, &dev_attr_switch
);
71 dev_err(&pdev
->dev
, "Failed creating device attrs\n");
77 INIT_WORK(&psw
->work
, switch_work_handler
);
78 timer_setup(&psw
->debounce
, switch_timer
, 0);
80 /* Workqueue API brain-damage */
83 platform_set_drvdata(pdev
, psw
);
94 static void switch_drv_remove(struct platform_device
*pdev
)
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);
101 device_remove_file(&pdev
->dev
, &dev_attr_switch
);
103 platform_set_drvdata(pdev
, NULL
);
104 timer_shutdown_sync(&psw
->debounce
);
105 flush_work(&psw
->work
);
111 static struct platform_driver switch_driver
= {
112 .probe
= switch_drv_probe
,
113 .remove
= switch_drv_remove
,
119 static int __init
switch_init(void)
121 printk(KERN_NOTICE DRV_NAME
": version %s loaded\n", DRV_VERSION
);
122 return platform_driver_register(&switch_driver
);
125 static void __exit
switch_exit(void)
127 platform_driver_unregister(&switch_driver
);
129 module_init(switch_init
);
130 module_exit(switch_exit
);
132 MODULE_VERSION(DRV_VERSION
);
133 MODULE_AUTHOR("Paul Mundt");
134 MODULE_DESCRIPTION("Generic push-switch framework");
135 MODULE_LICENSE("GPL v2");