[go: nahoru, domu]

19dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch/*
29dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * GE PIO2 6U VME I/O Driver
39dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch *
49dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com>
59dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
69dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch *
79dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * This program is free software; you can redistribute  it and/or modify it
89dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * under  the terms of  the GNU General  Public License as published by the
99dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * Free Software Foundation;  either version 2 of the  License, or (at your
109dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * option) any later version.
119dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch */
129dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
13736f5d0a0980a6bf71e5c0d30c2d35225fb3f583Toshiaki Yamane#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14736f5d0a0980a6bf71e5c0d30c2d35225fb3f583Toshiaki Yamane
159dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/module.h>
169dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/moduleparam.h>
179dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/types.h>
189dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/kernel.h>
199dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/errno.h>
209dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/device.h>
219dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/ctype.h>
229dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/gpio.h>
239dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include <linux/slab.h>
24db3b9e990e75573402cda22faf933760f076c033Greg Kroah-Hartman#include <linux/vme.h>
259dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
269dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch#include "vme_pio2.h"
279dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
289dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
299dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic const char driver_name[] = "pio2";
309dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
319dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int bus[PIO2_CARDS_MAX];
329dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int bus_num;
339dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic long base[PIO2_CARDS_MAX];
349dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int base_num;
359dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int vector[PIO2_CARDS_MAX];
369dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int vector_num;
379dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int level[PIO2_CARDS_MAX];
389dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int level_num;
39eaa004a4ba3264d17d7e6882948a7980e14e9d20Gerard Snitselaarstatic char *variant[PIO2_CARDS_MAX];
409dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int variant_num;
419dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
42eaa004a4ba3264d17d7e6882948a7980e14e9d20Gerard Snitselaarstatic bool loopback;
439dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
449dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int pio2_match(struct vme_dev *);
45d7e530d26ba3dc59753e0d0b04fecdbb1f394c38Bill Pembertonstatic int pio2_probe(struct vme_dev *);
46f21a8247641329c40ab17b2d70c492c060bb3573Bill Pembertonstatic int pio2_remove(struct vme_dev *);
479dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
489dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int pio2_get_led(struct pio2_card *card)
499dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
509dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Can't read hardware, state saved in structure */
519dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return card->led;
529dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
539dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
549dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int pio2_set_led(struct pio2_card *card, int state)
559dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
569dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	u8 reg;
579dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int retval;
589dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
599dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	reg = card->irq_level;
609dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
619dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Register state inverse of led state */
629dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (!state)
639dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		reg |= PIO2_LED;
649dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
659dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (loopback)
669dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		reg |= PIO2_LOOP;
679dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
689dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_write(card->window, &reg, 1, PIO2_REGS_CTRL);
699dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
709dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
719dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
729dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->led = state ? 1 : 0;
739dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
749dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return 0;
759dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
769dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
779dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic void pio2_int(int level, int vector, void *ptr)
789dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
799dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int vec, i, channel, retval;
809dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	u8 reg;
819dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	struct pio2_card *card  = ptr;
829dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
839dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vec = vector & ~PIO2_VME_VECTOR_MASK;
849dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
859dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	switch (vec) {
869dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 0:
879dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_warn(&card->vdev->dev, "Spurious Interrupt\n");
889dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		break;
899dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 1:
909dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 2:
919dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 3:
929dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 4:
939dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		/* Channels 0 to 7 */
949dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = vme_master_read(card->window, &reg, 1,
959dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			PIO2_REGS_INT_STAT[vec - 1]);
969dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		if (retval < 0) {
979dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			dev_err(&card->vdev->dev,
989dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch				"Unable to read IRQ status register\n");
999dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			return;
1009dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		}
1019dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		for (i = 0; i < 8; i++) {
1029dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			channel = ((vec - 1) * 8) + i;
1039dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			if (reg & PIO2_CHANNEL_BIT[channel])
1049dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch				dev_info(&card->vdev->dev,
1059dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch					"Interrupt on I/O channel %d\n",
1069dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch					channel);
1079dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		}
1089dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		break;
1099dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 5:
1109dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 6:
1119dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 7:
1129dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 8:
1139dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 9:
1149dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	case 10:
1159dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		/* Counters are dealt with by their own handler */
1169dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
1179dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			"Counter interrupt\n");
1189dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		break;
1199dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
1209dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
1219dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1229dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1239dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch/*
1249dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * We return whether this has been successful - this is used in the probe to
1259dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch * ensure we have a valid card.
1269dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch */
1279dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int pio2_reset_card(struct pio2_card *card)
1289dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
1299dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int retval = 0;
1309dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	u8 data = 0;
1319dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1329dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Clear main register*/
1339dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_write(card->window, &data, 1, PIO2_REGS_CTRL);
1349dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
1359dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
1369dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1379dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Clear VME vector */
1389dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_write(card->window, &data, 1, PIO2_REGS_VME_VECTOR);
1399dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
1409dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
1419dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1429dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Reset GPIO */
1439dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = pio2_gpio_reset(card);
1449dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
1459dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
1469dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1479dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Reset counters */
1489dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = pio2_cntr_reset(card);
1499dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
1509dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
1519dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1529dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return 0;
1539dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
1549dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1559dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic struct vme_driver pio2_driver = {
1569dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	.name = driver_name,
1579dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	.match = pio2_match,
1589dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	.probe = pio2_probe,
15938930755b86082b8d44da038d0ec0b912a708679Bill Pemberton	.remove = pio2_remove,
1609dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch};
1619dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1629dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1639dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int __init pio2_init(void)
1649dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
1659dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (bus_num == 0) {
166736f5d0a0980a6bf71e5c0d30c2d35225fb3f583Toshiaki Yamane		pr_err("No cards, skipping registration\n");
1679349f8af28ea89639b3c97da583d60631ed10398Konstantin Khlebnikov		return -ENODEV;
1689dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
1699dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1709dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (bus_num > PIO2_CARDS_MAX) {
171736f5d0a0980a6bf71e5c0d30c2d35225fb3f583Toshiaki Yamane		pr_err("Driver only able to handle %d PIO2 Cards\n",
172736f5d0a0980a6bf71e5c0d30c2d35225fb3f583Toshiaki Yamane		       PIO2_CARDS_MAX);
1739dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		bus_num = PIO2_CARDS_MAX;
1749dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
1759dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1769dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Register the PIO2 driver */
1779349f8af28ea89639b3c97da583d60631ed10398Konstantin Khlebnikov	return  vme_register_driver(&pio2_driver, bus_num);
1789dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
1799dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1809dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic int pio2_match(struct vme_dev *vdev)
1819dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
1829dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1839dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (vdev->num >= bus_num) {
1849dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&vdev->dev,
185fbeca3ca16f3c362de55ec016f95f9e644064f91Masanari Iida			"The enumeration of the VMEbus to which the board is connected must be specified\n");
1869dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return 0;
1879dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
1889dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1899dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (vdev->num >= base_num) {
1909dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&vdev->dev,
191fbeca3ca16f3c362de55ec016f95f9e644064f91Masanari Iida			"The VME address for the cards registers must be specified\n");
1929dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return 0;
1939dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
1949dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
1959dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (vdev->num >= vector_num) {
1969dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&vdev->dev,
197fbeca3ca16f3c362de55ec016f95f9e644064f91Masanari Iida			"The IRQ vector used by the card must be specified\n");
1989dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return 0;
1999dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2009dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2019dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (vdev->num >= level_num) {
2029dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&vdev->dev,
203fbeca3ca16f3c362de55ec016f95f9e644064f91Masanari Iida			"The IRQ level used by the card must be specified\n");
2049dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return 0;
2059dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2069dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2079dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (vdev->num >= variant_num) {
208fbeca3ca16f3c362de55ec016f95f9e644064f91Masanari Iida		dev_err(&vdev->dev, "The variant of the card must be specified\n");
2099dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return 0;
2109dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2119dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2129dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return 1;
2139dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
2149dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
215d7e530d26ba3dc59753e0d0b04fecdbb1f394c38Bill Pembertonstatic int pio2_probe(struct vme_dev *vdev)
2169dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
2179dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	struct pio2_card *card;
2189dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int retval;
2199dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int i;
2209dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	u8 reg;
2219dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int vec;
2229dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2239dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL);
2249dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (card == NULL) {
2259dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = -ENOMEM;
2269dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_struct;
2279dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2289dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2299dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->id = vdev->num;
2309dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->bus = bus[card->id];
2319dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->base = base[card->id];
2329dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->irq_vector = vector[card->id];
2339dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->irq_level = level[card->id] & PIO2_VME_INT_MASK;
2349dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	strncpy(card->variant, variant[card->id], PIO2_VARIANT_LENGTH);
2359dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->vdev = vdev;
2369dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2379dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	for (i = 0; i < PIO2_VARIANT_LENGTH; i++) {
2389dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2399dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		if (isdigit(card->variant[i]) == 0) {
2409dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			dev_err(&card->vdev->dev, "Variant invalid\n");
2419dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			retval = -EINVAL;
2429dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			goto err_variant;
2439dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		}
2449dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2459dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2469dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/*
2479dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * Bottom 4 bits of VME interrupt vector used to determine source,
2489dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * provided vector should only use upper 4 bits.
2499dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 */
2509dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (card->irq_vector & ~PIO2_VME_VECTOR_MASK) {
2519dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
2529dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			"Invalid VME IRQ Vector, vector must not use lower 4 bits\n");
2539dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = -EINVAL;
2549dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_vector;
2559dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2569dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2579dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/*
2589dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * There is no way to determine the build variant or whether each bank
2599dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * is input, output or both at run time. The inputs are also inverted
2609dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * if configured as both.
2619dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 *
2629dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * We pass in the board variant and use that to determine the
2639dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * configuration of the banks.
2649dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 */
2659dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	for (i = 1; i < PIO2_VARIANT_LENGTH; i++) {
2669dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		switch (card->variant[i]) {
2679dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '0':
2689dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			card->bank[i-1].config = NOFIT;
2699dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			break;
2709dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '1':
2719dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '2':
2729dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '3':
2739dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '4':
2749dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			card->bank[i-1].config = INPUT;
2759dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			break;
2769dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '5':
2779dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			card->bank[i-1].config = OUTPUT;
2789dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			break;
2799dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '6':
2809dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '7':
2819dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '8':
2829dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		case '9':
2839dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			card->bank[i-1].config = BOTH;
2849dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			break;
2859dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		}
2869dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2879dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2889dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Get a master window and position over regs */
2899dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16);
2909dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (card->window == NULL) {
2919dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
2929dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			"Unable to assign VME master resource\n");
2939dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = -EIO;
2949dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_window;
2959dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
2969dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
2979dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24,
2989dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		(VME_SCT | VME_USER | VME_DATA), VME_D16);
2999dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval) {
3009dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
3019dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			"Unable to configure VME master resource\n");
3029dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_set;
3039dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3049dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3059dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/*
3069dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * There is also no obvious register which we can probe to determine
3079dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * whether the provided base is valid. If we can read the "ID Register"
3089dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * offset and the reset function doesn't error, assume we have a valid
3099dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * location.
3109dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 */
3119dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_read(card->window, &reg, 1, PIO2_REGS_ID);
3129dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0) {
3139dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev, "Unable to read from device\n");
3149dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_read;
3159dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3169dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3179dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	dev_dbg(&card->vdev->dev, "ID Register:%x\n", reg);
3189dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3199dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/*
3209dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * Ensure all the I/O is cleared. We can't read back the states, so
3219dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * this is the only method we have to ensure that the I/O is in a known
3229dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 * state.
3239dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 */
3249dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = pio2_reset_card(card);
3259dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval) {
3269dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
327fbeca3ca16f3c362de55ec016f95f9e644064f91Masanari Iida			"Failed to reset card, is location valid?\n");
3289dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = -ENODEV;
3299dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_reset;
3309dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3319dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3329dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Configure VME Interrupts */
3339dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	reg = card->irq_level;
3349dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (pio2_get_led(card))
3359dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		reg |= PIO2_LED;
3369dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (loopback)
3379dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		reg |= PIO2_LOOP;
3389dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_write(card->window, &reg, 1, PIO2_REGS_CTRL);
3399dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
3409dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
3419dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3429dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Set VME vector */
3439dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_master_write(card->window, &card->irq_vector, 1,
3449dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		PIO2_REGS_VME_VECTOR);
3459dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0)
3469dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		return retval;
3479dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3489dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Attach spurious interrupt handler. */
3499dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vec = card->irq_vector | PIO2_VME_VECTOR_SPUR;
3509dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3519dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = vme_irq_request(vdev, card->irq_level, vec,
3529dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		&pio2_int, (void *)card);
3539dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0) {
3549dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
3559dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
3569dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			 vec, card->irq_level);
3579dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_irq;
3589dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3599dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3609dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Attach GPIO interrupt handlers. */
3619dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	for (i = 0; i < 4; i++) {
3629dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vec = card->irq_vector | PIO2_VECTOR_BANK[i];
3639dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3649dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = vme_irq_request(vdev, card->irq_level, vec,
3659dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			&pio2_int, (void *)card);
3669dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		if (retval < 0) {
3679dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			dev_err(&card->vdev->dev,
3689dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch				"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
3699dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch				 vec, card->irq_level);
3709dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			goto err_gpio_irq;
3719dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		}
3729dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3739dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3749dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Attach counter interrupt handlers. */
3759dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	for (i = 0; i < 6; i++) {
3769dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
3779dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3789dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		retval = vme_irq_request(vdev, card->irq_level, vec,
3799dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			&pio2_int, (void *)card);
3809dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		if (retval < 0) {
3819dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			dev_err(&card->vdev->dev,
3829dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch				"Unable to attach VME interrupt vector0x%x, level 0x%x\n",
3839dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch				vec, card->irq_level);
3849dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			goto err_cntr_irq;
3859dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		}
3869dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3879dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3889dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Register IO */
3899dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = pio2_gpio_init(card);
3909dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0) {
3919dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev,
3929dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch			"Unable to register with GPIO framework\n");
3939dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_gpio;
3949dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
3959dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
3969dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	/* Set LED - This also sets interrupt level */
3979dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	retval = pio2_set_led(card, 0);
3989dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	if (retval < 0) {
3999dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		dev_err(&card->vdev->dev, "Unable to set LED\n");
4009dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		goto err_led;
4019dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
4029dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4039dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	dev_set_drvdata(&card->vdev->dev, card);
4049dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4059dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	dev_info(&card->vdev->dev,
4069dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		"PIO2 (variant %s) configured at 0x%lx\n", card->variant,
4079dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		card->base);
4089dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4099dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return 0;
4109dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4119dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_led:
4129dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	pio2_gpio_exit(card);
4139dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_gpio:
4149dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	i = 6;
4159dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_cntr_irq:
4169dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	while (i > 0) {
4179dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		i--;
4189dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
4199dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vme_irq_free(vdev, card->irq_level, vec);
4209dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
4219dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4229dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	i = 4;
4239dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_gpio_irq:
4249dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	while (i > 0) {
4259dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		i--;
4269dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vec = card->irq_vector | PIO2_VECTOR_BANK[i];
4279dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vme_irq_free(vdev, card->irq_level, vec);
4289dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
4299dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4309dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR;
4319dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_irq_free(vdev, card->irq_level, vec);
4329dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_irq:
4339dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	 pio2_reset_card(card);
4349dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_reset:
4359dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_read:
4369dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16);
4379dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_set:
4389dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_master_free(card->window);
4399dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_window:
4409dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_vector:
4419dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_variant:
4429dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	kfree(card);
4439dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welcherr_struct:
4449dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return retval;
4459dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
4469dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
447f21a8247641329c40ab17b2d70c492c060bb3573Bill Pembertonstatic int pio2_remove(struct vme_dev *vdev)
4489dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
4499dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int vec;
4509dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	int i;
4519dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4529dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	struct pio2_card *card = dev_get_drvdata(&vdev->dev);
4539dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4549dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	pio2_gpio_exit(card);
4559dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4569dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	for (i = 0; i < 6; i++) {
4579dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vec = card->irq_vector | PIO2_VECTOR_CNTR[i];
4589dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vme_irq_free(vdev, card->irq_level, vec);
4599dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
4609dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4619dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	for (i = 0; i < 4; i++) {
4629dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vec = card->irq_vector | PIO2_VECTOR_BANK[i];
4639dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch		vme_irq_free(vdev, card->irq_level, vec);
4649dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	}
4659dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4669dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR;
4679dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_irq_free(vdev, card->irq_level, vec);
4689dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4699dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	pio2_reset_card(card);
4709dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4719dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16);
4729dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4739dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_master_free(card->window);
4749dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4759dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	kfree(card);
4769dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4779dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	return 0;
4789dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
4799dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4809dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchstatic void __exit pio2_exit(void)
4819dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch{
4829dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch	vme_unregister_driver(&pio2_driver);
4839dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch}
4849dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4859dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4869dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch/* These are required for each board */
4879dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected");
4889dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_param_array(bus, int, &bus_num, S_IRUGO);
4899dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4909dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_PARM_DESC(base, "Base VME address for PIO2 Registers");
4919dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_param_array(base, long, &base_num, S_IRUGO);
4929dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4939dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)");
4949dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_param_array(vector, int, &vector_num, S_IRUGO);
4959dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4969dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_PARM_DESC(level, "VME IRQ Level");
4979dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_param_array(level, int, &level_num, S_IRUGO);
4989dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
4999dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant");
5009dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_param_array(variant, charp, &variant_num, S_IRUGO);
5019dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
5029dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch/* This is for debugging */
5039dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_PARM_DESC(loopback, "Enable loopback mode on all cards");
5049dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_param(loopback, bool, S_IRUGO);
5059dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
5069dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver");
5079dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
5089dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn WelchMODULE_LICENSE("GPL");
5099dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
5109dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_init(pio2_init);
5119dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welchmodule_exit(pio2_exit);
5129dc367bc4c76cc4c6595e9fab6a5a02523b537c6Martyn Welch
513