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
=
94 dev_get_platdata(&pdev
->dev
);
97 dev_err(&pdev
->dev
, "power key platform data not supplied\n");
101 if (pdata
->kpd_trigger_delay_us
> 62500) {
102 dev_err(&pdev
->dev
, "invalid power key trigger delay\n");
106 pwrkey
= kzalloc(sizeof(*pwrkey
), GFP_KERNEL
);
110 pwr
= input_allocate_device();
112 dev_dbg(&pdev
->dev
, "Can't allocate power button\n");
117 input_set_capability(pwr
, EV_KEY
, KEY_POWER
);
119 pwr
->name
= "pmic8xxx_pwrkey";
120 pwr
->phys
= "pmic8xxx_pwrkey/input0";
121 pwr
->dev
.parent
= &pdev
->dev
;
123 delay
= (pdata
->kpd_trigger_delay_us
<< 10) / USEC_PER_SEC
;
124 delay
= 1 + ilog2(delay
);
126 err
= pm8xxx_readb(pdev
->dev
.parent
, PON_CNTL_1
, &pon_cntl
);
128 dev_err(&pdev
->dev
, "failed reading PON_CNTL_1 err=%d\n", err
);
132 pon_cntl
&= ~PON_CNTL_TRIG_DELAY_MASK
;
133 pon_cntl
|= (delay
& PON_CNTL_TRIG_DELAY_MASK
);
135 pon_cntl
|= PON_CNTL_PULL_UP
;
137 pon_cntl
&= ~PON_CNTL_PULL_UP
;
139 err
= pm8xxx_writeb(pdev
->dev
.parent
, PON_CNTL_1
, pon_cntl
);
141 dev_err(&pdev
->dev
, "failed writing PON_CNTL_1 err=%d\n", err
);
145 err
= input_register_device(pwr
);
147 dev_dbg(&pdev
->dev
, "Can't register power key: %d\n", err
);
151 pwrkey
->key_press_irq
= key_press_irq
;
154 platform_set_drvdata(pdev
, pwrkey
);
156 err
= request_irq(key_press_irq
, pwrkey_press_irq
,
157 IRQF_TRIGGER_RISING
, "pmic8xxx_pwrkey_press", pwrkey
);
159 dev_dbg(&pdev
->dev
, "Can't get %d IRQ for pwrkey: %d\n",
161 goto unreg_input_dev
;
164 err
= request_irq(key_release_irq
, pwrkey_release_irq
,
165 IRQF_TRIGGER_RISING
, "pmic8xxx_pwrkey_release", pwrkey
);
167 dev_dbg(&pdev
->dev
, "Can't get %d IRQ for pwrkey: %d\n",
168 key_release_irq
, err
);
173 device_init_wakeup(&pdev
->dev
, pdata
->wakeup
);
178 free_irq(key_press_irq
, NULL
);
180 platform_set_drvdata(pdev
, NULL
);
181 input_unregister_device(pwr
);
184 input_free_device(pwr
);
190 static int __devexit
pmic8xxx_pwrkey_remove(struct platform_device
*pdev
)
192 struct pmic8xxx_pwrkey
*pwrkey
= platform_get_drvdata(pdev
);
193 int key_release_irq
= platform_get_irq(pdev
, 0);
194 int key_press_irq
= platform_get_irq(pdev
, 1);
196 device_init_wakeup(&pdev
->dev
, 0);
198 free_irq(key_press_irq
, pwrkey
);
199 free_irq(key_release_irq
, pwrkey
);
200 input_unregister_device(pwrkey
->pwr
);
201 platform_set_drvdata(pdev
, NULL
);
207 static struct platform_driver pmic8xxx_pwrkey_driver
= {
208 .probe
= pmic8xxx_pwrkey_probe
,
209 .remove
= __devexit_p(pmic8xxx_pwrkey_remove
),
211 .name
= PM8XXX_PWRKEY_DEV_NAME
,
212 .owner
= THIS_MODULE
,
213 .pm
= &pm8xxx_pwr_key_pm_ops
,
217 static int __init
pmic8xxx_pwrkey_init(void)
219 return platform_driver_register(&pmic8xxx_pwrkey_driver
);
221 module_init(pmic8xxx_pwrkey_init
);
223 static void __exit
pmic8xxx_pwrkey_exit(void)
225 platform_driver_unregister(&pmic8xxx_pwrkey_driver
);
227 module_exit(pmic8xxx_pwrkey_exit
);
229 MODULE_ALIAS("platform:pmic8xxx_pwrkey");
230 MODULE_DESCRIPTION("PMIC8XXX Power Key driver");
231 MODULE_LICENSE("GPL v2");
232 MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>");