1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2014, Sony Mobile Communications Inc.
5 */
6
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>
14 #include <linux/of.h>
15 #include <linux/of_device.h>
16 #include <linux/platform_device.h>
17 #include <linux/reboot.h>
18 #include <linux/regmap.h>
19
20 #define PON_REV2 0x01
21
22 #define PON_RT_STS 0x10
23 #define PON_KPDPWR_N_SET BIT(0)
24 #define PON_RESIN_N_SET BIT(1)
25 #define PON_GEN3_RESIN_N_SET BIT(6)
26 #define PON_GEN3_KPDPWR_N_SET BIT(7)
27
28 #define PON_PS_HOLD_RST_CTL 0x5a
29 #define PON_PS_HOLD_RST_CTL2 0x5b
30 #define PON_PS_HOLD_ENABLE BIT(7)
31 #define PON_PS_HOLD_TYPE_MASK 0x0f
32 #define PON_PS_HOLD_TYPE_SHUTDOWN 4
33 #define PON_PS_HOLD_TYPE_HARD_RESET 7
34
35 #define PON_PULL_CTL 0x70
36 #define PON_KPDPWR_PULL_UP BIT(1)
37 #define PON_RESIN_PULL_UP BIT(0)
38
39 #define PON_DBC_CTL 0x71
40 #define PON_DBC_DELAY_MASK 0x7
41
42 struct pm8941_data {
43 unsigned int pull_up_bit;
44 unsigned int status_bit;
45 bool supports_ps_hold_poff_config;
46 bool supports_debounce_config;
47 const char *name;
48 const char *phys;
49 };
50
51 struct pm8941_pwrkey {
52 struct device *dev;
53 int irq;
54 u32 baseaddr;
55 struct regmap *regmap;
56 struct input_dev *input;
57
58 unsigned int revision;
59 struct notifier_block reboot_notifier;
60
61 u32 code;
62 const struct pm8941_data *data;
63 };
64
pm8941_reboot_notify(struct notifier_block * nb,unsigned long code,void * unused)65 static int pm8941_reboot_notify(struct notifier_block *nb,
66 unsigned long code, void *unused)
67 {
68 struct pm8941_pwrkey *pwrkey = container_of(nb, struct pm8941_pwrkey,
69 reboot_notifier);
70 unsigned int enable_reg;
71 unsigned int reset_type;
72 int error;
73
74 /* PMICs with revision 0 have the enable bit in same register as ctrl */
75 if (pwrkey->revision == 0)
76 enable_reg = PON_PS_HOLD_RST_CTL;
77 else
78 enable_reg = PON_PS_HOLD_RST_CTL2;
79
80 error = regmap_update_bits(pwrkey->regmap,
81 pwrkey->baseaddr + enable_reg,
82 PON_PS_HOLD_ENABLE,
83 0);
84 if (error)
85 dev_err(pwrkey->dev,
86 "unable to clear ps hold reset enable: %d\n",
87 error);
88
89 /*
90 * Updates of PON_PS_HOLD_ENABLE requires 3 sleep cycles between
91 * writes.
92 */
93 usleep_range(100, 1000);
94
95 switch (code) {
96 case SYS_HALT:
97 case SYS_POWER_OFF:
98 reset_type = PON_PS_HOLD_TYPE_SHUTDOWN;
99 break;
100 case SYS_RESTART:
101 default:
102 reset_type = PON_PS_HOLD_TYPE_HARD_RESET;
103 break;
104 }
105
106 error = regmap_update_bits(pwrkey->regmap,
107 pwrkey->baseaddr + PON_PS_HOLD_RST_CTL,
108 PON_PS_HOLD_TYPE_MASK,
109 reset_type);
110 if (error)
111 dev_err(pwrkey->dev, "unable to set ps hold reset type: %d\n",
112 error);
113
114 error = regmap_update_bits(pwrkey->regmap,
115 pwrkey->baseaddr + enable_reg,
116 PON_PS_HOLD_ENABLE,
117 PON_PS_HOLD_ENABLE);
118 if (error)
119 dev_err(pwrkey->dev, "unable to re-set enable: %d\n", error);
120
121 return NOTIFY_DONE;
122 }
123
pm8941_pwrkey_irq(int irq,void * _data)124 static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data)
125 {
126 struct pm8941_pwrkey *pwrkey = _data;
127 unsigned int sts;
128 int error;
129
130 error = regmap_read(pwrkey->regmap,
131 pwrkey->baseaddr + PON_RT_STS, &sts);
132 if (error)
133 return IRQ_HANDLED;
134
135 input_report_key(pwrkey->input, pwrkey->code,
136 sts & pwrkey->data->status_bit);
137 input_sync(pwrkey->input);
138
139 return IRQ_HANDLED;
140 }
141
pm8941_pwrkey_suspend(struct device * dev)142 static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev)
143 {
144 struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
145
146 if (device_may_wakeup(dev))
147 enable_irq_wake(pwrkey->irq);
148
149 return 0;
150 }
151
pm8941_pwrkey_resume(struct device * dev)152 static int __maybe_unused pm8941_pwrkey_resume(struct device *dev)
153 {
154 struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev);
155
156 if (device_may_wakeup(dev))
157 disable_irq_wake(pwrkey->irq);
158
159 return 0;
160 }
161
162 static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,
163 pm8941_pwrkey_suspend, pm8941_pwrkey_resume);
164
pm8941_pwrkey_probe(struct platform_device * pdev)165 static int pm8941_pwrkey_probe(struct platform_device *pdev)
166 {
167 struct pm8941_pwrkey *pwrkey;
168 bool pull_up;
169 struct device *parent;
170 u32 req_delay;
171 int error;
172
173 if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay))
174 req_delay = 15625;
175
176 if (req_delay > 2000000 || req_delay == 0) {
177 dev_err(&pdev->dev, "invalid debounce time: %u\n", req_delay);
178 return -EINVAL;
179 }
180
181 pull_up = of_property_read_bool(pdev->dev.of_node, "bias-pull-up");
182
183 pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL);
184 if (!pwrkey)
185 return -ENOMEM;
186
187 pwrkey->dev = &pdev->dev;
188 pwrkey->data = of_device_get_match_data(&pdev->dev);
189
190 parent = pdev->dev.parent;
191 pwrkey->regmap = dev_get_regmap(parent, NULL);
192 if (!pwrkey->regmap) {
193 /*
194 * We failed to get regmap for parent. Let's see if we are
195 * a child of pon node and read regmap and reg from its
196 * parent.
197 */
198 pwrkey->regmap = dev_get_regmap(parent->parent, NULL);
199 if (!pwrkey->regmap) {
200 dev_err(&pdev->dev, "failed to locate regmap\n");
201 return -ENODEV;
202 }
203
204 error = of_property_read_u32(parent->of_node,
205 "reg", &pwrkey->baseaddr);
206 } else {
207 error = of_property_read_u32(pdev->dev.of_node, "reg",
208 &pwrkey->baseaddr);
209 }
210 if (error)
211 return error;
212
213 pwrkey->irq = platform_get_irq(pdev, 0);
214 if (pwrkey->irq < 0)
215 return pwrkey->irq;
216
217 error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2,
218 &pwrkey->revision);
219 if (error) {
220 dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
221 return error;
222 }
223
224 error = of_property_read_u32(pdev->dev.of_node, "linux,code",
225 &pwrkey->code);
226 if (error) {
227 dev_dbg(&pdev->dev,
228 "no linux,code assuming power (%d)\n", error);
229 pwrkey->code = KEY_POWER;
230 }
231
232 pwrkey->input = devm_input_allocate_device(&pdev->dev);
233 if (!pwrkey->input) {
234 dev_dbg(&pdev->dev, "unable to allocate input device\n");
235 return -ENOMEM;
236 }
237
238 input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
239
240 pwrkey->input->name = pwrkey->data->name;
241 pwrkey->input->phys = pwrkey->data->phys;
242
243 if (pwrkey->data->supports_debounce_config) {
244 req_delay = (req_delay << 6) / USEC_PER_SEC;
245 req_delay = ilog2(req_delay);
246
247 error = regmap_update_bits(pwrkey->regmap,
248 pwrkey->baseaddr + PON_DBC_CTL,
249 PON_DBC_DELAY_MASK,
250 req_delay);
251 if (error) {
252 dev_err(&pdev->dev, "failed to set debounce: %d\n",
253 error);
254 return error;
255 }
256 }
257
258 if (pwrkey->data->pull_up_bit) {
259 error = regmap_update_bits(pwrkey->regmap,
260 pwrkey->baseaddr + PON_PULL_CTL,
261 pwrkey->data->pull_up_bit,
262 pull_up ? pwrkey->data->pull_up_bit :
263 0);
264 if (error) {
265 dev_err(&pdev->dev, "failed to set pull: %d\n", error);
266 return error;
267 }
268 }
269
270 error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
271 NULL, pm8941_pwrkey_irq,
272 IRQF_ONESHOT,
273 pwrkey->data->name, pwrkey);
274 if (error) {
275 dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
276 return error;
277 }
278
279 error = input_register_device(pwrkey->input);
280 if (error) {
281 dev_err(&pdev->dev, "failed to register input device: %d\n",
282 error);
283 return error;
284 }
285
286 if (pwrkey->data->supports_ps_hold_poff_config) {
287 pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify;
288 error = register_reboot_notifier(&pwrkey->reboot_notifier);
289 if (error) {
290 dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
291 error);
292 return error;
293 }
294 }
295
296 platform_set_drvdata(pdev, pwrkey);
297 device_init_wakeup(&pdev->dev, 1);
298
299 return 0;
300 }
301
pm8941_pwrkey_remove(struct platform_device * pdev)302 static int pm8941_pwrkey_remove(struct platform_device *pdev)
303 {
304 struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
305
306 if (pwrkey->data->supports_ps_hold_poff_config)
307 unregister_reboot_notifier(&pwrkey->reboot_notifier);
308
309 return 0;
310 }
311
312 static const struct pm8941_data pwrkey_data = {
313 .pull_up_bit = PON_KPDPWR_PULL_UP,
314 .status_bit = PON_KPDPWR_N_SET,
315 .name = "pm8941_pwrkey",
316 .phys = "pm8941_pwrkey/input0",
317 .supports_ps_hold_poff_config = true,
318 .supports_debounce_config = true,
319 };
320
321 static const struct pm8941_data resin_data = {
322 .pull_up_bit = PON_RESIN_PULL_UP,
323 .status_bit = PON_RESIN_N_SET,
324 .name = "pm8941_resin",
325 .phys = "pm8941_resin/input0",
326 .supports_ps_hold_poff_config = true,
327 .supports_debounce_config = true,
328 };
329
330 static const struct pm8941_data pon_gen3_pwrkey_data = {
331 .status_bit = PON_GEN3_KPDPWR_N_SET,
332 .name = "pmic_pwrkey",
333 .phys = "pmic_pwrkey/input0",
334 .supports_ps_hold_poff_config = false,
335 .supports_debounce_config = false,
336 };
337
338 static const struct pm8941_data pon_gen3_resin_data = {
339 .status_bit = PON_GEN3_RESIN_N_SET,
340 .name = "pmic_resin",
341 .phys = "pmic_resin/input0",
342 .supports_ps_hold_poff_config = false,
343 .supports_debounce_config = false,
344 };
345
346 static const struct of_device_id pm8941_pwr_key_id_table[] = {
347 { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
348 { .compatible = "qcom,pm8941-resin", .data = &resin_data },
349 { .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data },
350 { .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data },
351 { }
352 };
353 MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
354
355 static struct platform_driver pm8941_pwrkey_driver = {
356 .probe = pm8941_pwrkey_probe,
357 .remove = pm8941_pwrkey_remove,
358 .driver = {
359 .name = "pm8941-pwrkey",
360 .pm = &pm8941_pwr_key_pm_ops,
361 .of_match_table = of_match_ptr(pm8941_pwr_key_id_table),
362 },
363 };
364 module_platform_driver(pm8941_pwrkey_driver);
365
366 MODULE_DESCRIPTION("PM8941 Power Key driver");
367 MODULE_LICENSE("GPL v2");
368