12e4355e4SKate Hsuan // SPDX-License-Identifier: GPL-2.0
22e4355e4SKate Hsuan /*
32e4355e4SKate Hsuan * Power-button driver for Dollar Cove TI PMIC
42e4355e4SKate Hsuan * Copyright (C) 2014 Intel Corp
52e4355e4SKate Hsuan * Copyright (c) 2017 Takashi Iwai <tiwai@suse.de>
62e4355e4SKate Hsuan */
72e4355e4SKate Hsuan
82e4355e4SKate Hsuan #include <linux/input.h>
92e4355e4SKate Hsuan #include <linux/interrupt.h>
102e4355e4SKate Hsuan #include <linux/device.h>
112e4355e4SKate Hsuan #include <linux/mfd/intel_soc_pmic.h>
122e4355e4SKate Hsuan #include <linux/module.h>
132e4355e4SKate Hsuan #include <linux/platform_device.h>
142e4355e4SKate Hsuan #include <linux/pm_wakeirq.h>
152e4355e4SKate Hsuan #include <linux/slab.h>
162e4355e4SKate Hsuan
172e4355e4SKate Hsuan #define CHTDC_TI_SIRQ_REG 0x3
182e4355e4SKate Hsuan #define SIRQ_PWRBTN_REL BIT(0)
192e4355e4SKate Hsuan
chtdc_ti_pwrbtn_interrupt(int irq,void * dev_id)202e4355e4SKate Hsuan static irqreturn_t chtdc_ti_pwrbtn_interrupt(int irq, void *dev_id)
212e4355e4SKate Hsuan {
222e4355e4SKate Hsuan struct input_dev *input = dev_id;
232e4355e4SKate Hsuan struct device *dev = input->dev.parent;
242e4355e4SKate Hsuan struct regmap *regmap = dev_get_drvdata(dev);
252e4355e4SKate Hsuan int state;
262e4355e4SKate Hsuan
272e4355e4SKate Hsuan if (!regmap_read(regmap, CHTDC_TI_SIRQ_REG, &state)) {
282e4355e4SKate Hsuan dev_dbg(dev, "SIRQ_REG=0x%x\n", state);
292e4355e4SKate Hsuan input_report_key(input, KEY_POWER, !(state & SIRQ_PWRBTN_REL));
302e4355e4SKate Hsuan input_sync(input);
312e4355e4SKate Hsuan }
322e4355e4SKate Hsuan
332e4355e4SKate Hsuan return IRQ_HANDLED;
342e4355e4SKate Hsuan }
352e4355e4SKate Hsuan
chtdc_ti_pwrbtn_probe(struct platform_device * pdev)362e4355e4SKate Hsuan static int chtdc_ti_pwrbtn_probe(struct platform_device *pdev)
372e4355e4SKate Hsuan {
382e4355e4SKate Hsuan struct device *dev = &pdev->dev;
392e4355e4SKate Hsuan struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent);
402e4355e4SKate Hsuan struct input_dev *input;
412e4355e4SKate Hsuan int irq, err;
422e4355e4SKate Hsuan
432e4355e4SKate Hsuan irq = platform_get_irq(pdev, 0);
442e4355e4SKate Hsuan if (irq < 0)
452e4355e4SKate Hsuan return irq;
462e4355e4SKate Hsuan input = devm_input_allocate_device(dev);
472e4355e4SKate Hsuan if (!input)
482e4355e4SKate Hsuan return -ENOMEM;
492e4355e4SKate Hsuan input->name = pdev->name;
502e4355e4SKate Hsuan input->phys = "power-button/input0";
512e4355e4SKate Hsuan input->id.bustype = BUS_HOST;
522e4355e4SKate Hsuan input_set_capability(input, EV_KEY, KEY_POWER);
532e4355e4SKate Hsuan err = input_register_device(input);
542e4355e4SKate Hsuan if (err)
552e4355e4SKate Hsuan return err;
562e4355e4SKate Hsuan
572e4355e4SKate Hsuan dev_set_drvdata(dev, pmic->regmap);
582e4355e4SKate Hsuan
592e4355e4SKate Hsuan err = devm_request_threaded_irq(dev, irq, NULL,
602e4355e4SKate Hsuan chtdc_ti_pwrbtn_interrupt,
612e4355e4SKate Hsuan IRQF_ONESHOT, KBUILD_MODNAME, input);
622e4355e4SKate Hsuan if (err)
632e4355e4SKate Hsuan return err;
642e4355e4SKate Hsuan
652e4355e4SKate Hsuan device_init_wakeup(dev, true);
662e4355e4SKate Hsuan dev_pm_set_wake_irq(dev, irq);
672e4355e4SKate Hsuan return 0;
682e4355e4SKate Hsuan }
692e4355e4SKate Hsuan
chtdc_ti_pwrbtn_remove(struct platform_device * pdev)70*bca92922SUwe Kleine-König static void chtdc_ti_pwrbtn_remove(struct platform_device *pdev)
712e4355e4SKate Hsuan {
722e4355e4SKate Hsuan dev_pm_clear_wake_irq(&pdev->dev);
732e4355e4SKate Hsuan device_init_wakeup(&pdev->dev, false);
742e4355e4SKate Hsuan }
752e4355e4SKate Hsuan
762e4355e4SKate Hsuan static const struct platform_device_id chtdc_ti_pwrbtn_id_table[] = {
772e4355e4SKate Hsuan { .name = "chtdc_ti_pwrbtn" },
782e4355e4SKate Hsuan {},
792e4355e4SKate Hsuan };
802e4355e4SKate Hsuan MODULE_DEVICE_TABLE(platform, chtdc_ti_pwrbtn_id_table);
812e4355e4SKate Hsuan
822e4355e4SKate Hsuan static struct platform_driver chtdc_ti_pwrbtn_driver = {
832e4355e4SKate Hsuan .driver = {
842e4355e4SKate Hsuan .name = KBUILD_MODNAME,
852e4355e4SKate Hsuan },
862e4355e4SKate Hsuan .probe = chtdc_ti_pwrbtn_probe,
87*bca92922SUwe Kleine-König .remove_new = chtdc_ti_pwrbtn_remove,
882e4355e4SKate Hsuan .id_table = chtdc_ti_pwrbtn_id_table,
892e4355e4SKate Hsuan };
902e4355e4SKate Hsuan module_platform_driver(chtdc_ti_pwrbtn_driver);
912e4355e4SKate Hsuan
922e4355e4SKate Hsuan MODULE_DESCRIPTION("Power-button driver for Dollar Cove TI PMIC");
932e4355e4SKate Hsuan MODULE_LICENSE("GPL v2");
94