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 17 struct tps6594_pwrbutton { 18 struct device *dev; 19 struct input_dev *idev; 20 char phys[32]; 21 }; 22 23 static 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 34 static 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 44 static 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 110 static const struct platform_device_id tps6594_pwrbtn_id_table[] = { 111 { "tps6594-pwrbutton", }, 112 { /* sentinel */ } 113 }; 114 MODULE_DEVICE_TABLE(platform, tps6594_pwrbtn_id_table); 115 116 static 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 }; 123 module_platform_driver(tps6594_pb_driver); 124 125 MODULE_DESCRIPTION("TPS6594 Power Button"); 126 MODULE_LICENSE("GPL"); 127