xref: /openbmc/linux/drivers/platform/x86/intel/chtdc_ti_pwrbtn.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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