2 * driver/input/misc/ricoh619-pwrkey.c
\r
4 * Power Key driver for RICOH RC5T619 power management chip.
\r
6 * Copyright (C) 2012-2013 RICOH COMPANY,LTD
\r
9 * This program is free software; you can redistribute it and/or modify
\r
10 * it under the terms of the GNU General Public License as published by
\r
11 * the Free Software Foundation; either version 2 of the License, or
\r
12 * (at your option) any later version.
\r
14 * This program is distributed in the hope that it will be useful, but WITHOUT
\r
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
19 * You should have received a copy of the GNU General Public License
\r
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
23 #include <linux/module.h>
\r
24 #include <linux/init.h>
\r
25 #include <linux/kernel.h>
\r
26 #include <linux/errno.h>
\r
27 #include <linux/input.h>
\r
28 #include <linux/interrupt.h>
\r
29 #include <linux/platform_device.h>
\r
30 #include <linux/mfd/ricoh619.h>
\r
31 #include <linux/spinlock.h>
\r
32 #include <linux/timer.h>
\r
33 #include <linux/pm.h>
\r
34 #include <linux/slab.h>
\r
35 #include <linux/pm_runtime.h>
\r
36 #include <linux/workqueue.h>
\r
37 #include <linux/gpio.h>
\r
39 #include <linux/mfd/ricoh619.h>
\r
41 #define RICOH619_ONKEY_TRIGGER_LEVEL 0
\r
42 #define RICOH619_ONKEY_OFF_IRQ 0
\r
44 struct ricoh619_pwrkey {
\r
46 struct input_dev *pwr;
\r
47 #if RICOH619_ONKEY_TRIGGER_LEVEL
\r
48 struct timer_list timer;
\r
50 struct workqueue_struct *workqueue;
\r
51 struct work_struct work;
\r
52 unsigned long delay;
\r
55 struct ricoh619_pwrkey_platform_data *pdata;
\r
59 struct ricoh619_pwrkey *g_pwrkey;
\r
61 #if RICOH619_ONKEY_TRIGGER_LEVEL
\r
62 void ricoh619_pwrkey_timer(unsigned long t)
\r
64 queue_work(g_pwrkey->workqueue, &g_pwrkey->work);
\r
68 static void ricoh619_irq_work(struct work_struct *work)
\r
70 /* unsigned long flags; */
\r
73 // printk("PMU: %s: \n",__func__);
\r
74 //spin_lock_irqsave(&g_pwrkey->lock, flags);
\r
77 // printk("PMU: %s: pwrkey_wakeup\n",__func__);
\r
79 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1);
\r
80 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
81 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0);
\r
82 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
86 ricoh619_read(g_pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val);
\r
87 dev_dbg(g_pwrkey->dev, "pwrkey is pressed?(0x%x): 0x%x\n",
\r
88 RICOH619_INT_MON_SYS, val);
\r
89 // printk(KERN_INFO "PMU: %s: val=0x%x\n", __func__, val);
\r
92 #if (RICOH619_ONKEY_TRIGGER_LEVEL)
\r
93 g_pwrkey->timer.expires = jiffies + g_pwrkey->delay;
\r
94 dd_timer(&g_pwrkey->timer);
\r
96 if (!g_pwrkey->pressed_first){
\r
97 g_pwrkey->pressed_first = true;
\r
98 // printk("PMU1: %s: Power Key!!!\n",__func__);
\r
99 //input_report_key(g_pwrkey->pwr, KEY_POWER, 1);
\r
100 //input_sync(g_pwrkey->pwr);
\r
101 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1);
\r
102 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
105 if (g_pwrkey->pressed_first) {
\r
106 // printk(KERN_INFO "PMU2: %s: Power Key!!!\n", __func__);
\r
107 /* input_report_key(g_pwrkey->pwr, KEY_POWER, 0); */
\r
108 /* input_sync(g_pwrkey->pwr); */
\r
109 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0);
\r
110 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
112 g_pwrkey->pressed_first = false;
\r
115 /* spin_unlock_irqrestore(&g_pwrkey->lock, flags); */
\r
118 static irqreturn_t pwrkey_irq(int irq, void *_pwrkey)
\r
120 // printk(KERN_INFO "PMU: %s:\n", __func__);
\r
122 #if (RICOH619_ONKEY_TRIGGER_LEVEL)
\r
123 g_pwrkey->timer.expires = jiffies + g_pwrkey->delay;
\r
124 add_timer(&g_pwrkey->timer);
\r
126 queue_work(g_pwrkey->workqueue, &g_pwrkey->work);
\r
128 return IRQ_HANDLED;
\r
131 #if RICOH619_ONKEY_OFF_IRQ
\r
132 static irqreturn_t pwrkey_irq_off(int irq, void *_pwrkey)
\r
134 dev_warn(g_pwrkey->dev, "ONKEY is pressed long time!\n");
\r
135 return IRQ_HANDLED;
\r
139 static int __devinit ricoh619_pwrkey_probe(struct platform_device *pdev)
\r
141 struct input_dev *pwr;
\r
144 struct ricoh619_pwrkey *pwrkey;
\r
145 struct ricoh619_pwrkey_platform_data *pdata = pdev->dev.platform_data;
\r
148 // printk("PMU: %s: \n",__func__);
\r
151 dev_err(&pdev->dev, "power key platform data not supplied\n");
\r
154 key_irq = (pdata->irq + RICOH619_IRQ_POWER_ON);
\r
155 printk(KERN_INFO "PMU1: %s: key_irq=%d\n", __func__, key_irq);
\r
156 pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL);
\r
160 pwrkey->dev = &pdev->dev;
\r
161 pwrkey->pdata = pdata;
\r
162 pwrkey->pressed_first = false;
\r
163 pwrkey->delay = HZ / 1000 * pdata->delay_ms;
\r
165 pwr = input_allocate_device();
\r
167 dev_dbg(&pdev->dev, "Can't allocate power button\n");
\r
171 input_set_capability(pwr, EV_KEY, KEY_POWER);
\r
172 pwr->name = "ricoh619_pwrkey";
\r
173 pwr->phys = "ricoh619_pwrkey/input0";
\r
174 pwr->dev.parent = &pdev->dev;
\r
176 #if RICOH619_ONKEY_TRIGGER_LEVEL
\r
177 init_timer(&pwrkey->timer);
\r
178 pwrkey->timer.function = ricoh619_pwrkey_timer;
\r
181 spin_lock_init(&pwrkey->lock);
\r
182 err = input_register_device(pwr);
\r
184 dev_dbg(&pdev->dev, "Can't register power key: %d\n", err);
\r
185 goto free_input_dev;
\r
187 pwrkey->key_irq = key_irq;
\r
189 platform_set_drvdata(pdev, pwrkey);
\r
191 /* Check if power-key is pressed at boot up */
\r
192 err = ricoh619_read(pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val);
\r
194 dev_err(&pdev->dev, "Key-press status at boot failed rc=%d\n",
\r
196 goto unreg_input_dev;
\r
200 input_report_key(pwrkey->pwr, KEY_POWER, 1);
\r
201 // printk(KERN_INFO "******KEY_POWER:1\n");
\r
202 input_sync(pwrkey->pwr);
\r
203 pwrkey->pressed_first = true;
\r
206 #if !(RICOH619_ONKEY_TRIGGER_LEVEL)
\r
207 /* trigger both edge */
\r
208 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1);
\r
211 err = request_threaded_irq(key_irq, NULL, pwrkey_irq,
\r
212 IRQF_ONESHOT, "ricoh619_pwrkey", pwrkey);
\r
214 dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
\r
216 goto unreg_input_dev;
\r
219 #if RICOH619_ONKEY_OFF_IRQ
\r
220 err = request_threaded_irq(key_irq + RICOH619_IRQ_ONKEY_OFF, NULL,
\r
221 pwrkey_irq_off, IRQF_ONESHOT,
\r
222 "ricoh619_pwrkey_off", pwrkey);
\r
224 dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
\r
225 key_irq + RICOH619_IRQ_ONKEY_OFF, err);
\r
226 free_irq(key_irq, pwrkey);
\r
227 goto unreg_input_dev;
\r
231 pwrkey->workqueue = create_singlethread_workqueue("ricoh619_pwrkey");
\r
232 INIT_WORK(&pwrkey->work, ricoh619_irq_work);
\r
234 /* Enable power key IRQ */
\r
235 /* trigger both edge */
\r
236 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1);
\r
237 /* Enable system interrupt */
\r
238 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INTC_INTEN, 0x1);
\r
239 /* Enable power-on interrupt */
\r
240 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INT_EN_SYS, 0x1);
\r
241 // printk(KERN_INFO "PMU: %s is OK!\n", __func__);
\r
245 input_unregister_device(pwr);
\r
249 input_free_device(pwr);
\r
256 static int __devexit ricoh619_pwrkey_remove(struct platform_device *pdev)
\r
258 struct ricoh619_pwrkey *pwrkey = platform_get_drvdata(pdev);
\r
260 flush_workqueue(pwrkey->workqueue);
\r
261 destroy_workqueue(pwrkey->workqueue);
\r
262 free_irq(pwrkey->key_irq, pwrkey);
\r
263 input_unregister_device(pwrkey->pwr);
\r
270 static int ricoh619_pwrkey_suspend(struct device *dev)
\r
272 struct ricoh619_pwrkey *info = dev_get_drvdata(dev);
\r
274 // printk(KERN_INFO "PMU: %s\n", __func__);
\r
277 disable_irq(info->key_irq);
\r
278 cancel_work_sync(&info->work);
\r
279 flush_workqueue(info->workqueue);
\r
284 static int ricoh619_pwrkey_resume(struct device *dev)
\r
286 struct ricoh619_pwrkey *info = dev_get_drvdata(dev);
\r
288 // printk(KERN_INFO "PMU: %s\n", __func__);
\r
289 queue_work(info->workqueue, &info->work);
\r
291 enable_irq(info->key_irq);
\r
296 static const struct dev_pm_ops ricoh619_pwrkey_pm_ops = {
\r
297 .suspend = ricoh619_pwrkey_suspend,
\r
298 .resume = ricoh619_pwrkey_resume,
\r
302 static struct platform_driver ricoh619_pwrkey_driver = {
\r
303 .probe = ricoh619_pwrkey_probe,
\r
304 .remove = __devexit_p(ricoh619_pwrkey_remove),
\r
306 .name = "ricoh619-pwrkey",
\r
307 .owner = THIS_MODULE,
\r
309 .pm = &ricoh619_pwrkey_pm_ops,
\r
314 static int __init ricoh619_pwrkey_init(void)
\r
316 return platform_driver_register(&ricoh619_pwrkey_driver);
\r
318 subsys_initcall_sync(ricoh619_pwrkey_init);
\r
320 static void __exit ricoh619_pwrkey_exit(void)
\r
322 platform_driver_unregister(&ricoh619_pwrkey_driver);
\r
324 module_exit(ricoh619_pwrkey_exit);
\r
327 MODULE_ALIAS("platform:ricoh619-pwrkey");
\r
328 MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
\r
329 MODULE_DESCRIPTION("ricoh619 Power Key");
\r
330 MODULE_LICENSE("GPL v2");