// SPDX-License-Identifier: GPL-2.0
/*
 * SAMA5D2 PIOBU GPIO controller
 *
 * Copyright (C) 2018 Microchip Technology Inc. and its subsidiaries
 *
 * Author: Andrei Stefanescu <andrei.stefanescu@microchip.com>
 *
 */
#include <linux/bits.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#define PIOBU_NUM 8
#define PIOBU_REG_SIZE 4

/*
 * backup mode protection register for tamper detection
 * normal mode protection register for tamper detection
 * wakeup signal generation
 */
#define PIOBU_BMPR 0x7C
#define PIOBU_NMPR 0x80
#define PIOBU_WKPR 0x90

#define PIOBU_BASE 0x18 /* PIOBU offset from SECUMOD base register address. */

#define PIOBU_DET_OFFSET 16

/* In the datasheet this bit is called OUTPUT */
#define PIOBU_DIRECTION BIT(8)
#define PIOBU_OUT BIT(8)
#define PIOBU_IN 0

#define PIOBU_SOD BIT(9)
#define PIOBU_PDS BIT(10)

#define PIOBU_HIGH BIT(9)
#define PIOBU_LOW 0

struct sama5d2_piobu {
	struct gpio_chip chip;
	struct regmap *regmap;
};

/**
 * sama5d2_piobu_setup_pin() - prepares a pin for set_direction call
 *
 * Do not consider pin for tamper detection (normal and backup modes)
 * Do not consider pin as tamper wakeup interrupt source
 */
static int sama5d2_piobu_setup_pin(struct gpio_chip *chip, unsigned int pin)
{
	int ret;
	struct sama5d2_piobu *piobu = container_of(chip, struct sama5d2_piobu,
						   chip);
	unsigned int mask = BIT(PIOBU_DET_OFFSET + pin);

	ret = regmap_update_bits(piobu->regmap, PIOBU_BMPR, mask, 0);
	if (ret)
		return ret;

	ret = regmap_update_bits(piobu->regmap, PIOBU_NMPR, mask, 0);
	if (ret)
		return ret;

	return regmap_update_bits(piobu->regmap, PIOBU_WKPR, mask, 0);
}

/**
 * sama5d2_piobu_write_value() - writes value & mask at the pin's PIOBU register
 */
static int sama5d2_piobu_write_value(struct gpio_chip *chip, unsigned int pin,
				     unsigned int mask, unsigned int value)
{
	int reg;
	struct sama5d2_piobu *piobu = container_of(chip, struct sama5d2_piobu,
						   chip);

	reg = PIOBU_BASE + pin * PIOBU_REG_SIZE;

	return regmap_update_bits(piobu->regmap, reg, mask, value);
}

/**
 * sama5d2_piobu_read_value() - read the value with masking from the pin's PIOBU
 *			      register
 */
static int sama5d2_piobu_read_value(struct gpio_chip *chip, unsigned int pin,
				    unsigned int mask)
{
	struct sama5d2_piobu *piobu = container_of(chip, struct sama5d2_piobu,
						   chip);
	unsigned int val, reg;
	int ret;

	reg = PIOBU_BASE + pin * PIOBU_REG_SIZE;
	ret = regmap_read(piobu->regmap, reg, &val);
	if (ret < 0)
		return ret;

	return val & mask;
}

/**
 * sama5d2_piobu_set_direction() - mark pin as input or output
 */
static int sama5d2_piobu_set_direction(struct gpio_chip *chip,
				       unsigned int direction,
				       unsigned int pin)
{
	return sama5d2_piobu_write_value(chip, pin, PIOBU_DIRECTION, direction);
}

/**
 * sama5d2_piobu_get_direction() - gpiochip get_direction
 */
static int sama5d2_piobu_get_direction(struct gpio_chip *chip,
				       unsigned int pin)
{
	int ret = sama5d2_piobu_read_value(chip, pin, PIOBU_DIRECTION);

	if (ret < 0)
		return ret;

	return (ret == PIOBU_IN) ? 1 : 0;
}

/**
 * sama5d2_piobu_direction_input() - gpiochip direction_input
 */
static int sama5d2_piobu_direction_input(struct gpio_chip *chip,
					 unsigned int pin)
{
	return sama5d2_piobu_set_direction(chip, PIOBU_IN, pin);
}

/**
 * sama5d2_piobu_direction_output() - gpiochip direction_output
 */
static int sama5d2_piobu_direction_output(struct gpio_chip *chip,
					  unsigned int pin, int value)
{
	return sama5d2_piobu_set_direction(chip, PIOBU_OUT, pin);
}

/**
 * sama5d2_piobu_get() - gpiochip get
 */
static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin)
{
	/* if pin is input, read value from PDS else read from SOD */
	int ret = sama5d2_piobu_get_direction(chip, pin);

	if (ret == 1)
		ret = sama5d2_piobu_read_value(chip, pin, PIOBU_PDS);
	else if (!ret)
		ret = sama5d2_piobu_read_value(chip, pin, PIOBU_SOD);

	if (ret < 0)
		return ret;

	return !!ret;
}

/**
 * sama5d2_piobu_set() - gpiochip set
 */
static void sama5d2_piobu_set(struct gpio_chip *chip, unsigned int pin,
			      int value)
{
	if (!value)
		value = PIOBU_LOW;
	else
		value = PIOBU_HIGH;

	sama5d2_piobu_write_value(chip, pin, PIOBU_SOD, value);
}

static int sama5d2_piobu_probe(struct platform_device *pdev)
{
	struct sama5d2_piobu *piobu;
	int ret, i;

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

	platform_set_drvdata(pdev, piobu);
	piobu->chip.label = pdev->name;
	piobu->chip.parent = &pdev->dev;
	piobu->chip.of_node = pdev->dev.of_node;
	piobu->chip.owner = THIS_MODULE,
	piobu->chip.get_direction = sama5d2_piobu_get_direction,
	piobu->chip.direction_input = sama5d2_piobu_direction_input,
	piobu->chip.direction_output = sama5d2_piobu_direction_output,
	piobu->chip.get = sama5d2_piobu_get,
	piobu->chip.set = sama5d2_piobu_set,
	piobu->chip.base = -1,
	piobu->chip.ngpio = PIOBU_NUM,
	piobu->chip.can_sleep = 0,

	piobu->regmap = syscon_node_to_regmap(pdev->dev.of_node);
	if (IS_ERR(piobu->regmap)) {
		dev_err(&pdev->dev, "Failed to get syscon regmap %ld\n",
			PTR_ERR(piobu->regmap));
		return PTR_ERR(piobu->regmap);
	}

	ret = devm_gpiochip_add_data(&pdev->dev, &piobu->chip, piobu);
	if (ret) {
		dev_err(&pdev->dev, "Failed to add gpiochip %d\n", ret);
		return ret;
	}

	for (i = 0; i < PIOBU_NUM; ++i) {
		ret = sama5d2_piobu_setup_pin(&piobu->chip, i);
		if (ret) {
			dev_err(&pdev->dev, "Failed to setup pin: %d %d\n",
				i, ret);
			return ret;
		}
	}

	return 0;
}

static const struct of_device_id sama5d2_piobu_ids[] = {
	{ .compatible = "atmel,sama5d2-secumod" },
	{},
};
MODULE_DEVICE_TABLE(of, sama5d2_piobu_ids);

static struct platform_driver sama5d2_piobu_driver = {
	.driver = {
		.name		= "sama5d2-piobu",
		.of_match_table	= of_match_ptr(sama5d2_piobu_ids)
	},
	.probe = sama5d2_piobu_probe,
};

module_platform_driver(sama5d2_piobu_driver);

MODULE_VERSION("1.0");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("SAMA5D2 PIOBU controller driver");
MODULE_AUTHOR("Andrei Stefanescu <andrei.stefanescu@microchip.com>");
