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