1 // SPDX-License-Identifier: GPL-2.0
3 // Driver for TPS65219 Push Button
5 // Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
7 #include <linux/init.h>
8 #include <linux/input.h>
9 #include <linux/interrupt.h>
10 #include <linux/kernel.h>
11 #include <linux/mfd/tps65219.h>
12 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/regmap.h>
16 #include <linux/slab.h>
18 struct tps65219_pwrbutton
{
20 struct input_dev
*idev
;
24 static irqreturn_t
tps65219_pb_push_irq(int irq
, void *_pwr
)
26 struct tps65219_pwrbutton
*pwr
= _pwr
;
28 input_report_key(pwr
->idev
, KEY_POWER
, 1);
29 pm_wakeup_event(pwr
->dev
, 0);
30 input_sync(pwr
->idev
);
35 static irqreturn_t
tps65219_pb_release_irq(int irq
, void *_pwr
)
37 struct tps65219_pwrbutton
*pwr
= _pwr
;
39 input_report_key(pwr
->idev
, KEY_POWER
, 0);
40 input_sync(pwr
->idev
);
45 static int tps65219_pb_probe(struct platform_device
*pdev
)
47 struct tps65219
*tps
= dev_get_drvdata(pdev
->dev
.parent
);
48 struct device
*dev
= &pdev
->dev
;
49 struct tps65219_pwrbutton
*pwr
;
50 struct input_dev
*idev
;
55 pwr
= devm_kzalloc(dev
, sizeof(*pwr
), GFP_KERNEL
);
59 idev
= devm_input_allocate_device(dev
);
63 idev
->name
= pdev
->name
;
64 snprintf(pwr
->phys
, sizeof(pwr
->phys
), "%s/input0",
66 idev
->phys
= pwr
->phys
;
67 idev
->id
.bustype
= BUS_I2C
;
69 input_set_capability(idev
, EV_KEY
, KEY_POWER
);
73 device_init_wakeup(dev
, true);
75 push_irq
= platform_get_irq(pdev
, 0);
79 release_irq
= platform_get_irq(pdev
, 1);
83 error
= devm_request_threaded_irq(dev
, push_irq
, NULL
,
88 dev_err(dev
, "failed to request push IRQ #%d: %d\n", push_irq
,
93 error
= devm_request_threaded_irq(dev
, release_irq
, NULL
,
94 tps65219_pb_release_irq
,
98 dev_err(dev
, "failed to request release IRQ #%d: %d\n",
103 error
= input_register_device(idev
);
105 dev_err(dev
, "Can't register power button: %d\n", error
);
109 /* Enable interrupts for the pushbutton */
110 regmap_clear_bits(tps
->regmap
, TPS65219_REG_MASK_CONFIG
,
111 TPS65219_REG_MASK_INT_FOR_PB_MASK
);
113 /* Set PB/EN/VSENSE pin to be a pushbutton */
114 regmap_update_bits(tps
->regmap
, TPS65219_REG_MFP_2_CONFIG
,
115 TPS65219_MFP_2_EN_PB_VSENSE_MASK
, TPS65219_MFP_2_PB
);
120 static void tps65219_pb_remove(struct platform_device
*pdev
)
122 struct tps65219
*tps
= dev_get_drvdata(pdev
->dev
.parent
);
125 /* Disable interrupt for the pushbutton */
126 ret
= regmap_set_bits(tps
->regmap
, TPS65219_REG_MASK_CONFIG
,
127 TPS65219_REG_MASK_INT_FOR_PB_MASK
);
129 dev_warn(&pdev
->dev
, "Failed to disable irq (%pe)\n", ERR_PTR(ret
));
132 static const struct platform_device_id tps65219_pwrbtn_id_table
[] = {
133 { "tps65219-pwrbutton", },
136 MODULE_DEVICE_TABLE(platform
, tps65219_pwrbtn_id_table
);
138 static struct platform_driver tps65219_pb_driver
= {
139 .probe
= tps65219_pb_probe
,
140 .remove
= tps65219_pb_remove
,
142 .name
= "tps65219_pwrbutton",
144 .id_table
= tps65219_pwrbtn_id_table
,
146 module_platform_driver(tps65219_pb_driver
);
148 MODULE_DESCRIPTION("TPS65219 Power Button");
149 MODULE_LICENSE("GPL");
150 MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com");