/*
 * GE PIO2 6U VME I/O 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.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

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

#include "vme_pio2.h"


static const char driver_name[] = "pio2";

static int bus[PIO2_CARDS_MAX];
static int bus_num;
static long base[PIO2_CARDS_MAX];
static int base_num;
static int vector[PIO2_CARDS_MAX];
static int vector_num;
static int level[PIO2_CARDS_MAX];
static int level_num;
static char *variant[PIO2_CARDS_MAX];
static int variant_num;

static bool loopback;

static int pio2_match(struct vme_dev *);
static int pio2_probe(struct vme_dev *);
static int pio2_remove(struct vme_dev *);

static int pio2_get_led(struct pio2_card *card)
{
	/* Can't read hardware, state saved in structure */
	return card->led;
}

static int pio2_set_led(struct pio2_card *card, int state)
{
	u8 reg;
	int retval;

	reg = card->irq_level;

	/* Register state inverse of led state */
	if (!state)
		reg |= PIO2_LED;

	if (loopback)
		reg |= PIO2_LOOP;

	retval = vme_master_write(card->window, &reg, 1, PIO2_REGS_CTRL);
	if (retval < 0)
		return retval;

	card->led = state ? 1 : 0;

	return 0;
}

static void pio2_int(int level, int vector, void *ptr)
{
	int vec, i, channel, retval;
	u8 reg;
	struct pio2_card *card  = ptr;

	vec = vector & ~PIO2_VME_VECTOR_MASK;

	switch (vec) {
	case 0:
		dev_warn(&card->vdev->dev, "Spurious Interrupt\n");
		break;
	case 1:
	case 2:
	case 3:
	case 4:
		/* Channels 0 to 7 */
		retval = vme_master_read(card->window, &reg, 1,
			PIO2_REGS_INT_STAT[vec - 1]);
		if (retval < 0) {
			dev_err(&card->vdev->dev,
				"Unable to read IRQ status register\n");
			return;
		}
		for (i = 0; i < 8; i++) {
			channel = ((vec - 1) * 8) + i;
			if (reg & PIO2_CHANNEL_BIT[channel])
				dev_info(&card->vdev->dev,
					"Interrupt on I/O channel %d\n",
					channel);
		}
		break;
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	case 10:
		/* Counters are dealt with by their own handler */
		dev_err(&card->vdev->dev,
			"Counter interrupt\n");
		break;
	}
}


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

	/* Clear main register*/
	retval = vme_master_write(card->window, &data, 1, PIO2_REGS_CTRL);
	if (retval < 0)
		return retval;

	/* Clear VME vector */
	retval = vme_master_write(card->window, &data, 1, PIO2_REGS_VME_VECTOR);
	if (retval < 0)
		return retval;

	/* Reset GPIO */
	retval = pio2_gpio_reset(card);
	if (retval < 0)
		return retval;

	/* Reset counters */
	retval = pio2_cntr_reset(card);
	if (retval < 0)
		return retval;

	return 0;
}

static struct vme_driver pio2_driver = {
	.name = driver_name,
	.match = pio2_match,
	.probe = pio2_probe,
	.remove = pio2_remove,
};


static int __init pio2_init(void)
{
	if (bus_num == 0) {
		pr_err("No cards, skipping registration\n");
		return -ENODEV;
	}

	if (bus_num > PIO2_CARDS_MAX) {
		pr_err("Driver only able to handle %d PIO2 Cards\n",
		       PIO2_CARDS_MAX);
		bus_num = PIO2_CARDS_MAX;
	}

	/* Register the PIO2 driver */
	return  vme_register_driver(&pio2_driver, bus_num);
}

static int pio2_match(struct vme_dev *vdev)
{

	if (vdev->num >= bus_num) {
		dev_err(&vdev->dev,
			"The enumeration of the VMEbus to which the board is connected must be specified");
		return 0;
	}

	if (vdev->num >= base_num) {
		dev_err(&vdev->dev,
			"The VME address for the cards registers must be specified");
		return 0;
	}

	if (vdev->num >= vector_num) {
		dev_err(&vdev->dev,
			"The IRQ vector used by the card must be specified");
		return 0;
	}

	if (vdev->num >= level_num) {
		dev_err(&vdev->dev,
			"The IRQ level used by the card must be specified");
		return 0;
	}

	if (vdev->num >= variant_num) {
		dev_err(&vdev->dev, "The variant of the card must be specified");
		return 0;
	}

	return 1;
}

static int pio2_probe(struct vme_dev *vdev)
{
	struct pio2_card *card;
	int retval;
	int i;
	u8 reg;
	int vec;

	card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL);
	if (card == NULL) {
		retval = -ENOMEM;
		goto err_struct;
	}

	card->id = vdev->num;
	card->bus = bus[card->id];
	card->base = base[card->id];
	card->irq_vector = vector[card->id];
	card->irq_level = level[card->id] & PIO2_VME_INT_MASK;
	strncpy(card->variant, variant[card->id], PIO2_VARIANT_LENGTH);
	card->vdev = vdev;

	for (i = 0; i < PIO2_VARIANT_LENGTH; i++) {

		if (isdigit(card->variant[i]) == 0) {
			dev_err(&card->vdev->dev, "Variant invalid\n");
			retval = -EINVAL;
			goto err_variant;
		}
	}

	/*
	 * Bottom 4 bits of VME interrupt vector used to determine source,
	 * provided vector should only use upper 4 bits.
	 */
	if (card->irq_vector & ~PIO2_VME_VECTOR_MASK) {
		dev_err(&card->vdev->dev,
			"Invalid VME IRQ Vector, vector must not use lower 4 bits\n");
		retval = -EINVAL;
		goto err_vector;
	}

	/*
	 * There is no way to determine the build variant or whether each bank
	 * is input, output or both at run time. The inputs are also inverted
	 * if configured as both.
	 *
	 * We pass in the board variant and use that to determine the
	 * configuration of the banks.
	 */
	for (i = 1; i < PIO2_VARIANT_LENGTH; i++) {
		switch (card->variant[i]) {
		case '0':
			card->bank[i-1].config = NOFIT;
			break;
		case '1':
		case '2':
		case '3':
		case '4':
			card->bank[i-1].config = INPUT;
			break;
		case '5':
			card->bank[i-1].config = OUTPUT;
			break;
		case '6':
		case '7':
		case '8':
		case '9':
			card->bank[i-1].config = BOTH;
			break;
		}
	}

	/* Get a master window and position over regs */
	card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16);
	if (card->window == NULL) {
		dev_err(&card->vdev->dev,
			"Unable to assign VME master resource\n");
		retval = -EIO;
		goto err_window;
	}

	retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24,
		(VME_SCT | VME_USER | VME_DATA), VME_D16);
	if (retval) {
		dev_err(&card->vdev->dev,
			"Unable to configure VME master resource\n");
		goto err_set;
	}

	/*
	 * There is also no obvious register which we can probe to determine
	 * whether the provided base is valid. If we can read the "ID Register"
	 * offset and the reset function doesn't error, assume we have a valid
	 * location.
	 */
	retval = vme_master_read(card->window, &reg, 1, PIO2_REGS_ID);
	if (retval < 0) {
		dev_err(&card->vdev->dev, "Unable to read from device\n");
		goto err_read;
	}

	dev_dbg(&card->vdev->dev, "ID Register:%x\n", reg);

	/*
	 * Ensure all the I/O is cleared. We can't read back the states, so
	 * this is the only method we have to ensure that the I/O is in a known
	 * state.
	 */
	retval = pio2_reset_card(card);
	if (retval) {
		dev_err(&card->vdev->dev,
			"Failed to reset card, is location valid?");
		retval = -ENODEV;
		goto err_reset;
	}

	/* Configure VME Interrupts */
	reg = card->irq_level;
	if (pio2_get_led(card))
		reg |= PIO2_LED;
	if (loopback)
		reg |= PIO2_LOOP;
	retval = vme_master_write(card->window, &reg, 1, PIO2_REGS_CTRL);
	if (retval < 0)
		return retval;

	/* Set VME vector */
	retval = vme_master_write(card->window, &card->irq_vector, 1,
		PIO2_REGS_VME_VECTOR);
	if (retval < 0)
		return retval;

	/* Attach spurious interrupt handler. */
	vec = card->irq_vector | PIO2_VME_VECTOR_SPUR;

	retval = vme_irq_request(vdev, card->irq_level, vec,
		&pio2_int, (void *)card);
	if (retval < 0) {
		dev_err(&card->vdev->dev,
			"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
			 vec, card->irq_level);
		goto err_irq;
	}

	/* Attach GPIO interrupt handlers. */
	for (i = 0; i < 4; i++) {
		vec = card->irq_vector | PIO2_VECTOR_BANK[i];

		retval = vme_irq_request(vdev, card->irq_level, vec,
			&pio2_int, (void *)card);
		if (retval < 0) {
			dev_err(&card->vdev->dev,
				"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
				 vec, card->irq_level);
			goto err_gpio_irq;
		}
	}

	/* Attach counter interrupt handlers. */
	for (i = 0; i < 6; i++) {
		vec = card->irq_vector | PIO2_VECTOR_CNTR[i];

		retval = vme_irq_request(vdev, card->irq_level, vec,
			&pio2_int, (void *)card);
		if (retval < 0) {
			dev_err(&card->vdev->dev,
				"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
				vec, card->irq_level);
			goto err_cntr_irq;
		}
	}

	/* Register IO */
	retval = pio2_gpio_init(card);
	if (retval < 0) {
		dev_err(&card->vdev->dev,
			"Unable to register with GPIO framework\n");
		goto err_gpio;
	}

	/* Set LED - This also sets interrupt level */
	retval = pio2_set_led(card, 0);
	if (retval < 0) {
		dev_err(&card->vdev->dev, "Unable to set LED\n");
		goto err_led;
	}

	dev_set_drvdata(&card->vdev->dev, card);

	dev_info(&card->vdev->dev,
		"PIO2 (variant %s) configured at 0x%lx\n", card->variant,
		card->base);

	return 0;

err_led:
	pio2_gpio_exit(card);
err_gpio:
	i = 6;
err_cntr_irq:
	while (i > 0) {
		i--;
		vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
		vme_irq_free(vdev, card->irq_level, vec);
	}

	i = 4;
err_gpio_irq:
	while (i > 0) {
		i--;
		vec = card->irq_vector | PIO2_VECTOR_BANK[i];
		vme_irq_free(vdev, card->irq_level, vec);
	}

	vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR;
	vme_irq_free(vdev, card->irq_level, vec);
err_irq:
	 pio2_reset_card(card);
err_reset:
err_read:
	vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16);
err_set:
	vme_master_free(card->window);
err_window:
err_vector:
err_variant:
	kfree(card);
err_struct:
	return retval;
}

static int pio2_remove(struct vme_dev *vdev)
{
	int vec;
	int i;

	struct pio2_card *card = dev_get_drvdata(&vdev->dev);

	pio2_gpio_exit(card);

	for (i = 0; i < 6; i++) {
		vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
		vme_irq_free(vdev, card->irq_level, vec);
	}

	for (i = 0; i < 4; i++) {
		vec = card->irq_vector | PIO2_VECTOR_BANK[i];
		vme_irq_free(vdev, card->irq_level, vec);
	}

	vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR;
	vme_irq_free(vdev, card->irq_level, vec);

	pio2_reset_card(card);

	vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16);

	vme_master_free(card->window);

	kfree(card);

	return 0;
}

static void __exit pio2_exit(void)
{
	vme_unregister_driver(&pio2_driver);
}


/* These are required for each board */
MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected");
module_param_array(bus, int, &bus_num, S_IRUGO);

MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers");
module_param_array(base, long, &base_num, S_IRUGO);

MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)");
module_param_array(vector, int, &vector_num, S_IRUGO);

MODULE_PARM_DESC(level, "VME IRQ Level");
module_param_array(level, int, &level_num, S_IRUGO);

MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant");
module_param_array(variant, charp, &variant_num, S_IRUGO);

/* This is for debugging */
MODULE_PARM_DESC(loopback, "Enable loopback mode on all cards");
module_param(loopback, bool, S_IRUGO);

MODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver");
MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
MODULE_LICENSE("GPL");

module_init(pio2_init);
module_exit(pio2_exit);

