1 /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/slab.h>
18 #include <linux/input.h>
19 #include <linux/interrupt.h>
20 #include <linux/platform_device.h>
21 #include <linux/log2.h>
23 #include <linux/mfd/pm8xxx/core.h>
24 #include <linux/input/pmic8xxx-pwrkey.h>
26 #define PON_CNTL_1 0x1C
27 #define PON_CNTL_PULL_UP BIT(7)
28 #define PON_CNTL_TRIG_DELAY_MASK (0x7)
31 * struct pmic8xxx_pwrkey - pmic8xxx pwrkey information
32 * @key_press_irq: key press irq number
34 struct pmic8xxx_pwrkey
{
35 struct input_dev
*pwr
;
39 static irqreturn_t
pwrkey_press_irq(int irq
, void *_pwrkey
)
41 struct pmic8xxx_pwrkey
*pwrkey
= _pwrkey
;
43 input_report_key(pwrkey
->pwr
, KEY_POWER
, 1);
44 input_sync(pwrkey
->pwr
);
49 static irqreturn_t
pwrkey_release_irq(int irq
, void *_pwrkey
)
51 struct pmic8xxx_pwrkey
*pwrkey
= _pwrkey
;
53 input_report_key(pwrkey
->pwr
, KEY_POWER
, 0);
54 input_sync(pwrkey
->pwr
);
59 #ifdef CONFIG_PM_SLEEP
60 static int pmic8xxx_pwrkey_suspend(struct device
*dev
)
62 struct pmic8xxx_pwrkey
*pwrkey
= dev_get_drvdata(dev
);
64 if (device_may_wakeup(dev
))
65 enable_irq_wake(pwrkey
->key_press_irq
);
70 static int pmic8xxx_pwrkey_resume(struct device
*dev
)
72 struct pmic8xxx_pwrkey
*pwrkey
= dev_get_drvdata(dev
);
74 if (device_may_wakeup(dev
))
75 disable_irq_wake(pwrkey
->key_press_irq
);
81 static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops
,
82 pmic8xxx_pwrkey_suspend
, pmic8xxx_pwrkey_resume
);
84 static int __devinit
pmic8xxx_pwrkey_probe(struct platform_device
*pdev
)
86 struct input_dev
*pwr
;
87 int key_release_irq
= platform_get_irq(pdev
, 0);
88 int key_press_irq
= platform_get_irq(pdev
, 1);
92 struct pmic8xxx_pwrkey
*pwrkey
;
93 const struct pm8xxx_pwrkey_platform_data
*pdata
= mfd_get_data(pdev
);
96 dev_err(&pdev
->dev
, "power key platform data not supplied\n");
100 if (pdata
->kpd_trigger_delay_us
> 62500) {
101 dev_err(&pdev
->dev
, "invalid power key trigger delay\n");
105 pwrkey
= kzalloc(sizeof(*pwrkey
), GFP_KERNEL
);
109 pwr
= input_allocate_device();
111 dev_dbg(&pdev
->dev
, "Can't allocate power button\n");
116 input_set_capability(pwr
, EV_KEY
, KEY_POWER
);
118 pwr
->name
= "pmic8xxx_pwrkey";
119 pwr
->phys
= "pmic8xxx_pwrkey/input0";
120 pwr
->dev
.parent
= &pdev
->dev
;
122 delay
= (pdata
->kpd_trigger_delay_us
<< 10) / USEC_PER_SEC
;
123 delay
= 1 + ilog2(delay
);
125 err
= pm8xxx_readb(pdev
->dev
.parent
, PON_CNTL_1
, &pon_cntl
);
127 dev_err(&pdev
->dev
, "failed reading PON_CNTL_1 err=%d\n", err
);
131 pon_cntl
&= ~PON_CNTL_TRIG_DELAY_MASK
;
132 pon_cntl
|= (delay
& PON_CNTL_TRIG_DELAY_MASK
);
134 pon_cntl
|= PON_CNTL_PULL_UP
;
136 pon_cntl
&= ~PON_CNTL_PULL_UP
;
138 err
= pm8xxx_writeb(pdev
->dev
.parent
, PON_CNTL_1
, pon_cntl
);
140 dev_err(&pdev
->dev
, "failed writing PON_CNTL_1 err=%d\n", err
);
144 err
= input_register_device(pwr
);
146 dev_dbg(&pdev
->dev
, "Can't register power key: %d\n", err
);
150 pwrkey
->key_press_irq
= key_press_irq
;
153 platform_set_drvdata(pdev
, pwrkey
);
155 err
= request_irq(key_press_irq
, pwrkey_press_irq
,
156 IRQF_TRIGGER_RISING
, "pmic8xxx_pwrkey_press", pwrkey
);
158 dev_dbg(&pdev
->dev
, "Can't get %d IRQ for pwrkey: %d\n",
160 goto unreg_input_dev
;
163 err
= request_irq(key_release_irq
, pwrkey_release_irq
,
164 IRQF_TRIGGER_RISING
, "pmic8xxx_pwrkey_release", pwrkey
);
166 dev_dbg(&pdev
->dev
, "Can't get %d IRQ for pwrkey: %d\n",
167 key_release_irq
, err
);
172 device_init_wakeup(&pdev
->dev
, pdata
->wakeup
);
177 free_irq(key_press_irq
, NULL
);
179 platform_set_drvdata(pdev
, NULL
);
180 input_unregister_device(pwr
);
183 input_free_device(pwr
);
189 static int __devexit
pmic8xxx_pwrkey_remove(struct platform_device
*pdev
)
191 struct pmic8xxx_pwrkey
*pwrkey
= platform_get_drvdata(pdev
);
192 int key_release_irq
= platform_get_irq(pdev
, 0);
193 int key_press_irq
= platform_get_irq(pdev
, 1);
195 device_init_wakeup(&pdev
->dev
, 0);
197 free_irq(key_press_irq
, pwrkey
);
198 free_irq(key_release_irq
, pwrkey
);
199 input_unregister_device(pwrkey
->pwr
);
200 platform_set_drvdata(pdev
, NULL
);
206 static struct platform_driver pmic8xxx_pwrkey_driver
= {
207 .probe
= pmic8xxx_pwrkey_probe
,
208 .remove
= __devexit_p(pmic8xxx_pwrkey_remove
),
210 .name
= PM8XXX_PWRKEY_DEV_NAME
,
211 .owner
= THIS_MODULE
,
212 .pm
= &pm8xxx_pwr_key_pm_ops
,
216 static int __init
pmic8xxx_pwrkey_init(void)
218 return platform_driver_register(&pmic8xxx_pwrkey_driver
);
220 module_init(pmic8xxx_pwrkey_init
);
222 static void __exit
pmic8xxx_pwrkey_exit(void)
224 platform_driver_unregister(&pmic8xxx_pwrkey_driver
);
226 module_exit(pmic8xxx_pwrkey_exit
);
228 MODULE_ALIAS("platform:pmic8xxx_pwrkey");
229 MODULE_DESCRIPTION("PMIC8XXX Power Key driver");
230 MODULE_LICENSE("GPL v2");
231 MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>");