/*
 * Copyright 2015 Verifone Int.
 *
 * Author: Nicolas Saenz Julienne <nicolassaenzj@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify i t
 * under  the terms of the GNU General  Public License as published by th e
 * Free Software Foundation;  either version 2 of the License, or (at you r
 * option) any later version.
 *
 * This driver is based on the gpio-tps65912 implementation.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/mfd/tps65218.h>

struct tps65218_gpio {
	struct tps65218 *tps65218;
	struct gpio_chip gpio_chip;
};

static int tps65218_gpio_get(struct gpio_chip *gc, unsigned offset)
{
	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
	unsigned int val;
	int ret;

	ret = tps65218_reg_read(tps65218, TPS65218_REG_ENABLE2, &val);
	if (ret)
		return ret;

	return !!(val & (TPS65218_ENABLE2_GPIO1 << offset));
}

static void tps65218_gpio_set(struct gpio_chip *gc, unsigned offset,
			      int value)
{
	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
	struct tps65218 *tps65218 = tps65218_gpio->tps65218;

	if (value)
		tps65218_set_bits(tps65218, TPS65218_REG_ENABLE2,
				  TPS65218_ENABLE2_GPIO1 << offset,
				  TPS65218_ENABLE2_GPIO1 << offset,
				  TPS65218_PROTECT_L1);
	else
		tps65218_clear_bits(tps65218, TPS65218_REG_ENABLE2,
				    TPS65218_ENABLE2_GPIO1 << offset,
				    TPS65218_PROTECT_L1);
}

static int tps65218_gpio_output(struct gpio_chip *gc, unsigned offset,
				int value)
{
	/* Only drives GPOs */
	tps65218_gpio_set(gc, offset, value);
	return 0;
}

static int tps65218_gpio_input(struct gpio_chip *gc, unsigned offset)
{
	return -EPERM;
}

static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
{
	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
	int ret;

	if (gpiochip_line_is_open_source(gc, offset)) {
		dev_err(gc->parent, "can't work as open source\n");
		return -EINVAL;
	}

	switch (offset) {
	case 0:
		if (!gpiochip_line_is_open_drain(gc, offset)) {
			dev_err(gc->parent, "GPO1 works only as open drain\n");
			return -EINVAL;
		}

		/* Disable sequencer for GPO1 */
		ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7,
					  TPS65218_SEQ7_GPO1_SEQ_MASK,
					  TPS65218_PROTECT_L1);
		if (ret)
			return ret;

		/* Setup GPO1 */
		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
					  TPS65218_CONFIG1_IO1_SEL,
					  TPS65218_PROTECT_L1);
		if (ret)
			return ret;

		break;
	case 1:
		/* Setup GPO2 */
		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
					  TPS65218_CONFIG1_IO1_SEL,
					  TPS65218_PROTECT_L1);
		if (ret)
			return ret;

		break;

	case 2:
		if (!gpiochip_line_is_open_drain(gc, offset)) {
			dev_err(gc->parent, "GPO3 works only as open drain\n");
			return -EINVAL;
		}

		/* Disable sequencer for GPO3 */
		ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7,
					  TPS65218_SEQ7_GPO3_SEQ_MASK,
					  TPS65218_PROTECT_L1);
		if (ret)
			return ret;

		/* Setup GPO3 */
		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG2,
					  TPS65218_CONFIG2_DC12_RST,
					  TPS65218_PROTECT_L1);
		if (ret)
			return ret;

		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int tps65218_gpio_set_single_ended(struct gpio_chip *gc,
					  unsigned offset,
					  enum single_ended_mode mode)
{
	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
	struct tps65218 *tps65218 = tps65218_gpio->tps65218;

	switch (offset) {
	case 0:
	case 2:
		/* GPO1 is hardwired to be open drain */
		if (mode == LINE_MODE_OPEN_DRAIN)
			return 0;
		return -ENOTSUPP;
	case 1:
		/* GPO2 is push-pull by default, can be set as open drain. */
		if (mode == LINE_MODE_OPEN_DRAIN)
			return tps65218_clear_bits(tps65218,
						   TPS65218_REG_CONFIG1,
						   TPS65218_CONFIG1_GPO2_BUF,
						   TPS65218_PROTECT_L1);
		if (mode == LINE_MODE_PUSH_PULL)
			return tps65218_set_bits(tps65218,
						 TPS65218_REG_CONFIG1,
						 TPS65218_CONFIG1_GPO2_BUF,
						 TPS65218_CONFIG1_GPO2_BUF,
						 TPS65218_PROTECT_L1);
		return -ENOTSUPP;
	default:
		break;
	}
	return -ENOTSUPP;
}

static struct gpio_chip template_chip = {
	.label			= "gpio-tps65218",
	.owner			= THIS_MODULE,
	.request		= tps65218_gpio_request,
	.direction_output	= tps65218_gpio_output,
	.direction_input	= tps65218_gpio_input,
	.get			= tps65218_gpio_get,
	.set			= tps65218_gpio_set,
	.set_single_ended	= tps65218_gpio_set_single_ended,
	.can_sleep		= true,
	.ngpio			= 3,
	.base			= -1,
};

static int tps65218_gpio_probe(struct platform_device *pdev)
{
	struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent);
	struct tps65218_gpio *tps65218_gpio;
	int ret;

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

	tps65218_gpio->tps65218 = tps65218;
	tps65218_gpio->gpio_chip = template_chip;
	tps65218_gpio->gpio_chip.parent = &pdev->dev;
#ifdef CONFIG_OF_GPIO
	tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node;
#endif

	ret = gpiochip_add_data(&tps65218_gpio->gpio_chip, tps65218_gpio);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
		return ret;
	}

	platform_set_drvdata(pdev, tps65218_gpio);

	return ret;
}

static int tps65218_gpio_remove(struct platform_device *pdev)
{
	struct tps65218_gpio *tps65218_gpio = platform_get_drvdata(pdev);

	gpiochip_remove(&tps65218_gpio->gpio_chip);

	return 0;
}

static const struct of_device_id tps65218_dt_match[] = {
	{ .compatible = "ti,tps65218-gpio" },
	{  }
};
MODULE_DEVICE_TABLE(of, tps65218_dt_match);

static struct platform_driver tps65218_gpio_driver = {
	.driver = {
		.name = "tps65218-gpio",
		.of_match_table = of_match_ptr(tps65218_dt_match)
	},
	.probe = tps65218_gpio_probe,
	.remove = tps65218_gpio_remove,
};

module_platform_driver(tps65218_gpio_driver);

MODULE_AUTHOR("Nicolas Saenz Julienne <nicolassaenzj@gmail.com>");
MODULE_DESCRIPTION("GPO interface for TPS65218 PMICs");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:tps65218-gpio");
