/*
 * Qualcomm PMIC8XXX GPIO driver based on RPC
 *
 * Copyright (c) 2011, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#define pr_fmt(fmt)	"%s: " fmt, __func__

#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/gpio-pm8xxx-rpc.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <mach/pmic.h>

struct pm8xxx_gpio_rpc_chip {
	struct list_head	link;
	struct gpio_chip	gpio_chip;
};

static LIST_HEAD(pm8xxx_gpio_rpc_chips);
static DEFINE_MUTEX(pm8xxx_gpio_chips_lock);

static int pm8xxx_gpio_rpc_get(struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip,
								unsigned gpio)
{
	int rc;

	if (gpio >= pm8xxx_gpio_chip->gpio_chip.ngpio
					|| pm8xxx_gpio_chip == NULL)
		return -EINVAL;

	rc =  pmic_gpio_get_value(gpio);

	return rc;
}

static int pm8xxx_gpio_rpc_set(struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip,
						 unsigned gpio, int value)
{
	int rc;

	if (gpio >= pm8xxx_gpio_chip->gpio_chip.ngpio ||
					pm8xxx_gpio_chip == NULL)
		return -EINVAL;

	rc = pmic_gpio_set_value(gpio, value);

	return rc;
}

static int pm8xxx_gpio_rpc_set_direction(struct pm8xxx_gpio_rpc_chip
			*pm8xxx_gpio_chip, unsigned gpio, int direction)
{
	int rc = 0;

	if (!direction || pm8xxx_gpio_chip == NULL)
		return -EINVAL;

	if (direction ==  PM_GPIO_DIR_IN)
		rc = pmic_gpio_direction_input(gpio);
	else if (direction == PM_GPIO_DIR_OUT)
		rc = pmic_gpio_direction_output(gpio);

	return rc;
}

static int pm8xxx_gpio_rpc_read(struct gpio_chip *gpio_chip, unsigned offset)
{
	struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip =
					dev_get_drvdata(gpio_chip->dev);

	return pm8xxx_gpio_rpc_get(pm8xxx_gpio_chip, offset);
}

static void pm8xxx_gpio_rpc_write(struct gpio_chip *gpio_chip,
						unsigned offset, int val)
{
	struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip =
					dev_get_drvdata(gpio_chip->dev);

	pm8xxx_gpio_rpc_set(pm8xxx_gpio_chip, offset, !!val);
}

static int pm8xxx_gpio_rpc_direction_input(struct gpio_chip *gpio_chip,
							unsigned offset)
{
	struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip =
					dev_get_drvdata(gpio_chip->dev);

	return pm8xxx_gpio_rpc_set_direction(pm8xxx_gpio_chip, offset,
							PM_GPIO_DIR_IN);
}

static int pm8xxx_gpio_rpc_direction_output(struct gpio_chip *gpio_chip,
						unsigned offset, int val)
{
	int ret = 0;

	struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip =
					dev_get_drvdata(gpio_chip->dev);

	ret = pm8xxx_gpio_rpc_set_direction(pm8xxx_gpio_chip, offset,
							PM_GPIO_DIR_OUT);
	if (!ret)
		ret = pm8xxx_gpio_rpc_set(pm8xxx_gpio_chip, offset, !!val);

	return ret;
}

static void pm8xxx_gpio_rpc_dbg_show(struct seq_file *s, struct gpio_chip
								*gpio_chip)
{
	struct pm8xxx_gpio_rpc_chip *pmxx_gpio_chip =
					dev_get_drvdata(gpio_chip->dev);
	u8 state, mode;
	const char *label;
	int i;

	for (i = 0; i < gpio_chip->ngpio; i++) {
		label = gpiochip_is_requested(gpio_chip, i);
		state = pm8xxx_gpio_rpc_get(pmxx_gpio_chip, i);
		mode =  pmic_gpio_get_direction(i);
		seq_printf(s, "gpio-%-3d (%-12.12s) %s %s",
				gpio_chip->base + i,
				label ? label : " ", mode ? "out" : "in",
				state ? "hi" : "lo");
		seq_printf(s, "\n");
	}
}

static int pm8xxx_gpio_rpc_probe(struct platform_device *pdev)
{
	int ret;
	struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip;
	const struct pm8xxx_gpio_rpc_platform_data *pdata =
					pdev->dev.platform_data;

	if (!pdata) {
		pr_err("missing platform data\n");
		return -EINVAL;
	}

	pm8xxx_gpio_chip = kzalloc(sizeof(struct pm8xxx_gpio_rpc_chip),
								GFP_KERNEL);
	if (!pm8xxx_gpio_chip) {
		pr_err("Cannot allocate pm8xxx_gpio_chip\n");
		return -ENOMEM;
	}

	pm8xxx_gpio_chip->gpio_chip.label = "pm8xxx-gpio-rpc";
	pm8xxx_gpio_chip->gpio_chip.direction_input	=
					pm8xxx_gpio_rpc_direction_input;
	pm8xxx_gpio_chip->gpio_chip.direction_output	=
					pm8xxx_gpio_rpc_direction_output;
	pm8xxx_gpio_chip->gpio_chip.get		= pm8xxx_gpio_rpc_read;
	pm8xxx_gpio_chip->gpio_chip.set		= pm8xxx_gpio_rpc_write;
	pm8xxx_gpio_chip->gpio_chip.dbg_show	= pm8xxx_gpio_rpc_dbg_show;
	pm8xxx_gpio_chip->gpio_chip.ngpio	= pdata->ngpios;
	pm8xxx_gpio_chip->gpio_chip.can_sleep	= 1;
	pm8xxx_gpio_chip->gpio_chip.dev		= &pdev->dev;
	pm8xxx_gpio_chip->gpio_chip.base	= pdata->gpio_base;

	mutex_lock(&pm8xxx_gpio_chips_lock);
	list_add(&pm8xxx_gpio_chip->link, &pm8xxx_gpio_rpc_chips);
	mutex_unlock(&pm8xxx_gpio_chips_lock);
	platform_set_drvdata(pdev, pm8xxx_gpio_chip);

	ret = gpiochip_add(&pm8xxx_gpio_chip->gpio_chip);
	if (ret) {
		pr_err("gpiochip_add failed ret = %d\n", ret);
		goto reset_drvdata;
	}

	pr_info("OK: base=%d, ngpio=%d\n", pm8xxx_gpio_chip->gpio_chip.base,
		pm8xxx_gpio_chip->gpio_chip.ngpio);

	return 0;

reset_drvdata:
	mutex_lock(&pm8xxx_gpio_chips_lock);
	list_del(&pm8xxx_gpio_chip->link);
	mutex_unlock(&pm8xxx_gpio_chips_lock);
	platform_set_drvdata(pdev, NULL);
	kfree(pm8xxx_gpio_chip);
	mutex_destroy(&pm8xxx_gpio_chips_lock);
	return ret;
}

static int pm8xxx_gpio_rpc_remove(struct platform_device *pdev)
{
	struct pm8xxx_gpio_rpc_chip *pm8xxx_gpio_chip =
						platform_get_drvdata(pdev);

	mutex_lock(&pm8xxx_gpio_chips_lock);
	list_del(&pm8xxx_gpio_chip->link);
	mutex_unlock(&pm8xxx_gpio_chips_lock);
	platform_set_drvdata(pdev, NULL);
	if (gpiochip_remove(&pm8xxx_gpio_chip->gpio_chip))
		pr_err("failed to remove gpio chip\n");
	kfree(pm8xxx_gpio_chip);
	mutex_destroy(&pm8xxx_gpio_chips_lock);
	return 0;
}

static struct platform_driver pm8xxx_gpio_rpc_driver = {
	.probe		= pm8xxx_gpio_rpc_probe,
	.remove		= pm8xxx_gpio_rpc_remove,
	.driver		= {
		.name	= PM8XXX_GPIO_DEV_NAME,
		.owner	= THIS_MODULE,
	},
};

static int __init pm8xxx_gpio_rpc_init(void)
{
	return platform_driver_register(&pm8xxx_gpio_rpc_driver);
}
postcore_initcall(pm8xxx_gpio_rpc_init);

static void __exit pm8xxx_gpio_rpc_exit(void)
{
	platform_driver_unregister(&pm8xxx_gpio_rpc_driver);
}
module_exit(pm8xxx_gpio_rpc_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PMIC GPIO driver based on RPC");
MODULE_VERSION("1.0");
MODULE_ALIAS("platform:" PM8XXX_GPIO_DEV_NAME);
