/*
 * Driver for the PF1550 ON_KEY
 * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/pf1550.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

struct onkey_drv_data {
	struct device *dev;
	struct pf1550_dev *pf1550;
	int irq;
	int keycode;
	int wakeup;
	struct input_dev *input;
};

static struct pf1550_irq_info pf1550_onkey_irqs[] = {
	{ PF1550_ONKEY_IRQ_PUSHI,	"release" },
	{ PF1550_ONKEY_IRQ_1SI,		"1S" },
	{ PF1550_ONKEY_IRQ_2SI,		"2S" },
	{ PF1550_ONKEY_IRQ_3SI,		"3S" },
	{ PF1550_ONKEY_IRQ_4SI,		"4S" },
	{ PF1550_ONKEY_IRQ_8SI,		"8S" },
};

static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
{
	struct onkey_drv_data *onkey = data;
	int i, state, irq_type = -1;

	onkey->irq = irq;

	for (i = 0; i < ARRAY_SIZE(pf1550_onkey_irqs); i++)
		if (onkey->irq == pf1550_onkey_irqs[i].virq)
			irq_type = pf1550_onkey_irqs[i].irq;
	switch (irq_type) {
	case PF1550_ONKEY_IRQ_PUSHI:
		state = 0;
		break;
	case PF1550_ONKEY_IRQ_1SI:
	case PF1550_ONKEY_IRQ_2SI:
	case PF1550_ONKEY_IRQ_3SI:
	case PF1550_ONKEY_IRQ_4SI:
	case PF1550_ONKEY_IRQ_8SI:
		state = 1;
		break;
	default:
		dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
			irq_type);
		return IRQ_HANDLED;
	}

	input_event(onkey->input, EV_KEY, onkey->keycode, state);
	input_sync(onkey->input);

	return IRQ_HANDLED;
}

static int pf1550_onkey_probe(struct platform_device *pdev)
{
	struct onkey_drv_data *onkey;
	struct input_dev *input = NULL;
	struct device_node *np = pdev->dev.of_node;
	struct pf1550_dev *pf1550 = dev_get_drvdata(pdev->dev.parent);
	int i, error;

	if (!np)
		return -ENODEV;

	onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
	if (!onkey)
		return -ENOMEM;

	if (of_property_read_u32(np, "linux,keycode", &onkey->keycode)) {
		onkey->keycode = KEY_POWER;
		dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
	}

	onkey->wakeup = of_property_read_bool(np, "wakeup");

	input = devm_input_allocate_device(&pdev->dev);
	if (!input) {
		dev_err(&pdev->dev, "failed to allocate the input device\n");
		return -ENOMEM;
	}

	input->name = pdev->name;
	input->phys = "pf1550-onkey/input0";
	input->id.bustype = BUS_HOST;

	input_set_capability(input, EV_KEY, onkey->keycode);

	for (i = 0; i < ARRAY_SIZE(pf1550_onkey_irqs); i++) {
		struct pf1550_irq_info *onkey_irq =
						&pf1550_onkey_irqs[i];
		unsigned int virq = 0;

		virq = regmap_irq_get_virq(pf1550->irq_data_onkey,
					onkey_irq->irq);
		if (!virq)
			return -EINVAL;

		onkey_irq->virq = virq;

		error = devm_request_threaded_irq(&pdev->dev, virq, NULL,
					pf1550_onkey_irq_handler,
					IRQF_NO_SUSPEND,
					onkey_irq->name, onkey);
		if (error) {
			dev_err(&pdev->dev,
				"failed: irq request (IRQ: %d, error :%d)\n",
				onkey_irq->irq, error);
			return error;
		}
	}

	error = input_register_device(input);
	if (error < 0) {
		dev_err(&pdev->dev, "failed to register input device\n");
		input_free_device(input);
		return error;
	}

	onkey->input = input;
	onkey->pf1550 = pf1550;
	platform_set_drvdata(pdev, onkey);

	device_init_wakeup(&pdev->dev, onkey->wakeup);

	return 0;
}

static int pf1550_onkey_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct onkey_drv_data *onkey = platform_get_drvdata(pdev);

	if (!device_may_wakeup(&pdev->dev))
		regmap_write(onkey->pf1550->regmap,
			     PF1550_PMIC_REG_ONKEY_INT_MASK0,
			     ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
			     ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
	else
		enable_irq_wake(onkey->pf1550->irq);

	return 0;
}

static int pf1550_onkey_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct onkey_drv_data *onkey = platform_get_drvdata(pdev);

	if (!device_may_wakeup(&pdev->dev))
		regmap_write(onkey->pf1550->regmap,
			     PF1550_PMIC_REG_ONKEY_INT_MASK0,
			     ~(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
			     ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI));
	else
		disable_irq_wake(onkey->pf1550->irq);

	return 0;
}

static const struct of_device_id pf1550_onkey_ids[] = {
	{ .compatible = "fsl,pf1550-onkey" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pf1550_onkey_ids);

static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
				pf1550_onkey_resume);

static struct platform_driver pf1550_onkey_driver = {
	.driver = {
		.name = "pf1550-onkey",
		.pm     = &pf1550_onkey_pm_ops,
		.of_match_table = pf1550_onkey_ids,
	},
	.probe = pf1550_onkey_probe,
};
module_platform_driver(pf1550_onkey_driver);

MODULE_AUTHOR("Freescale Semiconductor");
MODULE_DESCRIPTION(" PF1550 onkey Driver");
MODULE_LICENSE("GPL");
