// SPDX-License-Identifier: GPL-2.0+
/*
 * Qualcomm GPIO driver
 *
 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
 */

#include <dm.h>
#include <errno.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <mach/gpio.h>

DECLARE_GLOBAL_DATA_PTR;

/* OE */
#define GPIO_OE_DISABLE  (0x0 << 9)
#define GPIO_OE_ENABLE   (0x1 << 9)
#define GPIO_OE_MASK     (0x1 << 9)

/* GPIO_IN_OUT register shifts. */
#define GPIO_IN          0
#define GPIO_OUT         1

struct msm_gpio_bank {
	phys_addr_t base;
	const struct msm_pin_data *pin_data;
};

#define GPIO_CONFIG_REG(dev, x) \
	(qcom_pin_offset(((struct msm_gpio_bank *)dev_get_priv(dev))->pin_data->pin_offsets, x))

#define GPIO_IN_OUT_REG(dev, x) \
	(GPIO_CONFIG_REG(dev, x) + 0x4)

static void msm_gpio_direction_input_special(struct msm_gpio_bank *priv,
					     unsigned int gpio)
{
	unsigned int offset = gpio - priv->pin_data->special_pins_start;
	const struct msm_special_pin_data *data;

	if (!priv->pin_data->special_pins_data)
		return;

	data = &priv->pin_data->special_pins_data[offset];

	if (!data->ctl_reg || data->oe_bit >= 31)
		return;

	/* switch direction */
	clrsetbits_le32(priv->base + data->ctl_reg,
			BIT(data->oe_bit), 0);
}

static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
{
	struct msm_gpio_bank *priv = dev_get_priv(dev);

	if (qcom_is_special_pin(priv->pin_data, gpio))
		msm_gpio_direction_input_special(priv, gpio);

	/* Disable OE bit */
	clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
			GPIO_OE_MASK, GPIO_OE_DISABLE);

	return;
}

static int msm_gpio_set_value_special(struct msm_gpio_bank *priv,
				      unsigned int gpio, int value)
{
	unsigned int offset = gpio - priv->pin_data->special_pins_start;
	const struct msm_special_pin_data *data;

	if (!priv->pin_data->special_pins_data)
		return 0;

	data = &priv->pin_data->special_pins_data[offset];

	if (!data->io_reg || data->out_bit >= 31)
		return 0;

	value = !!value;
	/* set value */
	writel(value << data->out_bit, priv->base + data->io_reg);

	return 0;
}

static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
{
	struct msm_gpio_bank *priv = dev_get_priv(dev);

	if (qcom_is_special_pin(priv->pin_data, gpio))
		return msm_gpio_set_value_special(priv, gpio, value);

	value = !!value;
	/* set value */
	writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));

	return 0;
}

static int msm_gpio_direction_output_special(struct msm_gpio_bank *priv,
					     unsigned int gpio,
					     int value)
{
	unsigned int offset = gpio - priv->pin_data->special_pins_start;
	const struct msm_special_pin_data *data;

	if (!priv->pin_data->special_pins_data)
		return 0;

	data = &priv->pin_data->special_pins_data[offset];

	if (!data->io_reg || data->out_bit >= 31)
		return 0;

	value = !!value;
	/* set value */
	writel(value << data->out_bit, priv->base + data->io_reg);

	if (!data->ctl_reg || data->oe_bit >= 31)
		return 0;

	/* switch direction */
	clrsetbits_le32(priv->base + data->ctl_reg,
			BIT(data->oe_bit), BIT(data->oe_bit));

	return 0;
}

static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
				     int value)
{
	struct msm_gpio_bank *priv = dev_get_priv(dev);

	if (qcom_is_special_pin(priv->pin_data, gpio))
		return msm_gpio_direction_output_special(priv, gpio, value);

	value = !!value;
	/* set value */
	writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
	/* switch direction */
	clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
			GPIO_OE_MASK, GPIO_OE_ENABLE);

	return 0;
}

static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flags)
{
	if (flags & GPIOD_IS_OUT_ACTIVE) {
		return msm_gpio_direction_output(dev, gpio, 1);
	} else if (flags & GPIOD_IS_OUT) {
		return msm_gpio_direction_output(dev, gpio, 0);
	} else if (flags & GPIOD_IS_IN) {
		msm_gpio_direction_input(dev, gpio);
		if (flags & GPIOD_PULL_UP)
			return msm_gpio_set_value(dev, gpio, 1);
		else if (flags & GPIOD_PULL_DOWN)
			return msm_gpio_set_value(dev, gpio, 0);
	}

	return 0;
}

static int msm_gpio_get_value_special(struct msm_gpio_bank *priv, unsigned int gpio)
{
	unsigned int offset = gpio - priv->pin_data->special_pins_start;
	const struct msm_special_pin_data *data;

	if (!priv->pin_data->special_pins_data)
		return 0;

	data = &priv->pin_data->special_pins_data[offset];

	if (!data->io_reg || data->in_bit >= 31)
		return 0;

	return !!(readl(priv->base + data->io_reg) >> data->in_bit);
}

static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
{
	struct msm_gpio_bank *priv = dev_get_priv(dev);

	if (qcom_is_special_pin(priv->pin_data, gpio))
		return msm_gpio_get_value_special(priv, gpio);

	return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
}

static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio)
{
	struct msm_gpio_bank *priv = dev_get_priv(dev);

	/* Always NOP for special pins, assume they're in the correct state */
	if (qcom_is_special_pin(priv->pin_data, gpio))
		return 0;

	if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE)
		return GPIOF_OUTPUT;

	return GPIOF_INPUT;
}

static const struct dm_gpio_ops gpio_msm_ops = {
	.set_flags		= msm_gpio_set_flags,
	.get_value		= msm_gpio_get_value,
	.get_function		= msm_gpio_get_function,
};

static int msm_gpio_probe(struct udevice *dev)
{
	struct msm_gpio_bank *priv = dev_get_priv(dev);

	priv->base = dev_read_addr(dev);
	priv->pin_data = (struct msm_pin_data *)dev_get_driver_data(dev);

	return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
}

static int msm_gpio_of_to_plat(struct udevice *dev)
{
	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
	const struct msm_pin_data *pin_data = (struct msm_pin_data *)dev_get_driver_data(dev);

	/* Get the pin count from the pinctrl driver */
	uc_priv->gpio_count = pin_data->pin_count;
	uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
					 "gpio-bank-name", NULL);
	if (uc_priv->bank_name == NULL)
		uc_priv->bank_name = "soc";

	return 0;
}

U_BOOT_DRIVER(gpio_msm) = {
	.name	= "gpio_msm",
	.id	= UCLASS_GPIO,
	.of_to_plat = msm_gpio_of_to_plat,
	.probe	= msm_gpio_probe,
	.ops	= &gpio_msm_ops,
	.flags	= DM_UC_FLAG_SEQ_ALIAS,
	.priv_auto	= sizeof(struct msm_gpio_bank),
};
