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
45 struct device * dev;
\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
60 //static int test_set = 0;
\r
62 #if RICOH619_ONKEY_TRIGGER_LEVEL
\r
63 void ricoh619_pwrkey_timer(unsigned long t)
\r
65 queue_work(g_pwrkey->workqueue, &g_pwrkey->work);
\r
69 extern int pwrkey_wakeup;
\r
70 static void ricoh619_irq_work(struct work_struct * work)
\r
72 unsigned long flags;
\r
75 // printk("PMU: %s: \n",__func__);
\r
76 //spin_lock_irqsave(&g_pwrkey->lock, flags);
\r
79 // printk("PMU: %s: pwrkey_wakeup\n",__func__);
\r
81 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1);
\r
82 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
83 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0);
\r
84 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
88 ricoh619_read(g_pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val);
\r
89 dev_dbg(g_pwrkey->dev, "pwrkey is pressed?(0x%x): 0x%x\n", RICOH619_INT_MON_SYS, val);
\r
90 // printk("PMU: %s: val=0x%x\n",__func__,val);
\r
93 #if (RICOH619_ONKEY_TRIGGER_LEVEL)
\r
94 g_pwrkey->timer.expires = jiffies + g_pwrkey->delay;
\r
95 dd_timer(&g_pwrkey->timer);
\r
97 if (!g_pwrkey->pressed_first){
\r
98 g_pwrkey->pressed_first = true;
\r
99 // printk("PMU1: %s: Power Key!!!\n",__func__);
\r
100 //input_report_key(g_pwrkey->pwr, KEY_POWER, 1);
\r
101 //input_sync(g_pwrkey->pwr);
\r
102 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1);
\r
103 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
107 if (g_pwrkey->pressed_first){
\r
108 // printk("PMU2: %s: Power Key!!!\n",__func__);
\r
109 //input_report_key(g_pwrkey->pwr, KEY_POWER, 0);
\r
110 //input_sync(g_pwrkey->pwr);
\r
111 input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0);
\r
112 input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
\r
114 g_pwrkey->pressed_first = false;
\r
117 //spin_unlock_irqrestore(&g_pwrkey->lock, flags);
\r
119 extern struct ricoh619 *g_ricoh619;
\r
120 static irqreturn_t pwrkey_irq(int irq, void *_pwrkey)
\r
122 // printk("PMU: %s: \n",__func__);
\r
123 struct ricoh619 *ricoh619 = g_ricoh619;
\r
124 #if (RICOH619_ONKEY_TRIGGER_LEVEL)
\r
125 g_pwrkey->timer.expires = jiffies + g_pwrkey->delay;
\r
126 add_timer(&g_pwrkey->timer);
\r
128 queue_work(g_pwrkey->workqueue, &g_pwrkey->work);
\r
130 ricoh619_clr_bits(g_ricoh619->dev, RICOH619_INT_IR_SYS, 0x1); //clr power-on interrupt
\r
131 return IRQ_HANDLED;
\r
134 #if RICOH619_ONKEY_OFF_IRQ
\r
135 static irqreturn_t pwrkey_irq_off(int irq, void *_pwrkey)
\r
137 dev_warn(g_pwrkey->dev, "ONKEY is pressed long time!\n");
\r
138 return IRQ_HANDLED;
\r
142 static int __devinit ricoh619_pwrkey_probe(struct platform_device *pdev)
\r
144 struct input_dev *pwr;
\r
147 struct ricoh619_pwrkey *pwrkey;
\r
148 struct ricoh619_pwrkey_platform_data *pdata = pdev->dev.platform_data;
\r
151 // printk("PMU: %s: \n",__func__);
\r
154 dev_err(&pdev->dev, "power key platform data not supplied\n");
\r
157 key_irq = (pdata->irq + RICOH619_IRQ_POWER_ON);
\r
158 printk(KERN_INFO "PMU1: %s: key_irq=%d\n", __func__, key_irq);
\r
159 pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL);
\r
163 pwrkey->dev = &pdev->dev;
\r
164 pwrkey->pdata = pdata;
\r
165 pwrkey->pressed_first = false;
\r
166 pwrkey->delay = HZ / 1000 * pdata->delay_ms;
\r
168 pwr = input_allocate_device();
\r
170 dev_dbg(&pdev->dev, "Can't allocate power button\n");
\r
174 input_set_capability(pwr, EV_KEY, KEY_POWER);
\r
175 pwr->name = "ricoh619_pwrkey";
\r
176 pwr->phys = "ricoh619_pwrkey/input0";
\r
177 pwr->dev.parent = &pdev->dev;
\r
179 #if RICOH619_ONKEY_TRIGGER_LEVEL
\r
180 init_timer(&pwrkey->timer);
\r
181 pwrkey->timer.function = ricoh619_pwrkey_timer;
\r
184 spin_lock_init(&pwrkey->lock);
\r
185 err = input_register_device(pwr);
\r
187 dev_dbg(&pdev->dev, "Can't register power key: %d\n", err);
\r
188 goto free_input_dev;
\r
190 pwrkey->key_irq = key_irq;
\r
192 platform_set_drvdata(pdev, pwrkey);
\r
194 // Check if power-key is pressed at boot up
\r
195 err = ricoh619_read(pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val);
\r
197 dev_err(&pdev->dev, "Key-press status at boot failed rc=%d\n",
\r
199 goto unreg_input_dev;
\r
203 input_report_key(pwrkey->pwr, KEY_POWER, 1);
\r
204 // printk(KERN_INFO "******KEY_POWER:1\n");
\r
205 input_sync(pwrkey->pwr);
\r
206 pwrkey->pressed_first = true;
\r
209 #if !(RICOH619_ONKEY_TRIGGER_LEVEL)
\r
210 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1); //trigger both edge
\r
213 err = request_threaded_irq(key_irq, NULL, pwrkey_irq,
\r
214 IRQF_ONESHOT, "ricoh619_pwrkey", pwrkey);
\r
216 dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
\r
218 goto unreg_input_dev;
\r
221 #if RICOH619_ONKEY_OFF_IRQ
\r
222 err = request_threaded_irq(key_irq + RICOH619_IRQ_ONKEY_OFF, NULL,
\r
223 pwrkey_irq_off, IRQF_ONESHOT,
\r
224 "ricoh619_pwrkey_off", pwrkey);
\r
226 dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
\r
227 key_irq + RICOH619_IRQ_ONKEY_OFF, err);
\r
228 free_irq(key_irq, pwrkey);
\r
229 goto unreg_input_dev;
\r
233 pwrkey->workqueue = create_singlethread_workqueue("ricoh619_pwrkey");
\r
234 INIT_WORK(&pwrkey->work, ricoh619_irq_work);
\r
236 /* Enable power key IRQ */
\r
237 /* trigger both edge */
\r
238 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1);
\r
239 /* Enable system interrupt */
\r
240 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INTC_INTEN, 0x1);
\r
241 /* Enable power-on interrupt */
\r
242 ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INT_EN_SYS, 0x1);
\r
243 // printk(KERN_INFO "PMU: %s is OK!\n", __func__);
\r
247 input_unregister_device(pwr);
\r
251 input_free_device(pwr);
\r
258 static int __devexit ricoh619_pwrkey_remove(struct platform_device *pdev)
\r
260 struct ricoh619_pwrkey *pwrkey = platform_get_drvdata(pdev);
\r
262 flush_workqueue(pwrkey->workqueue);
\r
263 destroy_workqueue(pwrkey->workqueue);
\r
264 free_irq(pwrkey->key_irq, pwrkey);
\r
265 input_unregister_device(pwrkey->pwr);
\r
272 static int ricoh619_pwrkey_suspend(struct device *dev)
\r
274 struct ricoh619_pwrkey *info = dev_get_drvdata(dev);
\r
276 // printk(KERN_INFO "PMU: %s\n", __func__);
\r
279 disable_irq(info->key_irq);
\r
280 cancel_work_sync(&info->work);
\r
281 flush_workqueue(info->workqueue);
\r
286 static int ricoh619_pwrkey_resume(struct device *dev)
\r
288 struct ricoh619_pwrkey *info = dev_get_drvdata(dev);
\r
290 // printk(KERN_INFO "PMU: %s\n", __func__);
\r
291 queue_work(info->workqueue, &info->work);
\r
293 enable_irq(info->key_irq);
\r
298 static const struct dev_pm_ops ricoh619_pwrkey_pm_ops = {
\r
299 .suspend = ricoh619_pwrkey_suspend,
\r
300 .resume = ricoh619_pwrkey_resume,
\r
304 static struct platform_driver ricoh619_pwrkey_driver = {
\r
305 .probe = ricoh619_pwrkey_probe,
\r
306 .remove = __devexit_p(ricoh619_pwrkey_remove),
\r
308 .name = "ricoh619-pwrkey",
\r
309 .owner = THIS_MODULE,
\r
311 .pm = &ricoh619_pwrkey_pm_ops,
\r
316 static int __init ricoh619_pwrkey_init(void)
\r
318 return platform_driver_register(&ricoh619_pwrkey_driver);
\r
320 subsys_initcall_sync(ricoh619_pwrkey_init);
\r
322 static void __exit ricoh619_pwrkey_exit(void)
\r
324 platform_driver_unregister(&ricoh619_pwrkey_driver);
\r
326 module_exit(ricoh619_pwrkey_exit);
\r
329 MODULE_ALIAS("platform:ricoh619-pwrkey");
\r
330 MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
\r
331 MODULE_DESCRIPTION("ricoh619 Power Key");
\r
332 MODULE_LICENSE("GPL v2");