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