/*
 * MEN 16Z127 GPIO driver
 *
 * Copyright (C) 2016 MEN Mikroelektronik GmbH (www.men.de)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; version 2 of the License.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/mcb.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>

#define MEN_Z127_CTRL	0x00
#define MEN_Z127_PSR	0x04
#define MEN_Z127_IRQR	0x08
#define MEN_Z127_GPIODR	0x0c
#define MEN_Z127_IER1	0x10
#define MEN_Z127_IER2	0x14
#define MEN_Z127_DBER	0x18
#define MEN_Z127_ODER	0x1C
#define GPIO_TO_DBCNT_REG(gpio)	((gpio * 4) + 0x80)

#define MEN_Z127_DB_MIN_US	50
/* 16 bit compare register. Each bit represents 50us */
#define MEN_Z127_DB_MAX_US	(0xffff * MEN_Z127_DB_MIN_US)
#define MEN_Z127_DB_IN_RANGE(db)	((db >= MEN_Z127_DB_MIN_US) && \
					 (db <= MEN_Z127_DB_MAX_US))

struct men_z127_gpio {
	struct gpio_chip gc;
	void __iomem *reg_base;
	struct mcb_device *mdev;
	struct resource *mem;
	spinlock_t lock;
};

static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
			     unsigned debounce)
{
	struct men_z127_gpio *priv = gpiochip_get_data(gc);
	struct device *dev = &priv->mdev->dev;
	unsigned int rnd;
	u32 db_en, db_cnt;

	if (!MEN_Z127_DB_IN_RANGE(debounce)) {
		dev_err(dev, "debounce value %u out of range", debounce);
		return -EINVAL;
	}

	if (debounce > 0) {
		/* round up or down depending on MSB-1 */
		rnd = fls(debounce) - 1;

		if (rnd && (debounce & BIT(rnd - 1)))
			debounce = round_up(debounce, MEN_Z127_DB_MIN_US);
		else
			debounce = round_down(debounce, MEN_Z127_DB_MIN_US);

		if (debounce > MEN_Z127_DB_MAX_US)
			debounce = MEN_Z127_DB_MAX_US;

		/* 50us per register unit */
		debounce /= 50;
	}

	spin_lock(&priv->lock);

	db_en = readl(priv->reg_base + MEN_Z127_DBER);

	if (debounce == 0) {
		db_en &= ~BIT(gpio);
		db_cnt = 0;
	} else {
		db_en |= BIT(gpio);
		db_cnt = debounce;
	}

	writel(db_en, priv->reg_base + MEN_Z127_DBER);
	writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio));

	spin_unlock(&priv->lock);

	return 0;
}

static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin)
{
	struct men_z127_gpio *priv = gpiochip_get_data(gc);
	u32 od_en;

	if (gpio_pin >= gc->ngpio)
		return -EINVAL;

	spin_lock(&priv->lock);
	od_en = readl(priv->reg_base + MEN_Z127_ODER);

	if (gpiochip_line_is_open_drain(gc, gpio_pin))
		od_en |= BIT(gpio_pin);
	else
		od_en &= ~BIT(gpio_pin);

	writel(od_en, priv->reg_base + MEN_Z127_ODER);
	spin_unlock(&priv->lock);

	return 0;
}

static int men_z127_probe(struct mcb_device *mdev,
			  const struct mcb_device_id *id)
{
	struct men_z127_gpio *men_z127_gpio;
	struct device *dev = &mdev->dev;
	int ret;

	men_z127_gpio = devm_kzalloc(dev, sizeof(struct men_z127_gpio),
				     GFP_KERNEL);
	if (!men_z127_gpio)
		return -ENOMEM;

	men_z127_gpio->mem = mcb_request_mem(mdev, dev_name(dev));
	if (IS_ERR(men_z127_gpio->mem)) {
		dev_err(dev, "failed to request device memory");
		return PTR_ERR(men_z127_gpio->mem);
	}

	men_z127_gpio->reg_base = ioremap(men_z127_gpio->mem->start,
					  resource_size(men_z127_gpio->mem));
	if (men_z127_gpio->reg_base == NULL) {
		ret = -ENXIO;
		goto err_release;
	}

	men_z127_gpio->mdev = mdev;
	mcb_set_drvdata(mdev, men_z127_gpio);

	ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4,
			 men_z127_gpio->reg_base + MEN_Z127_PSR,
			 men_z127_gpio->reg_base + MEN_Z127_CTRL,
			 NULL,
			 men_z127_gpio->reg_base + MEN_Z127_GPIODR,
			 NULL, 0);
	if (ret)
		goto err_unmap;

	men_z127_gpio->gc.set_debounce = men_z127_debounce;
	men_z127_gpio->gc.request = men_z127_request;

	ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
	if (ret) {
		dev_err(dev, "failed to register MEN 16Z127 GPIO controller");
		goto err_unmap;
	}

	dev_info(dev, "MEN 16Z127 GPIO driver registered");

	return 0;

err_unmap:
	iounmap(men_z127_gpio->reg_base);
err_release:
	mcb_release_mem(men_z127_gpio->mem);
	return ret;
}

static void men_z127_remove(struct mcb_device *mdev)
{
	struct men_z127_gpio *men_z127_gpio = mcb_get_drvdata(mdev);

	gpiochip_remove(&men_z127_gpio->gc);
	iounmap(men_z127_gpio->reg_base);
	mcb_release_mem(men_z127_gpio->mem);
}

static const struct mcb_device_id men_z127_ids[] = {
	{ .device = 0x7f },
	{ }
};
MODULE_DEVICE_TABLE(mcb, men_z127_ids);

static struct mcb_driver men_z127_driver = {
	.driver = {
		.name = "z127-gpio",
		.owner = THIS_MODULE,
	},
	.probe = men_z127_probe,
	.remove = men_z127_remove,
	.id_table = men_z127_ids,
};
module_mcb_driver(men_z127_driver);

MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
MODULE_DESCRIPTION("MEN 16z127 GPIO Controller");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("mcb:16z127");
