diff options
Diffstat (limited to 'drivers/staging/vme')
-rw-r--r-- | drivers/staging/vme/TODO | 67 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.c | 31 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_tsi148.c | 36 | ||||
-rw-r--r-- | drivers/staging/vme/devices/Kconfig | 13 | ||||
-rw-r--r-- | drivers/staging/vme/devices/Makefile | 3 | ||||
-rw-r--r-- | drivers/staging/vme/devices/vme_pio2.h | 249 | ||||
-rw-r--r-- | drivers/staging/vme/devices/vme_pio2_cntr.c | 71 | ||||
-rw-r--r-- | drivers/staging/vme/devices/vme_pio2_core.c | 524 | ||||
-rw-r--r-- | drivers/staging/vme/devices/vme_pio2_gpio.c | 232 | ||||
-rw-r--r-- | drivers/staging/vme/devices/vme_user.h | 10 | ||||
-rw-r--r-- | drivers/staging/vme/vme.c | 69 | ||||
-rw-r--r-- | drivers/staging/vme/vme.h | 38 | ||||
-rw-r--r-- | drivers/staging/vme/vme_api.txt | 61 | ||||
-rw-r--r-- | drivers/staging/vme/vme_bridge.h | 38 |
14 files changed, 1217 insertions, 225 deletions
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO index 82c222b..79f0033 100644 --- a/drivers/staging/vme/TODO +++ b/drivers/staging/vme/TODO @@ -1,70 +1,5 @@ TODO ==== -API -=== - -Master window broadcast select mask ------------------------------------ - -API currently provides no method to set or get Broadcast Select mask. Suggest -somthing like: - - int vme_master_bmsk_set (struct vme_resource *res, int mask); - int vme_master_bmsk_get (struct vme_resource *res, int *mask); - - -Interrupt Generation --------------------- - -Add optional timeout when waiting for an IACK. - - -CR/CSR Buffer -------------- - -The VME API provides no functions to access the buffer mapped into the CR/CSR -space. - - -Mailboxes ---------- - -Whilst not part of the VME specification, they are provided by a number of -chips. They are currently not supported at all by the API. - - -Core -==== - -- Improve generic sanity checks (Such as does an offset and size fit within a - window and parameter checking). - -Bridge Support -============== - -Tempe (tsi148) --------------- - -- 2eSST Broadcast mode. -- Mailboxes unsupported. -- Improve error detection. -- Control of prefetch size, threshold. -- Arbiter control -- Requestor control - -Universe II (ca91c142) ----------------------- - -- Mailboxes unsupported. -- Error Detection. -- Control of prefetch size, threshold. -- Arbiter control -- Requestor control -- Slot detection - -Universe I (ca91x042) ---------------------- - -Currently completely unsupported. +- Add one or more device drivers which use the VME framework. diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 0e4feac..515b8b8 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -338,7 +338,7 @@ static int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, static int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, unsigned long long vme_base, unsigned long long size, - dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) + dma_addr_t pci_base, u32 aspace, u32 cycle) { unsigned int i, addr = 0, granularity; unsigned int temp_ctl = 0; @@ -444,7 +444,7 @@ static int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, static int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, unsigned long long *vme_base, unsigned long long *size, - dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) + dma_addr_t *pci_base, u32 *aspace, u32 *cycle) { unsigned int i, granularity = 0, ctl = 0; unsigned long long vme_bound, pci_offset; @@ -595,8 +595,8 @@ static void ca91cx42_free_resource(struct vme_master_resource *image) static int ca91cx42_master_set(struct vme_master_resource *image, int enabled, - unsigned long long vme_base, unsigned long long size, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) + unsigned long long vme_base, unsigned long long size, u32 aspace, + u32 cycle, u32 dwidth) { int retval = 0; unsigned int i, granularity = 0; @@ -753,7 +753,7 @@ err_window: static int __ca91cx42_master_get(struct vme_master_resource *image, int *enabled, unsigned long long *vme_base, unsigned long long *size, - vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) + u32 *aspace, u32 *cycle, u32 *dwidth) { unsigned int i, ctl; unsigned long long pci_base, pci_bound, vme_offset; @@ -839,8 +839,8 @@ static int __ca91cx42_master_get(struct vme_master_resource *image, } static int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) { int retval; @@ -876,13 +876,13 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image, * maximal configured data cycle is used and splits it * automatically for non-aligned addresses. */ - if ((int)addr & 0x1) { + if ((uintptr_t)addr & 0x1) { *(u8 *)buf = ioread8(addr); done += 1; if (done == count) goto out; } - if ((int)addr & 0x2) { + if ((uintptr_t)addr & 0x2) { if ((count - done) < 2) { *(u8 *)(buf + done) = ioread8(addr + done); done += 1; @@ -930,13 +930,13 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, /* Here we apply for the same strategy we do in master_read * function in order to assure D16 cycle when required. */ - if ((int)addr & 0x1) { + if ((uintptr_t)addr & 0x1) { iowrite8(*(u8 *)buf, addr); done += 1; if (done == count) goto out; } - if ((int)addr & 0x2) { + if ((uintptr_t)addr & 0x2) { if ((count - done) < 2) { iowrite8(*(u8 *)(buf + done), addr + done); done += 1; @@ -973,7 +973,8 @@ static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, unsigned int mask, unsigned int compare, unsigned int swap, loff_t offset) { - u32 pci_addr, result; + u32 result; + uintptr_t pci_addr; int i; struct ca91cx42_driver *bridge; struct device *dev; @@ -990,7 +991,7 @@ static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, /* Lock image */ spin_lock(&image->lock); - pci_addr = (u32)image->kern_base + offset; + pci_addr = (uintptr_t)image->kern_base + offset; /* Address must be 4-byte aligned */ if (pci_addr & 0x3) { @@ -1291,7 +1292,7 @@ static int ca91cx42_dma_list_empty(struct vme_dma_list *list) * callback is attached and disabled when the last callback is removed. */ static int ca91cx42_lm_set(struct vme_lm_resource *lm, - unsigned long long lm_base, vme_address_t aspace, vme_cycle_t cycle) + unsigned long long lm_base, u32 aspace, u32 cycle) { u32 temp_base, lm_ctl = 0; int i; @@ -1359,7 +1360,7 @@ static int ca91cx42_lm_set(struct vme_lm_resource *lm, * or disabled. */ static int ca91cx42_lm_get(struct vme_lm_resource *lm, - unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle) + unsigned long long *lm_base, u32 *aspace, u32 *cycle) { u32 lm_ctl, enabled = 0; struct ca91cx42_driver *bridge; diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c index 6c1167c..08a449b 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ b/drivers/staging/vme/bridges/vme_tsi148.c @@ -483,7 +483,7 @@ static int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, * Find the first error in this address range */ static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge, - vme_address_t aspace, unsigned long long address, size_t count) + u32 aspace, unsigned long long address, size_t count) { struct list_head *err_pos; struct vme_bus_error *vme_err, *valid = NULL; @@ -517,7 +517,7 @@ static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge, * Clear errors in the provided address range. */ static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge, - vme_address_t aspace, unsigned long long address, size_t count) + u32 aspace, unsigned long long address, size_t count) { struct list_head *err_pos, *temp; struct vme_bus_error *vme_err; @@ -551,7 +551,7 @@ static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge, */ static int tsi148_slave_set(struct vme_slave_resource *image, int enabled, unsigned long long vme_base, unsigned long long size, - dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) + dma_addr_t pci_base, u32 aspace, u32 cycle) { unsigned int i, addr = 0, granularity = 0; unsigned int temp_ctl = 0; @@ -701,7 +701,7 @@ static int tsi148_slave_set(struct vme_slave_resource *image, int enabled, */ static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, unsigned long long *vme_base, unsigned long long *size, - dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) + dma_addr_t *pci_base, u32 *aspace, u32 *cycle) { unsigned int i, granularity = 0, ctl = 0; unsigned int vme_base_low, vme_base_high; @@ -893,8 +893,8 @@ static void tsi148_free_resource(struct vme_master_resource *image) * Set the attributes of an outbound window. */ static int tsi148_master_set(struct vme_master_resource *image, int enabled, - unsigned long long vme_base, unsigned long long size, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) + unsigned long long vme_base, unsigned long long size, u32 aspace, + u32 cycle, u32 dwidth) { int retval = 0; unsigned int i; @@ -1129,8 +1129,8 @@ err_window: * XXX Not parsing prefetch information. */ static int __tsi148_master_get(struct vme_master_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) { unsigned int i, ctl; unsigned int pci_base_low, pci_base_high; @@ -1239,8 +1239,8 @@ static int __tsi148_master_get(struct vme_master_resource *image, int *enabled, static int tsi148_master_get(struct vme_master_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) { int retval; @@ -1259,9 +1259,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, { int retval, enabled; unsigned long long vme_base, size; - vme_address_t aspace; - vme_cycle_t cycle; - vme_width_t dwidth; + u32 aspace, cycle, dwidth; struct vme_bus_error *vme_err = NULL; struct vme_bridge *tsi148_bridge; @@ -1301,9 +1299,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, { int retval = 0, enabled; unsigned long long vme_base, size; - vme_address_t aspace; - vme_cycle_t cycle; - vme_width_t dwidth; + u32 aspace, cycle, dwidth; struct vme_bus_error *vme_err = NULL; struct vme_bridge *tsi148_bridge; @@ -1420,7 +1416,7 @@ static unsigned int tsi148_master_rmw(struct vme_master_resource *image, } static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) + u32 aspace, u32 cycle, u32 dwidth) { /* Setup 2eSST speeds */ switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { @@ -1514,7 +1510,7 @@ static int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr, } static int tsi148_dma_set_vme_dest_attributes(struct device *dev, u32 *attr, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) + u32 aspace, u32 cycle, u32 dwidth) { /* Setup 2eSST speeds */ switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { @@ -1886,7 +1882,7 @@ static int tsi148_dma_list_empty(struct vme_dma_list *list) * callback is attached and disabled when the last callback is removed. */ static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, - vme_address_t aspace, vme_cycle_t cycle) + u32 aspace, u32 cycle) { u32 lm_base_high, lm_base_low, lm_ctl = 0; int i; @@ -1953,7 +1949,7 @@ static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, * or disabled. */ static int tsi148_lm_get(struct vme_lm_resource *lm, - unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle) + unsigned long long *lm_base, u32 *aspace, u32 *cycle) { u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0; struct tsi148_driver *bridge; diff --git a/drivers/staging/vme/devices/Kconfig b/drivers/staging/vme/devices/Kconfig index ca5ba89..55ec30c 100644 --- a/drivers/staging/vme/devices/Kconfig +++ b/drivers/staging/vme/devices/Kconfig @@ -6,3 +6,16 @@ config VME_USER If you say Y here you want to be able to access a limited number of VME windows in a manner at least semi-compatible with the interface provided with the original driver at http://vmelinux.org/. + +config VME_PIO2 + tristate "GE PIO2 VME" + depends on GPIOLIB + help + Say Y here to include support for the GE PIO2. The PIO2 is a 6U VME + slave card, implementing 32 solid-state relay switched IO lines, in + 4 groups of 8. Each bank of IO lines is built to function as input, + output or both depending on the variant of the card. + + To compile this driver as a module, choose M here. The module will + be called vme_pio2. If unsure, say N. + diff --git a/drivers/staging/vme/devices/Makefile b/drivers/staging/vme/devices/Makefile index 459742a..172512c 100644 --- a/drivers/staging/vme/devices/Makefile +++ b/drivers/staging/vme/devices/Makefile @@ -3,3 +3,6 @@ # obj-$(CONFIG_VME_USER) += vme_user.o + +vme_pio2-objs := vme_pio2_cntr.o vme_pio2_gpio.o vme_pio2_core.o +obj-$(CONFIG_VME_PIO2) += vme_pio2.o diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h new file mode 100644 index 0000000..3c59313 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2.h @@ -0,0 +1,249 @@ +#ifndef _VME_PIO2_H_ +#define _VME_PIO2_H_ + +#define PIO2_CARDS_MAX 32 + +#define PIO2_VARIANT_LENGTH 5 + +#define PIO2_NUM_CHANNELS 32 +#define PIO2_NUM_IRQS 11 +#define PIO2_NUM_CNTRS 6 + +#define PIO2_REGS_SIZE 0x40 + +#define PIO2_REGS_DATA0 0x0 +#define PIO2_REGS_DATA1 0x1 +#define PIO2_REGS_DATA2 0x2 +#define PIO2_REGS_DATA3 0x3 + +static const int PIO2_REGS_DATA[4] = { PIO2_REGS_DATA0, PIO2_REGS_DATA1, + PIO2_REGS_DATA2, PIO2_REGS_DATA3 }; + +#define PIO2_REGS_INT_STAT0 0x8 +#define PIO2_REGS_INT_STAT1 0x9 +#define PIO2_REGS_INT_STAT2 0xa +#define PIO2_REGS_INT_STAT3 0xb + +static const int PIO2_REGS_INT_STAT[4] = { PIO2_REGS_INT_STAT0, + PIO2_REGS_INT_STAT1, + PIO2_REGS_INT_STAT2, + PIO2_REGS_INT_STAT3 }; + +#define PIO2_REGS_INT_STAT_CNTR 0xc +#define PIO2_REGS_INT_MASK0 0x10 +#define PIO2_REGS_INT_MASK1 0x11 +#define PIO2_REGS_INT_MASK2 0x12 +#define PIO2_REGS_INT_MASK3 0x13 +#define PIO2_REGS_INT_MASK4 0x14 +#define PIO2_REGS_INT_MASK5 0x15 +#define PIO2_REGS_INT_MASK6 0x16 +#define PIO2_REGS_INT_MASK7 0x17 + +static const int PIO2_REGS_INT_MASK[8] = { PIO2_REGS_INT_MASK0, + PIO2_REGS_INT_MASK1, + PIO2_REGS_INT_MASK2, + PIO2_REGS_INT_MASK3, + PIO2_REGS_INT_MASK4, + PIO2_REGS_INT_MASK5, + PIO2_REGS_INT_MASK6, + PIO2_REGS_INT_MASK7 }; + + + +#define PIO2_REGS_CTRL 0x18 +#define PIO2_REGS_VME_VECTOR 0x19 +#define PIO2_REGS_CNTR0 0x20 +#define PIO2_REGS_CNTR1 0x22 +#define PIO2_REGS_CNTR2 0x24 +#define PIO2_REGS_CTRL_WRD0 0x26 +#define PIO2_REGS_CNTR3 0x28 +#define PIO2_REGS_CNTR4 0x2a +#define PIO2_REGS_CNTR5 0x2c +#define PIO2_REGS_CTRL_WRD1 0x2e + +#define PIO2_REGS_ID 0x30 + + +/* PIO2_REGS_DATAx (0x0 - 0x3) */ + +static const int PIO2_CHANNEL_BANK[32] = { 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }; + +#define PIO2_CHANNEL0_BIT (1 << 0) +#define PIO2_CHANNEL1_BIT (1 << 1) +#define PIO2_CHANNEL2_BIT (1 << 2) +#define PIO2_CHANNEL3_BIT (1 << 3) +#define PIO2_CHANNEL4_BIT (1 << 4) +#define PIO2_CHANNEL5_BIT (1 << 5) +#define PIO2_CHANNEL6_BIT (1 << 6) +#define PIO2_CHANNEL7_BIT (1 << 7) +#define PIO2_CHANNEL8_BIT (1 << 0) +#define PIO2_CHANNEL9_BIT (1 << 1) +#define PIO2_CHANNEL10_BIT (1 << 2) +#define PIO2_CHANNEL11_BIT (1 << 3) +#define PIO2_CHANNEL12_BIT (1 << 4) +#define PIO2_CHANNEL13_BIT (1 << 5) +#define PIO2_CHANNEL14_BIT (1 << 6) +#define PIO2_CHANNEL15_BIT (1 << 7) +#define PIO2_CHANNEL16_BIT (1 << 0) +#define PIO2_CHANNEL17_BIT (1 << 1) +#define PIO2_CHANNEL18_BIT (1 << 2) +#define PIO2_CHANNEL19_BIT (1 << 3) +#define PIO2_CHANNEL20_BIT (1 << 4) +#define PIO2_CHANNEL21_BIT (1 << 5) +#define PIO2_CHANNEL22_BIT (1 << 6) +#define PIO2_CHANNEL23_BIT (1 << 7) +#define PIO2_CHANNEL24_BIT (1 << 0) +#define PIO2_CHANNEL25_BIT (1 << 1) +#define PIO2_CHANNEL26_BIT (1 << 2) +#define PIO2_CHANNEL27_BIT (1 << 3) +#define PIO2_CHANNEL28_BIT (1 << 4) +#define PIO2_CHANNEL29_BIT (1 << 5) +#define PIO2_CHANNEL30_BIT (1 << 6) +#define PIO2_CHANNEL31_BIT (1 << 7) + +static const int PIO2_CHANNEL_BIT[32] = { PIO2_CHANNEL0_BIT, PIO2_CHANNEL1_BIT, + PIO2_CHANNEL2_BIT, PIO2_CHANNEL3_BIT, + PIO2_CHANNEL4_BIT, PIO2_CHANNEL5_BIT, + PIO2_CHANNEL6_BIT, PIO2_CHANNEL7_BIT, + PIO2_CHANNEL8_BIT, PIO2_CHANNEL9_BIT, + PIO2_CHANNEL10_BIT, PIO2_CHANNEL11_BIT, + PIO2_CHANNEL12_BIT, PIO2_CHANNEL13_BIT, + PIO2_CHANNEL14_BIT, PIO2_CHANNEL15_BIT, + PIO2_CHANNEL16_BIT, PIO2_CHANNEL17_BIT, + PIO2_CHANNEL18_BIT, PIO2_CHANNEL19_BIT, + PIO2_CHANNEL20_BIT, PIO2_CHANNEL21_BIT, + PIO2_CHANNEL22_BIT, PIO2_CHANNEL23_BIT, + PIO2_CHANNEL24_BIT, PIO2_CHANNEL25_BIT, + PIO2_CHANNEL26_BIT, PIO2_CHANNEL27_BIT, + PIO2_CHANNEL28_BIT, PIO2_CHANNEL29_BIT, + PIO2_CHANNEL30_BIT, PIO2_CHANNEL31_BIT + }; + +/* PIO2_REGS_INT_STAT_CNTR (0xc) */ +#define PIO2_COUNTER0 (1 << 0) +#define PIO2_COUNTER1 (1 << 1) +#define PIO2_COUNTER2 (1 << 2) +#define PIO2_COUNTER3 (1 << 3) +#define PIO2_COUNTER4 (1 << 4) +#define PIO2_COUNTER5 (1 << 5) + +static const int PIO2_COUNTER[6] = { PIO2_COUNTER0, PIO2_COUNTER1, + PIO2_COUNTER2, PIO2_COUNTER3, + PIO2_COUNTER4, PIO2_COUNTER5 }; + +/* PIO2_REGS_CTRL (0x18) */ +#define PIO2_VME_INT_MASK 0x7 +#define PIO2_LED (1 << 6) +#define PIO2_LOOP (1 << 7) + +/* PIO2_REGS_VME_VECTOR (0x19) */ +#define PIO2_VME_VECTOR_SPUR 0x0 +#define PIO2_VME_VECTOR_BANK0 0x1 +#define PIO2_VME_VECTOR_BANK1 0x2 +#define PIO2_VME_VECTOR_BANK2 0x3 +#define PIO2_VME_VECTOR_BANK3 0x4 +#define PIO2_VME_VECTOR_CNTR0 0x5 +#define PIO2_VME_VECTOR_CNTR1 0x6 +#define PIO2_VME_VECTOR_CNTR2 0x7 +#define PIO2_VME_VECTOR_CNTR3 0x8 +#define PIO2_VME_VECTOR_CNTR4 0x9 +#define PIO2_VME_VECTOR_CNTR5 0xa + +#define PIO2_VME_VECTOR_MASK 0xf0 + +static const int PIO2_VECTOR_BANK[4] = { PIO2_VME_VECTOR_BANK0, + PIO2_VME_VECTOR_BANK1, + PIO2_VME_VECTOR_BANK2, + PIO2_VME_VECTOR_BANK3 }; + +static const int PIO2_VECTOR_CNTR[6] = { PIO2_VME_VECTOR_CNTR0, + PIO2_VME_VECTOR_CNTR1, + PIO2_VME_VECTOR_CNTR2, + PIO2_VME_VECTOR_CNTR3, + PIO2_VME_VECTOR_CNTR4, + PIO2_VME_VECTOR_CNTR5 }; + +/* PIO2_REGS_CNTRx (0x20 - 0x24 & 0x28 - 0x2c) */ + +static const int PIO2_CNTR_DATA[6] = { PIO2_REGS_CNTR0, PIO2_REGS_CNTR1, + PIO2_REGS_CNTR2, PIO2_REGS_CNTR3, + PIO2_REGS_CNTR4, PIO2_REGS_CNTR5 }; + +/* PIO2_REGS_CTRL_WRDx (0x26 & 0x2e) */ + +static const int PIO2_CNTR_CTRL[6] = { PIO2_REGS_CTRL_WRD0, + PIO2_REGS_CTRL_WRD0, + PIO2_REGS_CTRL_WRD0, + PIO2_REGS_CTRL_WRD1, + PIO2_REGS_CTRL_WRD1, + PIO2_REGS_CTRL_WRD1 }; + +#define PIO2_CNTR_SC_DEV0 0 +#define PIO2_CNTR_SC_DEV1 (1 << 6) +#define PIO2_CNTR_SC_DEV2 (2 << 6) +#define PIO2_CNTR_SC_RDBACK (3 << 6) + +static const int PIO2_CNTR_SC_DEV[6] = { PIO2_CNTR_SC_DEV0, PIO2_CNTR_SC_DEV1, + PIO2_CNTR_SC_DEV2, PIO2_CNTR_SC_DEV0, + PIO2_CNTR_SC_DEV1, PIO2_CNTR_SC_DEV2 }; + +#define PIO2_CNTR_RW_LATCH 0 +#define PIO2_CNTR_RW_LSB (1 << 4) +#define PIO2_CNTR_RW_MSB (2 << 4) +#define PIO2_CNTR_RW_BOTH (3 << 4) + +#define PIO2_CNTR_MODE0 0 +#define PIO2_CNTR_MODE1 (1 << 1) +#define PIO2_CNTR_MODE2 (2 << 1) +#define PIO2_CNTR_MODE3 (3 << 1) +#define PIO2_CNTR_MODE4 (4 << 1) +#define PIO2_CNTR_MODE5 (5 << 1) + +#define PIO2_CNTR_BCD 1 + + + +enum pio2_bank_config { NOFIT, INPUT, OUTPUT, BOTH }; +enum pio2_int_config { NONE = 0, LOW2HIGH = 1, HIGH2LOW = 2, EITHER = 4 }; + +/* Bank configuration structure */ +struct pio2_io_bank { + enum pio2_bank_config config; + u8 value; + enum pio2_int_config irq[8]; +}; + +/* Counter configuration structure */ +struct pio2_cntr { + int mode; + int count; +}; + +struct pio2_card { + int id; + int bus; + long base; + int irq_vector; + int irq_level; + char variant[6]; + int led; + + struct vme_dev *vdev; + struct vme_resource *window; + + struct gpio_chip gc; + struct pio2_io_bank bank[4]; + + struct pio2_cntr cntr[6]; +}; + +int pio2_cntr_reset(struct pio2_card *); + +int pio2_gpio_reset(struct pio2_card *); +int __init pio2_gpio_init(struct pio2_card *); +void __exit pio2_gpio_exit(struct pio2_card *); + +#endif /* _VME_PIO2_H_ */ diff --git a/drivers/staging/vme/devices/vme_pio2_cntr.c b/drivers/staging/vme/devices/vme_pio2_cntr.c new file mode 100644 index 0000000..08e0d59 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_cntr.c @@ -0,0 +1,71 @@ +/* + * GE PIO2 Counter Driver + * + * Author: Martyn Welch <martyn.welch@ge.com> + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The PIO-2 has 6 counters, currently this code just disables the interrupts + * and leaves them alone. + * + */ + +#include <linux/device.h> +#include <linux/types.h> +#include <linux/gpio.h> + +#include "../vme.h" +#include "vme_pio2.h" + +static int pio2_cntr_irq_set(struct pio2_card *card, int id) +{ + int retval; + u8 data; + + data = PIO2_CNTR_SC_DEV[id] | PIO2_CNTR_RW_BOTH | card->cntr[id].mode; + retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_CTRL[id]); + if (retval < 0) + return retval; + + data = card->cntr[id].count & 0xFF; + retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_DATA[id]); + if (retval < 0) + return retval; + + data = (card->cntr[id].count >> 8) & 0xFF; + retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_DATA[id]); + if (retval < 0) + return retval; + + return 0; +} + +int pio2_cntr_reset(struct pio2_card *card) +{ + int i, retval = 0; + u8 reg; + + /* Clear down all timers */ + for (i = 0; i < 6; i++) { + card->cntr[i].mode = PIO2_CNTR_MODE5; + card->cntr[i].count = 0; + retval = pio2_cntr_irq_set(card, i); + if (retval < 0) + return retval; + } + + /* Ensure all counter interrupts are cleared */ + do { + retval = vme_master_read(card->window, ®, 1, + PIO2_REGS_INT_STAT_CNTR); + if (retval < 0) + return retval; + } while (reg != 0); + + return retval; +} + diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c new file mode 100644 index 0000000..9fedc44 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -0,0 +1,524 @@ +/* + * GE PIO2 6U VME I/O Driver + * + * Author: Martyn Welch <martyn.welch@ge.com> + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/device.h> +#include <linux/ctype.h> +#include <linux/gpio.h> +#include <linux/slab.h> + +#include "../vme.h" +#include "vme_pio2.h" + + +static const char driver_name[] = "pio2"; + +static int bus[PIO2_CARDS_MAX]; +static int bus_num; +static long base[PIO2_CARDS_MAX]; +static int base_num; +static int vector[PIO2_CARDS_MAX]; +static int vector_num; +static int level[PIO2_CARDS_MAX]; +static int level_num; +static const char *variant[PIO2_CARDS_MAX]; +static int variant_num; + +static int loopback; + +static int pio2_match(struct vme_dev *); +static int __devinit pio2_probe(struct vme_dev *); +static int __devexit pio2_remove(struct vme_dev *); + +static int pio2_get_led(struct pio2_card *card) +{ + /* Can't read hardware, state saved in structure */ + return card->led; +} + +static int pio2_set_led(struct pio2_card *card, int state) +{ + u8 reg; + int retval; + + reg = card->irq_level; + + /* Register state inverse of led state */ + if (!state) + reg |= PIO2_LED; + + if (loopback) + reg |= PIO2_LOOP; + + retval = vme_master_write(card->window, ®, 1, PIO2_REGS_CTRL); + if (retval < 0) + return retval; + + card->led = state ? 1 : 0; + + return 0; +} + +static void pio2_int(int level, int vector, void *ptr) +{ + int vec, i, channel, retval; + u8 reg; + struct pio2_card *card = ptr; + + vec = vector & ~PIO2_VME_VECTOR_MASK; + + switch (vec) { + case 0: + dev_warn(&card->vdev->dev, "Spurious Interrupt\n"); + break; + case 1: + case 2: + case 3: + case 4: + /* Channels 0 to 7 */ + retval = vme_master_read(card->window, ®, 1, + PIO2_REGS_INT_STAT[vec - 1]); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to read IRQ status register\n"); + return; + } + for (i = 0; i < 8; i++) { + channel = ((vec - 1) * 8) + i; + if (reg & PIO2_CHANNEL_BIT[channel]) + dev_info(&card->vdev->dev, + "Interrupt on I/O channel %d\n", + channel); + } + break; + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + /* Counters are dealt with by their own handler */ + dev_err(&card->vdev->dev, + "Counter interrupt\n"); + break; + } +} + + +/* + * We return whether this has been successful - this is used in the probe to + * ensure we have a valid card. + */ +static int pio2_reset_card(struct pio2_card *card) +{ + int retval = 0; + u8 data = 0; + + /* Clear main register*/ + retval = vme_master_write(card->window, &data, 1, PIO2_REGS_CTRL); + if (retval < 0) + return retval; + + /* Clear VME vector */ + retval = vme_master_write(card->window, &data, 1, PIO2_REGS_VME_VECTOR); + if (retval < 0) + return retval; + + /* Reset GPIO */ + retval = pio2_gpio_reset(card); + if (retval < 0) + return retval; + + /* Reset counters */ + retval = pio2_cntr_reset(card); + if (retval < 0) + return retval; + + return 0; +} + +static struct vme_driver pio2_driver = { + .name = driver_name, + .match = pio2_match, + .probe = pio2_probe, + .remove = __devexit_p(pio2_remove), +}; + + +static int __init pio2_init(void) +{ + int retval = 0; + + if (bus_num == 0) { + printk(KERN_ERR "%s: No cards, skipping registration\n", + driver_name); + goto err_nocard; + } + + if (bus_num > PIO2_CARDS_MAX) { + printk(KERN_ERR + "%s: Driver only able to handle %d PIO2 Cards\n", + driver_name, PIO2_CARDS_MAX); + bus_num = PIO2_CARDS_MAX; + } + + /* Register the PIO2 driver */ + retval = vme_register_driver(&pio2_driver, bus_num); + if (retval != 0) + goto err_reg; + + return retval; + +err_reg: +err_nocard: + return retval; +} + +static int pio2_match(struct vme_dev *vdev) +{ + + if (vdev->num >= bus_num) { + dev_err(&vdev->dev, + "The enumeration of the VMEbus to which the board is connected must be specified"); + return 0; + } + + if (vdev->num >= base_num) { + dev_err(&vdev->dev, + "The VME address for the cards registers must be specified"); + return 0; + } + + if (vdev->num >= vector_num) { + dev_err(&vdev->dev, + "The IRQ vector used by the card must be specified"); + return 0; + } + + if (vdev->num >= level_num) { + dev_err(&vdev->dev, + "The IRQ level used by the card must be specified"); + return 0; + } + + if (vdev->num >= variant_num) { + dev_err(&vdev->dev, "The variant of the card must be specified"); + return 0; + } + + return 1; +} + +static int __devinit pio2_probe(struct vme_dev *vdev) +{ + struct pio2_card *card; + int retval; + int i; + u8 reg; + int vec; + + card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL); + if (card == NULL) { + dev_err(&vdev->dev, "Unable to allocate card structure\n"); + retval = -ENOMEM; + goto err_struct; + } + + card->id = vdev->num; + card->bus = bus[card->id]; + card->base = base[card->id]; + card->irq_vector = vector[card->id]; + card->irq_level = level[card->id] & PIO2_VME_INT_MASK; + strncpy(card->variant, variant[card->id], PIO2_VARIANT_LENGTH); + card->vdev = vdev; + + for (i = 0; i < PIO2_VARIANT_LENGTH; i++) { + + if (isdigit(card->variant[i]) == 0) { + dev_err(&card->vdev->dev, "Variant invalid\n"); + retval = -EINVAL; + goto err_variant; + } + } + + /* + * Bottom 4 bits of VME interrupt vector used to determine source, + * provided vector should only use upper 4 bits. + */ + if (card->irq_vector & ~PIO2_VME_VECTOR_MASK) { + dev_err(&card->vdev->dev, + "Invalid VME IRQ Vector, vector must not use lower 4 bits\n"); + retval = -EINVAL; + goto err_vector; + } + + /* + * There is no way to determine the build variant or whether each bank + * is input, output or both at run time. The inputs are also inverted + * if configured as both. + * + * We pass in the board variant and use that to determine the + * configuration of the banks. + */ + for (i = 1; i < PIO2_VARIANT_LENGTH; i++) { + switch (card->variant[i]) { + case '0': + card->bank[i-1].config = NOFIT; + break; + case '1': + case '2': + case '3': + case '4': + card->bank[i-1].config = INPUT; + break; + case '5': + card->bank[i-1].config = OUTPUT; + break; + case '6': + case '7': + case '8': + case '9': + card->bank[i-1].config = BOTH; + break; + } + } + + /* Get a master window and position over regs */ + card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16); + if (card->window == NULL) { + dev_err(&card->vdev->dev, + "Unable to assign VME master resource\n"); + retval = -EIO; + goto err_window; + } + + retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24, + (VME_SCT | VME_USER | VME_DATA), VME_D16); + if (retval) { + dev_err(&card->vdev->dev, + "Unable to configure VME master resource\n"); + goto err_set; + } + + /* + * There is also no obvious register which we can probe to determine + * whether the provided base is valid. If we can read the "ID Register" + * offset and the reset function doesn't error, assume we have a valid + * location. + */ + retval = vme_master_read(card->window, ®, 1, PIO2_REGS_ID); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to read from device\n"); + goto err_read; + } + + dev_dbg(&card->vdev->dev, "ID Register:%x\n", reg); + + /* + * Ensure all the I/O is cleared. We can't read back the states, so + * this is the only method we have to ensure that the I/O is in a known + * state. + */ + retval = pio2_reset_card(card); + if (retval) { + dev_err(&card->vdev->dev, + "Failed to reset card, is location valid?"); + retval = -ENODEV; + goto err_reset; + } + + /* Configure VME Interrupts */ + reg = card->irq_level; + if (pio2_get_led(card)) + reg |= PIO2_LED; + if (loopback) + reg |= PIO2_LOOP; + retval = vme_master_write(card->window, ®, 1, PIO2_REGS_CTRL); + if (retval < 0) + return retval; + + /* Set VME vector */ + retval = vme_master_write(card->window, &card->irq_vector, 1, + PIO2_REGS_VME_VECTOR); + if (retval < 0) + return retval; + + /* Attach spurious interrupt handler. */ + vec = card->irq_vector | PIO2_VME_VECTOR_SPUR; + + retval = vme_irq_request(vdev, card->irq_level, vec, + &pio2_int, (void *)card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to attach VME interrupt vector0x%x, level 0x%x\n", + vec, card->irq_level); + goto err_irq; + } + + /* Attach GPIO interrupt handlers. */ + for (i = 0; i < 4; i++) { + vec = card->irq_vector | PIO2_VECTOR_BANK[i]; + + retval = vme_irq_request(vdev, card->irq_level, vec, + &pio2_int, (void *)card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to attach VME interrupt vector0x%x, level 0x%x\n", + vec, card->irq_level); + goto err_gpio_irq; + } + } + + /* Attach counter interrupt handlers. */ + for (i = 0; i < 6; i++) { + vec = card->irq_vector | PIO2_VECTOR_CNTR[i]; + + retval = vme_irq_request(vdev, card->irq_level, vec, + &pio2_int, (void *)card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to attach VME interrupt vector0x%x, level 0x%x\n", + vec, card->irq_level); + goto err_cntr_irq; + } + } + + /* Register IO */ + retval = pio2_gpio_init(card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to register with GPIO framework\n"); + goto err_gpio; + } + + /* Set LED - This also sets interrupt level */ + retval = pio2_set_led(card, 0); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to set LED\n"); + goto err_led; + } + + dev_set_drvdata(&card->vdev->dev, card); + + dev_info(&card->vdev->dev, + "PIO2 (variant %s) configured at 0x%lx\n", card->variant, + card->base); + + return 0; + +err_led: + pio2_gpio_exit(card); +err_gpio: + i = 6; +err_cntr_irq: + while (i > 0) { + i--; + vec = card->irq_vector | PIO2_VECTOR_CNTR[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + i = 4; +err_gpio_irq: + while (i > 0) { + i--; + vec = card->irq_vector | PIO2_VECTOR_BANK[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR; + vme_irq_free(vdev, card->irq_level, vec); +err_irq: + pio2_reset_card(card); +err_reset: +err_read: + vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16); +err_set: + vme_master_free(card->window); +err_window: +err_vector: +err_variant: + kfree(card); +err_struct: + return retval; +} + +static int __devexit pio2_remove(struct vme_dev *vdev) +{ + int vec; + int i; + + struct pio2_card *card = dev_get_drvdata(&vdev->dev); + + pio2_gpio_exit(card); + + for (i = 0; i < 6; i++) { + vec = card->irq_vector | PIO2_VECTOR_CNTR[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + for (i = 0; i < 4; i++) { + vec = card->irq_vector | PIO2_VECTOR_BANK[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR; + vme_irq_free(vdev, card->irq_level, vec); + + pio2_reset_card(card); + + vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16); + + vme_master_free(card->window); + + kfree(card); + + return 0; +} + +static void __exit pio2_exit(void) +{ + vme_unregister_driver(&pio2_driver); +} + + +/* These are required for each board */ +MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected"); +module_param_array(bus, int, &bus_num, S_IRUGO); + +MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers"); +module_param_array(base, long, &base_num, S_IRUGO); + +MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)"); +module_param_array(vector, int, &vector_num, S_IRUGO); + +MODULE_PARM_DESC(level, "VME IRQ Level"); +module_param_array(level, int, &level_num, S_IRUGO); + +MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant"); +module_param_array(variant, charp, &variant_num, S_IRUGO); + +/* This is for debugging */ +MODULE_PARM_DESC(loopback, "Enable loopback mode on all cards"); +module_param(loopback, bool, S_IRUGO); + +MODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver"); +MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); +MODULE_LICENSE("GPL"); + +module_init(pio2_init); +module_exit(pio2_exit); + diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c new file mode 100644 index 0000000..dc837de --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -0,0 +1,232 @@ +/* + * GE PIO2 GPIO Driver + * + * Author: Martyn Welch <martyn.welch@ge.com> + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/ctype.h> +#include <linux/gpio.h> +#include <linux/slab.h> + +#include "../vme.h" +#include "vme_pio2.h" + +static const char driver_name[] = "pio2_gpio"; + +static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip) +{ + return container_of(chip, struct pio2_card, gc); +} + +static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + u8 reg; + int retval; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + + dev_err(&card->vdev->dev, "Channel not available as input\n"); + return 0; + } + + retval = vme_master_read(card->window, ®, 1, + PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to read from GPIO\n"); + return 0; + } + + /* + * Remember, input on channels configured as both input and output + * are inverted! + */ + if (reg & PIO2_CHANNEL_BIT[offset]) { + if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH) + return 0; + else + return 1; + } else { + if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH) + return 1; + else + return 0; + } +} + +static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + u8 reg; + int retval; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + + dev_err(&card->vdev->dev, "Channel not availabe as output\n"); + return; + } + + if (value) + reg = card->bank[PIO2_CHANNEL_BANK[offset]].value | + PIO2_CHANNEL_BIT[offset]; + else + reg = card->bank[PIO2_CHANNEL_BANK[offset]].value & + ~PIO2_CHANNEL_BIT[offset]; + + retval = vme_master_write(card->window, ®, 1, + PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to write to GPIO\n"); + return; + } + + card->bank[PIO2_CHANNEL_BANK[offset]].value = reg; +} + +/* Directionality configured at board build - send appropriate response */ +static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) +{ + int data; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + dev_err(&card->vdev->dev, + "Channel directionality not configurable at runtine\n"); + + data = -EINVAL; + } else { + data = 0; + } + + return data; +} + +/* Directionality configured at board build - send appropriate response */ +static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) +{ + int data; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + dev_err(&card->vdev->dev, + "Channel directionality not configurable at runtine\n"); + + data = -EINVAL; + } else { + data = 0; + } + + return data; +} + +/* + * We return whether this has been successful - this is used in the probe to + * ensure we have a valid card. + */ +int pio2_gpio_reset(struct pio2_card *card) +{ + int retval = 0; + int i, j; + + u8 data = 0; + + /* Zero output registers */ + for (i = 0; i < 4; i++) { + retval = vme_master_write(card->window, &data, 1, + PIO2_REGS_DATA[i]); + if (retval < 0) + return retval; + card->bank[i].value = 0; + } + + /* Set input interrupt masks */ + for (i = 0; i < 4; i++) { + retval = vme_master_write(card->window, &data, 1, + PIO2_REGS_INT_MASK[i * 2]); + if (retval < 0) + return retval; + + retval = vme_master_write(card->window, &data, 1, + PIO2_REGS_INT_MASK[(i * 2) + 1]); + if (retval < 0) + return retval; + + for (j = 0; j < 8; j++) + card->bank[i].irq[j] = NONE; + } + + /* Ensure all I/O interrupts are cleared */ + for (i = 0; i < 4; i++) { + do { + retval = vme_master_read(card->window, &data, 1, + PIO2_REGS_INT_STAT[i]); + if (retval < 0) + return retval; + } while (data != 0); + } + + return 0; +} + +int __init pio2_gpio_init(struct pio2_card *card) +{ + int retval = 0; + char *label; + + label = kmalloc(PIO2_NUM_CHANNELS, GFP_KERNEL); + if (label == NULL) { + dev_err(&card->vdev->dev, "Unable to allocate GPIO label\n"); + return -ENOMEM; + } + + sprintf(label, "%s@%s", driver_name, dev_name(&card->vdev->dev)); + card->gc.label = label; + + card->gc.ngpio = PIO2_NUM_CHANNELS; + /* Dynamic allocation of base */ + card->gc.base = -1; + /* Setup pointers to chip functions */ + card->gc.direction_input = pio2_gpio_dir_in; + card->gc.direction_output = pio2_gpio_dir_out; + card->gc.get = pio2_gpio_get; + card->gc.set = pio2_gpio_set; + + /* This function adds a memory mapped GPIO chip */ + retval = gpiochip_add(&(card->gc)); + if (retval) { + dev_err(&card->vdev->dev, "Unable to register GPIO\n"); + kfree(card->gc.label); + } + + return retval; +}; + +void __exit pio2_gpio_exit(struct pio2_card *card) +{ + const char *label = card->gc.label; + + if (gpiochip_remove(&(card->gc))) + dev_err(&card->vdev->dev, "Failed to remove GPIO"); + + kfree(label); +} + diff --git a/drivers/staging/vme/devices/vme_user.h b/drivers/staging/vme/devices/vme_user.h index d85a1e9..7d24cd6 100644 --- a/drivers/staging/vme/devices/vme_user.h +++ b/drivers/staging/vme/devices/vme_user.h @@ -10,9 +10,9 @@ struct vme_master { int enable; /* State of Window */ unsigned long long vme_addr; /* Starting Address on the VMEbus */ unsigned long long size; /* Window Size */ - vme_address_t aspace; /* Address Space */ - vme_cycle_t cycle; /* Cycle properties */ - vme_width_t dwidth; /* Maximum Data Width */ + u32 aspace; /* Address Space */ + u32 cycle; /* Cycle properties */ + u32 dwidth; /* Maximum Data Width */ #if 0 char prefetchEnable; /* Prefetch Read Enable State */ int prefetchSize; /* Prefetch Read Size (Cache Lines) */ @@ -34,8 +34,8 @@ struct vme_slave { int enable; /* State of Window */ unsigned long long vme_addr; /* Starting Address on the VMEbus */ unsigned long long size; /* Window Size */ - vme_address_t aspace; /* Address Space */ - vme_cycle_t cycle; /* Cycle properties */ + u32 aspace; /* Address Space */ + u32 cycle; /* Cycle properties */ #if 0 char wrPostEnable; /* Write Post State */ char rmwLock; /* Lock PCI during RMW Cycles */ diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c index b04b468..70722ae 100644 --- a/drivers/staging/vme/vme.c +++ b/drivers/staging/vme/vme.c @@ -153,9 +153,7 @@ size_t vme_get_size(struct vme_resource *resource) int enabled, retval; unsigned long long base, size; dma_addr_t buf_base; - vme_address_t aspace; - vme_cycle_t cycle; - vme_width_t dwidth; + u32 aspace, cycle, dwidth; switch (resource->type) { case VME_MASTER: @@ -181,7 +179,7 @@ size_t vme_get_size(struct vme_resource *resource) } EXPORT_SYMBOL(vme_get_size); -static int vme_check_window(vme_address_t aspace, unsigned long long vme_base, +static int vme_check_window(u32 aspace, unsigned long long vme_base, unsigned long long size) { int retval = 0; @@ -232,8 +230,8 @@ static int vme_check_window(vme_address_t aspace, unsigned long long vme_base, * Request a slave image with specific attributes, return some unique * identifier. */ -struct vme_resource *vme_slave_request(struct vme_dev *vdev, - vme_address_t address, vme_cycle_t cycle) +struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, + u32 cycle) { struct vme_bridge *bridge; struct list_head *slave_pos = NULL; @@ -298,7 +296,7 @@ EXPORT_SYMBOL(vme_slave_request); int vme_slave_set(struct vme_resource *resource, int enabled, unsigned long long vme_base, unsigned long long size, - dma_addr_t buf_base, vme_address_t aspace, vme_cycle_t cycle) + dma_addr_t buf_base, u32 aspace, u32 cycle) { struct vme_bridge *bridge = find_bridge(resource); struct vme_slave_resource *image; @@ -333,7 +331,7 @@ EXPORT_SYMBOL(vme_slave_set); int vme_slave_get(struct vme_resource *resource, int *enabled, unsigned long long *vme_base, unsigned long long *size, - dma_addr_t *buf_base, vme_address_t *aspace, vme_cycle_t *cycle) + dma_addr_t *buf_base, u32 *aspace, u32 *cycle) { struct vme_bridge *bridge = find_bridge(resource); struct vme_slave_resource *image; @@ -388,8 +386,8 @@ EXPORT_SYMBOL(vme_slave_free); * Request a master image with specific attributes, return some unique * identifier. */ -struct vme_resource *vme_master_request(struct vme_dev *vdev, - vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth) +struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, + u32 cycle, u32 dwidth) { struct vme_bridge *bridge; struct list_head *master_pos = NULL; @@ -456,8 +454,8 @@ err_bus: EXPORT_SYMBOL(vme_master_request); int vme_master_set(struct vme_resource *resource, int enabled, - unsigned long long vme_base, unsigned long long size, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) + unsigned long long vme_base, unsigned long long size, u32 aspace, + u32 cycle, u32 dwidth) { struct vme_bridge *bridge = find_bridge(resource); struct vme_master_resource *image; @@ -492,8 +490,8 @@ int vme_master_set(struct vme_resource *resource, int enabled, EXPORT_SYMBOL(vme_master_set); int vme_master_get(struct vme_resource *resource, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) { struct vme_bridge *bridge = find_bridge(resource); struct vme_master_resource *image; @@ -646,8 +644,7 @@ EXPORT_SYMBOL(vme_master_free); * Request a DMA controller with specific attributes, return some unique * identifier. */ -struct vme_resource *vme_dma_request(struct vme_dev *vdev, - vme_dma_route_t route) +struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) { struct vme_bridge *bridge; struct list_head *dma_pos = NULL; @@ -743,8 +740,7 @@ EXPORT_SYMBOL(vme_new_dma_list); /* * Create "Pattern" type attributes */ -struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, - vme_pattern_t type) +struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type) { struct vme_dma_attr *attributes; struct vme_dma_pattern *pattern_attr; @@ -822,7 +818,7 @@ EXPORT_SYMBOL(vme_dma_pci_attribute); * Create "VME" type attributes */ struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) + u32 aspace, u32 cycle, u32 dwidth) { struct vme_dma_attr *attributes; struct vme_dma_vme *vme_attr; @@ -1173,7 +1169,7 @@ int vme_lm_count(struct vme_resource *resource) EXPORT_SYMBOL(vme_lm_count); int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, - vme_address_t aspace, vme_cycle_t cycle) + u32 aspace, u32 cycle) { struct vme_bridge *bridge = find_bridge(resource); struct vme_lm_resource *lm; @@ -1195,7 +1191,7 @@ int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, EXPORT_SYMBOL(vme_lm_set); int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base, - vme_address_t *aspace, vme_cycle_t *cycle) + u32 *aspace, u32 *cycle) { struct vme_bridge *bridge = find_bridge(resource); struct vme_lm_resource *lm; @@ -1307,7 +1303,12 @@ EXPORT_SYMBOL(vme_slot_get); /* - Bridge Registration --------------------------------------------------- */ -static int vme_add_bus(struct vme_bridge *bridge) +static void vme_dev_release(struct device *dev) +{ + kfree(dev_to_vme_dev(dev)); +} + +int vme_register_bridge(struct vme_bridge *bridge) { int i; int ret = -1; @@ -1327,8 +1328,9 @@ static int vme_add_bus(struct vme_bridge *bridge) return ret; } +EXPORT_SYMBOL(vme_register_bridge); -static void vme_remove_bus(struct vme_bridge *bridge) +void vme_unregister_bridge(struct vme_bridge *bridge) { struct vme_dev *vdev; struct vme_dev *tmp; @@ -1343,22 +1345,6 @@ static void vme_remove_bus(struct vme_bridge *bridge) list_del(&bridge->bus_list); mutex_unlock(&vme_buses_lock); } - -static void vme_dev_release(struct device *dev) -{ - kfree(dev_to_vme_dev(dev)); -} - -int vme_register_bridge(struct vme_bridge *bridge) -{ - return vme_add_bus(bridge); -} -EXPORT_SYMBOL(vme_register_bridge); - -void vme_unregister_bridge(struct vme_bridge *bridge) -{ - vme_remove_bus(bridge); -} EXPORT_SYMBOL(vme_unregister_bridge); /* - Driver Registration --------------------------------------------------- */ @@ -1421,10 +1407,7 @@ static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs) * and if the bridge is removed, it will have to go through * vme_unregister_bridge() to do it (which calls remove() on * the bridge which in turn tries to acquire vme_buses_lock and - * will have to wait). The probe() called after device - * registration in __vme_register_driver below will also fail - * as the bridge is being removed (since the probe() calls - * vme_bridge_get()). + * will have to wait). */ err = __vme_register_driver_bus(drv, bridge, ndevs); if (err) diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h index e3828ba..9d38cee 100644 --- a/drivers/staging/vme/vme.h +++ b/drivers/staging/vme/vme.h @@ -10,7 +10,6 @@ enum vme_resource_type { }; /* VME Address Spaces */ -typedef u32 vme_address_t; #define VME_A16 0x1 #define VME_A24 0x2 #define VME_A32 0x4 @@ -29,7 +28,6 @@ typedef u32 vme_address_t; /* VME Cycle Types */ -typedef u32 vme_cycle_t; #define VME_SCT 0x1 #define VME_BLT 0x2 #define VME_MBLT 0x4 @@ -47,28 +45,23 @@ typedef u32 vme_cycle_t; #define VME_DATA 0x8000 /* VME Data Widths */ -typedef u32 vme_width_t; #define VME_D8 0x1 #define VME_D16 0x2 #define VME_D32 0x4 #define VME_D64 0x8 /* Arbitration Scheduling Modes */ -typedef u32 vme_arbitration_t; #define VME_R_ROBIN_MODE 0x1 #define VME_PRIORITY_MODE 0x2 -typedef u32 vme_dma_t; #define VME_DMA_PATTERN (1<<0) #define VME_DMA_PCI (1<<1) #define VME_DMA_VME (1<<2) -typedef u32 vme_pattern_t; #define VME_DMA_PATTERN_BYTE (1<<0) #define VME_DMA_PATTERN_WORD (1<<1) #define VME_DMA_PATTERN_INCREMENT (1<<2) -typedef u32 vme_dma_route_t; #define VME_DMA_VME_TO_MEM (1<<0) #define VME_DMA_MEM_TO_VME (1<<1) #define VME_DMA_VME_TO_VME (1<<2) @@ -77,7 +70,7 @@ typedef u32 vme_dma_route_t; #define VME_DMA_PATTERN_TO_MEM (1<<5) struct vme_dma_attr { - vme_dma_t type; + u32 type; void *private; }; @@ -97,7 +90,7 @@ extern struct bus_type vme_bus_type; /** * Structure representing a VME device - * @id: The ID of the device (currently the bus and slot number) + * @num: The device number * @bridge: Pointer to the bridge device this device is on * @dev: Internal device structure * @drv_list: List of devices (per driver) @@ -128,32 +121,29 @@ void vme_free_consistent(struct vme_resource *, size_t, void *, size_t vme_get_size(struct vme_resource *); -struct vme_resource *vme_slave_request(struct vme_dev *, vme_address_t, - vme_cycle_t); +struct vme_resource *vme_slave_request(struct vme_dev *, u32, u32); int vme_slave_set(struct vme_resource *, int, unsigned long long, - unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t); + unsigned long long, dma_addr_t, u32, u32); int vme_slave_get(struct vme_resource *, int *, unsigned long long *, - unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *); + unsigned long long *, dma_addr_t *, u32 *, u32 *); void vme_slave_free(struct vme_resource *); -struct vme_resource *vme_master_request(struct vme_dev *, vme_address_t, - vme_cycle_t, vme_width_t); +struct vme_resource *vme_master_request(struct vme_dev *, u32, u32, u32); int vme_master_set(struct vme_resource *, int, unsigned long long, - unsigned long long, vme_address_t, vme_cycle_t, vme_width_t); + unsigned long long, u32, u32, u32); int vme_master_get(struct vme_resource *, int *, unsigned long long *, - unsigned long long *, vme_address_t *, vme_cycle_t *, vme_width_t *); + unsigned long long *, u32 *, u32 *, u32 *); ssize_t vme_master_read(struct vme_resource *, void *, size_t, loff_t); ssize_t vme_master_write(struct vme_resource *, void *, size_t, loff_t); unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int, unsigned int, loff_t); void vme_master_free(struct vme_resource *); -struct vme_resource *vme_dma_request(struct vme_dev *, vme_dma_route_t); +struct vme_resource *vme_dma_request(struct vme_dev *, u32); struct vme_dma_list *vme_new_dma_list(struct vme_resource *); -struct vme_dma_attr *vme_dma_pattern_attribute(u32, vme_pattern_t); +struct vme_dma_attr *vme_dma_pattern_attribute(u32, u32); struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t); -struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long, vme_address_t, - vme_cycle_t, vme_width_t); +struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long, u32, u32, u32); void vme_dma_free_attribute(struct vme_dma_attr *); int vme_dma_list_add(struct vme_dma_list *, struct vme_dma_attr *, struct vme_dma_attr *, size_t); @@ -168,10 +158,8 @@ int vme_irq_generate(struct vme_dev *, int, int); struct vme_resource * vme_lm_request(struct vme_dev *); int vme_lm_count(struct vme_resource *); -int vme_lm_set(struct vme_resource *, unsigned long long, vme_address_t, - vme_cycle_t); -int vme_lm_get(struct vme_resource *, unsigned long long *, vme_address_t *, - vme_cycle_t *); +int vme_lm_set(struct vme_resource *, unsigned long long, u32, u32); +int vme_lm_get(struct vme_resource *, unsigned long long *, u32 *, u32 *); int vme_lm_attach(struct vme_resource *, int, void (*callback)(int)); int vme_lm_detach(struct vme_resource *, int); void vme_lm_free(struct vme_resource *); diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt index e8ff215..856efa3 100644 --- a/drivers/staging/vme/vme_api.txt +++ b/drivers/staging/vme/vme_api.txt @@ -86,26 +86,26 @@ driver allows a resource to be assigned based on the required attributes of the driver in question: struct vme_resource * vme_master_request(struct vme_dev *dev, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t width); - - struct vme_resource * vme_slave_request(struct vme_dev *dev, - vme_address_t aspace, vme_cycle_t cycle); - - struct vme_resource *vme_dma_request(struct vme_dev *dev, - vme_dma_route_t route); - -For slave windows these attributes are split into those of type 'vme_address_t' -and 'vme_cycle_t'. Master windows add a further set of attributes -'vme_cycle_t'. These attributes are defined as bitmasks and as such any -combination of the attributes can be requested for a single window, the core -will assign a window that meets the requirements, returning a pointer of type -vme_resource that should be used to identify the allocated resource when it is -used. For DMA controllers, the request function requires the potential -direction of any transfers to be provided in the route attributes. This is -typically VME-to-MEM and/or MEM-to-VME, though some hardware can support -VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. If an -unallocated window fitting the requirements can not be found a NULL pointer -will be returned. + u32 aspace, u32 cycle, u32 width); + + struct vme_resource * vme_slave_request(struct vme_dev *dev, u32 aspace, + u32 cycle); + + struct vme_resource *vme_dma_request(struct vme_dev *dev, u32 route); + +For slave windows these attributes are split into the VME address spaces that +need to be accessed in 'aspace' and VME bus cycle types required in 'cycle'. +Master windows add a further set of attributes in 'width' specifying the +required data transfer widths. These attributes are defined as bitmasks and as +such any combination of the attributes can be requested for a single window, +the core will assign a window that meets the requirements, returning a pointer +of type vme_resource that should be used to identify the allocated resource +when it is used. For DMA controllers, the request function requires the +potential direction of any transfers to be provided in the route attributes. +This is typically VME-to-MEM and/or MEM-to-VME, though some hardware can +support VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. +If an unallocated window fitting the requirements can not be found a NULL +pointer will be returned. Functions are also provided to free window allocations once they are no longer required. These functions should be passed the pointer to the resource provided @@ -133,12 +133,12 @@ Once a master window has been assigned the following functions can be used to configure it and retrieve the current settings: int vme_master_set (struct vme_resource *res, int enabled, - unsigned long long base, unsigned long long size, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t width); + unsigned long long base, unsigned long long size, u32 aspace, + u32 cycle, u32 width); int vme_master_get (struct vme_resource *res, int *enabled, - unsigned long long *base, unsigned long long *size, - vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *width); + unsigned long long *base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *width); The address spaces, transfer widths and cycle types are the same as described under resource management, however some of the options are mutually exclusive. @@ -189,11 +189,11 @@ configure it and retrieve the current settings: int vme_slave_set (struct vme_resource *res, int enabled, unsigned long long base, unsigned long long size, - dma_addr_t mem, vme_address_t aspace, vme_cycle_t cycle); + dma_addr_t mem, u32 aspace, u32 cycle); int vme_slave_get (struct vme_resource *res, int *enabled, unsigned long long *base, unsigned long long *size, - dma_addr_t *mem, vme_address_t *aspace, vme_cycle_t *cycle); + dma_addr_t *mem, u32 *aspace, u32 *cycle); The address spaces, transfer widths and cycle types are the same as described under resource management, however some of the options are mutually exclusive. @@ -273,8 +273,7 @@ and pattern sources and destinations (where appropriate): Pattern source: - struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, - vme_pattern_t type); + struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type); PCI source or destination: @@ -283,7 +282,7 @@ PCI source or destination: VME source or destination: struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base, - vme_address_t aspace, vme_cycle_t cycle, vme_width_t width); + u32 aspace, u32 cycle, u32 width); The following function should be used to free an attribute: @@ -366,10 +365,10 @@ Once a bank of location monitors has been allocated, the following functions are provided to configure the location and mode of the location monitor: int vme_lm_set(struct vme_resource *res, unsigned long long base, - vme_address_t aspace, vme_cycle_t cycle); + u32 aspace, u32 cycle); int vme_lm_get(struct vme_resource *res, unsigned long long *base, - vme_address_t *aspace, vme_cycle_t *cycle); + u32 *aspace, u32 *cycle); Location Monitor Use diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h index c2deda2..934949a 100644 --- a/drivers/staging/vme/vme_bridge.h +++ b/drivers/staging/vme/vme_bridge.h @@ -15,9 +15,9 @@ struct vme_master_resource { spinlock_t lock; int locked; int number; - vme_address_t address_attr; - vme_cycle_t cycle_attr; - vme_width_t width_attr; + u32 address_attr; + u32 cycle_attr; + u32 width_attr; struct resource bus_resource; void __iomem *kern_base; }; @@ -28,13 +28,13 @@ struct vme_slave_resource { struct mutex mtx; int locked; int number; - vme_address_t address_attr; - vme_cycle_t cycle_attr; + u32 address_attr; + u32 cycle_attr; }; struct vme_dma_pattern { u32 pattern; - vme_pattern_t type; + u32 type; }; struct vme_dma_pci { @@ -43,9 +43,9 @@ struct vme_dma_pci { struct vme_dma_vme { unsigned long long address; - vme_address_t aspace; - vme_cycle_t cycle; - vme_width_t dwidth; + u32 aspace; + u32 cycle; + u32 dwidth; }; struct vme_dma_list { @@ -63,7 +63,7 @@ struct vme_dma_resource { int number; struct list_head pending; struct list_head running; - vme_dma_route_t route_attr; + u32 route_attr; }; struct vme_lm_resource { @@ -122,17 +122,16 @@ struct vme_bridge { /* Slave Functions */ int (*slave_get) (struct vme_slave_resource *, int *, unsigned long long *, unsigned long long *, dma_addr_t *, - vme_address_t *, vme_cycle_t *); + u32 *, u32 *); int (*slave_set) (struct vme_slave_resource *, int, unsigned long long, - unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t); + unsigned long long, dma_addr_t, u32, u32); /* Master Functions */ int (*master_get) (struct vme_master_resource *, int *, - unsigned long long *, unsigned long long *, vme_address_t *, - vme_cycle_t *, vme_width_t *); + unsigned long long *, unsigned long long *, u32 *, u32 *, + u32 *); int (*master_set) (struct vme_master_resource *, int, - unsigned long long, unsigned long long, vme_address_t, - vme_cycle_t, vme_width_t); + unsigned long long, unsigned long long, u32, u32, u32); ssize_t (*master_read) (struct vme_master_resource *, void *, size_t, loff_t); ssize_t (*master_write) (struct vme_master_resource *, void *, size_t, @@ -151,10 +150,9 @@ struct vme_bridge { int (*irq_generate) (struct vme_bridge *, int, int); /* Location monitor functions */ - int (*lm_set) (struct vme_lm_resource *, unsigned long long, - vme_address_t, vme_cycle_t); - int (*lm_get) (struct vme_lm_resource *, unsigned long long *, - vme_address_t *, vme_cycle_t *); + int (*lm_set) (struct vme_lm_resource *, unsigned long long, u32, u32); + int (*lm_get) (struct vme_lm_resource *, unsigned long long *, u32 *, + u32 *); int (*lm_attach) (struct vme_lm_resource *, int, void (*callback)(int)); int (*lm_detach) (struct vme_lm_resource *, int); |