1 // SPDX-License-Identifier: GPL-2.0-only
3 * Texas Instruments' TPS65217 and TPS65218 Power Button Input Driver
5 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
6 * Author: Felipe Balbi <balbi@ti.com>
7 * Author: Marcin Niestroj <m.niestroj@grinn-global.com>
10 #include <linux/init.h>
11 #include <linux/input.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/mfd/tps65217.h>
15 #include <linux/mfd/tps65218.h>
16 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/regmap.h>
20 #include <linux/slab.h>
22 struct tps6521x_data
{
23 unsigned int reg_status
;
28 static const struct tps6521x_data tps65217_data
= {
29 .reg_status
= TPS65217_REG_STATUS
,
30 .pb_mask
= TPS65217_STATUS_PB
,
31 .name
= "tps65217_pwrbutton",
34 static const struct tps6521x_data tps65218_data
= {
35 .reg_status
= TPS65218_REG_STATUS
,
36 .pb_mask
= TPS65218_STATUS_PB_STATE
,
37 .name
= "tps65218_pwrbutton",
40 struct tps6521x_pwrbutton
{
42 struct regmap
*regmap
;
43 struct input_dev
*idev
;
44 const struct tps6521x_data
*data
;
48 static const struct of_device_id of_tps6521x_pb_match
[] = {
49 { .compatible
= "ti,tps65217-pwrbutton", .data
= &tps65217_data
},
50 { .compatible
= "ti,tps65218-pwrbutton", .data
= &tps65218_data
},
53 MODULE_DEVICE_TABLE(of
, of_tps6521x_pb_match
);
55 static irqreturn_t
tps6521x_pb_irq(int irq
, void *_pwr
)
57 struct tps6521x_pwrbutton
*pwr
= _pwr
;
58 const struct tps6521x_data
*tps_data
= pwr
->data
;
62 error
= regmap_read(pwr
->regmap
, tps_data
->reg_status
, ®
);
64 dev_err(pwr
->dev
, "can't read register: %d\n", error
);
68 if (reg
& tps_data
->pb_mask
) {
69 input_report_key(pwr
->idev
, KEY_POWER
, 1);
70 pm_wakeup_event(pwr
->dev
, 0);
72 input_report_key(pwr
->idev
, KEY_POWER
, 0);
75 input_sync(pwr
->idev
);
81 static int tps6521x_pb_probe(struct platform_device
*pdev
)
83 struct device
*dev
= &pdev
->dev
;
84 struct tps6521x_pwrbutton
*pwr
;
85 struct input_dev
*idev
;
86 const struct of_device_id
*match
;
90 match
= of_match_node(of_tps6521x_pb_match
, dev
->of_node
);
94 pwr
= devm_kzalloc(dev
, sizeof(*pwr
), GFP_KERNEL
);
98 pwr
->data
= match
->data
;
100 idev
= devm_input_allocate_device(dev
);
104 idev
->name
= pwr
->data
->name
;
105 snprintf(pwr
->phys
, sizeof(pwr
->phys
), "%s/input0",
107 idev
->phys
= pwr
->phys
;
108 idev
->dev
.parent
= dev
;
109 idev
->id
.bustype
= BUS_I2C
;
111 input_set_capability(idev
, EV_KEY
, KEY_POWER
);
113 pwr
->regmap
= dev_get_regmap(dev
->parent
, NULL
);
116 device_init_wakeup(dev
, true);
118 irq
= platform_get_irq(pdev
, 0);
122 error
= devm_request_threaded_irq(dev
, irq
, NULL
, tps6521x_pb_irq
,
123 IRQF_TRIGGER_RISING
|
124 IRQF_TRIGGER_FALLING
|
126 pwr
->data
->name
, pwr
);
128 dev_err(dev
, "failed to request IRQ #%d: %d\n", irq
, error
);
132 error
= input_register_device(idev
);
134 dev_err(dev
, "Can't register power button: %d\n", error
);
141 static const struct platform_device_id tps6521x_pwrbtn_id_table
[] = {
142 { "tps65218-pwrbutton", },
143 { "tps65217-pwrbutton", },
146 MODULE_DEVICE_TABLE(platform
, tps6521x_pwrbtn_id_table
);
148 static struct platform_driver tps6521x_pb_driver
= {
149 .probe
= tps6521x_pb_probe
,
151 .name
= "tps6521x_pwrbutton",
152 .of_match_table
= of_tps6521x_pb_match
,
154 .id_table
= tps6521x_pwrbtn_id_table
,
156 module_platform_driver(tps6521x_pb_driver
);
158 MODULE_DESCRIPTION("TPS6521X Power Button");
159 MODULE_LICENSE("GPL v2");
160 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");