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