/*
 * GPIO support for Cirrus Logic Madera codecs
 *
 * Copyright 2015-2017 Cirrus Logic
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>

struct madera_gpio {
	struct madera *madera;
	struct gpio_chip gpio_chip;
};

static int madera_gpio_get_direction(struct gpio_chip *chip,
				     unsigned int offset)
{
	struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
	struct madera *madera = madera_gpio->madera;
	unsigned int val;
	int ret;

	ret = regmap_read(madera->regmap,
			  MADERA_GPIO1_CTRL_2 + (2 * offset), &val);
	if (ret < 0)
		return ret;

	return (val & MADERA_GP1_DIR_MASK) >> MADERA_GP1_DIR_SHIFT;
}

static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
{
	struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
	struct madera *madera = madera_gpio->madera;

	return regmap_update_bits(madera->regmap,
				  MADERA_GPIO1_CTRL_2 + (2 * offset),
				  MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
}

static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
	struct madera *madera = madera_gpio->madera;
	unsigned int val;
	int ret;

	ret = regmap_read(madera->regmap,
			  MADERA_GPIO1_CTRL_1 + (2 * offset), &val);
	if (ret < 0)
		return ret;

	return !!(val & MADERA_GP1_LVL_MASK);
}

static int madera_gpio_direction_out(struct gpio_chip *chip,
				     unsigned int offset, int value)
{
	struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
	struct madera *madera = madera_gpio->madera;
	unsigned int regval;
	int ret;

	if (value)
		regval = MADERA_GP1_LVL;
	else
		regval = 0;

	ret = regmap_update_bits(madera->regmap,
				 MADERA_GPIO1_CTRL_2 + (2 * offset),
				 MADERA_GP1_DIR_MASK, 0);
	if (ret < 0)
		return ret;

	return regmap_update_bits(madera->regmap,
				  MADERA_GPIO1_CTRL_1 + (2 * offset),
				  MADERA_GP1_LVL_MASK, regval);
}

static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
			    int value)
{
	struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
	struct madera *madera = madera_gpio->madera;
	unsigned int regval;
	int ret;

	if (value)
		regval = MADERA_GP1_LVL;
	else
		regval = 0;

	ret = regmap_update_bits(madera->regmap,
				 MADERA_GPIO1_CTRL_1 + (2 * offset),
				 MADERA_GP1_LVL_MASK, regval);
	if (ret)
		dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
			 MADERA_GPIO1_CTRL_1 + (2 * offset), ret);
}

static const struct gpio_chip template_chip = {
	.label			= "madera",
	.owner			= THIS_MODULE,
	.get_direction		= madera_gpio_get_direction,
	.direction_input	= madera_gpio_direction_in,
	.get			= madera_gpio_get,
	.direction_output	= madera_gpio_direction_out,
	.set			= madera_gpio_set,
	.can_sleep		= true,
};

static int madera_gpio_probe(struct platform_device *pdev)
{
	struct madera *madera = dev_get_drvdata(pdev->dev.parent);
	struct madera_pdata *pdata = dev_get_platdata(madera->dev);
	struct madera_gpio *madera_gpio;
	int ret;

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

	madera_gpio->madera = madera;
	madera_gpio->gpio_chip = template_chip;
	madera_gpio->gpio_chip.parent = &pdev->dev;

	if (IS_ENABLED(CONFIG_OF_GPIO))
		madera_gpio->gpio_chip.of_node = madera->dev->of_node;

	switch (madera->type) {
	case CS47L15:
		madera_gpio->gpio_chip.ngpio = CS47L15_NUM_GPIOS;
		break;
	case CS47L35:
		madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
		break;
	case CS47L85:
	case WM1840:
		madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
		break;
	case CS47L90:
	case CS47L91:
		madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
		break;
	case CS47L92:
	case CS47L93:
		madera_gpio->gpio_chip.ngpio = CS47L92_NUM_GPIOS;
		break;
	default:
		dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
		return -EINVAL;
	}

	if (pdata && pdata->gpio_base)
		madera_gpio->gpio_chip.base = pdata->gpio_base;
	else
		madera_gpio->gpio_chip.base = -1;

	ret = devm_gpiochip_add_data(&pdev->dev, &madera_gpio->gpio_chip,
				     madera_gpio);
	if (ret < 0) {
		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
		return ret;
	}

	return 0;
}

static struct platform_driver madera_gpio_driver = {
	.driver = {
		.name	= "madera-gpio",
		.owner	= THIS_MODULE,
		.suppress_bind_attrs = true,
	},
	.probe		= madera_gpio_probe,
};

module_platform_driver(madera_gpio_driver);

MODULE_DESCRIPTION("GPIO interface for Madera codecs");
MODULE_AUTHOR("Nariman Poushin <nariman@opensource.wolfsonmicro.com>");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:madera-gpio");
