Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * power button driver for TI TPS6594 PMICs
4 *
5 * Copyright (C) 2025 Critical Link LLC - https://www.criticallink.com/
6 */
7#include <linux/init.h>
8#include <linux/input.h>
9#include <linux/interrupt.h>
10#include <linux/kernel.h>
11#include <linux/mfd/tps6594.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/regmap.h>
15#include <linux/slab.h>
16
17struct tps6594_pwrbutton {
18 struct device *dev;
19 struct input_dev *idev;
20 char phys[32];
21};
22
23static irqreturn_t tps6594_pb_push_irq(int irq, void *_pwr)
24{
25 struct tps6594_pwrbutton *pwr = _pwr;
26
27 input_report_key(pwr->idev, KEY_POWER, 1);
28 pm_wakeup_event(pwr->dev, 0);
29 input_sync(pwr->idev);
30
31 return IRQ_HANDLED;
32}
33
34static irqreturn_t tps6594_pb_release_irq(int irq, void *_pwr)
35{
36 struct tps6594_pwrbutton *pwr = _pwr;
37
38 input_report_key(pwr->idev, KEY_POWER, 0);
39 input_sync(pwr->idev);
40
41 return IRQ_HANDLED;
42}
43
44static int tps6594_pb_probe(struct platform_device *pdev)
45{
46 struct device *dev = &pdev->dev;
47 struct tps6594_pwrbutton *pwr;
48 struct input_dev *idev;
49 int error;
50 int push_irq;
51 int release_irq;
52
53 pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL);
54 if (!pwr)
55 return -ENOMEM;
56
57 idev = devm_input_allocate_device(dev);
58 if (!idev)
59 return -ENOMEM;
60
61 idev->name = pdev->name;
62 snprintf(pwr->phys, sizeof(pwr->phys), "%s/input0",
63 pdev->name);
64 idev->phys = pwr->phys;
65 idev->id.bustype = BUS_I2C;
66
67 input_set_capability(idev, EV_KEY, KEY_POWER);
68
69 pwr->dev = dev;
70 pwr->idev = idev;
71 device_init_wakeup(dev, true);
72
73 push_irq = platform_get_irq(pdev, 0);
74 if (push_irq < 0)
75 return -EINVAL;
76
77 release_irq = platform_get_irq(pdev, 1);
78 if (release_irq < 0)
79 return -EINVAL;
80
81 error = devm_request_threaded_irq(dev, push_irq, NULL,
82 tps6594_pb_push_irq,
83 IRQF_ONESHOT,
84 pdev->resource[0].name, pwr);
85 if (error) {
86 dev_err(dev, "failed to request push IRQ #%d: %d\n", push_irq,
87 error);
88 return error;
89 }
90
91 error = devm_request_threaded_irq(dev, release_irq, NULL,
92 tps6594_pb_release_irq,
93 IRQF_ONESHOT,
94 pdev->resource[1].name, pwr);
95 if (error) {
96 dev_err(dev, "failed to request release IRQ #%d: %d\n",
97 release_irq, error);
98 return error;
99 }
100
101 error = input_register_device(idev);
102 if (error) {
103 dev_err(dev, "Can't register power button: %d\n", error);
104 return error;
105 }
106
107 return 0;
108}
109
110static const struct platform_device_id tps6594_pwrbtn_id_table[] = {
111 { "tps6594-pwrbutton", },
112 { /* sentinel */ }
113};
114MODULE_DEVICE_TABLE(platform, tps6594_pwrbtn_id_table);
115
116static struct platform_driver tps6594_pb_driver = {
117 .probe = tps6594_pb_probe,
118 .driver = {
119 .name = "tps6594_pwrbutton",
120 },
121 .id_table = tps6594_pwrbtn_id_table,
122};
123module_platform_driver(tps6594_pb_driver);
124
125MODULE_DESCRIPTION("TPS6594 Power Button");
126MODULE_LICENSE("GPL");