1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
4 * Copyright (c) 2014, Sony Mobile Communications Inc.
7 #include <linux/delay.h>
8 #include <linux/errno.h>
9 #include <linux/input.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
12 #include <linux/log2.h>
13 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/platform_device.h>
17 #include <linux/reboot.h>
18 #include <linux/regmap.h>
22 #define PON_RT_STS 0x10
23 #define PON_KPDPWR_N_SET BIT(0)
24 #define PON_RESIN_N_SET BIT(1)
26 #define PON_PS_HOLD_RST_CTL 0x5a
27 #define PON_PS_HOLD_RST_CTL2 0x5b
28 #define PON_PS_HOLD_ENABLE BIT(7)
29 #define PON_PS_HOLD_TYPE_MASK 0x0f
30 #define PON_PS_HOLD_TYPE_SHUTDOWN 4
31 #define PON_PS_HOLD_TYPE_HARD_RESET 7
33 #define PON_PULL_CTL 0x70
34 #define PON_KPDPWR_PULL_UP BIT(1)
35 #define PON_RESIN_PULL_UP BIT(0)
37 #define PON_DBC_CTL 0x71
38 #define PON_DBC_DELAY_MASK 0x7
41 unsigned int pull_up_bit
;
42 unsigned int status_bit
;
45 struct pm8941_pwrkey
{
49 struct regmap
*regmap
;
50 struct input_dev
*input
;
52 unsigned int revision
;
53 struct notifier_block reboot_notifier
;
56 const struct pm8941_data
*data
;
59 static int pm8941_reboot_notify(struct notifier_block
*nb
,
60 unsigned long code
, void *unused
)
62 struct pm8941_pwrkey
*pwrkey
= container_of(nb
, struct pm8941_pwrkey
,
64 unsigned int enable_reg
;
65 unsigned int reset_type
;
68 /* PMICs with revision 0 have the enable bit in same register as ctrl */
69 if (pwrkey
->revision
== 0)
70 enable_reg
= PON_PS_HOLD_RST_CTL
;
72 enable_reg
= PON_PS_HOLD_RST_CTL2
;
74 error
= regmap_update_bits(pwrkey
->regmap
,
75 pwrkey
->baseaddr
+ enable_reg
,
80 "unable to clear ps hold reset enable: %d\n",
84 * Updates of PON_PS_HOLD_ENABLE requires 3 sleep cycles between
87 usleep_range(100, 1000);
92 reset_type
= PON_PS_HOLD_TYPE_SHUTDOWN
;
96 reset_type
= PON_PS_HOLD_TYPE_HARD_RESET
;
100 error
= regmap_update_bits(pwrkey
->regmap
,
101 pwrkey
->baseaddr
+ PON_PS_HOLD_RST_CTL
,
102 PON_PS_HOLD_TYPE_MASK
,
105 dev_err(pwrkey
->dev
, "unable to set ps hold reset type: %d\n",
108 error
= regmap_update_bits(pwrkey
->regmap
,
109 pwrkey
->baseaddr
+ enable_reg
,
113 dev_err(pwrkey
->dev
, "unable to re-set enable: %d\n", error
);
118 static irqreturn_t
pm8941_pwrkey_irq(int irq
, void *_data
)
120 struct pm8941_pwrkey
*pwrkey
= _data
;
124 error
= regmap_read(pwrkey
->regmap
,
125 pwrkey
->baseaddr
+ PON_RT_STS
, &sts
);
129 input_report_key(pwrkey
->input
, pwrkey
->code
,
130 sts
& pwrkey
->data
->status_bit
);
131 input_sync(pwrkey
->input
);
136 static int __maybe_unused
pm8941_pwrkey_suspend(struct device
*dev
)
138 struct pm8941_pwrkey
*pwrkey
= dev_get_drvdata(dev
);
140 if (device_may_wakeup(dev
))
141 enable_irq_wake(pwrkey
->irq
);
146 static int __maybe_unused
pm8941_pwrkey_resume(struct device
*dev
)
148 struct pm8941_pwrkey
*pwrkey
= dev_get_drvdata(dev
);
150 if (device_may_wakeup(dev
))
151 disable_irq_wake(pwrkey
->irq
);
156 static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops
,
157 pm8941_pwrkey_suspend
, pm8941_pwrkey_resume
);
159 static int pm8941_pwrkey_probe(struct platform_device
*pdev
)
161 struct pm8941_pwrkey
*pwrkey
;
163 struct device
*parent
;
167 if (of_property_read_u32(pdev
->dev
.of_node
, "debounce", &req_delay
))
170 if (req_delay
> 2000000 || req_delay
== 0) {
171 dev_err(&pdev
->dev
, "invalid debounce time: %u\n", req_delay
);
175 pull_up
= of_property_read_bool(pdev
->dev
.of_node
, "bias-pull-up");
177 pwrkey
= devm_kzalloc(&pdev
->dev
, sizeof(*pwrkey
), GFP_KERNEL
);
181 pwrkey
->dev
= &pdev
->dev
;
182 pwrkey
->data
= of_device_get_match_data(&pdev
->dev
);
184 parent
= pdev
->dev
.parent
;
185 pwrkey
->regmap
= dev_get_regmap(parent
, NULL
);
186 if (!pwrkey
->regmap
) {
188 * We failed to get regmap for parent. Let's see if we are
189 * a child of pon node and read regmap and reg from its
192 pwrkey
->regmap
= dev_get_regmap(parent
->parent
, NULL
);
193 if (!pwrkey
->regmap
) {
194 dev_err(&pdev
->dev
, "failed to locate regmap\n");
198 error
= of_property_read_u32(parent
->of_node
,
199 "reg", &pwrkey
->baseaddr
);
201 error
= of_property_read_u32(pdev
->dev
.of_node
, "reg",
207 pwrkey
->irq
= platform_get_irq(pdev
, 0);
211 error
= regmap_read(pwrkey
->regmap
, pwrkey
->baseaddr
+ PON_REV2
,
214 dev_err(&pdev
->dev
, "failed to set debounce: %d\n", error
);
218 error
= of_property_read_u32(pdev
->dev
.of_node
, "linux,code",
222 "no linux,code assuming power (%d)\n", error
);
223 pwrkey
->code
= KEY_POWER
;
226 pwrkey
->input
= devm_input_allocate_device(&pdev
->dev
);
227 if (!pwrkey
->input
) {
228 dev_dbg(&pdev
->dev
, "unable to allocate input device\n");
232 input_set_capability(pwrkey
->input
, EV_KEY
, pwrkey
->code
);
234 pwrkey
->input
->name
= "pm8941_pwrkey";
235 pwrkey
->input
->phys
= "pm8941_pwrkey/input0";
237 req_delay
= (req_delay
<< 6) / USEC_PER_SEC
;
238 req_delay
= ilog2(req_delay
);
240 error
= regmap_update_bits(pwrkey
->regmap
,
241 pwrkey
->baseaddr
+ PON_DBC_CTL
,
245 dev_err(&pdev
->dev
, "failed to set debounce: %d\n", error
);
249 error
= regmap_update_bits(pwrkey
->regmap
,
250 pwrkey
->baseaddr
+ PON_PULL_CTL
,
251 pwrkey
->data
->pull_up_bit
,
252 pull_up
? pwrkey
->data
->pull_up_bit
: 0);
254 dev_err(&pdev
->dev
, "failed to set pull: %d\n", error
);
258 error
= devm_request_threaded_irq(&pdev
->dev
, pwrkey
->irq
,
259 NULL
, pm8941_pwrkey_irq
,
261 "pm8941_pwrkey", pwrkey
);
263 dev_err(&pdev
->dev
, "failed requesting IRQ: %d\n", error
);
267 error
= input_register_device(pwrkey
->input
);
269 dev_err(&pdev
->dev
, "failed to register input device: %d\n",
274 pwrkey
->reboot_notifier
.notifier_call
= pm8941_reboot_notify
,
275 error
= register_reboot_notifier(&pwrkey
->reboot_notifier
);
277 dev_err(&pdev
->dev
, "failed to register reboot notifier: %d\n",
282 platform_set_drvdata(pdev
, pwrkey
);
283 device_init_wakeup(&pdev
->dev
, 1);
288 static int pm8941_pwrkey_remove(struct platform_device
*pdev
)
290 struct pm8941_pwrkey
*pwrkey
= platform_get_drvdata(pdev
);
292 unregister_reboot_notifier(&pwrkey
->reboot_notifier
);
297 static const struct pm8941_data pwrkey_data
= {
298 .pull_up_bit
= PON_KPDPWR_PULL_UP
,
299 .status_bit
= PON_KPDPWR_N_SET
,
302 static const struct pm8941_data resin_data
= {
303 .pull_up_bit
= PON_RESIN_PULL_UP
,
304 .status_bit
= PON_RESIN_N_SET
,
307 static const struct of_device_id pm8941_pwr_key_id_table
[] = {
308 { .compatible
= "qcom,pm8941-pwrkey", .data
= &pwrkey_data
},
309 { .compatible
= "qcom,pm8941-resin", .data
= &resin_data
},
312 MODULE_DEVICE_TABLE(of
, pm8941_pwr_key_id_table
);
314 static struct platform_driver pm8941_pwrkey_driver
= {
315 .probe
= pm8941_pwrkey_probe
,
316 .remove
= pm8941_pwrkey_remove
,
318 .name
= "pm8941-pwrkey",
319 .pm
= &pm8941_pwr_key_pm_ops
,
320 .of_match_table
= of_match_ptr(pm8941_pwr_key_id_table
),
323 module_platform_driver(pm8941_pwrkey_driver
);
325 MODULE_DESCRIPTION("PM8941 Power Key driver");
326 MODULE_LICENSE("GPL v2");