// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Janz MODULbus VMOD-TTL GPIO Driver
 *
 * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/bitops.h>

#include <linux/mfd/janz.h>

#define DRV_NAME "janz-ttl"

#define PORTA_DIRECTION		0x23
#define PORTB_DIRECTION		0x2B
#define PORTC_DIRECTION		0x06
#define PORTA_IOCTL		0x24
#define PORTB_IOCTL		0x2C
#define PORTC_IOCTL		0x07

#define MASTER_INT_CTL		0x00
#define MASTER_CONF_CTL		0x01

#define CONF_PAE		BIT(2)
#define CONF_PBE		BIT(7)
#define CONF_PCE		BIT(4)

struct ttl_control_regs {
	__be16 portc;
	__be16 portb;
	__be16 porta;
	__be16 control;
};

struct ttl_module {
	struct gpio_chip gpio;

	/* base address of registers */
	struct ttl_control_regs __iomem *regs;

	u8 portc_shadow;
	u8 portb_shadow;
	u8 porta_shadow;

	spinlock_t lock;
};

static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
{
	struct ttl_module *mod = dev_get_drvdata(gpio->parent);
	u8 *shadow;
	int ret;

	if (offset < 8) {
		shadow = &mod->porta_shadow;
	} else if (offset < 16) {
		shadow = &mod->portb_shadow;
		offset -= 8;
	} else {
		shadow = &mod->portc_shadow;
		offset -= 16;
	}

	spin_lock(&mod->lock);
	ret = *shadow & BIT(offset);
	spin_unlock(&mod->lock);
	return !!ret;
}

static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
{
	struct ttl_module *mod = dev_get_drvdata(gpio->parent);
	void __iomem *port;
	u8 *shadow;

	if (offset < 8) {
		port = &mod->regs->porta;
		shadow = &mod->porta_shadow;
	} else if (offset < 16) {
		port = &mod->regs->portb;
		shadow = &mod->portb_shadow;
		offset -= 8;
	} else {
		port = &mod->regs->portc;
		shadow = &mod->portc_shadow;
		offset -= 16;
	}

	spin_lock(&mod->lock);
	if (value)
		*shadow |= BIT(offset);
	else
		*shadow &= ~BIT(offset);

	iowrite16be(*shadow, port);
	spin_unlock(&mod->lock);
}

static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
{
	iowrite16be(reg, &mod->regs->control);
	iowrite16be(val, &mod->regs->control);
}

static void ttl_setup_device(struct ttl_module *mod)
{
	/* reset the device to a known state */
	iowrite16be(0x0000, &mod->regs->control);
	iowrite16be(0x0001, &mod->regs->control);
	iowrite16be(0x0000, &mod->regs->control);

	/* put all ports in open-drain mode */
	ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
	ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
	ttl_write_reg(mod, PORTC_IOCTL, 0x000f);

	/* set all ports as outputs */
	ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
	ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
	ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);

	/* set all ports to drive zeroes */
	iowrite16be(0x0000, &mod->regs->porta);
	iowrite16be(0x0000, &mod->regs->portb);
	iowrite16be(0x0000, &mod->regs->portc);

	/* enable all ports */
	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
}

static int ttl_probe(struct platform_device *pdev)
{
	struct janz_platform_data *pdata;
	struct device *dev = &pdev->dev;
	struct ttl_module *mod;
	struct gpio_chip *gpio;
	int ret;

	pdata = dev_get_platdata(&pdev->dev);
	if (!pdata) {
		dev_err(dev, "no platform data\n");
		return -ENXIO;
	}

	mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL);
	if (!mod)
		return -ENOMEM;

	platform_set_drvdata(pdev, mod);
	spin_lock_init(&mod->lock);

	/* get access to the MODULbus registers for this module */
	mod->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(mod->regs))
		return PTR_ERR(mod->regs);

	ttl_setup_device(mod);

	/* Initialize the GPIO data structures */
	gpio = &mod->gpio;
	gpio->parent = &pdev->dev;
	gpio->label = pdev->name;
	gpio->get = ttl_get_value;
	gpio->set = ttl_set_value;
	gpio->owner = THIS_MODULE;

	/* request dynamic allocation */
	gpio->base = -1;
	gpio->ngpio = 20;

	ret = devm_gpiochip_add_data(dev, gpio, NULL);
	if (ret) {
		dev_err(dev, "unable to add GPIO chip\n");
		return ret;
	}

	return 0;
}

static struct platform_driver ttl_driver = {
	.driver		= {
		.name	= DRV_NAME,
	},
	.probe		= ttl_probe,
};

module_platform_driver(ttl_driver);

MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:janz-ttl");
