2 * Generic push-switch framework
4 * Copyright (C) 2006 Paul Mundt
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <asm/push-switch.h>
16 #define DRV_NAME "push-switch"
17 #define DRV_VERSION "0.1.1"
19 static ssize_t
switch_show(struct device
*dev
,
20 struct device_attribute
*attr
,
23 struct push_switch_platform_info
*psw_info
= dev
->platform_data
;
24 return sprintf(buf
, "%s\n", psw_info
->name
);
26 static DEVICE_ATTR(switch, S_IRUGO
, switch_show
, NULL
);
28 static void switch_timer(unsigned long data
)
30 struct push_switch
*psw
= (struct push_switch
*)data
;
32 schedule_work(&psw
->work
);
35 static void switch_work_handler(struct work_struct
*work
)
37 struct push_switch
*psw
= container_of(work
, struct push_switch
, work
);
38 struct platform_device
*pdev
= psw
->pdev
;
42 kobject_uevent(&pdev
->dev
.kobj
, KOBJ_CHANGE
);
45 static int switch_drv_probe(struct platform_device
*pdev
)
47 struct push_switch_platform_info
*psw_info
;
48 struct push_switch
*psw
;
51 psw
= kzalloc(sizeof(struct push_switch
), GFP_KERNEL
);
55 irq
= platform_get_irq(pdev
, 0);
56 if (unlikely(irq
< 0)) {
61 psw_info
= pdev
->dev
.platform_data
;
64 ret
= request_irq(irq
, psw_info
->irq_handler
,
65 IRQF_DISABLED
| psw_info
->irq_flags
,
66 psw_info
->name
? psw_info
->name
: DRV_NAME
, pdev
);
67 if (unlikely(ret
< 0))
71 ret
= device_create_file(&pdev
->dev
, &dev_attr_switch
);
73 dev_err(&pdev
->dev
, "Failed creating device attrs\n");
79 INIT_WORK(&psw
->work
, switch_work_handler
);
80 init_timer(&psw
->debounce
);
82 psw
->debounce
.function
= switch_timer
;
83 psw
->debounce
.data
= (unsigned long)psw
;
85 /* Workqueue API brain-damage */
88 platform_set_drvdata(pdev
, psw
);
99 static int switch_drv_remove(struct platform_device
*pdev
)
101 struct push_switch
*psw
= platform_get_drvdata(pdev
);
102 struct push_switch_platform_info
*psw_info
= pdev
->dev
.platform_data
;
103 int irq
= platform_get_irq(pdev
, 0);
106 device_remove_file(&pdev
->dev
, &dev_attr_switch
);
108 platform_set_drvdata(pdev
, NULL
);
109 flush_scheduled_work();
110 del_timer_sync(&psw
->debounce
);
118 static struct platform_driver switch_driver
= {
119 .probe
= switch_drv_probe
,
120 .remove
= switch_drv_remove
,
126 static int __init
switch_init(void)
128 printk(KERN_NOTICE DRV_NAME
": version %s loaded\n", DRV_VERSION
);
129 return platform_driver_register(&switch_driver
);
132 static void __exit
switch_exit(void)
134 platform_driver_unregister(&switch_driver
);
136 module_init(switch_init
);
137 module_exit(switch_exit
);
139 MODULE_VERSION(DRV_VERSION
);
140 MODULE_AUTHOR("Paul Mundt");
141 MODULE_LICENSE("GPL v2");