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, ®, 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, ®, 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, ®, 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, ®, 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