/*
 * Pinctrl driver for the Wondermedia SoC's
 *
 * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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.
 */

#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include "pinctrl-wmt.h"

static inline void wmt_setbits(struct wmt_pinctrl_data *data, u32 reg,
				 u32 mask)
{
	u32 val;

	val = readl_relaxed(data->base + reg);
	val |= mask;
	writel_relaxed(val, data->base + reg);
}

static inline void wmt_clearbits(struct wmt_pinctrl_data *data, u32 reg,
				   u32 mask)
{
	u32 val;

	val = readl_relaxed(data->base + reg);
	val &= ~mask;
	writel_relaxed(val, data->base + reg);
}

enum wmt_func_sel {
	WMT_FSEL_GPIO_IN = 0,
	WMT_FSEL_GPIO_OUT = 1,
	WMT_FSEL_ALT = 2,
	WMT_FSEL_COUNT = 3,
};

static const char * const wmt_functions[WMT_FSEL_COUNT] = {
	[WMT_FSEL_GPIO_IN] = "gpio_in",
	[WMT_FSEL_GPIO_OUT] = "gpio_out",
	[WMT_FSEL_ALT] = "alt",
};

static int wmt_pmx_get_functions_count(struct pinctrl_dev *pctldev)
{
	return WMT_FSEL_COUNT;
}

static const char *wmt_pmx_get_function_name(struct pinctrl_dev *pctldev,
					     unsigned selector)
{
	return wmt_functions[selector];
}

static int wmt_pmx_get_function_groups(struct pinctrl_dev *pctldev,
				       unsigned selector,
				       const char * const **groups,
				       unsigned * const num_groups)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	/* every pin does every function */
	*groups = data->groups;
	*num_groups = data->ngroups;

	return 0;
}

static int wmt_set_pinmux(struct wmt_pinctrl_data *data, unsigned func,
			  unsigned pin)
{
	u32 bank = WMT_BANK_FROM_PIN(pin);
	u32 bit = WMT_BIT_FROM_PIN(pin);
	u32 reg_en = data->banks[bank].reg_en;
	u32 reg_dir = data->banks[bank].reg_dir;

	if (reg_dir == NO_REG) {
		dev_err(data->dev, "pin:%d no direction register defined\n",
			pin);
		return -EINVAL;
	}

	/*
	 * If reg_en == NO_REG, we assume it is a dedicated GPIO and cannot be
	 * disabled (as on VT8500) and that no alternate function is available.
	 */
	switch (func) {
	case WMT_FSEL_GPIO_IN:
		if (reg_en != NO_REG)
			wmt_setbits(data, reg_en, BIT(bit));
		wmt_clearbits(data, reg_dir, BIT(bit));
		break;
	case WMT_FSEL_GPIO_OUT:
		if (reg_en != NO_REG)
			wmt_setbits(data, reg_en, BIT(bit));
		wmt_setbits(data, reg_dir, BIT(bit));
		break;
	case WMT_FSEL_ALT:
		if (reg_en == NO_REG) {
			dev_err(data->dev, "pin:%d no alt function available\n",
				pin);
			return -EINVAL;
		}
		wmt_clearbits(data, reg_en, BIT(bit));
	}

	return 0;
}

static int wmt_pmx_set_mux(struct pinctrl_dev *pctldev,
			   unsigned func_selector,
			   unsigned group_selector)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
	u32 pinnum = data->pins[group_selector].number;

	return wmt_set_pinmux(data, func_selector, pinnum);
}

static void wmt_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
				      struct pinctrl_gpio_range *range,
				      unsigned offset)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	/* disable by setting GPIO_IN */
	wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, offset);
}

static int wmt_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
				      struct pinctrl_gpio_range *range,
				      unsigned offset,
				      bool input)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	wmt_set_pinmux(data, (input ? WMT_FSEL_GPIO_IN : WMT_FSEL_GPIO_OUT),
		       offset);

	return 0;
}

static const struct pinmux_ops wmt_pinmux_ops = {
	.get_functions_count = wmt_pmx_get_functions_count,
	.get_function_name = wmt_pmx_get_function_name,
	.get_function_groups = wmt_pmx_get_function_groups,
	.set_mux = wmt_pmx_set_mux,
	.gpio_disable_free = wmt_pmx_gpio_disable_free,
	.gpio_set_direction = wmt_pmx_gpio_set_direction,
};

static int wmt_get_groups_count(struct pinctrl_dev *pctldev)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	return data->ngroups;
}

static const char *wmt_get_group_name(struct pinctrl_dev *pctldev,
				      unsigned selector)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	return data->groups[selector];
}

static int wmt_get_group_pins(struct pinctrl_dev *pctldev,
			      unsigned selector,
			      const unsigned **pins,
			      unsigned *num_pins)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	*pins = &data->pins[selector].number;
	*num_pins = 1;

	return 0;
}

static int wmt_pctl_find_group_by_pin(struct wmt_pinctrl_data *data, u32 pin)
{
	int i;

	for (i = 0; i < data->npins; i++) {
		if (data->pins[i].number == pin)
			return i;
	}

	return -EINVAL;
}

static int wmt_pctl_dt_node_to_map_func(struct wmt_pinctrl_data *data,
					struct device_node *np,
					u32 pin, u32 fnum,
					struct pinctrl_map **maps)
{
	int group;
	struct pinctrl_map *map = *maps;

	if (fnum >= ARRAY_SIZE(wmt_functions)) {
		dev_err(data->dev, "invalid wm,function %d\n", fnum);
		return -EINVAL;
	}

	group = wmt_pctl_find_group_by_pin(data, pin);
	if (group < 0) {
		dev_err(data->dev, "unable to match pin %d to group\n", pin);
		return group;
	}

	map->type = PIN_MAP_TYPE_MUX_GROUP;
	map->data.mux.group = data->groups[group];
	map->data.mux.function = wmt_functions[fnum];
	(*maps)++;

	return 0;
}

static int wmt_pctl_dt_node_to_map_pull(struct wmt_pinctrl_data *data,
					struct device_node *np,
					u32 pin, u32 pull,
					struct pinctrl_map **maps)
{
	int group;
	unsigned long *configs;
	struct pinctrl_map *map = *maps;

	if (pull > 2) {
		dev_err(data->dev, "invalid wm,pull %d\n", pull);
		return -EINVAL;
	}

	group = wmt_pctl_find_group_by_pin(data, pin);
	if (group < 0) {
		dev_err(data->dev, "unable to match pin %d to group\n", pin);
		return group;
	}

	configs = kzalloc(sizeof(*configs), GFP_KERNEL);
	if (!configs)
		return -ENOMEM;

	switch (pull) {
	case 0:
		configs[0] = PIN_CONFIG_BIAS_DISABLE;
		break;
	case 1:
		configs[0] = PIN_CONFIG_BIAS_PULL_DOWN;
		break;
	case 2:
		configs[0] = PIN_CONFIG_BIAS_PULL_UP;
		break;
	default:
		configs[0] = PIN_CONFIG_BIAS_DISABLE;
		dev_err(data->dev, "invalid pull state %d - disabling\n", pull);
	}

	map->type = PIN_MAP_TYPE_CONFIGS_PIN;
	map->data.configs.group_or_pin = data->groups[group];
	map->data.configs.configs = configs;
	map->data.configs.num_configs = 1;
	(*maps)++;

	return 0;
}

static void wmt_pctl_dt_free_map(struct pinctrl_dev *pctldev,
				 struct pinctrl_map *maps,
				 unsigned num_maps)
{
	int i;

	for (i = 0; i < num_maps; i++)
		if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
			kfree(maps[i].data.configs.configs);

	kfree(maps);
}

static int wmt_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
				   struct device_node *np,
				   struct pinctrl_map **map,
				   unsigned *num_maps)
{
	struct pinctrl_map *maps, *cur_map;
	struct property *pins, *funcs, *pulls;
	u32 pin, func, pull;
	int num_pins, num_funcs, num_pulls, maps_per_pin;
	int i, err;
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);

	pins = of_find_property(np, "wm,pins", NULL);
	if (!pins) {
		dev_err(data->dev, "missing wmt,pins property\n");
		return -EINVAL;
	}

	funcs = of_find_property(np, "wm,function", NULL);
	pulls = of_find_property(np, "wm,pull", NULL);

	if (!funcs && !pulls) {
		dev_err(data->dev, "neither wm,function nor wm,pull specified\n");
		return -EINVAL;
	}

	/*
	 * The following lines calculate how many values are defined for each
	 * of the properties.
	 */
	num_pins = pins->length / sizeof(u32);
	num_funcs = funcs ? (funcs->length / sizeof(u32)) : 0;
	num_pulls = pulls ? (pulls->length / sizeof(u32)) : 0;

	if (num_funcs > 1 && num_funcs != num_pins) {
		dev_err(data->dev, "wm,function must have 1 or %d entries\n",
			num_pins);
		return -EINVAL;
	}

	if (num_pulls > 1 && num_pulls != num_pins) {
		dev_err(data->dev, "wm,pull must have 1 or %d entries\n",
			num_pins);
		return -EINVAL;
	}

	maps_per_pin = 0;
	if (num_funcs)
		maps_per_pin++;
	if (num_pulls)
		maps_per_pin++;

	cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
				 GFP_KERNEL);
	if (!maps)
		return -ENOMEM;

	for (i = 0; i < num_pins; i++) {
		err = of_property_read_u32_index(np, "wm,pins", i, &pin);
		if (err)
			goto fail;

		if (pin >= (data->nbanks * 32)) {
			dev_err(data->dev, "invalid wm,pins value\n");
			err = -EINVAL;
			goto fail;
		}

		if (num_funcs) {
			err = of_property_read_u32_index(np, "wm,function",
						(num_funcs > 1 ? i : 0), &func);
			if (err)
				goto fail;

			err = wmt_pctl_dt_node_to_map_func(data, np, pin, func,
							   &cur_map);
			if (err)
				goto fail;
		}

		if (num_pulls) {
			err = of_property_read_u32_index(np, "wm,pull",
						(num_pulls > 1 ? i : 0), &pull);
			if (err)
				goto fail;

			err = wmt_pctl_dt_node_to_map_pull(data, np, pin, pull,
							   &cur_map);
			if (err)
				goto fail;
		}
	}
	*map = maps;
	*num_maps = num_pins * maps_per_pin;
	return 0;

/*
 * The fail path removes any maps that have been allocated. The fail path is
 * only called from code after maps has been kzalloc'd. It is also safe to
 * pass 'num_pins * maps_per_pin' as the map count even though we probably
 * failed before all the mappings were read as all maps are allocated at once,
 * and configs are only allocated for .type = PIN_MAP_TYPE_CONFIGS_PIN - there
 * is no failpath where a config can be allocated without .type being set.
 */
fail:
	wmt_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin);
	return err;
}

static const struct pinctrl_ops wmt_pctl_ops = {
	.get_groups_count = wmt_get_groups_count,
	.get_group_name	= wmt_get_group_name,
	.get_group_pins	= wmt_get_group_pins,
	.dt_node_to_map = wmt_pctl_dt_node_to_map,
	.dt_free_map = wmt_pctl_dt_free_map,
};

static int wmt_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
			   unsigned long *config)
{
	return -ENOTSUPP;
}

static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
			   unsigned long *configs, unsigned num_configs)
{
	struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
	enum pin_config_param param;
	u32 arg;
	u32 bank = WMT_BANK_FROM_PIN(pin);
	u32 bit = WMT_BIT_FROM_PIN(pin);
	u32 reg_pull_en = data->banks[bank].reg_pull_en;
	u32 reg_pull_cfg = data->banks[bank].reg_pull_cfg;
	int i;

	if ((reg_pull_en == NO_REG) || (reg_pull_cfg == NO_REG)) {
		dev_err(data->dev, "bias functions not supported on pin %d\n",
			pin);
		return -EINVAL;
	}

	for (i = 0; i < num_configs; i++) {
		param = pinconf_to_config_param(configs[i]);
		arg = pinconf_to_config_argument(configs[i]);

		if ((param == PIN_CONFIG_BIAS_PULL_DOWN) ||
		    (param == PIN_CONFIG_BIAS_PULL_UP)) {
			if (arg == 0)
				param = PIN_CONFIG_BIAS_DISABLE;
		}

		switch (param) {
		case PIN_CONFIG_BIAS_DISABLE:
			wmt_clearbits(data, reg_pull_en, BIT(bit));
			break;
		case PIN_CONFIG_BIAS_PULL_DOWN:
			wmt_clearbits(data, reg_pull_cfg, BIT(bit));
			wmt_setbits(data, reg_pull_en, BIT(bit));
			break;
		case PIN_CONFIG_BIAS_PULL_UP:
			wmt_setbits(data, reg_pull_cfg, BIT(bit));
			wmt_setbits(data, reg_pull_en, BIT(bit));
			break;
		default:
			dev_err(data->dev, "unknown pinconf param\n");
			return -EINVAL;
		}
	} /* for each config */

	return 0;
}

static const struct pinconf_ops wmt_pinconf_ops = {
	.pin_config_get = wmt_pinconf_get,
	.pin_config_set = wmt_pinconf_set,
};

static struct pinctrl_desc wmt_desc = {
	.owner = THIS_MODULE,
	.name = "pinctrl-wmt",
	.pctlops = &wmt_pctl_ops,
	.pmxops = &wmt_pinmux_ops,
	.confops = &wmt_pinconf_ops,
};

static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
	struct wmt_pinctrl_data *data = gpiochip_get_data(chip);
	u32 bank = WMT_BANK_FROM_PIN(offset);
	u32 bit = WMT_BIT_FROM_PIN(offset);
	u32 reg_dir = data->banks[bank].reg_dir;
	u32 val;

	val = readl_relaxed(data->base + reg_dir);
	if (val & BIT(bit))
		return GPIOF_DIR_OUT;
	else
		return GPIOF_DIR_IN;
}

static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset)
{
	struct wmt_pinctrl_data *data = gpiochip_get_data(chip);
	u32 bank = WMT_BANK_FROM_PIN(offset);
	u32 bit = WMT_BIT_FROM_PIN(offset);
	u32 reg_data_in = data->banks[bank].reg_data_in;

	if (reg_data_in == NO_REG) {
		dev_err(data->dev, "no data in register defined\n");
		return -EINVAL;
	}

	return !!(readl_relaxed(data->base + reg_data_in) & BIT(bit));
}

static void wmt_gpio_set_value(struct gpio_chip *chip, unsigned offset,
			       int val)
{
	struct wmt_pinctrl_data *data = gpiochip_get_data(chip);
	u32 bank = WMT_BANK_FROM_PIN(offset);
	u32 bit = WMT_BIT_FROM_PIN(offset);
	u32 reg_data_out = data->banks[bank].reg_data_out;

	if (reg_data_out == NO_REG) {
		dev_err(data->dev, "no data out register defined\n");
		return;
	}

	if (val)
		wmt_setbits(data, reg_data_out, BIT(bit));
	else
		wmt_clearbits(data, reg_data_out, BIT(bit));
}

static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
	return pinctrl_gpio_direction_input(chip->base + offset);
}

static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
				     int value)
{
	wmt_gpio_set_value(chip, offset, value);
	return pinctrl_gpio_direction_output(chip->base + offset);
}

static const struct gpio_chip wmt_gpio_chip = {
	.label = "gpio-wmt",
	.owner = THIS_MODULE,
	.request = gpiochip_generic_request,
	.free = gpiochip_generic_free,
	.get_direction = wmt_gpio_get_direction,
	.direction_input = wmt_gpio_direction_input,
	.direction_output = wmt_gpio_direction_output,
	.get = wmt_gpio_get_value,
	.set = wmt_gpio_set_value,
	.can_sleep = false,
};

int wmt_pinctrl_probe(struct platform_device *pdev,
		      struct wmt_pinctrl_data *data)
{
	int err;
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	data->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(data->base))
		return PTR_ERR(data->base);

	wmt_desc.pins = data->pins;
	wmt_desc.npins = data->npins;

	data->gpio_chip = wmt_gpio_chip;
	data->gpio_chip.parent = &pdev->dev;
	data->gpio_chip.of_node = pdev->dev.of_node;
	data->gpio_chip.ngpio = data->nbanks * 32;

	platform_set_drvdata(pdev, data);

	data->dev = &pdev->dev;

	data->pctl_dev = devm_pinctrl_register(&pdev->dev, &wmt_desc, data);
	if (IS_ERR(data->pctl_dev)) {
		dev_err(&pdev->dev, "Failed to register pinctrl\n");
		return PTR_ERR(data->pctl_dev);
	}

	err = gpiochip_add_data(&data->gpio_chip, data);
	if (err) {
		dev_err(&pdev->dev, "could not add GPIO chip\n");
		return err;
	}

	err = gpiochip_add_pin_range(&data->gpio_chip, dev_name(data->dev),
				     0, 0, data->nbanks * 32);
	if (err)
		goto fail_range;

	dev_info(&pdev->dev, "Pin controller initialized\n");

	return 0;

fail_range:
	gpiochip_remove(&data->gpio_chip);
	return err;
}
