/*
 * GE PIO2 GPIO Driver
 *
 * Author: Martyn Welch <martyn.welch@ge.com>
 * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
 *
 * 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;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/ctype.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/vme.h>

#include "vme_pio2.h"

static const char driver_name[] = "pio2_gpio";

static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	u8 reg;
	int retval;
	struct pio2_card *card = gpiochip_get_data(chip);

	if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
	    (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
		dev_err(&card->vdev->dev, "Channel not available as input\n");
		return 0;
	}

	retval = vme_master_read(card->window, &reg, 1,
				 PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
	if (retval < 0) {
		dev_err(&card->vdev->dev, "Unable to read from GPIO\n");
		return 0;
	}

	/*
	 * Remember, input on channels configured as both input and output
	 * are inverted!
	 */
	if (reg & PIO2_CHANNEL_BIT[offset]) {
		if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
			return 0;

		return 1;
	}

	if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH)
		return 1;

	return 0;
}

static void pio2_gpio_set(struct gpio_chip *chip,
			  unsigned int offset, int value)
{
	u8 reg;
	int retval;
	struct pio2_card *card = gpiochip_get_data(chip);

	if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
	    (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
		dev_err(&card->vdev->dev, "Channel not available as output\n");
		return;
	}

	if (value)
		reg = card->bank[PIO2_CHANNEL_BANK[offset]].value |
			PIO2_CHANNEL_BIT[offset];
	else
		reg = card->bank[PIO2_CHANNEL_BANK[offset]].value &
			~PIO2_CHANNEL_BIT[offset];

	retval = vme_master_write(card->window, &reg, 1,
				  PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]);
	if (retval < 0) {
		dev_err(&card->vdev->dev, "Unable to write to GPIO\n");
		return;
	}

	card->bank[PIO2_CHANNEL_BANK[offset]].value = reg;
}

/* Directionality configured at board build - send appropriate response */
static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
{
	int data;
	struct pio2_card *card = gpiochip_get_data(chip);

	if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) |
	    (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
		dev_err(&card->vdev->dev,
			"Channel directionality not configurable at runtime\n");

		data = -EINVAL;
	} else {
		data = 0;
	}

	return data;
}

/* Directionality configured at board build - send appropriate response */
static int pio2_gpio_dir_out(struct gpio_chip *chip,
			     unsigned int offset, int value)
{
	int data;
	struct pio2_card *card = gpiochip_get_data(chip);

	if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) |
	    (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) {
		dev_err(&card->vdev->dev,
			"Channel directionality not configurable at runtime\n");

		data = -EINVAL;
	} else {
		data = 0;
	}

	return data;
}

/*
 * We return whether this has been successful - this is used in the probe to
 * ensure we have a valid card.
 */
int pio2_gpio_reset(struct pio2_card *card)
{
	int retval = 0;
	int i, j;

	u8 data = 0;

	/* Zero output registers */
	for (i = 0; i < 4; i++) {
		retval = vme_master_write(card->window, &data, 1,
					  PIO2_REGS_DATA[i]);
		if (retval < 0)
			return retval;
		card->bank[i].value = 0;
	}

	/* Set input interrupt masks */
	for (i = 0; i < 4; i++) {
		retval = vme_master_write(card->window, &data, 1,
					  PIO2_REGS_INT_MASK[i * 2]);
		if (retval < 0)
			return retval;

		retval = vme_master_write(card->window, &data, 1,
					  PIO2_REGS_INT_MASK[(i * 2) + 1]);
		if (retval < 0)
			return retval;

		for (j = 0; j < 8; j++)
			card->bank[i].irq[j] = NONE;
	}

	/* Ensure all I/O interrupts are cleared */
	for (i = 0; i < 4; i++) {
		do {
			retval = vme_master_read(card->window, &data, 1,
						 PIO2_REGS_INT_STAT[i]);
			if (retval < 0)
				return retval;
		} while (data != 0);
	}

	return 0;
}

int pio2_gpio_init(struct pio2_card *card)
{
	int retval = 0;
	char *label;

	label = kasprintf(GFP_KERNEL,
			  "%s@%s", driver_name, dev_name(&card->vdev->dev));
	if (!label)
		return -ENOMEM;

	card->gc.label = label;

	card->gc.ngpio = PIO2_NUM_CHANNELS;
	/* Dynamic allocation of base */
	card->gc.base = -1;
	/* Setup pointers to chip functions */
	card->gc.direction_input = pio2_gpio_dir_in;
	card->gc.direction_output = pio2_gpio_dir_out;
	card->gc.get = pio2_gpio_get;
	card->gc.set = pio2_gpio_set;

	/* This function adds a memory mapped GPIO chip */
	retval = gpiochip_add_data(&card->gc, card);
	if (retval) {
		dev_err(&card->vdev->dev, "Unable to register GPIO\n");
		kfree(card->gc.label);
	}

	return retval;
};

void pio2_gpio_exit(struct pio2_card *card)
{
	const char *label = card->gc.label;

	gpiochip_remove(&card->gc);
	kfree(label);
}

