1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/input.h> 3 #include <linux/interrupt.h> 4 #include <linux/irq.h> 5 #include <linux/platform_device.h> 6 #include <linux/regmap.h> 7 8 #include <linux/mfd/88pm886.h> 9 10 struct pm886_onkey { 11 struct input_dev *idev; 12 struct pm886_chip *chip; 13 }; 14 15 static irqreturn_t pm886_onkey_irq_handler(int irq, void *data) 16 { 17 struct pm886_onkey *onkey = data; 18 struct regmap *regmap = onkey->chip->regmap; 19 struct input_dev *idev = onkey->idev; 20 struct device *parent = idev->dev.parent; 21 unsigned int val; 22 int err; 23 24 err = regmap_read(regmap, PM886_REG_STATUS1, &val); 25 if (err) { 26 dev_err(parent, "Failed to read status: %d\n", err); 27 return IRQ_NONE; 28 } 29 val &= PM886_ONKEY_STS1; 30 31 input_report_key(idev, KEY_POWER, val); 32 input_sync(idev); 33 34 return IRQ_HANDLED; 35 } 36 37 static int pm886_onkey_probe(struct platform_device *pdev) 38 { 39 struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent); 40 struct device *dev = &pdev->dev; 41 struct pm886_onkey *onkey; 42 struct input_dev *idev; 43 int irq, err; 44 45 onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL); 46 if (!onkey) 47 return -ENOMEM; 48 49 onkey->chip = chip; 50 51 irq = platform_get_irq(pdev, 0); 52 if (irq < 0) 53 return dev_err_probe(dev, irq, "Failed to get IRQ\n"); 54 55 idev = devm_input_allocate_device(dev); 56 if (!idev) { 57 dev_err(dev, "Failed to allocate input device\n"); 58 return -ENOMEM; 59 } 60 onkey->idev = idev; 61 62 idev->name = "88pm886-onkey"; 63 idev->phys = "88pm886-onkey/input0"; 64 idev->id.bustype = BUS_I2C; 65 66 input_set_capability(idev, EV_KEY, KEY_POWER); 67 68 err = devm_request_threaded_irq(dev, irq, NULL, pm886_onkey_irq_handler, 69 IRQF_ONESHOT | IRQF_NO_SUSPEND, "onkey", 70 onkey); 71 if (err) 72 return dev_err_probe(dev, err, "Failed to request IRQ\n"); 73 74 err = input_register_device(idev); 75 if (err) 76 return dev_err_probe(dev, err, "Failed to register input device\n"); 77 78 return 0; 79 } 80 81 static const struct platform_device_id pm886_onkey_id_table[] = { 82 { "88pm886-onkey", }, 83 { } 84 }; 85 MODULE_DEVICE_TABLE(platform, pm886_onkey_id_table); 86 87 static struct platform_driver pm886_onkey_driver = { 88 .driver = { 89 .name = "88pm886-onkey", 90 }, 91 .probe = pm886_onkey_probe, 92 .id_table = pm886_onkey_id_table, 93 }; 94 module_platform_driver(pm886_onkey_driver); 95 96 MODULE_DESCRIPTION("Marvell 88PM886 onkey driver"); 97 MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>"); 98 MODULE_LICENSE("GPL"); 99