10376148fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
277686517SSundar R Iyer /*
377686517SSundar R Iyer  * Copyright (C) ST-Ericsson SA 2010
477686517SSundar R Iyer  *
577686517SSundar R Iyer  * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
677686517SSundar R Iyer  *
777686517SSundar R Iyer  * AB8500 Power-On Key handler
877686517SSundar R Iyer  */
977686517SSundar R Iyer 
107b961d5bSHimangi Saraogi #include <linux/device.h>
1177686517SSundar R Iyer #include <linux/kernel.h>
1277686517SSundar R Iyer #include <linux/module.h>
1377686517SSundar R Iyer #include <linux/platform_device.h>
1477686517SSundar R Iyer #include <linux/input.h>
1577686517SSundar R Iyer #include <linux/interrupt.h>
16ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h>
1703ecd229SLee Jones #include <linux/of.h>
1877686517SSundar R Iyer #include <linux/slab.h>
1977686517SSundar R Iyer 
2077686517SSundar R Iyer /**
2177686517SSundar R Iyer  * struct ab8500_ponkey - ab8500 ponkey information
22*d8c58078SLee Jones  * @idev: pointer to input device
2377686517SSundar R Iyer  * @ab8500: ab8500 parent
2477686517SSundar R Iyer  * @irq_dbf: irq number for falling transition
2577686517SSundar R Iyer  * @irq_dbr: irq number for rising transition
2677686517SSundar R Iyer  */
2777686517SSundar R Iyer struct ab8500_ponkey {
2877686517SSundar R Iyer 	struct input_dev	*idev;
2977686517SSundar R Iyer 	struct ab8500		*ab8500;
3077686517SSundar R Iyer 	int			irq_dbf;
3177686517SSundar R Iyer 	int			irq_dbr;
3277686517SSundar R Iyer };
3377686517SSundar R Iyer 
3477686517SSundar R Iyer /* AB8500 gives us an interrupt when ONKEY is held */
ab8500_ponkey_handler(int irq,void * data)3577686517SSundar R Iyer static irqreturn_t ab8500_ponkey_handler(int irq, void *data)
3677686517SSundar R Iyer {
3777686517SSundar R Iyer 	struct ab8500_ponkey *ponkey = data;
3877686517SSundar R Iyer 
3977686517SSundar R Iyer 	if (irq == ponkey->irq_dbf)
4077686517SSundar R Iyer 		input_report_key(ponkey->idev, KEY_POWER, true);
4177686517SSundar R Iyer 	else if (irq == ponkey->irq_dbr)
4277686517SSundar R Iyer 		input_report_key(ponkey->idev, KEY_POWER, false);
4377686517SSundar R Iyer 
4477686517SSundar R Iyer 	input_sync(ponkey->idev);
4577686517SSundar R Iyer 
4677686517SSundar R Iyer 	return IRQ_HANDLED;
4777686517SSundar R Iyer }
4877686517SSundar R Iyer 
ab8500_ponkey_probe(struct platform_device * pdev)495298cc4cSBill Pemberton static int ab8500_ponkey_probe(struct platform_device *pdev)
5077686517SSundar R Iyer {
5177686517SSundar R Iyer 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
5277686517SSundar R Iyer 	struct ab8500_ponkey *ponkey;
5377686517SSundar R Iyer 	struct input_dev *input;
5477686517SSundar R Iyer 	int irq_dbf, irq_dbr;
5577686517SSundar R Iyer 	int error;
5677686517SSundar R Iyer 
5777686517SSundar R Iyer 	irq_dbf = platform_get_irq_byname(pdev, "ONKEY_DBF");
580bec8b7eSStephen Boyd 	if (irq_dbf < 0)
5977686517SSundar R Iyer 		return irq_dbf;
6077686517SSundar R Iyer 
6177686517SSundar R Iyer 	irq_dbr = platform_get_irq_byname(pdev, "ONKEY_DBR");
620bec8b7eSStephen Boyd 	if (irq_dbr < 0)
6377686517SSundar R Iyer 		return irq_dbr;
6477686517SSundar R Iyer 
657b961d5bSHimangi Saraogi 	ponkey = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_ponkey),
667b961d5bSHimangi Saraogi 			      GFP_KERNEL);
677b961d5bSHimangi Saraogi 	if (!ponkey)
687b961d5bSHimangi Saraogi 		return -ENOMEM;
697b961d5bSHimangi Saraogi 
707b961d5bSHimangi Saraogi 	input = devm_input_allocate_device(&pdev->dev);
717b961d5bSHimangi Saraogi 	if (!input)
727b961d5bSHimangi Saraogi 		return -ENOMEM;
7377686517SSundar R Iyer 
7477686517SSundar R Iyer 	ponkey->idev = input;
7577686517SSundar R Iyer 	ponkey->ab8500 = ab8500;
76527df5faSDmitry Torokhov 	ponkey->irq_dbf = irq_dbf;
77527df5faSDmitry Torokhov 	ponkey->irq_dbr = irq_dbr;
7877686517SSundar R Iyer 
7977686517SSundar R Iyer 	input->name = "AB8500 POn(PowerOn) Key";
8077686517SSundar R Iyer 	input->dev.parent = &pdev->dev;
8177686517SSundar R Iyer 
8277686517SSundar R Iyer 	input_set_capability(input, EV_KEY, KEY_POWER);
8377686517SSundar R Iyer 
847b961d5bSHimangi Saraogi 	error = devm_request_any_context_irq(&pdev->dev, ponkey->irq_dbf,
857b961d5bSHimangi Saraogi 					     ab8500_ponkey_handler, 0,
867b961d5bSHimangi Saraogi 					     "ab8500-ponkey-dbf", ponkey);
8777686517SSundar R Iyer 	if (error < 0) {
8877686517SSundar R Iyer 		dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n",
8977686517SSundar R Iyer 			ponkey->irq_dbf, error);
907b961d5bSHimangi Saraogi 		return error;
9177686517SSundar R Iyer 	}
9277686517SSundar R Iyer 
937b961d5bSHimangi Saraogi 	error = devm_request_any_context_irq(&pdev->dev, ponkey->irq_dbr,
947b961d5bSHimangi Saraogi 					     ab8500_ponkey_handler, 0,
957b961d5bSHimangi Saraogi 					     "ab8500-ponkey-dbr", ponkey);
9677686517SSundar R Iyer 	if (error < 0) {
9777686517SSundar R Iyer 		dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n",
9877686517SSundar R Iyer 			ponkey->irq_dbr, error);
997b961d5bSHimangi Saraogi 		return error;
10077686517SSundar R Iyer 	}
10177686517SSundar R Iyer 
10277686517SSundar R Iyer 	error = input_register_device(ponkey->idev);
10377686517SSundar R Iyer 	if (error) {
10477686517SSundar R Iyer 		dev_err(ab8500->dev, "Can't register input device: %d\n", error);
10577686517SSundar R Iyer 		return error;
10677686517SSundar R Iyer 	}
10777686517SSundar R Iyer 
10877686517SSundar R Iyer 	return 0;
10977686517SSundar R Iyer }
11077686517SSundar R Iyer 
11103ecd229SLee Jones #ifdef CONFIG_OF
11203ecd229SLee Jones static const struct of_device_id ab8500_ponkey_match[] = {
11303ecd229SLee Jones 	{ .compatible = "stericsson,ab8500-ponkey", },
11403ecd229SLee Jones 	{}
11503ecd229SLee Jones };
116e4dbe796SLuis de Bethencourt MODULE_DEVICE_TABLE(of, ab8500_ponkey_match);
11703ecd229SLee Jones #endif
11803ecd229SLee Jones 
11977686517SSundar R Iyer static struct platform_driver ab8500_ponkey_driver = {
12077686517SSundar R Iyer 	.driver		= {
12177686517SSundar R Iyer 		.name	= "ab8500-poweron-key",
12203ecd229SLee Jones 		.of_match_table = of_match_ptr(ab8500_ponkey_match),
12377686517SSundar R Iyer 	},
12477686517SSundar R Iyer 	.probe		= ab8500_ponkey_probe,
12577686517SSundar R Iyer };
126840a746bSJJ Ding module_platform_driver(ab8500_ponkey_driver);
12777686517SSundar R Iyer 
12877686517SSundar R Iyer MODULE_LICENSE("GPL v2");
12977686517SSundar R Iyer MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
13077686517SSundar R Iyer MODULE_DESCRIPTION("ST-Ericsson AB8500 Power-ON(Pon) Key driver");
131