diff options
Diffstat (limited to 'drivers/staging/vme')
25 files changed, 1285 insertions, 9294 deletions
diff --git a/drivers/staging/vme/Kconfig b/drivers/staging/vme/Kconfig deleted file mode 100644 index 6411ae51ed3..00000000000 --- a/drivers/staging/vme/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# -# VME configuration. -# - -menuconfig VME_BUS -	tristate "VME bridge support" -	depends on PCI -	---help--- -	  If you say Y here you get support for the VME bridge Framework. - -if VME_BUS - -source "drivers/staging/vme/bridges/Kconfig" - -source "drivers/staging/vme/devices/Kconfig" - -source "drivers/staging/vme/boards/Kconfig" - -endif # VME diff --git a/drivers/staging/vme/Makefile b/drivers/staging/vme/Makefile index b4ea3f8d0a5..accdb72e39e 100644 --- a/drivers/staging/vme/Makefile +++ b/drivers/staging/vme/Makefile @@ -1,8 +1 @@ -# -# Makefile for the VME bridge device drivers. -# -obj-$(CONFIG_VME_BUS)		+= vme.o - -obj-y				+= bridges/  obj-y				+= devices/ -obj-y				+= boards/ diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO deleted file mode 100644 index 82c222b4a14..00000000000 --- a/drivers/staging/vme/TODO +++ /dev/null @@ -1,70 +0,0 @@ -				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. - diff --git a/drivers/staging/vme/boards/Kconfig b/drivers/staging/vme/boards/Kconfig deleted file mode 100644 index 76163135352..00000000000 --- a/drivers/staging/vme/boards/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -comment "VME Board Drivers" - -config VMIVME_7805 -	tristate "VMIVME-7805" -	help -	  If you say Y here you get support for the VMIVME-7805 board. -	  This board has an additional control interface to the Universe II -	  chip. This driver has to be included if you want to access VME bus -	  with VMIVME-7805 board. diff --git a/drivers/staging/vme/boards/Makefile b/drivers/staging/vme/boards/Makefile deleted file mode 100644 index 43658340885..00000000000 --- a/drivers/staging/vme/boards/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the VME board drivers. -# - -obj-$(CONFIG_VMIVME_7805)	+= vme_vmivme7805.o diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/staging/vme/boards/vme_vmivme7805.c deleted file mode 100644 index 80eaa0c4fe1..00000000000 --- a/drivers/staging/vme/boards/vme_vmivme7805.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Support for the VMIVME-7805 board access to the Universe II bridge. - * - * Author: Arthur Benilov <arthur.benilov@iba-group.com> - * Copyright 2010 Ion Beam Application, 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/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/poll.h> -#include <linux/io.h> - -#include "vme_vmivme7805.h" - -static int __init vmic_init(void); -static int vmic_probe(struct pci_dev *, const struct pci_device_id *); -static void vmic_remove(struct pci_dev *); -static void __exit vmic_exit(void); - -/** Base address to access FPGA register */ -static void *vmic_base; - -static char driver_name[] = "vmivme_7805"; - -static struct pci_device_id vmic_ids[] = { -	{ PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) }, -	{ }, -}; - -static struct pci_driver vmic_driver = { -	.name = driver_name, -	.id_table = vmic_ids, -	.probe = vmic_probe, -	.remove = vmic_remove, -}; - -static int __init vmic_init(void) -{ -	return pci_register_driver(&vmic_driver); -} - -static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ -	int retval; -	u32 data; - -	/* Enable the device */ -	retval = pci_enable_device(pdev); -	if (retval) { -		dev_err(&pdev->dev, "Unable to enable device\n"); -		goto err; -	} - -	/* Map Registers */ -	retval = pci_request_regions(pdev, driver_name); -	if (retval) { -		dev_err(&pdev->dev, "Unable to reserve resources\n"); -		goto err_resource; -	} - -	/* Map registers in BAR 0 */ -	vmic_base = ioremap_nocache(pci_resource_start(pdev, 0), 16); -	if (!vmic_base) { -		dev_err(&pdev->dev, "Unable to remap CRG region\n"); -		retval = -EIO; -		goto err_remap; -	} - -	/* Clear the FPGA VME IF contents */ -	iowrite32(0, vmic_base + VME_CONTROL); - -	/* Clear any initial BERR  */ -	data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF; -	data |= BM_VME_CONTROL_BERRST; -	iowrite32(data, vmic_base + VME_CONTROL); - -	/* Enable the vme interface and byte swapping */ -	data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF; -	data = data | BM_VME_CONTROL_MASTER_ENDIAN | -			BM_VME_CONTROL_SLAVE_ENDIAN | -			BM_VME_CONTROL_ABLE | -			BM_VME_CONTROL_BERRI | -			BM_VME_CONTROL_BPENA | -			BM_VME_CONTROL_VBENA; -	iowrite32(data, vmic_base + VME_CONTROL); - -	return 0; - -err_remap: -	pci_release_regions(pdev); -err_resource: -	pci_disable_device(pdev); -err: -	return retval; -} - -static void vmic_remove(struct pci_dev *pdev) -{ -	iounmap(vmic_base); -	pci_release_regions(pdev); -	pci_disable_device(pdev); - -} - -static void __exit vmic_exit(void) -{ -	pci_unregister_driver(&vmic_driver); -} - -MODULE_DESCRIPTION("VMIVME-7805 board support driver"); -MODULE_AUTHOR("Arthur Benilov <arthur.benilov@iba-group.com>"); -MODULE_LICENSE("GPL"); - -module_init(vmic_init); -module_exit(vmic_exit); - diff --git a/drivers/staging/vme/boards/vme_vmivme7805.h b/drivers/staging/vme/boards/vme_vmivme7805.h deleted file mode 100644 index 44c2c449808..00000000000 --- a/drivers/staging/vme/boards/vme_vmivme7805.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * vmivme_7805.h - * - * Support for the VMIVME-7805 board access to the Universe II bridge. - * - * Author: Arthur Benilov <arthur.benilov@iba-group.com> - * Copyright 2010 Ion Beam Application, 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. - */ - - -#ifndef _VMIVME_7805_H -#define _VMIVME_7805_H - -#ifndef PCI_VENDOR_ID_VMIC -#define PCI_VENDOR_ID_VMIC		0x114A -#endif - -#ifndef PCI_DEVICE_ID_VTIMR -#define PCI_DEVICE_ID_VTIMR		0x0004 -#endif - -#define VME_CONTROL			0x0000 -#define BM_VME_CONTROL_MASTER_ENDIAN	0x0001 -#define BM_VME_CONTROL_SLAVE_ENDIAN	0x0002 -#define BM_VME_CONTROL_ABLE		0x0004 -#define BM_VME_CONTROL_BERRI		0x0040 -#define BM_VME_CONTROL_BERRST		0x0080 -#define BM_VME_CONTROL_BPENA		0x0400 -#define BM_VME_CONTROL_VBENA		0x0800 - -#endif /* _VMIVME_7805_H */ - diff --git a/drivers/staging/vme/bridges/Kconfig b/drivers/staging/vme/bridges/Kconfig deleted file mode 100644 index 9331064e047..00000000000 --- a/drivers/staging/vme/bridges/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -comment "VME Bridge Drivers" - -config VME_CA91CX42 -	tristate "Universe II" -	depends on VIRT_TO_BUS -	help -	 If you say Y here you get support for the Tundra CA91C142 -	 (Universe II) VME bridge chip. - -config VME_TSI148 -	tristate "Tempe" -	depends on VIRT_TO_BUS -	help -	 If you say Y here you get support for the Tundra TSI148 VME bridge -	 chip. diff --git a/drivers/staging/vme/bridges/Makefile b/drivers/staging/vme/bridges/Makefile deleted file mode 100644 index 59638afcd50..00000000000 --- a/drivers/staging/vme/bridges/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_VME_CA91CX42)	+= vme_ca91cx42.o -obj-$(CONFIG_VME_TSI148)	+= vme_tsi148.o diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c deleted file mode 100644 index 4d745623211..00000000000 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ /dev/null @@ -1,1924 +0,0 @@ -/* - * Support for the Tundra Universe I/II VME-PCI Bridge Chips - * - * Author: Martyn Welch <martyn.welch@ge.com> - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. - * - * Based on work by Tom Armistead and Ajit Prem - * Copyright 2004 Motorola Inc. - * - * Derived from ca91c042.c by Michael Wyrick - * - * 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/module.h> -#include <linux/mm.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/poll.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/io.h> -#include <linux/uaccess.h> - -#include "../vme.h" -#include "../vme_bridge.h" -#include "vme_ca91cx42.h" - -static int __init ca91cx42_init(void); -static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); -static void ca91cx42_remove(struct pci_dev *); -static void __exit ca91cx42_exit(void); - -/* Module parameters */ -static int geoid; - -static char driver_name[] = "vme_ca91cx42"; - -static const struct pci_device_id ca91cx42_ids[] = { -	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, -	{ }, -}; - -static struct pci_driver ca91cx42_driver = { -	.name = driver_name, -	.id_table = ca91cx42_ids, -	.probe = ca91cx42_probe, -	.remove = ca91cx42_remove, -}; - -static u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge) -{ -	wake_up(&(bridge->dma_queue)); - -	return CA91CX42_LINT_DMA; -} - -static u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat) -{ -	int i; -	u32 serviced = 0; - -	for (i = 0; i < 4; i++) { -		if (stat & CA91CX42_LINT_LM[i]) { -			/* We only enable interrupts if the callback is set */ -			bridge->lm_callback[i](i); -			serviced |= CA91CX42_LINT_LM[i]; -		} -	} - -	return serviced; -} - -/* XXX This needs to be split into 4 queues */ -static u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask) -{ -	wake_up(&(bridge->mbox_queue)); - -	return CA91CX42_LINT_MBOX; -} - -static u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge) -{ -	wake_up(&(bridge->iack_queue)); - -	return CA91CX42_LINT_SW_IACK; -} - -static u32 ca91cx42_VERR_irqhandler(struct vme_bridge *ca91cx42_bridge) -{ -	int val; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	val = ioread32(bridge->base + DGCS); - -	if (!(val & 0x00000800)) { -		dev_err(ca91cx42_bridge->parent, "ca91cx42_VERR_irqhandler DMA " -			"Read Error DGCS=%08X\n", val); -	} - -	return CA91CX42_LINT_VERR; -} - -static u32 ca91cx42_LERR_irqhandler(struct vme_bridge *ca91cx42_bridge) -{ -	int val; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	val = ioread32(bridge->base + DGCS); - -	if (!(val & 0x00000800)) -		dev_err(ca91cx42_bridge->parent, "ca91cx42_LERR_irqhandler DMA " -			"Read Error DGCS=%08X\n", val); - -	return CA91CX42_LINT_LERR; -} - - -static u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge, -	int stat) -{ -	int vec, i, serviced = 0; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - - -	for (i = 7; i > 0; i--) { -		if (stat & (1 << i)) { -			vec = ioread32(bridge->base + -				CA91CX42_V_STATID[i]) & 0xff; - -			vme_irq_handler(ca91cx42_bridge, i, vec); - -			serviced |= (1 << i); -		} -	} - -	return serviced; -} - -static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr) -{ -	u32 stat, enable, serviced = 0; -	struct vme_bridge *ca91cx42_bridge; -	struct ca91cx42_driver *bridge; - -	ca91cx42_bridge = ptr; - -	bridge = ca91cx42_bridge->driver_priv; - -	enable = ioread32(bridge->base + LINT_EN); -	stat = ioread32(bridge->base + LINT_STAT); - -	/* Only look at unmasked interrupts */ -	stat &= enable; - -	if (unlikely(!stat)) -		return IRQ_NONE; - -	if (stat & CA91CX42_LINT_DMA) -		serviced |= ca91cx42_DMA_irqhandler(bridge); -	if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | -			CA91CX42_LINT_LM3)) -		serviced |= ca91cx42_LM_irqhandler(bridge, stat); -	if (stat & CA91CX42_LINT_MBOX) -		serviced |= ca91cx42_MB_irqhandler(bridge, stat); -	if (stat & CA91CX42_LINT_SW_IACK) -		serviced |= ca91cx42_IACK_irqhandler(bridge); -	if (stat & CA91CX42_LINT_VERR) -		serviced |= ca91cx42_VERR_irqhandler(ca91cx42_bridge); -	if (stat & CA91CX42_LINT_LERR) -		serviced |= ca91cx42_LERR_irqhandler(ca91cx42_bridge); -	if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | -			CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | -			CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | -			CA91CX42_LINT_VIRQ7)) -		serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat); - -	/* Clear serviced interrupts */ -	iowrite32(stat, bridge->base + LINT_STAT); - -	return IRQ_HANDLED; -} - -static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) -{ -	int result, tmp; -	struct pci_dev *pdev; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	/* Need pdev */ -	pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); - -	/* Initialise list for VME bus errors */ -	INIT_LIST_HEAD(&(ca91cx42_bridge->vme_errors)); - -	mutex_init(&(ca91cx42_bridge->irq_mtx)); - -	/* Disable interrupts from PCI to VME */ -	iowrite32(0, bridge->base + VINT_EN); - -	/* Disable PCI interrupts */ -	iowrite32(0, bridge->base + LINT_EN); -	/* Clear Any Pending PCI Interrupts */ -	iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); - -	result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, -			driver_name, ca91cx42_bridge); -	if (result) { -		dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", -		       pdev->irq); -		return result; -	} - -	/* Ensure all interrupts are mapped to PCI Interrupt 0 */ -	iowrite32(0, bridge->base + LINT_MAP0); -	iowrite32(0, bridge->base + LINT_MAP1); -	iowrite32(0, bridge->base + LINT_MAP2); - -	/* Enable DMA, mailbox & LM Interrupts */ -	tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | -		CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | -		CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; - -	iowrite32(tmp, bridge->base + LINT_EN); - -	return 0; -} - -static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, -	struct pci_dev *pdev) -{ -	/* Disable interrupts from PCI to VME */ -	iowrite32(0, bridge->base + VINT_EN); - -	/* Disable PCI interrupts */ -	iowrite32(0, bridge->base + LINT_EN); -	/* Clear Any Pending PCI Interrupts */ -	iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); - -	free_irq(pdev->irq, pdev); -} - -/* - * Set up an VME interrupt - */ -void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, int state, -	int sync) - -{ -	struct pci_dev *pdev; -	u32 tmp; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	/* Enable IRQ level */ -	tmp = ioread32(bridge->base + LINT_EN); - -	if (state == 0) -		tmp &= ~CA91CX42_LINT_VIRQ[level]; -	else -		tmp |= CA91CX42_LINT_VIRQ[level]; - -	iowrite32(tmp, bridge->base + LINT_EN); - -	if ((state == 0) && (sync != 0)) { -		pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, -			dev); - -		synchronize_irq(pdev->irq); -	} -} - -int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, -	int statid) -{ -	u32 tmp; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	/* Universe can only generate even vectors */ -	if (statid & 1) -		return -EINVAL; - -	mutex_lock(&(bridge->vme_int)); - -	tmp = ioread32(bridge->base + VINT_EN); - -	/* Set Status/ID */ -	iowrite32(statid << 24, bridge->base + STATID); - -	/* Assert VMEbus IRQ */ -	tmp = tmp | (1 << (level + 24)); -	iowrite32(tmp, bridge->base + VINT_EN); - -	/* Wait for IACK */ -	wait_event_interruptible(bridge->iack_queue, 0); - -	/* Return interrupt to low state */ -	tmp = ioread32(bridge->base + VINT_EN); -	tmp = tmp & ~(1 << (level + 24)); -	iowrite32(tmp, bridge->base + VINT_EN); - -	mutex_unlock(&(bridge->vme_int)); - -	return 0; -} - -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) -{ -	unsigned int i, addr = 0, granularity; -	unsigned int temp_ctl = 0; -	unsigned int vme_bound, pci_offset; -	struct vme_bridge *ca91cx42_bridge; -	struct ca91cx42_driver *bridge; - -	ca91cx42_bridge = image->parent; - -	bridge = ca91cx42_bridge->driver_priv; - -	i = image->number; - -	switch (aspace) { -	case VME_A16: -		addr |= CA91CX42_VSI_CTL_VAS_A16; -		break; -	case VME_A24: -		addr |= CA91CX42_VSI_CTL_VAS_A24; -		break; -	case VME_A32: -		addr |= CA91CX42_VSI_CTL_VAS_A32; -		break; -	case VME_USER1: -		addr |= CA91CX42_VSI_CTL_VAS_USER1; -		break; -	case VME_USER2: -		addr |= CA91CX42_VSI_CTL_VAS_USER2; -		break; -	case VME_A64: -	case VME_CRCSR: -	case VME_USER3: -	case VME_USER4: -	default: -		dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	/* -	 * Bound address is a valid address for the window, adjust -	 * accordingly -	 */ -	vme_bound = vme_base + size; -	pci_offset = pci_base - vme_base; - -	if ((i == 0) || (i == 4)) -		granularity = 0x1000; -	else -		granularity = 0x10000; - -	if (vme_base & (granularity - 1)) { -		dev_err(ca91cx42_bridge->parent, "Invalid VME base " -			"alignment\n"); -		return -EINVAL; -	} -	if (vme_bound & (granularity - 1)) { -		dev_err(ca91cx42_bridge->parent, "Invalid VME bound " -			"alignment\n"); -		return -EINVAL; -	} -	if (pci_offset & (granularity - 1)) { -		dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " -			"alignment\n"); -		return -EINVAL; -	} - -	/* Disable while we are mucking around */ -	temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); -	temp_ctl &= ~CA91CX42_VSI_CTL_EN; -	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); - -	/* Setup mapping */ -	iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); -	iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); -	iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); - -	/* Setup address space */ -	temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; -	temp_ctl |= addr; - -	/* Setup cycle types */ -	temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); -	if (cycle & VME_SUPER) -		temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; -	if (cycle & VME_USER) -		temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; -	if (cycle & VME_PROG) -		temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; -	if (cycle & VME_DATA) -		temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; - -	/* Write ctl reg without enable */ -	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); - -	if (enabled) -		temp_ctl |= CA91CX42_VSI_CTL_EN; - -	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); - -	return 0; -} - -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) -{ -	unsigned int i, granularity = 0, ctl = 0; -	unsigned long long vme_bound, pci_offset; -	struct ca91cx42_driver *bridge; - -	bridge = image->parent->driver_priv; - -	i = image->number; - -	if ((i == 0) || (i == 4)) -		granularity = 0x1000; -	else -		granularity = 0x10000; - -	/* Read Registers */ -	ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); - -	*vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); -	vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); -	pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); - -	*pci_base = (dma_addr_t)vme_base + pci_offset; -	*size = (unsigned long long)((vme_bound - *vme_base) + granularity); - -	*enabled = 0; -	*aspace = 0; -	*cycle = 0; - -	if (ctl & CA91CX42_VSI_CTL_EN) -		*enabled = 1; - -	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) -		*aspace = VME_A16; -	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) -		*aspace = VME_A24; -	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) -		*aspace = VME_A32; -	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) -		*aspace = VME_USER1; -	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) -		*aspace = VME_USER2; - -	if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) -		*cycle |= VME_SUPER; -	if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) -		*cycle |= VME_USER; -	if (ctl & CA91CX42_VSI_CTL_PGM_PGM) -		*cycle |= VME_PROG; -	if (ctl & CA91CX42_VSI_CTL_PGM_DATA) -		*cycle |= VME_DATA; - -	return 0; -} - -/* - * Allocate and map PCI Resource - */ -static int ca91cx42_alloc_resource(struct vme_master_resource *image, -	unsigned long long size) -{ -	unsigned long long existing_size; -	int retval = 0; -	struct pci_dev *pdev; -	struct vme_bridge *ca91cx42_bridge; - -	ca91cx42_bridge = image->parent; - -	/* Find pci_dev container of dev */ -	if (ca91cx42_bridge->parent == NULL) { -		dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); -		return -EINVAL; -	} -	pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); - -	existing_size = (unsigned long long)(image->bus_resource.end - -		image->bus_resource.start); - -	/* If the existing size is OK, return */ -	if (existing_size == (size - 1)) -		return 0; - -	if (existing_size != 0) { -		iounmap(image->kern_base); -		image->kern_base = NULL; -		if (image->bus_resource.name != NULL) -			kfree(image->bus_resource.name); -		release_resource(&(image->bus_resource)); -		memset(&(image->bus_resource), 0, sizeof(struct resource)); -	} - -	if (image->bus_resource.name == NULL) { -		image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); -		if (image->bus_resource.name == NULL) { -			dev_err(ca91cx42_bridge->parent, "Unable to allocate " -				"memory for resource name\n"); -			retval = -ENOMEM; -			goto err_name; -		} -	} - -	sprintf((char *)image->bus_resource.name, "%s.%d", -		ca91cx42_bridge->name, image->number); - -	image->bus_resource.start = 0; -	image->bus_resource.end = (unsigned long)size; -	image->bus_resource.flags = IORESOURCE_MEM; - -	retval = pci_bus_alloc_resource(pdev->bus, -		&(image->bus_resource), size, size, PCIBIOS_MIN_MEM, -		0, NULL, NULL); -	if (retval) { -		dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " -			"resource for window %d size 0x%lx start 0x%lx\n", -			image->number, (unsigned long)size, -			(unsigned long)image->bus_resource.start); -		goto err_resource; -	} - -	image->kern_base = ioremap_nocache( -		image->bus_resource.start, size); -	if (image->kern_base == NULL) { -		dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); -		retval = -ENOMEM; -		goto err_remap; -	} - -	return 0; - -	iounmap(image->kern_base); -	image->kern_base = NULL; -err_remap: -	release_resource(&(image->bus_resource)); -err_resource: -	kfree(image->bus_resource.name); -	memset(&(image->bus_resource), 0, sizeof(struct resource)); -err_name: -	return retval; -} - -/* - * Free and unmap PCI Resource - */ -static void ca91cx42_free_resource(struct vme_master_resource *image) -{ -	iounmap(image->kern_base); -	image->kern_base = NULL; -	release_resource(&(image->bus_resource)); -	kfree(image->bus_resource.name); -	memset(&(image->bus_resource), 0, sizeof(struct resource)); -} - - -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) -{ -	int retval = 0; -	unsigned int i, granularity = 0; -	unsigned int temp_ctl = 0; -	unsigned long long pci_bound, vme_offset, pci_base; -	struct vme_bridge *ca91cx42_bridge; -	struct ca91cx42_driver *bridge; - -	ca91cx42_bridge = image->parent; - -	bridge = ca91cx42_bridge->driver_priv; - -	i = image->number; - -	if ((i == 0) || (i == 4)) -		granularity = 0x1000; -	else -		granularity = 0x10000; - -	/* Verify input data */ -	if (vme_base & (granularity - 1)) { -		dev_err(ca91cx42_bridge->parent, "Invalid VME Window " -			"alignment\n"); -		retval = -EINVAL; -		goto err_window; -	} -	if (size & (granularity - 1)) { -		dev_err(ca91cx42_bridge->parent, "Invalid VME Window " -			"alignment\n"); -		retval = -EINVAL; -		goto err_window; -	} - -	spin_lock(&(image->lock)); - -	/* -	 * Let's allocate the resource here rather than further up the stack as -	 * it avoids pushing loads of bus dependant stuff up the stack -	 */ -	retval = ca91cx42_alloc_resource(image, size); -	if (retval) { -		spin_unlock(&(image->lock)); -		dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " -			"for resource name\n"); -		retval = -ENOMEM; -		goto err_res; -	} - -	pci_base = (unsigned long long)image->bus_resource.start; - -	/* -	 * Bound address is a valid address for the window, adjust -	 * according to window granularity. -	 */ -	pci_bound = pci_base + size; -	vme_offset = vme_base - pci_base; - -	/* Disable while we are mucking around */ -	temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); -	temp_ctl &= ~CA91CX42_LSI_CTL_EN; -	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); - -	/* Setup cycle types */ -	temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; -	if (cycle & VME_BLT) -		temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; -	if (cycle & VME_MBLT) -		temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; - -	/* Setup data width */ -	temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; -	switch (dwidth) { -	case VME_D8: -		temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; -		break; -	case VME_D16: -		temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; -		break; -	case VME_D32: -		temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; -		break; -	case VME_D64: -		temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; -		break; -	default: -		spin_unlock(&(image->lock)); -		dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); -		retval = -EINVAL; -		goto err_dwidth; -		break; -	} - -	/* Setup address space */ -	temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; -	switch (aspace) { -	case VME_A16: -		temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; -		break; -	case VME_A24: -		temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; -		break; -	case VME_A32: -		temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; -		break; -	case VME_CRCSR: -		temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; -		break; -	case VME_USER1: -		temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; -		break; -	case VME_USER2: -		temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; -		break; -	case VME_A64: -	case VME_USER3: -	case VME_USER4: -	default: -		spin_unlock(&(image->lock)); -		dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); -		retval = -EINVAL; -		goto err_aspace; -		break; -	} - -	temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); -	if (cycle & VME_SUPER) -		temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; -	if (cycle & VME_PROG) -		temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; - -	/* Setup mapping */ -	iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); -	iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); -	iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); - -	/* Write ctl reg without enable */ -	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); - -	if (enabled) -		temp_ctl |= CA91CX42_LSI_CTL_EN; - -	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); - -	spin_unlock(&(image->lock)); -	return 0; - -err_aspace: -err_dwidth: -	ca91cx42_free_resource(image); -err_res: -err_window: -	return retval; -} - -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 int i, ctl; -	unsigned long long pci_base, pci_bound, vme_offset; -	struct ca91cx42_driver *bridge; - -	bridge = image->parent->driver_priv; - -	i = image->number; - -	ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); - -	pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); -	vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); -	pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); - -	*vme_base = pci_base + vme_offset; -	*size = (unsigned long long)(pci_bound - pci_base); - -	*enabled = 0; -	*aspace = 0; -	*cycle = 0; -	*dwidth = 0; - -	if (ctl & CA91CX42_LSI_CTL_EN) -		*enabled = 1; - -	/* Setup address space */ -	switch (ctl & CA91CX42_LSI_CTL_VAS_M) { -	case CA91CX42_LSI_CTL_VAS_A16: -		*aspace = VME_A16; -		break; -	case CA91CX42_LSI_CTL_VAS_A24: -		*aspace = VME_A24; -		break; -	case CA91CX42_LSI_CTL_VAS_A32: -		*aspace = VME_A32; -		break; -	case CA91CX42_LSI_CTL_VAS_CRCSR: -		*aspace = VME_CRCSR; -		break; -	case CA91CX42_LSI_CTL_VAS_USER1: -		*aspace = VME_USER1; -		break; -	case CA91CX42_LSI_CTL_VAS_USER2: -		*aspace = VME_USER2; -		break; -	} - -	/* XXX Not sure howto check for MBLT */ -	/* Setup cycle types */ -	if (ctl & CA91CX42_LSI_CTL_VCT_BLT) -		*cycle |= VME_BLT; -	else -		*cycle |= VME_SCT; - -	if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) -		*cycle |= VME_SUPER; -	else -		*cycle |= VME_USER; - -	if (ctl & CA91CX42_LSI_CTL_PGM_PGM) -		*cycle = VME_PROG; -	else -		*cycle = VME_DATA; - -	/* Setup data width */ -	switch (ctl & CA91CX42_LSI_CTL_VDW_M) { -	case CA91CX42_LSI_CTL_VDW_D8: -		*dwidth = VME_D8; -		break; -	case CA91CX42_LSI_CTL_VDW_D16: -		*dwidth = VME_D16; -		break; -	case CA91CX42_LSI_CTL_VDW_D32: -		*dwidth = VME_D32; -		break; -	case CA91CX42_LSI_CTL_VDW_D64: -		*dwidth = VME_D64; -		break; -	} - -	return 0; -} - -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) -{ -	int retval; - -	spin_lock(&(image->lock)); - -	retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, -		cycle, dwidth); - -	spin_unlock(&(image->lock)); - -	return retval; -} - -ssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf, -	size_t count, loff_t offset) -{ -	ssize_t retval; -	void *addr = image->kern_base + offset; -	unsigned int done = 0; -	unsigned int count32; - -	if (count == 0) -		return 0; - -	spin_lock(&(image->lock)); - -	/* The following code handles VME address alignment problem -	 * in order to assure the maximal data width cycle. -	 * We cannot use memcpy_xxx directly here because it -	 * may cut data transfer in 8-bits cycles, thus making -	 * D16 cycle impossible. -	 * From the other hand, the bridge itself assures that -	 * maximal configured data cycle is used and splits it -	 * automatically for non-aligned addresses. -	 */ -	if ((int)addr & 0x1) { -		*(u8 *)buf = ioread8(addr); -		done += 1; -		if (done == count) -			goto out; -	} -	if ((int)addr & 0x2) { -		if ((count - done) < 2) { -			*(u8 *)(buf + done) = ioread8(addr + done); -			done += 1; -			goto out; -		} else { -			*(u16 *)(buf + done) = ioread16(addr + done); -			done += 2; -		} -	} - -	count32 = (count - done) & ~0x3; -	if (count32 > 0) { -		memcpy_fromio(buf + done, addr + done, (unsigned int)count); -		done += count32; -	} - -	if ((count - done) & 0x2) { -		*(u16 *)(buf + done) = ioread16(addr + done); -		done += 2; -	} -	if ((count - done) & 0x1) { -		*(u8 *)(buf + done) = ioread8(addr + done); -		done += 1; -	} -out: -	retval = count; -	spin_unlock(&(image->lock)); - -	return retval; -} - -ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf, -	size_t count, loff_t offset) -{ -	ssize_t retval; -	void *addr = image->kern_base + offset; -	unsigned int done = 0; -	unsigned int count32; - -	if (count == 0) -		return 0; - -	spin_lock(&(image->lock)); - -	/* 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) { -		iowrite8(*(u8 *)buf, addr); -		done += 1; -		if (done == count) -			goto out; -	} -	if ((int)addr & 0x2) { -		if ((count - done) < 2) { -			iowrite8(*(u8 *)(buf + done), addr + done); -			done += 1; -			goto out; -		} else { -			iowrite16(*(u16 *)(buf + done), addr + done); -			done += 2; -		} -	} - -	count32 = (count - done) & ~0x3; -	if (count32 > 0) { -		memcpy_toio(addr + done, buf + done, count32); -		done += count32; -	} - -	if ((count - done) & 0x2) { -		iowrite16(*(u16 *)(buf + done), addr + done); -		done += 2; -	} -	if ((count - done) & 0x1) { -		iowrite8(*(u8 *)(buf + done), addr + done); -		done += 1; -	} -out: -	retval = count; - -	spin_unlock(&(image->lock)); -	return retval; -} - -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; -	int i; -	struct ca91cx42_driver *bridge; -	struct device *dev; - -	bridge = image->parent->driver_priv; -	dev = image->parent->parent; - -	/* Find the PCI address that maps to the desired VME address */ -	i = image->number; - -	/* Locking as we can only do one of these at a time */ -	mutex_lock(&(bridge->vme_rmw)); - -	/* Lock image */ -	spin_lock(&(image->lock)); - -	pci_addr = (u32)image->kern_base + offset; - -	/* Address must be 4-byte aligned */ -	if (pci_addr & 0x3) { -		dev_err(dev, "RMW Address not 4-byte aligned\n"); -		result = -EINVAL; -		goto out; -	} - -	/* Ensure RMW Disabled whilst configuring */ -	iowrite32(0, bridge->base + SCYC_CTL); - -	/* Configure registers */ -	iowrite32(mask, bridge->base + SCYC_EN); -	iowrite32(compare, bridge->base + SCYC_CMP); -	iowrite32(swap, bridge->base + SCYC_SWP); -	iowrite32(pci_addr, bridge->base + SCYC_ADDR); - -	/* Enable RMW */ -	iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); - -	/* Kick process off with a read to the required address. */ -	result = ioread32(image->kern_base + offset); - -	/* Disable RMW */ -	iowrite32(0, bridge->base + SCYC_CTL); - -out: -	spin_unlock(&(image->lock)); - -	mutex_unlock(&(bridge->vme_rmw)); - -	return result; -} - -int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, -	struct vme_dma_attr *dest, size_t count) -{ -	struct ca91cx42_dma_entry *entry, *prev; -	struct vme_dma_pci *pci_attr; -	struct vme_dma_vme *vme_attr; -	dma_addr_t desc_ptr; -	int retval = 0; -	struct device *dev; - -	dev = list->parent->parent->parent; - -	/* XXX descriptor must be aligned on 64-bit boundaries */ -	entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); -	if (entry == NULL) { -		dev_err(dev, "Failed to allocate memory for dma resource " -			"structure\n"); -		retval = -ENOMEM; -		goto err_mem; -	} - -	/* Test descriptor alignment */ -	if ((unsigned long)&(entry->descriptor) & CA91CX42_DCPP_M) { -		dev_err(dev, "Descriptor not aligned to 16 byte boundary as " -			"required: %p\n", &(entry->descriptor)); -		retval = -EINVAL; -		goto err_align; -	} - -	memset(&(entry->descriptor), 0, sizeof(struct ca91cx42_dma_descriptor)); - -	if (dest->type == VME_DMA_VME) { -		entry->descriptor.dctl |= CA91CX42_DCTL_L2V; -		vme_attr = dest->private; -		pci_attr = src->private; -	} else { -		vme_attr = src->private; -		pci_attr = dest->private; -	} - -	/* Check we can do fullfill required attributes */ -	if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | -		VME_USER2)) != 0) { - -		dev_err(dev, "Unsupported cycle type\n"); -		retval = -EINVAL; -		goto err_aspace; -	} - -	if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | -		VME_PROG | VME_DATA)) != 0) { - -		dev_err(dev, "Unsupported cycle type\n"); -		retval = -EINVAL; -		goto err_cycle; -	} - -	/* Check to see if we can fullfill source and destination */ -	if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || -		((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { - -		dev_err(dev, "Cannot perform transfer with this " -			"source-destination combination\n"); -		retval = -EINVAL; -		goto err_direct; -	} - -	/* Setup cycle types */ -	if (vme_attr->cycle & VME_BLT) -		entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; - -	/* Setup data width */ -	switch (vme_attr->dwidth) { -	case VME_D8: -		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; -		break; -	case VME_D16: -		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; -		break; -	case VME_D32: -		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; -		break; -	case VME_D64: -		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; -		break; -	default: -		dev_err(dev, "Invalid data width\n"); -		return -EINVAL; -	} - -	/* Setup address space */ -	switch (vme_attr->aspace) { -	case VME_A16: -		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; -		break; -	case VME_A24: -		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; -		break; -	case VME_A32: -		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; -		break; -	case VME_USER1: -		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; -		break; -	case VME_USER2: -		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; -		break; -	default: -		dev_err(dev, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	if (vme_attr->cycle & VME_SUPER) -		entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; -	if (vme_attr->cycle & VME_PROG) -		entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; - -	entry->descriptor.dtbc = count; -	entry->descriptor.dla = pci_attr->address; -	entry->descriptor.dva = vme_attr->address; -	entry->descriptor.dcpp = CA91CX42_DCPP_NULL; - -	/* Add to list */ -	list_add_tail(&(entry->list), &(list->entries)); - -	/* Fill out previous descriptors "Next Address" */ -	if (entry->list.prev != &(list->entries)) { -		prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, -			list); -		/* We need the bus address for the pointer */ -		desc_ptr = virt_to_bus(&(entry->descriptor)); -		prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; -	} - -	return 0; - -err_cycle: -err_aspace: -err_direct: -err_align: -	kfree(entry); -err_mem: -	return retval; -} - -static int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) -{ -	u32 tmp; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	tmp = ioread32(bridge->base + DGCS); - -	if (tmp & CA91CX42_DGCS_ACT) -		return 0; -	else -		return 1; -} - -int ca91cx42_dma_list_exec(struct vme_dma_list *list) -{ -	struct vme_dma_resource *ctrlr; -	struct ca91cx42_dma_entry *entry; -	int retval = 0; -	dma_addr_t bus_addr; -	u32 val; -	struct device *dev; -	struct ca91cx42_driver *bridge; - -	ctrlr = list->parent; - -	bridge = ctrlr->parent->driver_priv; -	dev = ctrlr->parent->parent; - -	mutex_lock(&(ctrlr->mtx)); - -	if (!(list_empty(&(ctrlr->running)))) { -		/* -		 * XXX We have an active DMA transfer and currently haven't -		 *     sorted out the mechanism for "pending" DMA transfers. -		 *     Return busy. -		 */ -		/* Need to add to pending here */ -		mutex_unlock(&(ctrlr->mtx)); -		return -EBUSY; -	} else { -		list_add(&(list->list), &(ctrlr->running)); -	} - -	/* Get first bus address and write into registers */ -	entry = list_first_entry(&(list->entries), struct ca91cx42_dma_entry, -		list); - -	bus_addr = virt_to_bus(&(entry->descriptor)); - -	mutex_unlock(&(ctrlr->mtx)); - -	iowrite32(0, bridge->base + DTBC); -	iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); - -	/* Start the operation */ -	val = ioread32(bridge->base + DGCS); - -	/* XXX Could set VMEbus On and Off Counters here */ -	val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); - -	val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | -		CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | -		CA91CX42_DGCS_PERR); - -	iowrite32(val, bridge->base + DGCS); - -	val |= CA91CX42_DGCS_GO; - -	iowrite32(val, bridge->base + DGCS); - -	wait_event_interruptible(bridge->dma_queue, -		ca91cx42_dma_busy(ctrlr->parent)); - -	/* -	 * Read status register, this register is valid until we kick off a -	 * new transfer. -	 */ -	val = ioread32(bridge->base + DGCS); - -	if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | -		CA91CX42_DGCS_PERR)) { - -		dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); -		val = ioread32(bridge->base + DCTL); -	} - -	/* Remove list from running list */ -	mutex_lock(&(ctrlr->mtx)); -	list_del(&(list->list)); -	mutex_unlock(&(ctrlr->mtx)); - -	return retval; - -} - -int ca91cx42_dma_list_empty(struct vme_dma_list *list) -{ -	struct list_head *pos, *temp; -	struct ca91cx42_dma_entry *entry; - -	/* detach and free each entry */ -	list_for_each_safe(pos, temp, &(list->entries)) { -		list_del(pos); -		entry = list_entry(pos, struct ca91cx42_dma_entry, list); -		kfree(entry); -	} - -	return 0; -} - -/* - * All 4 location monitors reside at the same base - this is therefore a - * system wide configuration. - * - * This does not enable the LM monitor - that should be done when the first - * callback is attached and disabled when the last callback is removed. - */ -int ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, -	vme_address_t aspace, vme_cycle_t cycle) -{ -	u32 temp_base, lm_ctl = 0; -	int i; -	struct ca91cx42_driver *bridge; -	struct device *dev; - -	bridge = lm->parent->driver_priv; -	dev = lm->parent->parent; - -	/* Check the alignment of the location monitor */ -	temp_base = (u32)lm_base; -	if (temp_base & 0xffff) { -		dev_err(dev, "Location monitor must be aligned to 64KB " -			"boundary"); -		return -EINVAL; -	} - -	mutex_lock(&(lm->mtx)); - -	/* If we already have a callback attached, we can't move it! */ -	for (i = 0; i < lm->monitors; i++) { -		if (bridge->lm_callback[i] != NULL) { -			mutex_unlock(&(lm->mtx)); -			dev_err(dev, "Location monitor callback attached, " -				"can't reset\n"); -			return -EBUSY; -		} -	} - -	switch (aspace) { -	case VME_A16: -		lm_ctl |= CA91CX42_LM_CTL_AS_A16; -		break; -	case VME_A24: -		lm_ctl |= CA91CX42_LM_CTL_AS_A24; -		break; -	case VME_A32: -		lm_ctl |= CA91CX42_LM_CTL_AS_A32; -		break; -	default: -		mutex_unlock(&(lm->mtx)); -		dev_err(dev, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	if (cycle & VME_SUPER) -		lm_ctl |= CA91CX42_LM_CTL_SUPR; -	if (cycle & VME_USER) -		lm_ctl |= CA91CX42_LM_CTL_NPRIV; -	if (cycle & VME_PROG) -		lm_ctl |= CA91CX42_LM_CTL_PGM; -	if (cycle & VME_DATA) -		lm_ctl |= CA91CX42_LM_CTL_DATA; - -	iowrite32(lm_base, bridge->base + LM_BS); -	iowrite32(lm_ctl, bridge->base + LM_CTL); - -	mutex_unlock(&(lm->mtx)); - -	return 0; -} - -/* Get configuration of the callback monitor and return whether it is enabled - * or disabled. - */ -int ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base, -	vme_address_t *aspace, vme_cycle_t *cycle) -{ -	u32 lm_ctl, enabled = 0; -	struct ca91cx42_driver *bridge; - -	bridge = lm->parent->driver_priv; - -	mutex_lock(&(lm->mtx)); - -	*lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); -	lm_ctl = ioread32(bridge->base + LM_CTL); - -	if (lm_ctl & CA91CX42_LM_CTL_EN) -		enabled = 1; - -	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) -		*aspace = VME_A16; -	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) -		*aspace = VME_A24; -	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) -		*aspace = VME_A32; - -	*cycle = 0; -	if (lm_ctl & CA91CX42_LM_CTL_SUPR) -		*cycle |= VME_SUPER; -	if (lm_ctl & CA91CX42_LM_CTL_NPRIV) -		*cycle |= VME_USER; -	if (lm_ctl & CA91CX42_LM_CTL_PGM) -		*cycle |= VME_PROG; -	if (lm_ctl & CA91CX42_LM_CTL_DATA) -		*cycle |= VME_DATA; - -	mutex_unlock(&(lm->mtx)); - -	return enabled; -} - -/* - * Attach a callback to a specific location monitor. - * - * Callback will be passed the monitor triggered. - */ -int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, -	void (*callback)(int)) -{ -	u32 lm_ctl, tmp; -	struct ca91cx42_driver *bridge; -	struct device *dev; - -	bridge = lm->parent->driver_priv; -	dev = lm->parent->parent; - -	mutex_lock(&(lm->mtx)); - -	/* Ensure that the location monitor is configured - need PGM or DATA */ -	lm_ctl = ioread32(bridge->base + LM_CTL); -	if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { -		mutex_unlock(&(lm->mtx)); -		dev_err(dev, "Location monitor not properly configured\n"); -		return -EINVAL; -	} - -	/* Check that a callback isn't already attached */ -	if (bridge->lm_callback[monitor] != NULL) { -		mutex_unlock(&(lm->mtx)); -		dev_err(dev, "Existing callback attached\n"); -		return -EBUSY; -	} - -	/* Attach callback */ -	bridge->lm_callback[monitor] = callback; - -	/* Enable Location Monitor interrupt */ -	tmp = ioread32(bridge->base + LINT_EN); -	tmp |= CA91CX42_LINT_LM[monitor]; -	iowrite32(tmp, bridge->base + LINT_EN); - -	/* Ensure that global Location Monitor Enable set */ -	if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { -		lm_ctl |= CA91CX42_LM_CTL_EN; -		iowrite32(lm_ctl, bridge->base + LM_CTL); -	} - -	mutex_unlock(&(lm->mtx)); - -	return 0; -} - -/* - * Detach a callback function forn a specific location monitor. - */ -int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) -{ -	u32 tmp; -	struct ca91cx42_driver *bridge; - -	bridge = lm->parent->driver_priv; - -	mutex_lock(&(lm->mtx)); - -	/* Disable Location Monitor and ensure previous interrupts are clear */ -	tmp = ioread32(bridge->base + LINT_EN); -	tmp &= ~CA91CX42_LINT_LM[monitor]; -	iowrite32(tmp, bridge->base + LINT_EN); - -	iowrite32(CA91CX42_LINT_LM[monitor], -		 bridge->base + LINT_STAT); - -	/* Detach callback */ -	bridge->lm_callback[monitor] = NULL; - -	/* If all location monitors disabled, disable global Location Monitor */ -	if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | -			CA91CX42_LINT_LM3)) == 0) { -		tmp = ioread32(bridge->base + LM_CTL); -		tmp &= ~CA91CX42_LM_CTL_EN; -		iowrite32(tmp, bridge->base + LM_CTL); -	} - -	mutex_unlock(&(lm->mtx)); - -	return 0; -} - -int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) -{ -	u32 slot = 0; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	if (!geoid) { -		slot = ioread32(bridge->base + VCSR_BS); -		slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); -	} else -		slot = geoid; - -	return (int)slot; - -} - -static int __init ca91cx42_init(void) -{ -	return pci_register_driver(&ca91cx42_driver); -} - -/* - * Configure CR/CSR space - * - * Access to the CR/CSR can be configured at power-up. The location of the - * CR/CSR registers in the CR/CSR address space is determined by the boards - * Auto-ID or Geographic address. This function ensures that the window is - * enabled at an offset consistent with the boards geopgraphic address. - */ -static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, -	struct pci_dev *pdev) -{ -	unsigned int crcsr_addr; -	int tmp, slot; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	slot = ca91cx42_slot_get(ca91cx42_bridge); - -	/* Write CSR Base Address if slot ID is supplied as a module param */ -	if (geoid) -		iowrite32(geoid << 27, bridge->base + VCSR_BS); - -	dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); -	if (slot == 0) { -		dev_err(&pdev->dev, "Slot number is unset, not configuring " -			"CR/CSR space\n"); -		return -EINVAL; -	} - -	/* Allocate mem for CR/CSR image */ -	bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, -		&(bridge->crcsr_bus)); -	if (bridge->crcsr_kernel == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " -			"image\n"); -		return -ENOMEM; -	} - -	memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); - -	crcsr_addr = slot * (512 * 1024); -	iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); - -	tmp = ioread32(bridge->base + VCSR_CTL); -	tmp |= CA91CX42_VCSR_CTL_EN; -	iowrite32(tmp, bridge->base + VCSR_CTL); - -	return 0; -} - -static void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, -	struct pci_dev *pdev) -{ -	u32 tmp; -	struct ca91cx42_driver *bridge; - -	bridge = ca91cx42_bridge->driver_priv; - -	/* Turn off CR/CSR space */ -	tmp = ioread32(bridge->base + VCSR_CTL); -	tmp &= ~CA91CX42_VCSR_CTL_EN; -	iowrite32(tmp, bridge->base + VCSR_CTL); - -	/* Free image */ -	iowrite32(0, bridge->base + VCSR_TO); - -	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, -		bridge->crcsr_bus); -} - -static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ -	int retval, i; -	u32 data; -	struct list_head *pos = NULL; -	struct vme_bridge *ca91cx42_bridge; -	struct ca91cx42_driver *ca91cx42_device; -	struct vme_master_resource *master_image; -	struct vme_slave_resource *slave_image; -	struct vme_dma_resource *dma_ctrlr; -	struct vme_lm_resource *lm; - -	/* We want to support more than one of each bridge so we need to -	 * dynamically allocate the bridge structure -	 */ -	ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); - -	if (ca91cx42_bridge == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for device " -			"structure\n"); -		retval = -ENOMEM; -		goto err_struct; -	} - -	ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); - -	if (ca91cx42_device == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for device " -			"structure\n"); -		retval = -ENOMEM; -		goto err_driver; -	} - -	ca91cx42_bridge->driver_priv = ca91cx42_device; - -	/* Enable the device */ -	retval = pci_enable_device(pdev); -	if (retval) { -		dev_err(&pdev->dev, "Unable to enable device\n"); -		goto err_enable; -	} - -	/* Map Registers */ -	retval = pci_request_regions(pdev, driver_name); -	if (retval) { -		dev_err(&pdev->dev, "Unable to reserve resources\n"); -		goto err_resource; -	} - -	/* map registers in BAR 0 */ -	ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), -		4096); -	if (!ca91cx42_device->base) { -		dev_err(&pdev->dev, "Unable to remap CRG region\n"); -		retval = -EIO; -		goto err_remap; -	} - -	/* Check to see if the mapping worked out */ -	data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; -	if (data != PCI_VENDOR_ID_TUNDRA) { -		dev_err(&pdev->dev, "PCI_ID check failed\n"); -		retval = -EIO; -		goto err_test; -	} - -	/* Initialize wait queues & mutual exclusion flags */ -	init_waitqueue_head(&(ca91cx42_device->dma_queue)); -	init_waitqueue_head(&(ca91cx42_device->iack_queue)); -	mutex_init(&(ca91cx42_device->vme_int)); -	mutex_init(&(ca91cx42_device->vme_rmw)); - -	ca91cx42_bridge->parent = &(pdev->dev); -	strcpy(ca91cx42_bridge->name, driver_name); - -	/* Setup IRQ */ -	retval = ca91cx42_irq_init(ca91cx42_bridge); -	if (retval != 0) { -		dev_err(&pdev->dev, "Chip Initialization failed.\n"); -		goto err_irq; -	} - -	/* Add master windows to list */ -	INIT_LIST_HEAD(&(ca91cx42_bridge->master_resources)); -	for (i = 0; i < CA91C142_MAX_MASTER; i++) { -		master_image = kmalloc(sizeof(struct vme_master_resource), -			GFP_KERNEL); -		if (master_image == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"master resource structure\n"); -			retval = -ENOMEM; -			goto err_master; -		} -		master_image->parent = ca91cx42_bridge; -		spin_lock_init(&(master_image->lock)); -		master_image->locked = 0; -		master_image->number = i; -		master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | -			VME_CRCSR | VME_USER1 | VME_USER2; -		master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | -			VME_SUPER | VME_USER | VME_PROG | VME_DATA; -		master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; -		memset(&(master_image->bus_resource), 0, -			sizeof(struct resource)); -		master_image->kern_base  = NULL; -		list_add_tail(&(master_image->list), -			&(ca91cx42_bridge->master_resources)); -	} - -	/* Add slave windows to list */ -	INIT_LIST_HEAD(&(ca91cx42_bridge->slave_resources)); -	for (i = 0; i < CA91C142_MAX_SLAVE; i++) { -		slave_image = kmalloc(sizeof(struct vme_slave_resource), -			GFP_KERNEL); -		if (slave_image == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"slave resource structure\n"); -			retval = -ENOMEM; -			goto err_slave; -		} -		slave_image->parent = ca91cx42_bridge; -		mutex_init(&(slave_image->mtx)); -		slave_image->locked = 0; -		slave_image->number = i; -		slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | -			VME_USER2; - -		/* Only windows 0 and 4 support A16 */ -		if (i == 0 || i == 4) -			slave_image->address_attr |= VME_A16; - -		slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | -			VME_SUPER | VME_USER | VME_PROG | VME_DATA; -		list_add_tail(&(slave_image->list), -			&(ca91cx42_bridge->slave_resources)); -	} - -	/* Add dma engines to list */ -	INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources)); -	for (i = 0; i < CA91C142_MAX_DMA; i++) { -		dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), -			GFP_KERNEL); -		if (dma_ctrlr == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"dma resource structure\n"); -			retval = -ENOMEM; -			goto err_dma; -		} -		dma_ctrlr->parent = ca91cx42_bridge; -		mutex_init(&(dma_ctrlr->mtx)); -		dma_ctrlr->locked = 0; -		dma_ctrlr->number = i; -		dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | -			VME_DMA_MEM_TO_VME; -		INIT_LIST_HEAD(&(dma_ctrlr->pending)); -		INIT_LIST_HEAD(&(dma_ctrlr->running)); -		list_add_tail(&(dma_ctrlr->list), -			&(ca91cx42_bridge->dma_resources)); -	} - -	/* Add location monitor to list */ -	INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources)); -	lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); -	if (lm == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for " -		"location monitor resource structure\n"); -		retval = -ENOMEM; -		goto err_lm; -	} -	lm->parent = ca91cx42_bridge; -	mutex_init(&(lm->mtx)); -	lm->locked = 0; -	lm->number = 1; -	lm->monitors = 4; -	list_add_tail(&(lm->list), &(ca91cx42_bridge->lm_resources)); - -	ca91cx42_bridge->slave_get = ca91cx42_slave_get; -	ca91cx42_bridge->slave_set = ca91cx42_slave_set; -	ca91cx42_bridge->master_get = ca91cx42_master_get; -	ca91cx42_bridge->master_set = ca91cx42_master_set; -	ca91cx42_bridge->master_read = ca91cx42_master_read; -	ca91cx42_bridge->master_write = ca91cx42_master_write; -	ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; -	ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; -	ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; -	ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; -	ca91cx42_bridge->irq_set = ca91cx42_irq_set; -	ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; -	ca91cx42_bridge->lm_set = ca91cx42_lm_set; -	ca91cx42_bridge->lm_get = ca91cx42_lm_get; -	ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; -	ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; -	ca91cx42_bridge->slot_get = ca91cx42_slot_get; - -	data = ioread32(ca91cx42_device->base + MISC_CTL); -	dev_info(&pdev->dev, "Board is%s the VME system controller\n", -		(data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); -	dev_info(&pdev->dev, "Slot ID is %d\n", -		ca91cx42_slot_get(ca91cx42_bridge)); - -	if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) -		dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); - -	/* Need to save ca91cx42_bridge pointer locally in link list for use in -	 * ca91cx42_remove() -	 */ -	retval = vme_register_bridge(ca91cx42_bridge); -	if (retval != 0) { -		dev_err(&pdev->dev, "Chip Registration failed.\n"); -		goto err_reg; -	} - -	pci_set_drvdata(pdev, ca91cx42_bridge); - -	return 0; - -	vme_unregister_bridge(ca91cx42_bridge); -err_reg: -	ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); -err_lm: -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { -		lm = list_entry(pos, struct vme_lm_resource, list); -		list_del(pos); -		kfree(lm); -	} -err_dma: -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { -		dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); -		list_del(pos); -		kfree(dma_ctrlr); -	} -err_slave: -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { -		slave_image = list_entry(pos, struct vme_slave_resource, list); -		list_del(pos); -		kfree(slave_image); -	} -err_master: -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->master_resources)) { -		master_image = list_entry(pos, struct vme_master_resource, -			list); -		list_del(pos); -		kfree(master_image); -	} - -	ca91cx42_irq_exit(ca91cx42_device, pdev); -err_irq: -err_test: -	iounmap(ca91cx42_device->base); -err_remap: -	pci_release_regions(pdev); -err_resource: -	pci_disable_device(pdev); -err_enable: -	kfree(ca91cx42_device); -err_driver: -	kfree(ca91cx42_bridge); -err_struct: -	return retval; - -} - -void ca91cx42_remove(struct pci_dev *pdev) -{ -	struct list_head *pos = NULL; -	struct vme_master_resource *master_image; -	struct vme_slave_resource *slave_image; -	struct vme_dma_resource *dma_ctrlr; -	struct vme_lm_resource *lm; -	struct ca91cx42_driver *bridge; -	struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); - -	bridge = ca91cx42_bridge->driver_priv; - - -	/* Turn off Ints */ -	iowrite32(0, bridge->base + LINT_EN); - -	/* Turn off the windows */ -	iowrite32(0x00800000, bridge->base + LSI0_CTL); -	iowrite32(0x00800000, bridge->base + LSI1_CTL); -	iowrite32(0x00800000, bridge->base + LSI2_CTL); -	iowrite32(0x00800000, bridge->base + LSI3_CTL); -	iowrite32(0x00800000, bridge->base + LSI4_CTL); -	iowrite32(0x00800000, bridge->base + LSI5_CTL); -	iowrite32(0x00800000, bridge->base + LSI6_CTL); -	iowrite32(0x00800000, bridge->base + LSI7_CTL); -	iowrite32(0x00F00000, bridge->base + VSI0_CTL); -	iowrite32(0x00F00000, bridge->base + VSI1_CTL); -	iowrite32(0x00F00000, bridge->base + VSI2_CTL); -	iowrite32(0x00F00000, bridge->base + VSI3_CTL); -	iowrite32(0x00F00000, bridge->base + VSI4_CTL); -	iowrite32(0x00F00000, bridge->base + VSI5_CTL); -	iowrite32(0x00F00000, bridge->base + VSI6_CTL); -	iowrite32(0x00F00000, bridge->base + VSI7_CTL); - -	vme_unregister_bridge(ca91cx42_bridge); - -	ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); - -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { -		lm = list_entry(pos, struct vme_lm_resource, list); -		list_del(pos); -		kfree(lm); -	} - -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { -		dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); -		list_del(pos); -		kfree(dma_ctrlr); -	} - -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { -		slave_image = list_entry(pos, struct vme_slave_resource, list); -		list_del(pos); -		kfree(slave_image); -	} - -	/* resources are stored in link list */ -	list_for_each(pos, &(ca91cx42_bridge->master_resources)) { -		master_image = list_entry(pos, struct vme_master_resource, -			list); -		list_del(pos); -		kfree(master_image); -	} - -	ca91cx42_irq_exit(bridge, pdev); - -	iounmap(bridge->base); - -	pci_release_regions(pdev); - -	pci_disable_device(pdev); - -	kfree(ca91cx42_bridge); -} - -static void __exit ca91cx42_exit(void) -{ -	pci_unregister_driver(&ca91cx42_driver); -} - -MODULE_PARM_DESC(geoid, "Override geographical addressing"); -module_param(geoid, int, 0); - -MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); -MODULE_LICENSE("GPL"); - -module_init(ca91cx42_init); -module_exit(ca91cx42_exit); diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h deleted file mode 100644 index e72c65b193e..00000000000 --- a/drivers/staging/vme/bridges/vme_ca91cx42.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - * ca91c042.h - * - * Support for the Tundra Universe 1 and Universe II VME bridge chips - * - * Author: Tom Armistead - * Updated by Ajit Prem - * Copyright 2004 Motorola Inc. - * - * Further updated by Martyn Welch <martyn.welch@ge.com> - * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. - * - * Derived from ca91c042.h by Michael Wyrick - * - * 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. - */ - -#ifndef _CA91CX42_H -#define _CA91CX42_H - -#ifndef	PCI_VENDOR_ID_TUNDRA -#define	PCI_VENDOR_ID_TUNDRA 0x10e3 -#endif - -#ifndef	PCI_DEVICE_ID_TUNDRA_CA91C142 -#define	PCI_DEVICE_ID_TUNDRA_CA91C142 0x0000 -#endif - -/* - *  Define the number of each that the CA91C142 supports. - */ -#define CA91C142_MAX_MASTER		8	/* Max Master Windows */ -#define CA91C142_MAX_SLAVE		8	/* Max Slave Windows */ -#define CA91C142_MAX_DMA		1	/* Max DMA Controllers */ -#define CA91C142_MAX_MAILBOX		4	/* Max Mail Box registers */ - -/* Structure used to hold driver specific information */ -struct ca91cx42_driver { -	void *base;	/* Base Address of device registers */ -	wait_queue_head_t dma_queue; -	wait_queue_head_t iack_queue; -	wait_queue_head_t mbox_queue; -	void (*lm_callback[4])(int);	/* Called in interrupt handler */ -	void *crcsr_kernel; -	dma_addr_t crcsr_bus; -	struct mutex vme_rmw;		/* Only one RMW cycle at a time */ -	struct mutex vme_int;		/* -					 * Only one VME interrupt can be -					 * generated at a time, provide locking -					 */ -}; - -/* See Page 2-77 in the Universe User Manual */ -struct ca91cx42_dma_descriptor { -	unsigned int dctl;      /* DMA Control */ -	unsigned int dtbc;      /* Transfer Byte Count */ -	unsigned int dla;       /* PCI Address */ -	unsigned int res1;      /* Reserved */ -	unsigned int dva;       /* Vme Address */ -	unsigned int res2;      /* Reserved */ -	unsigned int dcpp;      /* Pointer to Numed Cmd Packet with rPN */ -	unsigned int res3;      /* Reserved */ -}; - -struct ca91cx42_dma_entry { -	struct ca91cx42_dma_descriptor descriptor; -	struct list_head list; -}; - -/* Universe Register Offsets */ -/* general PCI configuration registers */ -#define CA91CX42_PCI_ID		0x000 -#define CA91CX42_PCI_CSR	0x004 -#define CA91CX42_PCI_CLASS	0x008 -#define CA91CX42_PCI_MISC0	0x00C -#define CA91CX42_PCI_BS		0x010 -#define CA91CX42_PCI_MISC1	0x03C - -#define LSI0_CTL		0x0100 -#define LSI0_BS			0x0104 -#define LSI0_BD			0x0108 -#define LSI0_TO			0x010C - -#define LSI1_CTL		0x0114 -#define LSI1_BS			0x0118 -#define LSI1_BD			0x011C -#define LSI1_TO			0x0120 - -#define LSI2_CTL		0x0128 -#define LSI2_BS			0x012C -#define LSI2_BD			0x0130 -#define LSI2_TO			0x0134 - -#define LSI3_CTL		0x013C -#define LSI3_BS			0x0140 -#define LSI3_BD			0x0144 -#define LSI3_TO			0x0148 - -#define LSI4_CTL		0x01A0 -#define LSI4_BS			0x01A4 -#define LSI4_BD			0x01A8 -#define LSI4_TO			0x01AC - -#define LSI5_CTL		0x01B4 -#define LSI5_BS			0x01B8 -#define LSI5_BD			0x01BC -#define LSI5_TO			0x01C0 - -#define LSI6_CTL		0x01C8 -#define LSI6_BS			0x01CC -#define LSI6_BD			0x01D0 -#define LSI6_TO			0x01D4 - -#define LSI7_CTL		0x01DC -#define LSI7_BS			0x01E0 -#define LSI7_BD			0x01E4 -#define LSI7_TO			0x01E8 - -static const int CA91CX42_LSI_CTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, -				LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL }; - -static const int CA91CX42_LSI_BS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, -				LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS }; - -static const int CA91CX42_LSI_BD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, -				LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD }; - -static const int CA91CX42_LSI_TO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, -				LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO }; - -#define SCYC_CTL		0x0170 -#define SCYC_ADDR		0x0174 -#define SCYC_EN			0x0178 -#define SCYC_CMP		0x017C -#define SCYC_SWP		0x0180 -#define LMISC			0x0184 -#define SLSI		        0x0188 -#define L_CMDERR		0x018C -#define LAERR		        0x0190 - -#define DCTL		        0x0200 -#define DTBC		        0x0204 -#define DLA			0x0208 -#define DVA			0x0210 -#define DCPP		        0x0218 -#define DGCS		        0x0220 -#define D_LLUE			0x0224 - -#define LINT_EN			0x0300 -#define LINT_STAT		0x0304 -#define LINT_MAP0		0x0308 -#define LINT_MAP1		0x030C -#define VINT_EN			0x0310 -#define VINT_STAT		0x0314 -#define VINT_MAP0		0x0318 -#define VINT_MAP1		0x031C -#define STATID			0x0320 - -#define V1_STATID		0x0324 -#define V2_STATID		0x0328 -#define V3_STATID		0x032C -#define V4_STATID		0x0330 -#define V5_STATID		0x0334 -#define V6_STATID		0x0338 -#define V7_STATID		0x033C - -static const int CA91CX42_V_STATID[8] = { 0, V1_STATID, V2_STATID, V3_STATID, -					V4_STATID, V5_STATID, V6_STATID, -					V7_STATID }; - -#define LINT_MAP2		0x0340 -#define VINT_MAP2		0x0344 - -#define MBOX0			0x0348 -#define MBOX1			0x034C -#define MBOX2			0x0350 -#define MBOX3			0x0354 -#define SEMA0			0x0358 -#define SEMA1			0x035C - -#define MAST_CTL		0x0400 -#define MISC_CTL		0x0404 -#define MISC_STAT		0x0408 -#define USER_AM			0x040C - -#define VSI0_CTL		0x0F00 -#define VSI0_BS			0x0F04 -#define VSI0_BD			0x0F08 -#define VSI0_TO			0x0F0C - -#define VSI1_CTL		0x0F14 -#define VSI1_BS			0x0F18 -#define VSI1_BD			0x0F1C -#define VSI1_TO			0x0F20 - -#define VSI2_CTL		0x0F28 -#define VSI2_BS			0x0F2C -#define VSI2_BD			0x0F30 -#define VSI2_TO			0x0F34 - -#define VSI3_CTL		0x0F3C -#define VSI3_BS			0x0F40 -#define VSI3_BD			0x0F44 -#define VSI3_TO			0x0F48 - -#define LM_CTL			0x0F64 -#define LM_BS			0x0F68 - -#define VRAI_CTL		0x0F70 - -#define VRAI_BS			0x0F74 -#define VCSR_CTL		0x0F80 -#define VCSR_TO			0x0F84 -#define V_AMERR			0x0F88 -#define VAERR			0x0F8C - -#define VSI4_CTL		0x0F90 -#define VSI4_BS			0x0F94 -#define VSI4_BD			0x0F98 -#define VSI4_TO			0x0F9C - -#define VSI5_CTL		0x0FA4 -#define VSI5_BS			0x0FA8 -#define VSI5_BD			0x0FAC -#define VSI5_TO			0x0FB0 - -#define VSI6_CTL		0x0FB8 -#define VSI6_BS			0x0FBC -#define VSI6_BD			0x0FC0 -#define VSI6_TO			0x0FC4 - -#define VSI7_CTL		0x0FCC -#define VSI7_BS			0x0FD0 -#define VSI7_BD			0x0FD4 -#define VSI7_TO			0x0FD8 - -static const int CA91CX42_VSI_CTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, -				VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL }; - -static const int CA91CX42_VSI_BS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, -				VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS }; - -static const int CA91CX42_VSI_BD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, -				VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD }; - -static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, -				VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO }; - -#define VCSR_CLR		0x0FF4 -#define VCSR_SET		0x0FF8 -#define VCSR_BS			0x0FFC - -/* - * PCI Class Register - * offset 008 - */ -#define CA91CX42_BM_PCI_CLASS_BASE          0xFF000000 -#define CA91CX42_OF_PCI_CLASS_BASE          24 -#define CA91CX42_BM_PCI_CLASS_SUB           0x00FF0000 -#define CA91CX42_OF_PCI_CLASS_SUB           16 -#define CA91CX42_BM_PCI_CLASS_PROG          0x0000FF00 -#define CA91CX42_OF_PCI_CLASS_PROG          8 -#define CA91CX42_BM_PCI_CLASS_RID           0x000000FF -#define CA91CX42_OF_PCI_CLASS_RID           0 - -#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_I 0 -#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_II 1 - -/* - * PCI Misc Register - * offset 00C - */ -#define CA91CX42_BM_PCI_MISC0_BISTC         0x80000000 -#define CA91CX42_BM_PCI_MISC0_SBIST         0x60000000 -#define CA91CX42_BM_PCI_MISC0_CCODE         0x0F000000 -#define CA91CX42_BM_PCI_MISC0_MFUNCT        0x00800000 -#define CA91CX42_BM_PCI_MISC0_LAYOUT        0x007F0000 -#define CA91CX42_BM_PCI_MISC0_LTIMER        0x0000FF00 -#define CA91CX42_OF_PCI_MISC0_LTIMER        8 - - -/* - * LSI Control Register - * offset  100 - */ -#define CA91CX42_LSI_CTL_EN		(1<<31) -#define CA91CX42_LSI_CTL_PWEN		(1<<30) - -#define CA91CX42_LSI_CTL_VDW_M		(3<<22) -#define CA91CX42_LSI_CTL_VDW_D8		0 -#define CA91CX42_LSI_CTL_VDW_D16	(1<<22) -#define CA91CX42_LSI_CTL_VDW_D32	(1<<23) -#define CA91CX42_LSI_CTL_VDW_D64	(3<<22) - -#define CA91CX42_LSI_CTL_VAS_M		(7<<16) -#define CA91CX42_LSI_CTL_VAS_A16	0 -#define CA91CX42_LSI_CTL_VAS_A24	(1<<16) -#define CA91CX42_LSI_CTL_VAS_A32	(1<<17) -#define CA91CX42_LSI_CTL_VAS_CRCSR	(5<<16) -#define CA91CX42_LSI_CTL_VAS_USER1	(3<<17) -#define CA91CX42_LSI_CTL_VAS_USER2	(7<<16) - -#define CA91CX42_LSI_CTL_PGM_M		(1<<14) -#define CA91CX42_LSI_CTL_PGM_DATA	0 -#define CA91CX42_LSI_CTL_PGM_PGM	(1<<14) - -#define CA91CX42_LSI_CTL_SUPER_M	(1<<12) -#define CA91CX42_LSI_CTL_SUPER_NPRIV	0 -#define CA91CX42_LSI_CTL_SUPER_SUPR	(1<<12) - -#define CA91CX42_LSI_CTL_VCT_M		(1<<8) -#define CA91CX42_LSI_CTL_VCT_BLT	(1<<8) -#define CA91CX42_LSI_CTL_VCT_MBLT	(1<<8) -#define CA91CX42_LSI_CTL_LAS		(1<<0) - -/* - * SCYC_CTL Register - * offset 178 - */ -#define CA91CX42_SCYC_CTL_LAS_PCIMEM	0 -#define CA91CX42_SCYC_CTL_LAS_PCIIO	(1<<2) - -#define CA91CX42_SCYC_CTL_CYC_M		(3<<0) -#define CA91CX42_SCYC_CTL_CYC_RMW	(1<<0) -#define CA91CX42_SCYC_CTL_CYC_ADOH	(1<<1) - -/* - * LMISC Register - * offset  184 - */ -#define CA91CX42_BM_LMISC_CRT               0xF0000000 -#define CA91CX42_OF_LMISC_CRT               28 -#define CA91CX42_BM_LMISC_CWT               0x0F000000 -#define CA91CX42_OF_LMISC_CWT               24 - -/* - * SLSI Register - * offset  188 - */ -#define CA91CX42_BM_SLSI_EN                 0x80000000 -#define CA91CX42_BM_SLSI_PWEN               0x40000000 -#define CA91CX42_BM_SLSI_VDW                0x00F00000 -#define CA91CX42_OF_SLSI_VDW                20 -#define CA91CX42_BM_SLSI_PGM                0x0000F000 -#define CA91CX42_OF_SLSI_PGM                12 -#define CA91CX42_BM_SLSI_SUPER              0x00000F00 -#define CA91CX42_OF_SLSI_SUPER              8 -#define CA91CX42_BM_SLSI_BS                 0x000000F6 -#define CA91CX42_OF_SLSI_BS                 2 -#define CA91CX42_BM_SLSI_LAS                0x00000003 -#define CA91CX42_OF_SLSI_LAS                0 -#define CA91CX42_BM_SLSI_RESERVED           0x3F0F0000 - -/* - * DCTL Register - * offset 200 - */ -#define CA91CX42_DCTL_L2V		(1<<31) -#define CA91CX42_DCTL_VDW_M		(3<<22) -#define CA91CX42_DCTL_VDW_M		(3<<22) -#define CA91CX42_DCTL_VDW_D8		0 -#define CA91CX42_DCTL_VDW_D16		(1<<22) -#define CA91CX42_DCTL_VDW_D32		(1<<23) -#define CA91CX42_DCTL_VDW_D64		(3<<22) - -#define CA91CX42_DCTL_VAS_M		(7<<16) -#define CA91CX42_DCTL_VAS_A16		0 -#define CA91CX42_DCTL_VAS_A24		(1<<16) -#define CA91CX42_DCTL_VAS_A32		(1<<17) -#define CA91CX42_DCTL_VAS_USER1		(3<<17) -#define CA91CX42_DCTL_VAS_USER2		(7<<16) - -#define CA91CX42_DCTL_PGM_M		(1<<14) -#define CA91CX42_DCTL_PGM_DATA		0 -#define CA91CX42_DCTL_PGM_PGM		(1<<14) - -#define CA91CX42_DCTL_SUPER_M		(1<<12) -#define CA91CX42_DCTL_SUPER_NPRIV	0 -#define CA91CX42_DCTL_SUPER_SUPR	(1<<12) - -#define CA91CX42_DCTL_VCT_M		(1<<8) -#define CA91CX42_DCTL_VCT_BLT		(1<<8) -#define CA91CX42_DCTL_LD64EN		(1<<7) - -/* - * DCPP Register - * offset 218 - */ -#define CA91CX42_DCPP_M			0xf -#define CA91CX42_DCPP_NULL		(1<<0) - -/* - * DMA General Control/Status Register (DGCS) - * offset 220 - */ -#define CA91CX42_DGCS_GO		(1<<31) -#define CA91CX42_DGCS_STOP_REQ		(1<<30) -#define CA91CX42_DGCS_HALT_REQ		(1<<29) -#define CA91CX42_DGCS_CHAIN		(1<<27) - -#define CA91CX42_DGCS_VON_M		(7<<20) - -#define CA91CX42_DGCS_VOFF_M		(0xf<<16) - -#define CA91CX42_DGCS_ACT		(1<<15) -#define CA91CX42_DGCS_STOP		(1<<14) -#define CA91CX42_DGCS_HALT		(1<<13) -#define CA91CX42_DGCS_DONE		(1<<11) -#define CA91CX42_DGCS_LERR		(1<<10) -#define CA91CX42_DGCS_VERR		(1<<9) -#define CA91CX42_DGCS_PERR		(1<<8) -#define CA91CX42_DGCS_INT_STOP		(1<<6) -#define CA91CX42_DGCS_INT_HALT		(1<<5) -#define CA91CX42_DGCS_INT_DONE		(1<<3) -#define CA91CX42_DGCS_INT_LERR		(1<<2) -#define CA91CX42_DGCS_INT_VERR		(1<<1) -#define CA91CX42_DGCS_INT_PERR		(1<<0) - -/* - * PCI Interrupt Enable Register - * offset  300 - */ -#define CA91CX42_LINT_LM3		0x00800000 -#define CA91CX42_LINT_LM2		0x00400000 -#define CA91CX42_LINT_LM1		0x00200000 -#define CA91CX42_LINT_LM0		0x00100000 -#define CA91CX42_LINT_MBOX3		0x00080000 -#define CA91CX42_LINT_MBOX2		0x00040000 -#define CA91CX42_LINT_MBOX1		0x00020000 -#define CA91CX42_LINT_MBOX0		0x00010000 -#define CA91CX42_LINT_ACFAIL		0x00008000 -#define CA91CX42_LINT_SYSFAIL		0x00004000 -#define CA91CX42_LINT_SW_INT		0x00002000 -#define CA91CX42_LINT_SW_IACK		0x00001000 - -#define CA91CX42_LINT_VERR		0x00000400 -#define CA91CX42_LINT_LERR		0x00000200 -#define CA91CX42_LINT_DMA		0x00000100 -#define CA91CX42_LINT_VIRQ7		0x00000080 -#define CA91CX42_LINT_VIRQ6		0x00000040 -#define CA91CX42_LINT_VIRQ5		0x00000020 -#define CA91CX42_LINT_VIRQ4		0x00000010 -#define CA91CX42_LINT_VIRQ3		0x00000008 -#define CA91CX42_LINT_VIRQ2		0x00000004 -#define CA91CX42_LINT_VIRQ1		0x00000002 -#define CA91CX42_LINT_VOWN		0x00000001 - -static const int CA91CX42_LINT_VIRQ[] = { 0, CA91CX42_LINT_VIRQ1, -				CA91CX42_LINT_VIRQ2, CA91CX42_LINT_VIRQ3, -				CA91CX42_LINT_VIRQ4, CA91CX42_LINT_VIRQ5, -				CA91CX42_LINT_VIRQ6, CA91CX42_LINT_VIRQ7 }; - -#define CA91CX42_LINT_MBOX		0x000F0000 - -static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1, -					CA91CX42_LINT_LM2, CA91CX42_LINT_LM3 }; - -/* - * MAST_CTL Register - * offset  400 - */ -#define CA91CX42_BM_MAST_CTL_MAXRTRY        0xF0000000 -#define CA91CX42_OF_MAST_CTL_MAXRTRY        28 -#define CA91CX42_BM_MAST_CTL_PWON           0x0F000000 -#define CA91CX42_OF_MAST_CTL_PWON           24 -#define CA91CX42_BM_MAST_CTL_VRL            0x00C00000 -#define CA91CX42_OF_MAST_CTL_VRL            22 -#define CA91CX42_BM_MAST_CTL_VRM            0x00200000 -#define CA91CX42_BM_MAST_CTL_VREL           0x00100000 -#define CA91CX42_BM_MAST_CTL_VOWN           0x00080000 -#define CA91CX42_BM_MAST_CTL_VOWN_ACK       0x00040000 -#define CA91CX42_BM_MAST_CTL_PABS           0x00001000 -#define CA91CX42_BM_MAST_CTL_BUS_NO         0x0000000F -#define CA91CX42_OF_MAST_CTL_BUS_NO         0 - -/* - * MISC_CTL Register - * offset  404 - */ -#define CA91CX42_MISC_CTL_VBTO           0xF0000000 -#define CA91CX42_MISC_CTL_VARB           0x04000000 -#define CA91CX42_MISC_CTL_VARBTO         0x03000000 -#define CA91CX42_MISC_CTL_SW_LRST        0x00800000 -#define CA91CX42_MISC_CTL_SW_SRST        0x00400000 -#define CA91CX42_MISC_CTL_BI             0x00100000 -#define CA91CX42_MISC_CTL_ENGBI          0x00080000 -#define CA91CX42_MISC_CTL_RESCIND        0x00040000 -#define CA91CX42_MISC_CTL_SYSCON         0x00020000 -#define CA91CX42_MISC_CTL_V64AUTO        0x00010000 -#define CA91CX42_MISC_CTL_RESERVED       0x0820FFFF - -#define CA91CX42_OF_MISC_CTL_VARBTO         24 -#define CA91CX42_OF_MISC_CTL_VBTO           28 - -/* - * MISC_STAT Register - * offset  408 - */ -#define CA91CX42_BM_MISC_STAT_ENDIAN        0x80000000 -#define CA91CX42_BM_MISC_STAT_LCLSIZE       0x40000000 -#define CA91CX42_BM_MISC_STAT_DY4AUTO       0x08000000 -#define CA91CX42_BM_MISC_STAT_MYBBSY        0x00200000 -#define CA91CX42_BM_MISC_STAT_DY4DONE       0x00080000 -#define CA91CX42_BM_MISC_STAT_TXFE          0x00040000 -#define CA91CX42_BM_MISC_STAT_RXFE          0x00020000 -#define CA91CX42_BM_MISC_STAT_DY4AUTOID     0x0000FF00 -#define CA91CX42_OF_MISC_STAT_DY4AUTOID     8 - -/* - * VSI Control Register - * offset  F00 - */ -#define CA91CX42_VSI_CTL_EN		(1<<31) -#define CA91CX42_VSI_CTL_PWEN		(1<<30) -#define CA91CX42_VSI_CTL_PREN		(1<<29) - -#define CA91CX42_VSI_CTL_PGM_M		(3<<22) -#define CA91CX42_VSI_CTL_PGM_DATA	(1<<22) -#define CA91CX42_VSI_CTL_PGM_PGM	(1<<23) - -#define CA91CX42_VSI_CTL_SUPER_M	(3<<20) -#define CA91CX42_VSI_CTL_SUPER_NPRIV	(1<<20) -#define CA91CX42_VSI_CTL_SUPER_SUPR	(1<<21) - -#define CA91CX42_VSI_CTL_VAS_M		(7<<16) -#define CA91CX42_VSI_CTL_VAS_A16	0 -#define CA91CX42_VSI_CTL_VAS_A24	(1<<16) -#define CA91CX42_VSI_CTL_VAS_A32	(1<<17) -#define CA91CX42_VSI_CTL_VAS_USER1	(3<<17) -#define CA91CX42_VSI_CTL_VAS_USER2	(7<<16) - -#define CA91CX42_VSI_CTL_LD64EN		(1<<7) -#define CA91CX42_VSI_CTL_LLRMW		(1<<6) - -#define CA91CX42_VSI_CTL_LAS_M		(3<<0) -#define CA91CX42_VSI_CTL_LAS_PCI_MS	0 -#define CA91CX42_VSI_CTL_LAS_PCI_IO	(1<<0) -#define CA91CX42_VSI_CTL_LAS_PCI_CONF	(1<<1) - -/* LM_CTL Register - * offset  F64 - */ -#define CA91CX42_LM_CTL_EN		(1<<31) -#define CA91CX42_LM_CTL_PGM		(1<<23) -#define CA91CX42_LM_CTL_DATA		(1<<22) -#define CA91CX42_LM_CTL_SUPR		(1<<21) -#define CA91CX42_LM_CTL_NPRIV		(1<<20) -#define CA91CX42_LM_CTL_AS_M		(5<<16) -#define CA91CX42_LM_CTL_AS_A16		0 -#define CA91CX42_LM_CTL_AS_A24		(1<<16) -#define CA91CX42_LM_CTL_AS_A32		(1<<17) - -/* - * VRAI_CTL Register - * offset  F70 - */ -#define CA91CX42_BM_VRAI_CTL_EN             0x80000000 -#define CA91CX42_BM_VRAI_CTL_PGM            0x00C00000 -#define CA91CX42_OF_VRAI_CTL_PGM            22 -#define CA91CX42_BM_VRAI_CTL_SUPER          0x00300000 -#define CA91CX42_OF_VRAI_CTL_SUPER          20 -#define CA91CX42_BM_VRAI_CTL_VAS            0x00030000 -#define CA91CX42_OF_VRAI_CTL_VAS            16 - -/* VCSR_CTL Register - * offset F80 - */ -#define CA91CX42_VCSR_CTL_EN		(1<<31) - -#define CA91CX42_VCSR_CTL_LAS_M		(3<<0) -#define CA91CX42_VCSR_CTL_LAS_PCI_MS	0 -#define CA91CX42_VCSR_CTL_LAS_PCI_IO	(1<<0) -#define CA91CX42_VCSR_CTL_LAS_PCI_CONF	(1<<1) - -/* VCSR_BS Register - * offset FFC - */ -#define CA91CX42_VCSR_BS_SLOT_M		(0x1F<<27) - -#endif /* _CA91CX42_H */ diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c deleted file mode 100644 index 492ddb2d510..00000000000 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ /dev/null @@ -1,2641 +0,0 @@ -/* - * Support for the Tundra TSI148 VME-PCI Bridge Chip - * - * Author: Martyn Welch <martyn.welch@ge.com> - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. - * - * Based on work by Tom Armistead and Ajit Prem - * Copyright 2004 Motorola 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/module.h> -#include <linux/moduleparam.h> -#include <linux/mm.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/proc_fs.h> -#include <linux/pci.h> -#include <linux/poll.h> -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/io.h> -#include <linux/uaccess.h> - -#include "../vme.h" -#include "../vme_bridge.h" -#include "vme_tsi148.h" - -static int __init tsi148_init(void); -static int tsi148_probe(struct pci_dev *, const struct pci_device_id *); -static void tsi148_remove(struct pci_dev *); -static void __exit tsi148_exit(void); - - -/* Module parameter */ -static int err_chk; -static int geoid; - -static char driver_name[] = "vme_tsi148"; - -static const struct pci_device_id tsi148_ids[] = { -	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) }, -	{ }, -}; - -static struct pci_driver tsi148_driver = { -	.name = driver_name, -	.id_table = tsi148_ids, -	.probe = tsi148_probe, -	.remove = tsi148_remove, -}; - -static void reg_join(unsigned int high, unsigned int low, -	unsigned long long *variable) -{ -	*variable = (unsigned long long)high << 32; -	*variable |= (unsigned long long)low; -} - -static void reg_split(unsigned long long variable, unsigned int *high, -	unsigned int *low) -{ -	*low = (unsigned int)variable & 0xFFFFFFFF; -	*high = (unsigned int)(variable >> 32); -} - -/* - * Wakes up DMA queue. - */ -static u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge, -	int channel_mask) -{ -	u32 serviced = 0; - -	if (channel_mask & TSI148_LCSR_INTS_DMA0S) { -		wake_up(&(bridge->dma_queue[0])); -		serviced |= TSI148_LCSR_INTC_DMA0C; -	} -	if (channel_mask & TSI148_LCSR_INTS_DMA1S) { -		wake_up(&(bridge->dma_queue[1])); -		serviced |= TSI148_LCSR_INTC_DMA1C; -	} - -	return serviced; -} - -/* - * Wake up location monitor queue - */ -static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat) -{ -	int i; -	u32 serviced = 0; - -	for (i = 0; i < 4; i++) { -		if (stat & TSI148_LCSR_INTS_LMS[i]) { -			/* We only enable interrupts if the callback is set */ -			bridge->lm_callback[i](i); -			serviced |= TSI148_LCSR_INTC_LMC[i]; -		} -	} - -	return serviced; -} - -/* - * Wake up mail box queue. - * - * XXX This functionality is not exposed up though API. - */ -static u32 tsi148_MB_irqhandler(struct vme_bridge *tsi148_bridge, u32 stat) -{ -	int i; -	u32 val; -	u32 serviced = 0; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	for (i = 0; i < 4; i++) { -		if (stat & TSI148_LCSR_INTS_MBS[i]) { -			val = ioread32be(bridge->base +	TSI148_GCSR_MBOX[i]); -			dev_err(tsi148_bridge->parent, "VME Mailbox %d received" -				": 0x%x\n", i, val); -			serviced |= TSI148_LCSR_INTC_MBC[i]; -		} -	} - -	return serviced; -} - -/* - * Display error & status message when PERR (PCI) exception interrupt occurs. - */ -static u32 tsi148_PERR_irqhandler(struct vme_bridge *tsi148_bridge) -{ -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	dev_err(tsi148_bridge->parent, "PCI Exception at address: 0x%08x:%08x, " -		"attributes: %08x\n", -		ioread32be(bridge->base + TSI148_LCSR_EDPAU), -		ioread32be(bridge->base + TSI148_LCSR_EDPAL), -		ioread32be(bridge->base + TSI148_LCSR_EDPAT)); - -	dev_err(tsi148_bridge->parent, "PCI-X attribute reg: %08x, PCI-X split " -		"completion reg: %08x\n", -		ioread32be(bridge->base + TSI148_LCSR_EDPXA), -		ioread32be(bridge->base + TSI148_LCSR_EDPXS)); - -	iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT); - -	return TSI148_LCSR_INTC_PERRC; -} - -/* - * Save address and status when VME error interrupt occurs. - */ -static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) -{ -	unsigned int error_addr_high, error_addr_low; -	unsigned long long error_addr; -	u32 error_attrib; -	struct vme_bus_error *error; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU); -	error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL); -	error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT); - -	reg_join(error_addr_high, error_addr_low, &error_addr); - -	/* Check for exception register overflow (we have lost error data) */ -	if (error_attrib & TSI148_LCSR_VEAT_VEOF) { -		dev_err(tsi148_bridge->parent, "VME Bus Exception Overflow " -			"Occurred\n"); -	} - -	error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); -	if (error) { -		error->address = error_addr; -		error->attributes = error_attrib; -		list_add_tail(&(error->list), &(tsi148_bridge->vme_errors)); -	} else { -		dev_err(tsi148_bridge->parent, "Unable to alloc memory for " -			"VMEbus Error reporting\n"); -		dev_err(tsi148_bridge->parent, "VME Bus Error at address: " -			"0x%llx, attributes: %08x\n", error_addr, error_attrib); -	} - -	/* Clear Status */ -	iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT); - -	return TSI148_LCSR_INTC_VERRC; -} - -/* - * Wake up IACK queue. - */ -static u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge) -{ -	wake_up(&(bridge->iack_queue)); - -	return TSI148_LCSR_INTC_IACKC; -} - -/* - * Calling VME bus interrupt callback if provided. - */ -static u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge, -	u32 stat) -{ -	int vec, i, serviced = 0; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	for (i = 7; i > 0; i--) { -		if (stat & (1 << i)) { -			/* -			 * Note: Even though the registers are defined as -			 * 32-bits in the spec, we only want to issue 8-bit -			 * IACK cycles on the bus, read from offset 3. -			 */ -			vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3); - -			vme_irq_handler(tsi148_bridge, i, vec); - -			serviced |= (1 << i); -		} -	} - -	return serviced; -} - -/* - * Top level interrupt handler.  Clears appropriate interrupt status bits and - * then calls appropriate sub handler(s). - */ -static irqreturn_t tsi148_irqhandler(int irq, void *ptr) -{ -	u32 stat, enable, serviced = 0; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	tsi148_bridge = ptr; - -	bridge = tsi148_bridge->driver_priv; - -	/* Determine which interrupts are unmasked and set */ -	enable = ioread32be(bridge->base + TSI148_LCSR_INTEO); -	stat = ioread32be(bridge->base + TSI148_LCSR_INTS); - -	/* Only look at unmasked interrupts */ -	stat &= enable; - -	if (unlikely(!stat)) -		return IRQ_NONE; - -	/* Call subhandlers as appropriate */ -	/* DMA irqs */ -	if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S)) -		serviced |= tsi148_DMA_irqhandler(bridge, stat); - -	/* Location monitor irqs */ -	if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S | -			TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S)) -		serviced |= tsi148_LM_irqhandler(bridge, stat); - -	/* Mail box irqs */ -	if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S | -			TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S)) -		serviced |= tsi148_MB_irqhandler(tsi148_bridge, stat); - -	/* PCI bus error */ -	if (stat & TSI148_LCSR_INTS_PERRS) -		serviced |= tsi148_PERR_irqhandler(tsi148_bridge); - -	/* VME bus error */ -	if (stat & TSI148_LCSR_INTS_VERRS) -		serviced |= tsi148_VERR_irqhandler(tsi148_bridge); - -	/* IACK irq */ -	if (stat & TSI148_LCSR_INTS_IACKS) -		serviced |= tsi148_IACK_irqhandler(bridge); - -	/* VME bus irqs */ -	if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S | -			TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S | -			TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S | -			TSI148_LCSR_INTS_IRQ1S)) -		serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat); - -	/* Clear serviced interrupts */ -	iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC); - -	return IRQ_HANDLED; -} - -static int tsi148_irq_init(struct vme_bridge *tsi148_bridge) -{ -	int result; -	unsigned int tmp; -	struct pci_dev *pdev; -	struct tsi148_driver *bridge; - -	pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); - -	bridge = tsi148_bridge->driver_priv; - -	/* Initialise list for VME bus errors */ -	INIT_LIST_HEAD(&(tsi148_bridge->vme_errors)); - -	mutex_init(&(tsi148_bridge->irq_mtx)); - -	result = request_irq(pdev->irq, -			     tsi148_irqhandler, -			     IRQF_SHARED, -			     driver_name, tsi148_bridge); -	if (result) { -		dev_err(tsi148_bridge->parent, "Can't get assigned pci irq " -			"vector %02X\n", pdev->irq); -		return result; -	} - -	/* Enable and unmask interrupts */ -	tmp = TSI148_LCSR_INTEO_DMA1EO | TSI148_LCSR_INTEO_DMA0EO | -		TSI148_LCSR_INTEO_MB3EO | TSI148_LCSR_INTEO_MB2EO | -		TSI148_LCSR_INTEO_MB1EO | TSI148_LCSR_INTEO_MB0EO | -		TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO | -		TSI148_LCSR_INTEO_IACKEO; - -	/* This leaves the following interrupts masked. -	 * TSI148_LCSR_INTEO_VIEEO -	 * TSI148_LCSR_INTEO_SYSFLEO -	 * TSI148_LCSR_INTEO_ACFLEO -	 */ - -	/* Don't enable Location Monitor interrupts here - they will be -	 * enabled when the location monitors are properly configured and -	 * a callback has been attached. -	 * TSI148_LCSR_INTEO_LM0EO -	 * TSI148_LCSR_INTEO_LM1EO -	 * TSI148_LCSR_INTEO_LM2EO -	 * TSI148_LCSR_INTEO_LM3EO -	 */ - -	/* Don't enable VME interrupts until we add a handler, else the board -	 * will respond to it and we don't want that unless it knows how to -	 * properly deal with it. -	 * TSI148_LCSR_INTEO_IRQ7EO -	 * TSI148_LCSR_INTEO_IRQ6EO -	 * TSI148_LCSR_INTEO_IRQ5EO -	 * TSI148_LCSR_INTEO_IRQ4EO -	 * TSI148_LCSR_INTEO_IRQ3EO -	 * TSI148_LCSR_INTEO_IRQ2EO -	 * TSI148_LCSR_INTEO_IRQ1EO -	 */ - -	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); -	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - -	return 0; -} - -static void tsi148_irq_exit(struct tsi148_driver *bridge, struct pci_dev *pdev) -{ -	/* Turn off interrupts */ -	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO); -	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN); - -	/* Clear all interrupts */ -	iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC); - -	/* Detach interrupt handler */ -	free_irq(pdev->irq, pdev); -} - -/* - * Check to see if an IACk has been received, return true (1) or false (0). - */ -int tsi148_iack_received(struct tsi148_driver *bridge) -{ -	u32 tmp; - -	tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); - -	if (tmp & TSI148_LCSR_VICR_IRQS) -		return 0; -	else -		return 1; -} - -/* - * Configure VME interrupt - */ -void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, -	int state, int sync) -{ -	struct pci_dev *pdev; -	u32 tmp; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	/* We need to do the ordering differently for enabling and disabling */ -	if (state == 0) { -		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); -		tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1]; -		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - -		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); -		tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1]; -		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - -		if (sync != 0) { -			pdev = container_of(tsi148_bridge->parent, -				struct pci_dev, dev); - -			synchronize_irq(pdev->irq); -		} -	} else { -		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); -		tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; -		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - -		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); -		tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; -		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); -	} -} - -/* - * Generate a VME bus interrupt at the requested level & vector. Wait for - * interrupt to be acked. - */ -int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, int statid) -{ -	u32 tmp; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	mutex_lock(&(bridge->vme_int)); - -	/* Read VICR register */ -	tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); - -	/* Set Status/ID */ -	tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) | -		(statid & TSI148_LCSR_VICR_STID_M); -	iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); - -	/* Assert VMEbus IRQ */ -	tmp = tmp | TSI148_LCSR_VICR_IRQL[level]; -	iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); - -	/* XXX Consider implementing a timeout? */ -	wait_event_interruptible(bridge->iack_queue, -		tsi148_iack_received(bridge)); - -	mutex_unlock(&(bridge->vme_int)); - -	return 0; -} - -/* - * 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) -{ -	struct list_head *err_pos; -	struct vme_bus_error *vme_err, *valid = NULL; -	unsigned long long bound; - -	bound = address + count; - -	/* -	 * XXX We are currently not looking at the address space when parsing -	 *     for errors. This is because parsing the Address Modifier Codes -	 *     is going to be quite resource intensive to do properly. We -	 *     should be OK just looking at the addresses and this is certainly -	 *     much better than what we had before. -	 */ -	err_pos = NULL; -	/* Iterate through errors */ -	list_for_each(err_pos, &(tsi148_bridge->vme_errors)) { -		vme_err = list_entry(err_pos, struct vme_bus_error, list); -		if ((vme_err->address >= address) && -			(vme_err->address < bound)) { - -			valid = vme_err; -			break; -		} -	} - -	return valid; -} - -/* - * 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) -{ -	struct list_head *err_pos, *temp; -	struct vme_bus_error *vme_err; -	unsigned long long bound; - -	bound = address + count; - -	/* -	 * XXX We are currently not looking at the address space when parsing -	 *     for errors. This is because parsing the Address Modifier Codes -	 *     is going to be quite resource intensive to do properly. We -	 *     should be OK just looking at the addresses and this is certainly -	 *     much better than what we had before. -	 */ -	err_pos = NULL; -	/* Iterate through errors */ -	list_for_each_safe(err_pos, temp, &(tsi148_bridge->vme_errors)) { -		vme_err = list_entry(err_pos, struct vme_bus_error, list); - -		if ((vme_err->address >= address) && -			(vme_err->address < bound)) { - -			list_del(err_pos); -			kfree(vme_err); -		} -	} -} - -/* - * Initialize a slave window with the requested attributes. - */ -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) -{ -	unsigned int i, addr = 0, granularity = 0; -	unsigned int temp_ctl = 0; -	unsigned int vme_base_low, vme_base_high; -	unsigned int vme_bound_low, vme_bound_high; -	unsigned int pci_offset_low, pci_offset_high; -	unsigned long long vme_bound, pci_offset; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	tsi148_bridge = image->parent; -	bridge = tsi148_bridge->driver_priv; - -	i = image->number; - -	switch (aspace) { -	case VME_A16: -		granularity = 0x10; -		addr |= TSI148_LCSR_ITAT_AS_A16; -		break; -	case VME_A24: -		granularity = 0x1000; -		addr |= TSI148_LCSR_ITAT_AS_A24; -		break; -	case VME_A32: -		granularity = 0x10000; -		addr |= TSI148_LCSR_ITAT_AS_A32; -		break; -	case VME_A64: -		granularity = 0x10000; -		addr |= TSI148_LCSR_ITAT_AS_A64; -		break; -	case VME_CRCSR: -	case VME_USER1: -	case VME_USER2: -	case VME_USER3: -	case VME_USER4: -	default: -		dev_err(tsi148_bridge->parent, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	/* Convert 64-bit variables to 2x 32-bit variables */ -	reg_split(vme_base, &vme_base_high, &vme_base_low); - -	/* -	 * Bound address is a valid address for the window, adjust -	 * accordingly -	 */ -	vme_bound = vme_base + size - granularity; -	reg_split(vme_bound, &vme_bound_high, &vme_bound_low); -	pci_offset = (unsigned long long)pci_base - vme_base; -	reg_split(pci_offset, &pci_offset_high, &pci_offset_low); - -	if (vme_base_low & (granularity - 1)) { -		dev_err(tsi148_bridge->parent, "Invalid VME base alignment\n"); -		return -EINVAL; -	} -	if (vme_bound_low & (granularity - 1)) { -		dev_err(tsi148_bridge->parent, "Invalid VME bound alignment\n"); -		return -EINVAL; -	} -	if (pci_offset_low & (granularity - 1)) { -		dev_err(tsi148_bridge->parent, "Invalid PCI Offset " -			"alignment\n"); -		return -EINVAL; -	} - -	/*  Disable while we are mucking around */ -	temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITAT); -	temp_ctl &= ~TSI148_LCSR_ITAT_EN; -	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITAT); - -	/* Setup mapping */ -	iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITSAU); -	iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITSAL); -	iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITEAU); -	iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITEAL); -	iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITOFU); -	iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITOFL); - -	/* Setup 2eSST speeds */ -	temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M; -	switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { -	case VME_2eSST160: -		temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_160; -		break; -	case VME_2eSST267: -		temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_267; -		break; -	case VME_2eSST320: -		temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_320; -		break; -	} - -	/* Setup cycle types */ -	temp_ctl &= ~(0x1F << 7); -	if (cycle & VME_BLT) -		temp_ctl |= TSI148_LCSR_ITAT_BLT; -	if (cycle & VME_MBLT) -		temp_ctl |= TSI148_LCSR_ITAT_MBLT; -	if (cycle & VME_2eVME) -		temp_ctl |= TSI148_LCSR_ITAT_2eVME; -	if (cycle & VME_2eSST) -		temp_ctl |= TSI148_LCSR_ITAT_2eSST; -	if (cycle & VME_2eSSTB) -		temp_ctl |= TSI148_LCSR_ITAT_2eSSTB; - -	/* Setup address space */ -	temp_ctl &= ~TSI148_LCSR_ITAT_AS_M; -	temp_ctl |= addr; - -	temp_ctl &= ~0xF; -	if (cycle & VME_SUPER) -		temp_ctl |= TSI148_LCSR_ITAT_SUPR ; -	if (cycle & VME_USER) -		temp_ctl |= TSI148_LCSR_ITAT_NPRIV; -	if (cycle & VME_PROG) -		temp_ctl |= TSI148_LCSR_ITAT_PGM; -	if (cycle & VME_DATA) -		temp_ctl |= TSI148_LCSR_ITAT_DATA; - -	/* Write ctl reg without enable */ -	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITAT); - -	if (enabled) -		temp_ctl |= TSI148_LCSR_ITAT_EN; - -	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITAT); - -	return 0; -} - -/* - * Get slave window configuration. - */ -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) -{ -	unsigned int i, granularity = 0, ctl = 0; -	unsigned int vme_base_low, vme_base_high; -	unsigned int vme_bound_low, vme_bound_high; -	unsigned int pci_offset_low, pci_offset_high; -	unsigned long long vme_bound, pci_offset; -	struct tsi148_driver *bridge; - -	bridge = image->parent->driver_priv; - -	i = image->number; - -	/* Read registers */ -	ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITAT); - -	vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITSAU); -	vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITSAL); -	vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITEAU); -	vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITEAL); -	pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITOFU); -	pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + -		TSI148_LCSR_OFFSET_ITOFL); - -	/* Convert 64-bit variables to 2x 32-bit variables */ -	reg_join(vme_base_high, vme_base_low, vme_base); -	reg_join(vme_bound_high, vme_bound_low, &vme_bound); -	reg_join(pci_offset_high, pci_offset_low, &pci_offset); - -	*pci_base = (dma_addr_t)vme_base + pci_offset; - -	*enabled = 0; -	*aspace = 0; -	*cycle = 0; - -	if (ctl & TSI148_LCSR_ITAT_EN) -		*enabled = 1; - -	if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A16) { -		granularity = 0x10; -		*aspace |= VME_A16; -	} -	if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A24) { -		granularity = 0x1000; -		*aspace |= VME_A24; -	} -	if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A32) { -		granularity = 0x10000; -		*aspace |= VME_A32; -	} -	if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A64) { -		granularity = 0x10000; -		*aspace |= VME_A64; -	} - -	/* Need granularity before we set the size */ -	*size = (unsigned long long)((vme_bound - *vme_base) + granularity); - - -	if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_160) -		*cycle |= VME_2eSST160; -	if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_267) -		*cycle |= VME_2eSST267; -	if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_320) -		*cycle |= VME_2eSST320; - -	if (ctl & TSI148_LCSR_ITAT_BLT) -		*cycle |= VME_BLT; -	if (ctl & TSI148_LCSR_ITAT_MBLT) -		*cycle |= VME_MBLT; -	if (ctl & TSI148_LCSR_ITAT_2eVME) -		*cycle |= VME_2eVME; -	if (ctl & TSI148_LCSR_ITAT_2eSST) -		*cycle |= VME_2eSST; -	if (ctl & TSI148_LCSR_ITAT_2eSSTB) -		*cycle |= VME_2eSSTB; - -	if (ctl & TSI148_LCSR_ITAT_SUPR) -		*cycle |= VME_SUPER; -	if (ctl & TSI148_LCSR_ITAT_NPRIV) -		*cycle |= VME_USER; -	if (ctl & TSI148_LCSR_ITAT_PGM) -		*cycle |= VME_PROG; -	if (ctl & TSI148_LCSR_ITAT_DATA) -		*cycle |= VME_DATA; - -	return 0; -} - -/* - * Allocate and map PCI Resource - */ -static int tsi148_alloc_resource(struct vme_master_resource *image, -	unsigned long long size) -{ -	unsigned long long existing_size; -	int retval = 0; -	struct pci_dev *pdev; -	struct vme_bridge *tsi148_bridge; - -	tsi148_bridge = image->parent; - -	pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); - -	existing_size = (unsigned long long)(image->bus_resource.end - -		image->bus_resource.start); - -	/* If the existing size is OK, return */ -	if ((size != 0) && (existing_size == (size - 1))) -		return 0; - -	if (existing_size != 0) { -		iounmap(image->kern_base); -		image->kern_base = NULL; -		if (image->bus_resource.name != NULL) -			kfree(image->bus_resource.name); -		release_resource(&(image->bus_resource)); -		memset(&(image->bus_resource), 0, sizeof(struct resource)); -	} - -	/* Exit here if size is zero */ -	if (size == 0) -		return 0; - -	if (image->bus_resource.name == NULL) { -		image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); -		if (image->bus_resource.name == NULL) { -			dev_err(tsi148_bridge->parent, "Unable to allocate " -				"memory for resource name\n"); -			retval = -ENOMEM; -			goto err_name; -		} -	} - -	sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name, -		image->number); - -	image->bus_resource.start = 0; -	image->bus_resource.end = (unsigned long)size; -	image->bus_resource.flags = IORESOURCE_MEM; - -	retval = pci_bus_alloc_resource(pdev->bus, -		&(image->bus_resource), size, size, PCIBIOS_MIN_MEM, -		0, NULL, NULL); -	if (retval) { -		dev_err(tsi148_bridge->parent, "Failed to allocate mem " -			"resource for window %d size 0x%lx start 0x%lx\n", -			image->number, (unsigned long)size, -			(unsigned long)image->bus_resource.start); -		goto err_resource; -	} - -	image->kern_base = ioremap_nocache( -		image->bus_resource.start, size); -	if (image->kern_base == NULL) { -		dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); -		retval = -ENOMEM; -		goto err_remap; -	} - -	return 0; - -	iounmap(image->kern_base); -	image->kern_base = NULL; -err_remap: -	release_resource(&(image->bus_resource)); -err_resource: -	kfree(image->bus_resource.name); -	memset(&(image->bus_resource), 0, sizeof(struct resource)); -err_name: -	return retval; -} - -/* - * Free and unmap PCI Resource - */ -static void tsi148_free_resource(struct vme_master_resource *image) -{ -	iounmap(image->kern_base); -	image->kern_base = NULL; -	release_resource(&(image->bus_resource)); -	kfree(image->bus_resource.name); -	memset(&(image->bus_resource), 0, sizeof(struct resource)); -} - -/* - * Set the attributes of an outbound window. - */ -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) -{ -	int retval = 0; -	unsigned int i; -	unsigned int temp_ctl = 0; -	unsigned int pci_base_low, pci_base_high; -	unsigned int pci_bound_low, pci_bound_high; -	unsigned int vme_offset_low, vme_offset_high; -	unsigned long long pci_bound, vme_offset, pci_base; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	tsi148_bridge = image->parent; - -	bridge = tsi148_bridge->driver_priv; - -	/* Verify input data */ -	if (vme_base & 0xFFFF) { -		dev_err(tsi148_bridge->parent, "Invalid VME Window " -			"alignment\n"); -		retval = -EINVAL; -		goto err_window; -	} - -	if ((size == 0) && (enabled != 0)) { -		dev_err(tsi148_bridge->parent, "Size must be non-zero for " -			"enabled windows\n"); -		retval = -EINVAL; -		goto err_window; -	} - -	spin_lock(&(image->lock)); - -	/* Let's allocate the resource here rather than further up the stack as -	 * it avoids pushing loads of bus dependant stuff up the stack. If size -	 * is zero, any existing resource will be freed. -	 */ -	retval = tsi148_alloc_resource(image, size); -	if (retval) { -		spin_unlock(&(image->lock)); -		dev_err(tsi148_bridge->parent, "Unable to allocate memory for " -			"resource\n"); -		goto err_res; -	} - -	if (size == 0) { -		pci_base = 0; -		pci_bound = 0; -		vme_offset = 0; -	} else { -		pci_base = (unsigned long long)image->bus_resource.start; - -		/* -		 * Bound address is a valid address for the window, adjust -		 * according to window granularity. -		 */ -		pci_bound = pci_base + (size - 0x10000); -		vme_offset = vme_base - pci_base; -	} - -	/* Convert 64-bit variables to 2x 32-bit variables */ -	reg_split(pci_base, &pci_base_high, &pci_base_low); -	reg_split(pci_bound, &pci_bound_high, &pci_bound_low); -	reg_split(vme_offset, &vme_offset_high, &vme_offset_low); - -	if (pci_base_low & 0xFFFF) { -		spin_unlock(&(image->lock)); -		dev_err(tsi148_bridge->parent, "Invalid PCI base alignment\n"); -		retval = -EINVAL; -		goto err_gran; -	} -	if (pci_bound_low & 0xFFFF) { -		spin_unlock(&(image->lock)); -		dev_err(tsi148_bridge->parent, "Invalid PCI bound alignment\n"); -		retval = -EINVAL; -		goto err_gran; -	} -	if (vme_offset_low & 0xFFFF) { -		spin_unlock(&(image->lock)); -		dev_err(tsi148_bridge->parent, "Invalid VME Offset " -			"alignment\n"); -		retval = -EINVAL; -		goto err_gran; -	} - -	i = image->number; - -	/* Disable while we are mucking around */ -	temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTAT); -	temp_ctl &= ~TSI148_LCSR_OTAT_EN; -	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTAT); - -	/* Setup 2eSST speeds */ -	temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M; -	switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { -	case VME_2eSST160: -		temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_160; -		break; -	case VME_2eSST267: -		temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_267; -		break; -	case VME_2eSST320: -		temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_320; -		break; -	} - -	/* Setup cycle types */ -	if (cycle & VME_BLT) { -		temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; -		temp_ctl |= TSI148_LCSR_OTAT_TM_BLT; -	} -	if (cycle & VME_MBLT) { -		temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; -		temp_ctl |= TSI148_LCSR_OTAT_TM_MBLT; -	} -	if (cycle & VME_2eVME) { -		temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; -		temp_ctl |= TSI148_LCSR_OTAT_TM_2eVME; -	} -	if (cycle & VME_2eSST) { -		temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; -		temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST; -	} -	if (cycle & VME_2eSSTB) { -		dev_warn(tsi148_bridge->parent, "Currently not setting " -			"Broadcast Select Registers\n"); -		temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; -		temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB; -	} - -	/* Setup data width */ -	temp_ctl &= ~TSI148_LCSR_OTAT_DBW_M; -	switch (dwidth) { -	case VME_D16: -		temp_ctl |= TSI148_LCSR_OTAT_DBW_16; -		break; -	case VME_D32: -		temp_ctl |= TSI148_LCSR_OTAT_DBW_32; -		break; -	default: -		spin_unlock(&(image->lock)); -		dev_err(tsi148_bridge->parent, "Invalid data width\n"); -		retval = -EINVAL; -		goto err_dwidth; -	} - -	/* Setup address space */ -	temp_ctl &= ~TSI148_LCSR_OTAT_AMODE_M; -	switch (aspace) { -	case VME_A16: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_A16; -		break; -	case VME_A24: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_A24; -		break; -	case VME_A32: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_A32; -		break; -	case VME_A64: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_A64; -		break; -	case VME_CRCSR: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_CRCSR; -		break; -	case VME_USER1: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER1; -		break; -	case VME_USER2: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER2; -		break; -	case VME_USER3: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER3; -		break; -	case VME_USER4: -		temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER4; -		break; -	default: -		spin_unlock(&(image->lock)); -		dev_err(tsi148_bridge->parent, "Invalid address space\n"); -		retval = -EINVAL; -		goto err_aspace; -		break; -	} - -	temp_ctl &= ~(3<<4); -	if (cycle & VME_SUPER) -		temp_ctl |= TSI148_LCSR_OTAT_SUP; -	if (cycle & VME_PROG) -		temp_ctl |= TSI148_LCSR_OTAT_PGM; - -	/* Setup mapping */ -	iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTSAU); -	iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTSAL); -	iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTEAU); -	iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTEAL); -	iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTOFU); -	iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTOFL); - -	/* Write ctl reg without enable */ -	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTAT); - -	if (enabled) -		temp_ctl |= TSI148_LCSR_OTAT_EN; - -	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTAT); - -	spin_unlock(&(image->lock)); -	return 0; - -err_aspace: -err_dwidth: -err_gran: -	tsi148_free_resource(image); -err_res: -err_window: -	return retval; - -} - -/* - * Set the attributes of an outbound window. - * - * XXX Not parsing prefetch information. - */ -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 int i, ctl; -	unsigned int pci_base_low, pci_base_high; -	unsigned int pci_bound_low, pci_bound_high; -	unsigned int vme_offset_low, vme_offset_high; - -	unsigned long long pci_base, pci_bound, vme_offset; -	struct tsi148_driver *bridge; - -	bridge = image->parent->driver_priv; - -	i = image->number; - -	ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTAT); - -	pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTSAU); -	pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTSAL); -	pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTEAU); -	pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTEAL); -	vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTOFU); -	vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTOFL); - -	/* Convert 64-bit variables to 2x 32-bit variables */ -	reg_join(pci_base_high, pci_base_low, &pci_base); -	reg_join(pci_bound_high, pci_bound_low, &pci_bound); -	reg_join(vme_offset_high, vme_offset_low, &vme_offset); - -	*vme_base = pci_base + vme_offset; -	*size = (unsigned long long)(pci_bound - pci_base) + 0x10000; - -	*enabled = 0; -	*aspace = 0; -	*cycle = 0; -	*dwidth = 0; - -	if (ctl & TSI148_LCSR_OTAT_EN) -		*enabled = 1; - -	/* Setup address space */ -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A16) -		*aspace |= VME_A16; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A24) -		*aspace |= VME_A24; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A32) -		*aspace |= VME_A32; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A64) -		*aspace |= VME_A64; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_CRCSR) -		*aspace |= VME_CRCSR; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER1) -		*aspace |= VME_USER1; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER2) -		*aspace |= VME_USER2; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER3) -		*aspace |= VME_USER3; -	if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER4) -		*aspace |= VME_USER4; - -	/* Setup 2eSST speeds */ -	if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_160) -		*cycle |= VME_2eSST160; -	if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_267) -		*cycle |= VME_2eSST267; -	if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_320) -		*cycle |= VME_2eSST320; - -	/* Setup cycle types */ -	if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_SCT) -		*cycle |= VME_SCT; -	if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_BLT) -		*cycle |= VME_BLT; -	if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_MBLT) -		*cycle |= VME_MBLT; -	if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eVME) -		*cycle |= VME_2eVME; -	if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSST) -		*cycle |= VME_2eSST; -	if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSSTB) -		*cycle |= VME_2eSSTB; - -	if (ctl & TSI148_LCSR_OTAT_SUP) -		*cycle |= VME_SUPER; -	else -		*cycle |= VME_USER; - -	if (ctl & TSI148_LCSR_OTAT_PGM) -		*cycle |= VME_PROG; -	else -		*cycle |= VME_DATA; - -	/* Setup data width */ -	if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_16) -		*dwidth = VME_D16; -	if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_32) -		*dwidth = VME_D32; - -	return 0; -} - - -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) -{ -	int retval; - -	spin_lock(&(image->lock)); - -	retval = __tsi148_master_get(image, enabled, vme_base, size, aspace, -		cycle, dwidth); - -	spin_unlock(&(image->lock)); - -	return retval; -} - -ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, -	size_t count, loff_t offset) -{ -	int retval, enabled; -	unsigned long long vme_base, size; -	vme_address_t aspace; -	vme_cycle_t cycle; -	vme_width_t dwidth; -	struct vme_bus_error *vme_err = NULL; -	struct vme_bridge *tsi148_bridge; - -	tsi148_bridge = image->parent; - -	spin_lock(&(image->lock)); - -	memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); -	retval = count; - -	if (!err_chk) -		goto skip_chk; - -	__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, -		&dwidth); - -	vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, -		count); -	if (vme_err != NULL) { -		dev_err(image->parent->parent, "First VME read error detected " -			"an at address 0x%llx\n", vme_err->address); -		retval = vme_err->address - (vme_base + offset); -		/* Clear down save errors in this address range */ -		tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, -			count); -	} - -skip_chk: -	spin_unlock(&(image->lock)); - -	return retval; -} - - -ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, -	size_t count, loff_t offset) -{ -	int retval = 0, enabled; -	unsigned long long vme_base, size; -	vme_address_t aspace; -	vme_cycle_t cycle; -	vme_width_t dwidth; - -	struct vme_bus_error *vme_err = NULL; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	tsi148_bridge = image->parent; - -	bridge = tsi148_bridge->driver_priv; - -	spin_lock(&(image->lock)); - -	memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); -	retval = count; - -	/* -	 * Writes are posted. We need to do a read on the VME bus to flush out -	 * all of the writes before we check for errors. We can't guarentee -	 * that reading the data we have just written is safe. It is believed -	 * that there isn't any read, write re-ordering, so we can read any -	 * location in VME space, so lets read the Device ID from the tsi148's -	 * own registers as mapped into CR/CSR space. -	 * -	 * We check for saved errors in the written address range/space. -	 */ - -	if (!err_chk) -		goto skip_chk; - -	/* -	 * Get window info first, to maximise the time that the buffers may -	 * fluch on their own -	 */ -	__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, -		&dwidth); - -	ioread16(bridge->flush_image->kern_base + 0x7F000); - -	vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, -		count); -	if (vme_err != NULL) { -		dev_warn(tsi148_bridge->parent, "First VME write error detected" -			" an at address 0x%llx\n", vme_err->address); -		retval = vme_err->address - (vme_base + offset); -		/* Clear down save errors in this address range */ -		tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, -			count); -	} - -skip_chk: -	spin_unlock(&(image->lock)); - -	return retval; -} - -/* - * Perform an RMW cycle on the VME bus. - * - * Requires a previously configured master window, returns final value. - */ -unsigned int tsi148_master_rmw(struct vme_master_resource *image, -	unsigned int mask, unsigned int compare, unsigned int swap, -	loff_t offset) -{ -	unsigned long long pci_addr; -	unsigned int pci_addr_high, pci_addr_low; -	u32 tmp, result; -	int i; -	struct tsi148_driver *bridge; - -	bridge = image->parent->driver_priv; - -	/* Find the PCI address that maps to the desired VME address */ -	i = image->number; - -	/* Locking as we can only do one of these at a time */ -	mutex_lock(&(bridge->vme_rmw)); - -	/* Lock image */ -	spin_lock(&(image->lock)); - -	pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTSAU); -	pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + -		TSI148_LCSR_OFFSET_OTSAL); - -	reg_join(pci_addr_high, pci_addr_low, &pci_addr); -	reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low); - -	/* Configure registers */ -	iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN); -	iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC); -	iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS); -	iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU); -	iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL); - -	/* Enable RMW */ -	tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); -	tmp |= TSI148_LCSR_VMCTRL_RMWEN; -	iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); - -	/* Kick process off with a read to the required address. */ -	result = ioread32be(image->kern_base + offset); - -	/* Disable RMW */ -	tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); -	tmp &= ~TSI148_LCSR_VMCTRL_RMWEN; -	iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); - -	spin_unlock(&(image->lock)); - -	mutex_unlock(&(bridge->vme_rmw)); - -	return result; -} - -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) -{ -	/* Setup 2eSST speeds */ -	switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { -	case VME_2eSST160: -		*attr |= TSI148_LCSR_DSAT_2eSSTM_160; -		break; -	case VME_2eSST267: -		*attr |= TSI148_LCSR_DSAT_2eSSTM_267; -		break; -	case VME_2eSST320: -		*attr |= TSI148_LCSR_DSAT_2eSSTM_320; -		break; -	} - -	/* Setup cycle types */ -	if (cycle & VME_SCT) -		*attr |= TSI148_LCSR_DSAT_TM_SCT; - -	if (cycle & VME_BLT) -		*attr |= TSI148_LCSR_DSAT_TM_BLT; - -	if (cycle & VME_MBLT) -		*attr |= TSI148_LCSR_DSAT_TM_MBLT; - -	if (cycle & VME_2eVME) -		*attr |= TSI148_LCSR_DSAT_TM_2eVME; - -	if (cycle & VME_2eSST) -		*attr |= TSI148_LCSR_DSAT_TM_2eSST; - -	if (cycle & VME_2eSSTB) { -		dev_err(dev, "Currently not setting Broadcast Select " -			"Registers\n"); -		*attr |= TSI148_LCSR_DSAT_TM_2eSSTB; -	} - -	/* Setup data width */ -	switch (dwidth) { -	case VME_D16: -		*attr |= TSI148_LCSR_DSAT_DBW_16; -		break; -	case VME_D32: -		*attr |= TSI148_LCSR_DSAT_DBW_32; -		break; -	default: -		dev_err(dev, "Invalid data width\n"); -		return -EINVAL; -	} - -	/* Setup address space */ -	switch (aspace) { -	case VME_A16: -		*attr |= TSI148_LCSR_DSAT_AMODE_A16; -		break; -	case VME_A24: -		*attr |= TSI148_LCSR_DSAT_AMODE_A24; -		break; -	case VME_A32: -		*attr |= TSI148_LCSR_DSAT_AMODE_A32; -		break; -	case VME_A64: -		*attr |= TSI148_LCSR_DSAT_AMODE_A64; -		break; -	case VME_CRCSR: -		*attr |= TSI148_LCSR_DSAT_AMODE_CRCSR; -		break; -	case VME_USER1: -		*attr |= TSI148_LCSR_DSAT_AMODE_USER1; -		break; -	case VME_USER2: -		*attr |= TSI148_LCSR_DSAT_AMODE_USER2; -		break; -	case VME_USER3: -		*attr |= TSI148_LCSR_DSAT_AMODE_USER3; -		break; -	case VME_USER4: -		*attr |= TSI148_LCSR_DSAT_AMODE_USER4; -		break; -	default: -		dev_err(dev, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	if (cycle & VME_SUPER) -		*attr |= TSI148_LCSR_DSAT_SUP; -	if (cycle & VME_PROG) -		*attr |= TSI148_LCSR_DSAT_PGM; - -	return 0; -} - -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) -{ -	/* Setup 2eSST speeds */ -	switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { -	case VME_2eSST160: -		*attr |= TSI148_LCSR_DDAT_2eSSTM_160; -		break; -	case VME_2eSST267: -		*attr |= TSI148_LCSR_DDAT_2eSSTM_267; -		break; -	case VME_2eSST320: -		*attr |= TSI148_LCSR_DDAT_2eSSTM_320; -		break; -	} - -	/* Setup cycle types */ -	if (cycle & VME_SCT) -		*attr |= TSI148_LCSR_DDAT_TM_SCT; - -	if (cycle & VME_BLT) -		*attr |= TSI148_LCSR_DDAT_TM_BLT; - -	if (cycle & VME_MBLT) -		*attr |= TSI148_LCSR_DDAT_TM_MBLT; - -	if (cycle & VME_2eVME) -		*attr |= TSI148_LCSR_DDAT_TM_2eVME; - -	if (cycle & VME_2eSST) -		*attr |= TSI148_LCSR_DDAT_TM_2eSST; - -	if (cycle & VME_2eSSTB) { -		dev_err(dev, "Currently not setting Broadcast Select " -			"Registers\n"); -		*attr |= TSI148_LCSR_DDAT_TM_2eSSTB; -	} - -	/* Setup data width */ -	switch (dwidth) { -	case VME_D16: -		*attr |= TSI148_LCSR_DDAT_DBW_16; -		break; -	case VME_D32: -		*attr |= TSI148_LCSR_DDAT_DBW_32; -		break; -	default: -		dev_err(dev, "Invalid data width\n"); -		return -EINVAL; -	} - -	/* Setup address space */ -	switch (aspace) { -	case VME_A16: -		*attr |= TSI148_LCSR_DDAT_AMODE_A16; -		break; -	case VME_A24: -		*attr |= TSI148_LCSR_DDAT_AMODE_A24; -		break; -	case VME_A32: -		*attr |= TSI148_LCSR_DDAT_AMODE_A32; -		break; -	case VME_A64: -		*attr |= TSI148_LCSR_DDAT_AMODE_A64; -		break; -	case VME_CRCSR: -		*attr |= TSI148_LCSR_DDAT_AMODE_CRCSR; -		break; -	case VME_USER1: -		*attr |= TSI148_LCSR_DDAT_AMODE_USER1; -		break; -	case VME_USER2: -		*attr |= TSI148_LCSR_DDAT_AMODE_USER2; -		break; -	case VME_USER3: -		*attr |= TSI148_LCSR_DDAT_AMODE_USER3; -		break; -	case VME_USER4: -		*attr |= TSI148_LCSR_DDAT_AMODE_USER4; -		break; -	default: -		dev_err(dev, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	if (cycle & VME_SUPER) -		*attr |= TSI148_LCSR_DDAT_SUP; -	if (cycle & VME_PROG) -		*attr |= TSI148_LCSR_DDAT_PGM; - -	return 0; -} - -/* - * Add a link list descriptor to the list - */ -int tsi148_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, -	struct vme_dma_attr *dest, size_t count) -{ -	struct tsi148_dma_entry *entry, *prev; -	u32 address_high, address_low; -	struct vme_dma_pattern *pattern_attr; -	struct vme_dma_pci *pci_attr; -	struct vme_dma_vme *vme_attr; -	dma_addr_t desc_ptr; -	int retval = 0; -	struct vme_bridge *tsi148_bridge; - -	tsi148_bridge = list->parent->parent; - -	/* Descriptor must be aligned on 64-bit boundaries */ -	entry = kmalloc(sizeof(struct tsi148_dma_entry), GFP_KERNEL); -	if (entry == NULL) { -		dev_err(tsi148_bridge->parent, "Failed to allocate memory for " -			"dma resource structure\n"); -		retval = -ENOMEM; -		goto err_mem; -	} - -	/* Test descriptor alignment */ -	if ((unsigned long)&(entry->descriptor) & 0x7) { -		dev_err(tsi148_bridge->parent, "Descriptor not aligned to 8 " -			"byte boundary as required: %p\n", -			&(entry->descriptor)); -		retval = -EINVAL; -		goto err_align; -	} - -	/* Given we are going to fill out the structure, we probably don't -	 * need to zero it, but better safe than sorry for now. -	 */ -	memset(&(entry->descriptor), 0, sizeof(struct tsi148_dma_descriptor)); - -	/* Fill out source part */ -	switch (src->type) { -	case VME_DMA_PATTERN: -		pattern_attr = src->private; - -		entry->descriptor.dsal = pattern_attr->pattern; -		entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PAT; -		/* Default behaviour is 32 bit pattern */ -		if (pattern_attr->type & VME_DMA_PATTERN_BYTE) -			entry->descriptor.dsat |= TSI148_LCSR_DSAT_PSZ; - -		/* It seems that the default behaviour is to increment */ -		if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0) -			entry->descriptor.dsat |= TSI148_LCSR_DSAT_NIN; - -		break; -	case VME_DMA_PCI: -		pci_attr = src->private; - -		reg_split((unsigned long long)pci_attr->address, &address_high, -			&address_low); -		entry->descriptor.dsau = address_high; -		entry->descriptor.dsal = address_low; -		entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PCI; -		break; -	case VME_DMA_VME: -		vme_attr = src->private; - -		reg_split((unsigned long long)vme_attr->address, &address_high, -			&address_low); -		entry->descriptor.dsau = address_high; -		entry->descriptor.dsal = address_low; -		entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_VME; - -		retval = tsi148_dma_set_vme_src_attributes( -			tsi148_bridge->parent, &(entry->descriptor.dsat), -			vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); -		if (retval < 0) -			goto err_source; -		break; -	default: -		dev_err(tsi148_bridge->parent, "Invalid source type\n"); -		retval = -EINVAL; -		goto err_source; -		break; -	} - -	/* Assume last link - this will be over-written by adding another */ -	entry->descriptor.dnlau = 0; -	entry->descriptor.dnlal = TSI148_LCSR_DNLAL_LLA; - - -	/* Fill out destination part */ -	switch (dest->type) { -	case VME_DMA_PCI: -		pci_attr = dest->private; - -		reg_split((unsigned long long)pci_attr->address, &address_high, -			&address_low); -		entry->descriptor.ddau = address_high; -		entry->descriptor.ddal = address_low; -		entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_PCI; -		break; -	case VME_DMA_VME: -		vme_attr = dest->private; - -		reg_split((unsigned long long)vme_attr->address, &address_high, -			&address_low); -		entry->descriptor.ddau = address_high; -		entry->descriptor.ddal = address_low; -		entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_VME; - -		retval = tsi148_dma_set_vme_dest_attributes( -			tsi148_bridge->parent, &(entry->descriptor.ddat), -			vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); -		if (retval < 0) -			goto err_dest; -		break; -	default: -		dev_err(tsi148_bridge->parent, "Invalid destination type\n"); -		retval = -EINVAL; -		goto err_dest; -		break; -	} - -	/* Fill out count */ -	entry->descriptor.dcnt = (u32)count; - -	/* Add to list */ -	list_add_tail(&(entry->list), &(list->entries)); - -	/* Fill out previous descriptors "Next Address" */ -	if (entry->list.prev != &(list->entries)) { -		prev = list_entry(entry->list.prev, struct tsi148_dma_entry, -			list); -		/* We need the bus address for the pointer */ -		desc_ptr = virt_to_bus(&(entry->descriptor)); -		reg_split(desc_ptr, &(prev->descriptor.dnlau), -			&(prev->descriptor.dnlal)); -	} - -	return 0; - -err_dest: -err_source: -err_align: -		kfree(entry); -err_mem: -	return retval; -} - -/* - * Check to see if the provided DMA channel is busy. - */ -static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel) -{ -	u32 tmp; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + -		TSI148_LCSR_OFFSET_DSTA); - -	if (tmp & TSI148_LCSR_DSTA_BSY) -		return 0; -	else -		return 1; - -} - -/* - * Execute a previously generated link list - * - * XXX Need to provide control register configuration. - */ -int tsi148_dma_list_exec(struct vme_dma_list *list) -{ -	struct vme_dma_resource *ctrlr; -	int channel, retval = 0; -	struct tsi148_dma_entry *entry; -	dma_addr_t bus_addr; -	u32 bus_addr_high, bus_addr_low; -	u32 val, dctlreg = 0; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	ctrlr = list->parent; - -	tsi148_bridge = ctrlr->parent; - -	bridge = tsi148_bridge->driver_priv; - -	mutex_lock(&(ctrlr->mtx)); - -	channel = ctrlr->number; - -	if (!list_empty(&(ctrlr->running))) { -		/* -		 * XXX We have an active DMA transfer and currently haven't -		 *     sorted out the mechanism for "pending" DMA transfers. -		 *     Return busy. -		 */ -		/* Need to add to pending here */ -		mutex_unlock(&(ctrlr->mtx)); -		return -EBUSY; -	} else { -		list_add(&(list->list), &(ctrlr->running)); -	} - -	/* Get first bus address and write into registers */ -	entry = list_first_entry(&(list->entries), struct tsi148_dma_entry, -		list); - -	bus_addr = virt_to_bus(&(entry->descriptor)); - -	mutex_unlock(&(ctrlr->mtx)); - -	reg_split(bus_addr, &bus_addr_high, &bus_addr_low); - -	iowrite32be(bus_addr_high, bridge->base + -		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU); -	iowrite32be(bus_addr_low, bridge->base + -		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL); - -	/* Start the operation */ -	iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base + -		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL); - -	wait_event_interruptible(bridge->dma_queue[channel], -		tsi148_dma_busy(ctrlr->parent, channel)); -	/* -	 * Read status register, this register is valid until we kick off a -	 * new transfer. -	 */ -	val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + -		TSI148_LCSR_OFFSET_DSTA); - -	if (val & TSI148_LCSR_DSTA_VBE) { -		dev_err(tsi148_bridge->parent, "DMA Error. DSTA=%08X\n", val); -		retval = -EIO; -	} - -	/* Remove list from running list */ -	mutex_lock(&(ctrlr->mtx)); -	list_del(&(list->list)); -	mutex_unlock(&(ctrlr->mtx)); - -	return retval; -} - -/* - * Clean up a previously generated link list - * - * We have a separate function, don't assume that the chain can't be reused. - */ -int tsi148_dma_list_empty(struct vme_dma_list *list) -{ -	struct list_head *pos, *temp; -	struct tsi148_dma_entry *entry; - -	/* detach and free each entry */ -	list_for_each_safe(pos, temp, &(list->entries)) { -		list_del(pos); -		entry = list_entry(pos, struct tsi148_dma_entry, list); -		kfree(entry); -	} - -	return 0; -} - -/* - * All 4 location monitors reside at the same base - this is therefore a - * system wide configuration. - * - * This does not enable the LM monitor - that should be done when the first - * callback is attached and disabled when the last callback is removed. - */ -int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, -	vme_address_t aspace, vme_cycle_t cycle) -{ -	u32 lm_base_high, lm_base_low, lm_ctl = 0; -	int i; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	tsi148_bridge = lm->parent; - -	bridge = tsi148_bridge->driver_priv; - -	mutex_lock(&(lm->mtx)); - -	/* If we already have a callback attached, we can't move it! */ -	for (i = 0; i < lm->monitors; i++) { -		if (bridge->lm_callback[i] != NULL) { -			mutex_unlock(&(lm->mtx)); -			dev_err(tsi148_bridge->parent, "Location monitor " -				"callback attached, can't reset\n"); -			return -EBUSY; -		} -	} - -	switch (aspace) { -	case VME_A16: -		lm_ctl |= TSI148_LCSR_LMAT_AS_A16; -		break; -	case VME_A24: -		lm_ctl |= TSI148_LCSR_LMAT_AS_A24; -		break; -	case VME_A32: -		lm_ctl |= TSI148_LCSR_LMAT_AS_A32; -		break; -	case VME_A64: -		lm_ctl |= TSI148_LCSR_LMAT_AS_A64; -		break; -	default: -		mutex_unlock(&(lm->mtx)); -		dev_err(tsi148_bridge->parent, "Invalid address space\n"); -		return -EINVAL; -		break; -	} - -	if (cycle & VME_SUPER) -		lm_ctl |= TSI148_LCSR_LMAT_SUPR ; -	if (cycle & VME_USER) -		lm_ctl |= TSI148_LCSR_LMAT_NPRIV; -	if (cycle & VME_PROG) -		lm_ctl |= TSI148_LCSR_LMAT_PGM; -	if (cycle & VME_DATA) -		lm_ctl |= TSI148_LCSR_LMAT_DATA; - -	reg_split(lm_base, &lm_base_high, &lm_base_low); - -	iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU); -	iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL); -	iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); - -	mutex_unlock(&(lm->mtx)); - -	return 0; -} - -/* Get configuration of the callback monitor and return whether it is enabled - * or disabled. - */ -int tsi148_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base, -	vme_address_t *aspace, vme_cycle_t *cycle) -{ -	u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0; -	struct tsi148_driver *bridge; - -	bridge = lm->parent->driver_priv; - -	mutex_lock(&(lm->mtx)); - -	lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU); -	lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL); -	lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); - -	reg_join(lm_base_high, lm_base_low, lm_base); - -	if (lm_ctl & TSI148_LCSR_LMAT_EN) -		enabled = 1; - -	if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A16) -		*aspace |= VME_A16; - -	if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A24) -		*aspace |= VME_A24; - -	if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A32) -		*aspace |= VME_A32; - -	if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A64) -		*aspace |= VME_A64; - - -	if (lm_ctl & TSI148_LCSR_LMAT_SUPR) -		*cycle |= VME_SUPER; -	if (lm_ctl & TSI148_LCSR_LMAT_NPRIV) -		*cycle |= VME_USER; -	if (lm_ctl & TSI148_LCSR_LMAT_PGM) -		*cycle |= VME_PROG; -	if (lm_ctl & TSI148_LCSR_LMAT_DATA) -		*cycle |= VME_DATA; - -	mutex_unlock(&(lm->mtx)); - -	return enabled; -} - -/* - * Attach a callback to a specific location monitor. - * - * Callback will be passed the monitor triggered. - */ -int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor, -	void (*callback)(int)) -{ -	u32 lm_ctl, tmp; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *bridge; - -	tsi148_bridge = lm->parent; - -	bridge = tsi148_bridge->driver_priv; - -	mutex_lock(&(lm->mtx)); - -	/* Ensure that the location monitor is configured - need PGM or DATA */ -	lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); -	if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) { -		mutex_unlock(&(lm->mtx)); -		dev_err(tsi148_bridge->parent, "Location monitor not properly " -			"configured\n"); -		return -EINVAL; -	} - -	/* Check that a callback isn't already attached */ -	if (bridge->lm_callback[monitor] != NULL) { -		mutex_unlock(&(lm->mtx)); -		dev_err(tsi148_bridge->parent, "Existing callback attached\n"); -		return -EBUSY; -	} - -	/* Attach callback */ -	bridge->lm_callback[monitor] = callback; - -	/* Enable Location Monitor interrupt */ -	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); -	tmp |= TSI148_LCSR_INTEN_LMEN[monitor]; -	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - -	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); -	tmp |= TSI148_LCSR_INTEO_LMEO[monitor]; -	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - -	/* Ensure that global Location Monitor Enable set */ -	if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) { -		lm_ctl |= TSI148_LCSR_LMAT_EN; -		iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); -	} - -	mutex_unlock(&(lm->mtx)); - -	return 0; -} - -/* - * Detach a callback function forn a specific location monitor. - */ -int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor) -{ -	u32 lm_en, tmp; -	struct tsi148_driver *bridge; - -	bridge = lm->parent->driver_priv; - -	mutex_lock(&(lm->mtx)); - -	/* Disable Location Monitor and ensure previous interrupts are clear */ -	lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN); -	lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor]; -	iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN); - -	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); -	tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor]; -	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - -	iowrite32be(TSI148_LCSR_INTC_LMC[monitor], -		 bridge->base + TSI148_LCSR_INTC); - -	/* Detach callback */ -	bridge->lm_callback[monitor] = NULL; - -	/* If all location monitors disabled, disable global Location Monitor */ -	if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S | -			TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) { -		tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT); -		tmp &= ~TSI148_LCSR_LMAT_EN; -		iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT); -	} - -	mutex_unlock(&(lm->mtx)); - -	return 0; -} - -/* - * Determine Geographical Addressing - */ -int tsi148_slot_get(struct vme_bridge *tsi148_bridge) -{ -	u32 slot = 0; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	if (!geoid) { -		slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT); -		slot = slot & TSI148_LCSR_VSTAT_GA_M; -	} else -		slot = geoid; - -	return (int)slot; -} - -static int __init tsi148_init(void) -{ -	return pci_register_driver(&tsi148_driver); -} - -/* - * Configure CR/CSR space - * - * Access to the CR/CSR can be configured at power-up. The location of the - * CR/CSR registers in the CR/CSR address space is determined by the boards - * Auto-ID or Geographic address. This function ensures that the window is - * enabled at an offset consistent with the boards geopgraphic address. - * - * Each board has a 512kB window, with the highest 4kB being used for the - * boards registers, this means there is a fix length 508kB window which must - * be mapped onto PCI memory. - */ -static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, -	struct pci_dev *pdev) -{ -	u32 cbar, crat, vstat; -	u32 crcsr_bus_high, crcsr_bus_low; -	int retval; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	/* Allocate mem for CR/CSR image */ -	bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, -		&(bridge->crcsr_bus)); -	if (bridge->crcsr_kernel == NULL) { -		dev_err(tsi148_bridge->parent, "Failed to allocate memory for " -			"CR/CSR image\n"); -		return -ENOMEM; -	} - -	memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); - -	reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low); - -	iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU); -	iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL); - -	/* Ensure that the CR/CSR is configured at the correct offset */ -	cbar = ioread32be(bridge->base + TSI148_CBAR); -	cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3; - -	vstat = tsi148_slot_get(tsi148_bridge); - -	if (cbar != vstat) { -		cbar = vstat; -		dev_info(tsi148_bridge->parent, "Setting CR/CSR offset\n"); -		iowrite32be(cbar<<3, bridge->base + TSI148_CBAR); -	} -	dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar); - -	crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); -	if (crat & TSI148_LCSR_CRAT_EN) { -		dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n"); -		iowrite32be(crat | TSI148_LCSR_CRAT_EN, -			bridge->base + TSI148_LCSR_CRAT); -	} else -		dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n"); - -	/* If we want flushed, error-checked writes, set up a window -	 * over the CR/CSR registers. We read from here to safely flush -	 * through VME writes. -	 */ -	if (err_chk) { -		retval = tsi148_master_set(bridge->flush_image, 1, -			(vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT, -			VME_D16); -		if (retval) -			dev_err(tsi148_bridge->parent, "Configuring flush image" -				" failed\n"); -	} - -	return 0; - -} - -static void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge, -	struct pci_dev *pdev) -{ -	u32 crat; -	struct tsi148_driver *bridge; - -	bridge = tsi148_bridge->driver_priv; - -	/* Turn off CR/CSR space */ -	crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); -	iowrite32be(crat & ~TSI148_LCSR_CRAT_EN, -		bridge->base + TSI148_LCSR_CRAT); - -	/* Free image */ -	iowrite32be(0, bridge->base + TSI148_LCSR_CROU); -	iowrite32be(0, bridge->base + TSI148_LCSR_CROL); - -	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, -		bridge->crcsr_bus); -} - -static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ -	int retval, i, master_num; -	u32 data; -	struct list_head *pos = NULL; -	struct vme_bridge *tsi148_bridge; -	struct tsi148_driver *tsi148_device; -	struct vme_master_resource *master_image; -	struct vme_slave_resource *slave_image; -	struct vme_dma_resource *dma_ctrlr; -	struct vme_lm_resource *lm; - -	/* If we want to support more than one of each bridge, we need to -	 * dynamically generate this so we get one per device -	 */ -	tsi148_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); -	if (tsi148_bridge == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for device " -			"structure\n"); -		retval = -ENOMEM; -		goto err_struct; -	} - -	tsi148_device = kzalloc(sizeof(struct tsi148_driver), GFP_KERNEL); -	if (tsi148_device == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for device " -			"structure\n"); -		retval = -ENOMEM; -		goto err_driver; -	} - -	tsi148_bridge->driver_priv = tsi148_device; - -	/* Enable the device */ -	retval = pci_enable_device(pdev); -	if (retval) { -		dev_err(&pdev->dev, "Unable to enable device\n"); -		goto err_enable; -	} - -	/* Map Registers */ -	retval = pci_request_regions(pdev, driver_name); -	if (retval) { -		dev_err(&pdev->dev, "Unable to reserve resources\n"); -		goto err_resource; -	} - -	/* map registers in BAR 0 */ -	tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0), -		4096); -	if (!tsi148_device->base) { -		dev_err(&pdev->dev, "Unable to remap CRG region\n"); -		retval = -EIO; -		goto err_remap; -	} - -	/* Check to see if the mapping worked out */ -	data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF; -	if (data != PCI_VENDOR_ID_TUNDRA) { -		dev_err(&pdev->dev, "CRG region check failed\n"); -		retval = -EIO; -		goto err_test; -	} - -	/* Initialize wait queues & mutual exclusion flags */ -	init_waitqueue_head(&(tsi148_device->dma_queue[0])); -	init_waitqueue_head(&(tsi148_device->dma_queue[1])); -	init_waitqueue_head(&(tsi148_device->iack_queue)); -	mutex_init(&(tsi148_device->vme_int)); -	mutex_init(&(tsi148_device->vme_rmw)); - -	tsi148_bridge->parent = &(pdev->dev); -	strcpy(tsi148_bridge->name, driver_name); - -	/* Setup IRQ */ -	retval = tsi148_irq_init(tsi148_bridge); -	if (retval != 0) { -		dev_err(&pdev->dev, "Chip Initialization failed.\n"); -		goto err_irq; -	} - -	/* If we are going to flush writes, we need to read from the VME bus. -	 * We need to do this safely, thus we read the devices own CR/CSR -	 * register. To do this we must set up a window in CR/CSR space and -	 * hence have one less master window resource available. -	 */ -	master_num = TSI148_MAX_MASTER; -	if (err_chk) { -		master_num--; - -		tsi148_device->flush_image = -			kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL); -		if (tsi148_device->flush_image == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"flush resource structure\n"); -			retval = -ENOMEM; -			goto err_master; -		} -		tsi148_device->flush_image->parent = tsi148_bridge; -		spin_lock_init(&(tsi148_device->flush_image->lock)); -		tsi148_device->flush_image->locked = 1; -		tsi148_device->flush_image->number = master_num; -		tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 | -			VME_A32 | VME_A64; -		tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT | -			VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB | -			VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER | -			VME_USER | VME_PROG | VME_DATA; -		tsi148_device->flush_image->width_attr = VME_D16 | VME_D32; -		memset(&(tsi148_device->flush_image->bus_resource), 0, -			sizeof(struct resource)); -		tsi148_device->flush_image->kern_base  = NULL; -	} - -	/* Add master windows to list */ -	INIT_LIST_HEAD(&(tsi148_bridge->master_resources)); -	for (i = 0; i < master_num; i++) { -		master_image = kmalloc(sizeof(struct vme_master_resource), -			GFP_KERNEL); -		if (master_image == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"master resource structure\n"); -			retval = -ENOMEM; -			goto err_master; -		} -		master_image->parent = tsi148_bridge; -		spin_lock_init(&(master_image->lock)); -		master_image->locked = 0; -		master_image->number = i; -		master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | -			VME_A64; -		master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | -			VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | -			VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | -			VME_PROG | VME_DATA; -		master_image->width_attr = VME_D16 | VME_D32; -		memset(&(master_image->bus_resource), 0, -			sizeof(struct resource)); -		master_image->kern_base  = NULL; -		list_add_tail(&(master_image->list), -			&(tsi148_bridge->master_resources)); -	} - -	/* Add slave windows to list */ -	INIT_LIST_HEAD(&(tsi148_bridge->slave_resources)); -	for (i = 0; i < TSI148_MAX_SLAVE; i++) { -		slave_image = kmalloc(sizeof(struct vme_slave_resource), -			GFP_KERNEL); -		if (slave_image == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"slave resource structure\n"); -			retval = -ENOMEM; -			goto err_slave; -		} -		slave_image->parent = tsi148_bridge; -		mutex_init(&(slave_image->mtx)); -		slave_image->locked = 0; -		slave_image->number = i; -		slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 | -			VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 | -			VME_USER3 | VME_USER4; -		slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | -			VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | -			VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | -			VME_PROG | VME_DATA; -		list_add_tail(&(slave_image->list), -			&(tsi148_bridge->slave_resources)); -	} - -	/* Add dma engines to list */ -	INIT_LIST_HEAD(&(tsi148_bridge->dma_resources)); -	for (i = 0; i < TSI148_MAX_DMA; i++) { -		dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), -			GFP_KERNEL); -		if (dma_ctrlr == NULL) { -			dev_err(&pdev->dev, "Failed to allocate memory for " -			"dma resource structure\n"); -			retval = -ENOMEM; -			goto err_dma; -		} -		dma_ctrlr->parent = tsi148_bridge; -		mutex_init(&(dma_ctrlr->mtx)); -		dma_ctrlr->locked = 0; -		dma_ctrlr->number = i; -		dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | -			VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME | -			VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME | -			VME_DMA_PATTERN_TO_MEM; -		INIT_LIST_HEAD(&(dma_ctrlr->pending)); -		INIT_LIST_HEAD(&(dma_ctrlr->running)); -		list_add_tail(&(dma_ctrlr->list), -			&(tsi148_bridge->dma_resources)); -	} - -	/* Add location monitor to list */ -	INIT_LIST_HEAD(&(tsi148_bridge->lm_resources)); -	lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); -	if (lm == NULL) { -		dev_err(&pdev->dev, "Failed to allocate memory for " -		"location monitor resource structure\n"); -		retval = -ENOMEM; -		goto err_lm; -	} -	lm->parent = tsi148_bridge; -	mutex_init(&(lm->mtx)); -	lm->locked = 0; -	lm->number = 1; -	lm->monitors = 4; -	list_add_tail(&(lm->list), &(tsi148_bridge->lm_resources)); - -	tsi148_bridge->slave_get = tsi148_slave_get; -	tsi148_bridge->slave_set = tsi148_slave_set; -	tsi148_bridge->master_get = tsi148_master_get; -	tsi148_bridge->master_set = tsi148_master_set; -	tsi148_bridge->master_read = tsi148_master_read; -	tsi148_bridge->master_write = tsi148_master_write; -	tsi148_bridge->master_rmw = tsi148_master_rmw; -	tsi148_bridge->dma_list_add = tsi148_dma_list_add; -	tsi148_bridge->dma_list_exec = tsi148_dma_list_exec; -	tsi148_bridge->dma_list_empty = tsi148_dma_list_empty; -	tsi148_bridge->irq_set = tsi148_irq_set; -	tsi148_bridge->irq_generate = tsi148_irq_generate; -	tsi148_bridge->lm_set = tsi148_lm_set; -	tsi148_bridge->lm_get = tsi148_lm_get; -	tsi148_bridge->lm_attach = tsi148_lm_attach; -	tsi148_bridge->lm_detach = tsi148_lm_detach; -	tsi148_bridge->slot_get = tsi148_slot_get; - -	data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); -	dev_info(&pdev->dev, "Board is%s the VME system controller\n", -		(data & TSI148_LCSR_VSTAT_SCONS) ? "" : " not"); -	if (!geoid) -		dev_info(&pdev->dev, "VME geographical address is %d\n", -			data & TSI148_LCSR_VSTAT_GA_M); -	else -		dev_info(&pdev->dev, "VME geographical address is set to %d\n", -			geoid); - -	dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", -		err_chk ? "enabled" : "disabled"); - -	if (tsi148_crcsr_init(tsi148_bridge, pdev)) { -		dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); -		goto err_crcsr; -	} - -	retval = vme_register_bridge(tsi148_bridge); -	if (retval != 0) { -		dev_err(&pdev->dev, "Chip Registration failed.\n"); -		goto err_reg; -	} - -	pci_set_drvdata(pdev, tsi148_bridge); - -	/* Clear VME bus "board fail", and "power-up reset" lines */ -	data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); -	data &= ~TSI148_LCSR_VSTAT_BRDFL; -	data |= TSI148_LCSR_VSTAT_CPURST; -	iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT); - -	return 0; - -	vme_unregister_bridge(tsi148_bridge); -err_reg: -	tsi148_crcsr_exit(tsi148_bridge, pdev); -err_crcsr: -err_lm: -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->lm_resources)) { -		lm = list_entry(pos, struct vme_lm_resource, list); -		list_del(pos); -		kfree(lm); -	} -err_dma: -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->dma_resources)) { -		dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); -		list_del(pos); -		kfree(dma_ctrlr); -	} -err_slave: -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->slave_resources)) { -		slave_image = list_entry(pos, struct vme_slave_resource, list); -		list_del(pos); -		kfree(slave_image); -	} -err_master: -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->master_resources)) { -		master_image = list_entry(pos, struct vme_master_resource, -			list); -		list_del(pos); -		kfree(master_image); -	} - -	tsi148_irq_exit(tsi148_device, pdev); -err_irq: -err_test: -	iounmap(tsi148_device->base); -err_remap: -	pci_release_regions(pdev); -err_resource: -	pci_disable_device(pdev); -err_enable: -	kfree(tsi148_device); -err_driver: -	kfree(tsi148_bridge); -err_struct: -	return retval; - -} - -static void tsi148_remove(struct pci_dev *pdev) -{ -	struct list_head *pos = NULL; -	struct vme_master_resource *master_image; -	struct vme_slave_resource *slave_image; -	struct vme_dma_resource *dma_ctrlr; -	int i; -	struct tsi148_driver *bridge; -	struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev); - -	bridge = tsi148_bridge->driver_priv; - - -	dev_dbg(&pdev->dev, "Driver is being unloaded.\n"); - -	/* -	 *  Shutdown all inbound and outbound windows. -	 */ -	for (i = 0; i < 8; i++) { -		iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] + -			TSI148_LCSR_OFFSET_ITAT); -		iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] + -			TSI148_LCSR_OFFSET_OTAT); -	} - -	/* -	 *  Shutdown Location monitor. -	 */ -	iowrite32be(0, bridge->base + TSI148_LCSR_LMAT); - -	/* -	 *  Shutdown CRG map. -	 */ -	iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT); - -	/* -	 *  Clear error status. -	 */ -	iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT); -	iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT); -	iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT); - -	/* -	 *  Remove VIRQ interrupt (if any) -	 */ -	if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800) -		iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR); - -	/* -	 *  Map all Interrupts to PCI INTA -	 */ -	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1); -	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2); - -	tsi148_irq_exit(bridge, pdev); - -	vme_unregister_bridge(tsi148_bridge); - -	tsi148_crcsr_exit(tsi148_bridge, pdev); - -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->dma_resources)) { -		dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); -		list_del(pos); -		kfree(dma_ctrlr); -	} - -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->slave_resources)) { -		slave_image = list_entry(pos, struct vme_slave_resource, list); -		list_del(pos); -		kfree(slave_image); -	} - -	/* resources are stored in link list */ -	list_for_each(pos, &(tsi148_bridge->master_resources)) { -		master_image = list_entry(pos, struct vme_master_resource, -			list); -		list_del(pos); -		kfree(master_image); -	} - -	tsi148_irq_exit(bridge, pdev); - -	iounmap(bridge->base); - -	pci_release_regions(pdev); - -	pci_disable_device(pdev); - -	kfree(tsi148_bridge->driver_priv); - -	kfree(tsi148_bridge); -} - -static void __exit tsi148_exit(void) -{ -	pci_unregister_driver(&tsi148_driver); -} - -MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes"); -module_param(err_chk, bool, 0); - -MODULE_PARM_DESC(geoid, "Override geographical addressing"); -module_param(geoid, int, 0); - -MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge"); -MODULE_LICENSE("GPL"); - -module_init(tsi148_init); -module_exit(tsi148_exit); diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/staging/vme/bridges/vme_tsi148.h deleted file mode 100644 index bda64ef8575..00000000000 --- a/drivers/staging/vme/bridges/vme_tsi148.h +++ /dev/null @@ -1,1409 +0,0 @@ -/* - * tsi148.h - * - * Support for the Tundra TSI148 VME Bridge chip - * - * Author: Tom Armistead - * Updated and maintained by Ajit Prem - * Copyright 2004 Motorola 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. - */ - -#ifndef TSI148_H -#define TSI148_H - -#ifndef	PCI_VENDOR_ID_TUNDRA -#define	PCI_VENDOR_ID_TUNDRA 0x10e3 -#endif - -#ifndef	PCI_DEVICE_ID_TUNDRA_TSI148 -#define	PCI_DEVICE_ID_TUNDRA_TSI148 0x148 -#endif - -/* - *  Define the number of each that the Tsi148 supports. - */ -#define TSI148_MAX_MASTER		8	/* Max Master Windows */ -#define TSI148_MAX_SLAVE		8	/* Max Slave Windows */ -#define TSI148_MAX_DMA			2	/* Max DMA Controllers */ -#define TSI148_MAX_MAILBOX		4	/* Max Mail Box registers */ -#define TSI148_MAX_SEMAPHORE		8	/* Max Semaphores */ - -/* Structure used to hold driver specific information */ -struct tsi148_driver { -	void *base;	/* Base Address of device registers */ -	wait_queue_head_t dma_queue[2]; -	wait_queue_head_t iack_queue; -	void (*lm_callback[4])(int);	/* Called in interrupt handler */ -	void *crcsr_kernel; -	dma_addr_t crcsr_bus; -	struct vme_master_resource *flush_image; -	struct mutex vme_rmw;		/* Only one RMW cycle at a time */ -	struct mutex vme_int;		/* -					 * Only one VME interrupt can be -					 * generated at a time, provide locking -					 */ -}; - -/* - * Layout of a DMAC Linked-List Descriptor - * - * Note: This structure is accessed via the chip and therefore must be - *       correctly laid out - It must also be aligned on 64-bit boundaries. - */ -struct tsi148_dma_descriptor { -	u32 dsau;      /* Source Address */ -	u32 dsal; -	u32 ddau;      /* Destination Address */ -	u32 ddal; -	u32 dsat;      /* Source attributes */ -	u32 ddat;      /* Destination attributes */ -	u32 dnlau;     /* Next link address */ -	u32 dnlal; -	u32 dcnt;      /* Byte count */ -	u32 ddbs;      /* 2eSST Broadcast select */ -}; - -struct tsi148_dma_entry { -	/* -	 * The descriptor needs to be aligned on a 64-bit boundary, we increase -	 * the chance of this by putting it first in the structure. -	 */ -	struct tsi148_dma_descriptor descriptor; -	struct list_head list; -}; - -/* - *  TSI148 ASIC register structure overlays and bit field definitions. - * - *      Note:   Tsi148 Register Group (CRG) consists of the following - *              combination of registers: - *                      PCFS    - PCI Configuration Space Registers - *                      LCSR    - Local Control and Status Registers - *                      GCSR    - Global Control and Status Registers - *                      CR/CSR  - Subset of Configuration ROM / - *                                Control and Status Registers - */ - - -/* - *  Command/Status Registers (CRG + $004) - */ -#define TSI148_PCFS_ID			0x0 -#define TSI148_PCFS_CSR			0x4 -#define TSI148_PCFS_CLASS		0x8 -#define TSI148_PCFS_MISC0		0xC -#define TSI148_PCFS_MBARL		0x10 -#define TSI148_PCFS_MBARU		0x14 - -#define TSI148_PCFS_SUBID		0x28 - -#define TSI148_PCFS_CAPP		0x34 - -#define TSI148_PCFS_MISC1		0x3C - -#define TSI148_PCFS_XCAPP		0x40 -#define TSI148_PCFS_XSTAT		0x44 - -/* - * LCSR definitions - */ - -/* - *    Outbound Translations - */ -#define TSI148_LCSR_OT0_OTSAU		0x100 -#define TSI148_LCSR_OT0_OTSAL		0x104 -#define TSI148_LCSR_OT0_OTEAU		0x108 -#define TSI148_LCSR_OT0_OTEAL		0x10C -#define TSI148_LCSR_OT0_OTOFU		0x110 -#define TSI148_LCSR_OT0_OTOFL		0x114 -#define TSI148_LCSR_OT0_OTBS		0x118 -#define TSI148_LCSR_OT0_OTAT		0x11C - -#define TSI148_LCSR_OT1_OTSAU		0x120 -#define TSI148_LCSR_OT1_OTSAL		0x124 -#define TSI148_LCSR_OT1_OTEAU		0x128 -#define TSI148_LCSR_OT1_OTEAL		0x12C -#define TSI148_LCSR_OT1_OTOFU		0x130 -#define TSI148_LCSR_OT1_OTOFL		0x134 -#define TSI148_LCSR_OT1_OTBS		0x138 -#define TSI148_LCSR_OT1_OTAT		0x13C - -#define TSI148_LCSR_OT2_OTSAU		0x140 -#define TSI148_LCSR_OT2_OTSAL		0x144 -#define TSI148_LCSR_OT2_OTEAU		0x148 -#define TSI148_LCSR_OT2_OTEAL		0x14C -#define TSI148_LCSR_OT2_OTOFU		0x150 -#define TSI148_LCSR_OT2_OTOFL		0x154 -#define TSI148_LCSR_OT2_OTBS		0x158 -#define TSI148_LCSR_OT2_OTAT		0x15C - -#define TSI148_LCSR_OT3_OTSAU		0x160 -#define TSI148_LCSR_OT3_OTSAL		0x164 -#define TSI148_LCSR_OT3_OTEAU		0x168 -#define TSI148_LCSR_OT3_OTEAL		0x16C -#define TSI148_LCSR_OT3_OTOFU		0x170 -#define TSI148_LCSR_OT3_OTOFL		0x174 -#define TSI148_LCSR_OT3_OTBS		0x178 -#define TSI148_LCSR_OT3_OTAT		0x17C - -#define TSI148_LCSR_OT4_OTSAU		0x180 -#define TSI148_LCSR_OT4_OTSAL		0x184 -#define TSI148_LCSR_OT4_OTEAU		0x188 -#define TSI148_LCSR_OT4_OTEAL		0x18C -#define TSI148_LCSR_OT4_OTOFU		0x190 -#define TSI148_LCSR_OT4_OTOFL		0x194 -#define TSI148_LCSR_OT4_OTBS		0x198 -#define TSI148_LCSR_OT4_OTAT		0x19C - -#define TSI148_LCSR_OT5_OTSAU		0x1A0 -#define TSI148_LCSR_OT5_OTSAL		0x1A4 -#define TSI148_LCSR_OT5_OTEAU		0x1A8 -#define TSI148_LCSR_OT5_OTEAL		0x1AC -#define TSI148_LCSR_OT5_OTOFU		0x1B0 -#define TSI148_LCSR_OT5_OTOFL		0x1B4 -#define TSI148_LCSR_OT5_OTBS		0x1B8 -#define TSI148_LCSR_OT5_OTAT		0x1BC - -#define TSI148_LCSR_OT6_OTSAU		0x1C0 -#define TSI148_LCSR_OT6_OTSAL		0x1C4 -#define TSI148_LCSR_OT6_OTEAU		0x1C8 -#define TSI148_LCSR_OT6_OTEAL		0x1CC -#define TSI148_LCSR_OT6_OTOFU		0x1D0 -#define TSI148_LCSR_OT6_OTOFL		0x1D4 -#define TSI148_LCSR_OT6_OTBS		0x1D8 -#define TSI148_LCSR_OT6_OTAT		0x1DC - -#define TSI148_LCSR_OT7_OTSAU		0x1E0 -#define TSI148_LCSR_OT7_OTSAL		0x1E4 -#define TSI148_LCSR_OT7_OTEAU		0x1E8 -#define TSI148_LCSR_OT7_OTEAL		0x1EC -#define TSI148_LCSR_OT7_OTOFU		0x1F0 -#define TSI148_LCSR_OT7_OTOFL		0x1F4 -#define TSI148_LCSR_OT7_OTBS		0x1F8 -#define TSI148_LCSR_OT7_OTAT		0x1FC - -#define TSI148_LCSR_OT0		0x100 -#define TSI148_LCSR_OT1		0x120 -#define TSI148_LCSR_OT2		0x140 -#define TSI148_LCSR_OT3		0x160 -#define TSI148_LCSR_OT4		0x180 -#define TSI148_LCSR_OT5		0x1A0 -#define TSI148_LCSR_OT6		0x1C0 -#define TSI148_LCSR_OT7		0x1E0 - -static const int TSI148_LCSR_OT[8] = { TSI148_LCSR_OT0, TSI148_LCSR_OT1, -					 TSI148_LCSR_OT2, TSI148_LCSR_OT3, -					 TSI148_LCSR_OT4, TSI148_LCSR_OT5, -					 TSI148_LCSR_OT6, TSI148_LCSR_OT7 }; - -#define TSI148_LCSR_OFFSET_OTSAU	0x0 -#define TSI148_LCSR_OFFSET_OTSAL	0x4 -#define TSI148_LCSR_OFFSET_OTEAU	0x8 -#define TSI148_LCSR_OFFSET_OTEAL	0xC -#define TSI148_LCSR_OFFSET_OTOFU	0x10 -#define TSI148_LCSR_OFFSET_OTOFL	0x14 -#define TSI148_LCSR_OFFSET_OTBS		0x18 -#define TSI148_LCSR_OFFSET_OTAT		0x1C - -/* - * VMEbus interupt ack - * offset  200 - */ -#define TSI148_LCSR_VIACK1	0x204 -#define TSI148_LCSR_VIACK2	0x208 -#define TSI148_LCSR_VIACK3	0x20C -#define TSI148_LCSR_VIACK4	0x210 -#define TSI148_LCSR_VIACK5	0x214 -#define TSI148_LCSR_VIACK6	0x218 -#define TSI148_LCSR_VIACK7	0x21C - -static const int TSI148_LCSR_VIACK[8] = { 0, TSI148_LCSR_VIACK1, -				TSI148_LCSR_VIACK2, TSI148_LCSR_VIACK3, -				TSI148_LCSR_VIACK4, TSI148_LCSR_VIACK5, -				TSI148_LCSR_VIACK6, TSI148_LCSR_VIACK7 }; - -/* - * RMW - * offset    220 - */ -#define TSI148_LCSR_RMWAU	0x220 -#define TSI148_LCSR_RMWAL	0x224 -#define TSI148_LCSR_RMWEN	0x228 -#define TSI148_LCSR_RMWC	0x22C -#define TSI148_LCSR_RMWS	0x230 - -/* - * VMEbus control - * offset    234 - */ -#define TSI148_LCSR_VMCTRL	0x234 -#define TSI148_LCSR_VCTRL	0x238 -#define TSI148_LCSR_VSTAT	0x23C - -/* - * PCI status - * offset  240 - */ -#define TSI148_LCSR_PSTAT	0x240 - -/* - * VME filter. - * offset  250 - */ -#define TSI148_LCSR_VMEFL	0x250 - -	/* -	 * VME exception. -	 * offset  260 - */ -#define TSI148_LCSR_VEAU	0x260 -#define TSI148_LCSR_VEAL	0x264 -#define TSI148_LCSR_VEAT	0x268 - -	/* -	 * PCI error -	 * offset  270 -	 */ -#define TSI148_LCSR_EDPAU	0x270 -#define TSI148_LCSR_EDPAL	0x274 -#define TSI148_LCSR_EDPXA	0x278 -#define TSI148_LCSR_EDPXS	0x27C -#define TSI148_LCSR_EDPAT	0x280 - -	/* -	 * Inbound Translations -	 * offset  300 -	 */ -#define TSI148_LCSR_IT0_ITSAU		0x300 -#define TSI148_LCSR_IT0_ITSAL		0x304 -#define TSI148_LCSR_IT0_ITEAU		0x308 -#define TSI148_LCSR_IT0_ITEAL		0x30C -#define TSI148_LCSR_IT0_ITOFU		0x310 -#define TSI148_LCSR_IT0_ITOFL		0x314 -#define TSI148_LCSR_IT0_ITAT		0x318 - -#define TSI148_LCSR_IT1_ITSAU		0x320 -#define TSI148_LCSR_IT1_ITSAL		0x324 -#define TSI148_LCSR_IT1_ITEAU		0x328 -#define TSI148_LCSR_IT1_ITEAL		0x32C -#define TSI148_LCSR_IT1_ITOFU		0x330 -#define TSI148_LCSR_IT1_ITOFL		0x334 -#define TSI148_LCSR_IT1_ITAT		0x338 - -#define TSI148_LCSR_IT2_ITSAU		0x340 -#define TSI148_LCSR_IT2_ITSAL		0x344 -#define TSI148_LCSR_IT2_ITEAU		0x348 -#define TSI148_LCSR_IT2_ITEAL		0x34C -#define TSI148_LCSR_IT2_ITOFU		0x350 -#define TSI148_LCSR_IT2_ITOFL		0x354 -#define TSI148_LCSR_IT2_ITAT		0x358 - -#define TSI148_LCSR_IT3_ITSAU		0x360 -#define TSI148_LCSR_IT3_ITSAL		0x364 -#define TSI148_LCSR_IT3_ITEAU		0x368 -#define TSI148_LCSR_IT3_ITEAL		0x36C -#define TSI148_LCSR_IT3_ITOFU		0x370 -#define TSI148_LCSR_IT3_ITOFL		0x374 -#define TSI148_LCSR_IT3_ITAT		0x378 - -#define TSI148_LCSR_IT4_ITSAU		0x380 -#define TSI148_LCSR_IT4_ITSAL		0x384 -#define TSI148_LCSR_IT4_ITEAU		0x388 -#define TSI148_LCSR_IT4_ITEAL		0x38C -#define TSI148_LCSR_IT4_ITOFU		0x390 -#define TSI148_LCSR_IT4_ITOFL		0x394 -#define TSI148_LCSR_IT4_ITAT		0x398 - -#define TSI148_LCSR_IT5_ITSAU		0x3A0 -#define TSI148_LCSR_IT5_ITSAL		0x3A4 -#define TSI148_LCSR_IT5_ITEAU		0x3A8 -#define TSI148_LCSR_IT5_ITEAL		0x3AC -#define TSI148_LCSR_IT5_ITOFU		0x3B0 -#define TSI148_LCSR_IT5_ITOFL		0x3B4 -#define TSI148_LCSR_IT5_ITAT		0x3B8 - -#define TSI148_LCSR_IT6_ITSAU		0x3C0 -#define TSI148_LCSR_IT6_ITSAL		0x3C4 -#define TSI148_LCSR_IT6_ITEAU		0x3C8 -#define TSI148_LCSR_IT6_ITEAL		0x3CC -#define TSI148_LCSR_IT6_ITOFU		0x3D0 -#define TSI148_LCSR_IT6_ITOFL		0x3D4 -#define TSI148_LCSR_IT6_ITAT		0x3D8 - -#define TSI148_LCSR_IT7_ITSAU		0x3E0 -#define TSI148_LCSR_IT7_ITSAL		0x3E4 -#define TSI148_LCSR_IT7_ITEAU		0x3E8 -#define TSI148_LCSR_IT7_ITEAL		0x3EC -#define TSI148_LCSR_IT7_ITOFU		0x3F0 -#define TSI148_LCSR_IT7_ITOFL		0x3F4 -#define TSI148_LCSR_IT7_ITAT		0x3F8 - - -#define TSI148_LCSR_IT0		0x300 -#define TSI148_LCSR_IT1		0x320 -#define TSI148_LCSR_IT2		0x340 -#define TSI148_LCSR_IT3		0x360 -#define TSI148_LCSR_IT4		0x380 -#define TSI148_LCSR_IT5		0x3A0 -#define TSI148_LCSR_IT6		0x3C0 -#define TSI148_LCSR_IT7		0x3E0 - -static const int TSI148_LCSR_IT[8] = { TSI148_LCSR_IT0, TSI148_LCSR_IT1, -					 TSI148_LCSR_IT2, TSI148_LCSR_IT3, -					 TSI148_LCSR_IT4, TSI148_LCSR_IT5, -					 TSI148_LCSR_IT6, TSI148_LCSR_IT7 }; - -#define TSI148_LCSR_OFFSET_ITSAU	0x0 -#define TSI148_LCSR_OFFSET_ITSAL	0x4 -#define TSI148_LCSR_OFFSET_ITEAU	0x8 -#define TSI148_LCSR_OFFSET_ITEAL	0xC -#define TSI148_LCSR_OFFSET_ITOFU	0x10 -#define TSI148_LCSR_OFFSET_ITOFL	0x14 -#define TSI148_LCSR_OFFSET_ITAT		0x18 - -	/* -	 * Inbound Translation GCSR -	 * offset  400 -	 */ -#define TSI148_LCSR_GBAU	0x400 -#define TSI148_LCSR_GBAL	0x404 -#define TSI148_LCSR_GCSRAT	0x408 - -	/* -	 * Inbound Translation CRG -	 * offset  40C -	 */ -#define TSI148_LCSR_CBAU	0x40C -#define TSI148_LCSR_CBAL	0x410 -#define TSI148_LCSR_CSRAT	0x414 - -	/* -	 * Inbound Translation CR/CSR -	 *         CRG -	 * offset  418 -	 */ -#define TSI148_LCSR_CROU	0x418 -#define TSI148_LCSR_CROL	0x41C -#define TSI148_LCSR_CRAT	0x420 - -	/* -	 * Inbound Translation Location Monitor -	 * offset  424 -	 */ -#define TSI148_LCSR_LMBAU	0x424 -#define TSI148_LCSR_LMBAL	0x428 -#define TSI148_LCSR_LMAT	0x42C - -	/* -	 * VMEbus Interrupt Control. -	 * offset  430 -	 */ -#define TSI148_LCSR_BCU		0x430 -#define TSI148_LCSR_BCL		0x434 -#define TSI148_LCSR_BPGTR	0x438 -#define TSI148_LCSR_BPCTR	0x43C -#define TSI148_LCSR_VICR	0x440 - -	/* -	 * Local Bus Interrupt Control. -	 * offset  448 -	 */ -#define TSI148_LCSR_INTEN	0x448 -#define TSI148_LCSR_INTEO	0x44C -#define TSI148_LCSR_INTS	0x450 -#define TSI148_LCSR_INTC	0x454 -#define TSI148_LCSR_INTM1	0x458 -#define TSI148_LCSR_INTM2	0x45C - -	/* -	 * DMA Controllers -	 * offset 500 -	 */ -#define TSI148_LCSR_DCTL0	0x500 -#define TSI148_LCSR_DSTA0	0x504 -#define TSI148_LCSR_DCSAU0	0x508 -#define TSI148_LCSR_DCSAL0	0x50C -#define TSI148_LCSR_DCDAU0	0x510 -#define TSI148_LCSR_DCDAL0	0x514 -#define TSI148_LCSR_DCLAU0	0x518 -#define TSI148_LCSR_DCLAL0	0x51C -#define TSI148_LCSR_DSAU0	0x520 -#define TSI148_LCSR_DSAL0	0x524 -#define TSI148_LCSR_DDAU0	0x528 -#define TSI148_LCSR_DDAL0	0x52C -#define TSI148_LCSR_DSAT0	0x530 -#define TSI148_LCSR_DDAT0	0x534 -#define TSI148_LCSR_DNLAU0	0x538 -#define TSI148_LCSR_DNLAL0	0x53C -#define TSI148_LCSR_DCNT0	0x540 -#define TSI148_LCSR_DDBS0	0x544 - -#define TSI148_LCSR_DCTL1	0x580 -#define TSI148_LCSR_DSTA1	0x584 -#define TSI148_LCSR_DCSAU1	0x588 -#define TSI148_LCSR_DCSAL1	0x58C -#define TSI148_LCSR_DCDAU1	0x590 -#define TSI148_LCSR_DCDAL1	0x594 -#define TSI148_LCSR_DCLAU1	0x598 -#define TSI148_LCSR_DCLAL1	0x59C -#define TSI148_LCSR_DSAU1	0x5A0 -#define TSI148_LCSR_DSAL1	0x5A4 -#define TSI148_LCSR_DDAU1	0x5A8 -#define TSI148_LCSR_DDAL1	0x5AC -#define TSI148_LCSR_DSAT1	0x5B0 -#define TSI148_LCSR_DDAT1	0x5B4 -#define TSI148_LCSR_DNLAU1	0x5B8 -#define TSI148_LCSR_DNLAL1	0x5BC -#define TSI148_LCSR_DCNT1	0x5C0 -#define TSI148_LCSR_DDBS1	0x5C4 - -#define TSI148_LCSR_DMA0	0x500 -#define TSI148_LCSR_DMA1	0x580 - - -static const int TSI148_LCSR_DMA[TSI148_MAX_DMA] = { TSI148_LCSR_DMA0, -						TSI148_LCSR_DMA1 }; - -#define TSI148_LCSR_OFFSET_DCTL		0x0 -#define TSI148_LCSR_OFFSET_DSTA		0x4 -#define TSI148_LCSR_OFFSET_DCSAU	0x8 -#define TSI148_LCSR_OFFSET_DCSAL	0xC -#define TSI148_LCSR_OFFSET_DCDAU	0x10 -#define TSI148_LCSR_OFFSET_DCDAL	0x14 -#define TSI148_LCSR_OFFSET_DCLAU	0x18 -#define TSI148_LCSR_OFFSET_DCLAL	0x1C -#define TSI148_LCSR_OFFSET_DSAU		0x20 -#define TSI148_LCSR_OFFSET_DSAL		0x24 -#define TSI148_LCSR_OFFSET_DDAU		0x28 -#define TSI148_LCSR_OFFSET_DDAL		0x2C -#define TSI148_LCSR_OFFSET_DSAT		0x30 -#define TSI148_LCSR_OFFSET_DDAT		0x34 -#define TSI148_LCSR_OFFSET_DNLAU	0x38 -#define TSI148_LCSR_OFFSET_DNLAL	0x3C -#define TSI148_LCSR_OFFSET_DCNT		0x40 -#define TSI148_LCSR_OFFSET_DDBS		0x44 - -	/* -	 * GCSR Register Group -	 */ - -	/* -	 *         GCSR    CRG -	 * offset   00     600 - DEVI/VENI -	 * offset   04     604 - CTRL/GA/REVID -	 * offset   08     608 - Semaphore3/2/1/0 -	 * offset   0C     60C - Seamphore7/6/5/4 -	 */ -#define TSI148_GCSR_ID		0x600 -#define TSI148_GCSR_CSR		0x604 -#define TSI148_GCSR_SEMA0	0x608 -#define TSI148_GCSR_SEMA1	0x60C - -	/* -	 * Mail Box -	 *         GCSR    CRG -	 * offset   10     610 - Mailbox0 -	 */ -#define TSI148_GCSR_MBOX0	0x610 -#define TSI148_GCSR_MBOX1	0x614 -#define TSI148_GCSR_MBOX2	0x618 -#define TSI148_GCSR_MBOX3	0x61C - -static const int TSI148_GCSR_MBOX[4] = { TSI148_GCSR_MBOX0, -					TSI148_GCSR_MBOX1, -					TSI148_GCSR_MBOX2, -					TSI148_GCSR_MBOX3 }; - -	/* -	 * CR/CSR -	 */ - -	/* -	 *        CR/CSR   CRG -	 * offset  7FFF4   FF4 - CSRBCR -	 * offset  7FFF8   FF8 - CSRBSR -	 * offset  7FFFC   FFC - CBAR -	 */ -#define TSI148_CSRBCR	0xFF4 -#define TSI148_CSRBSR	0xFF8 -#define TSI148_CBAR	0xFFC - - - - -	/* -	 *  TSI148 Register Bit Definitions -	 */ - -	/* -	 *  PFCS Register Set -	 */ -#define TSI148_PCFS_CMMD_SERR          (1<<8)	/* SERR_L out pin ssys err */ -#define TSI148_PCFS_CMMD_PERR          (1<<6)	/* PERR_L out pin  parity */ -#define TSI148_PCFS_CMMD_MSTR          (1<<2)	/* PCI bus master */ -#define TSI148_PCFS_CMMD_MEMSP         (1<<1)	/* PCI mem space access  */ -#define TSI148_PCFS_CMMD_IOSP          (1<<0)	/* PCI I/O space enable */ - -#define TSI148_PCFS_STAT_RCPVE         (1<<15)	/* Detected Parity Error */ -#define TSI148_PCFS_STAT_SIGSE         (1<<14)	/* Signalled System Error */ -#define TSI148_PCFS_STAT_RCVMA         (1<<13)	/* Received Master Abort */ -#define TSI148_PCFS_STAT_RCVTA         (1<<12)	/* Received Target Abort */ -#define TSI148_PCFS_STAT_SIGTA         (1<<11)	/* Signalled Target Abort */ -#define TSI148_PCFS_STAT_SELTIM        (3<<9)	/* DELSEL Timing */ -#define TSI148_PCFS_STAT_DPAR          (1<<8)	/* Data Parity Err Reported */ -#define TSI148_PCFS_STAT_FAST          (1<<7)	/* Fast back-to-back Cap */ -#define TSI148_PCFS_STAT_P66M          (1<<5)	/* 66 MHz Capable */ -#define TSI148_PCFS_STAT_CAPL          (1<<4)	/* Capab List - address $34 */ - -/* - *  Revision ID/Class Code Registers   (CRG +$008) - */ -#define TSI148_PCFS_CLAS_M             (0xFF<<24)	/* Class ID */ -#define TSI148_PCFS_SUBCLAS_M          (0xFF<<16)	/* Sub-Class ID */ -#define TSI148_PCFS_PROGIF_M           (0xFF<<8)	/* Sub-Class ID */ -#define TSI148_PCFS_REVID_M            (0xFF<<0)	/* Rev ID */ - -/* - * Cache Line Size/ Master Latency Timer/ Header Type Registers (CRG + $00C) - */ -#define TSI148_PCFS_HEAD_M             (0xFF<<16)	/* Master Lat Timer */ -#define TSI148_PCFS_MLAT_M             (0xFF<<8)	/* Master Lat Timer */ -#define TSI148_PCFS_CLSZ_M             (0xFF<<0)	/* Cache Line Size */ - -/* - *  Memory Base Address Lower Reg (CRG + $010) - */ -#define TSI148_PCFS_MBARL_BASEL_M      (0xFFFFF<<12) /* Base Addr Lower Mask */ -#define TSI148_PCFS_MBARL_PRE          (1<<3)	/* Prefetch */ -#define TSI148_PCFS_MBARL_MTYPE_M      (3<<1)	/* Memory Type Mask */ -#define TSI148_PCFS_MBARL_IOMEM        (1<<0)	/* I/O Space Indicator */ - -/* - *  Message Signaled Interrupt Capabilities Register (CRG + $040) - */ -#define TSI148_PCFS_MSICAP_64BAC       (1<<7)	/* 64-bit Address Capable */ -#define TSI148_PCFS_MSICAP_MME_M       (7<<4)	/* Multiple Msg Enable Mask */ -#define TSI148_PCFS_MSICAP_MMC_M       (7<<1)	/* Multiple Msg Capable Mask */ -#define TSI148_PCFS_MSICAP_MSIEN       (1<<0)	/* Msg signaled INT Enable */ - -/* - *  Message Address Lower Register (CRG +$044) - */ -#define TSI148_PCFS_MSIAL_M            (0x3FFFFFFF<<2)	/* Mask */ - -/* - *  Message Data Register (CRG + 4C) - */ -#define TSI148_PCFS_MSIMD_M            (0xFFFF<<0)	/* Mask */ - -/* - *  PCI-X Capabilities Register (CRG + $050) - */ -#define TSI148_PCFS_PCIXCAP_MOST_M     (7<<4)	/* Max outstanding Split Tran */ -#define TSI148_PCFS_PCIXCAP_MMRBC_M    (3<<2)	/* Max Mem Read byte cnt */ -#define TSI148_PCFS_PCIXCAP_ERO        (1<<1)	/* Enable Relaxed Ordering */ -#define TSI148_PCFS_PCIXCAP_DPERE      (1<<0)	/* Data Parity Recover Enable */ - -/* - *  PCI-X Status Register (CRG +$054) - */ -#define TSI148_PCFS_PCIXSTAT_RSCEM     (1<<29)	/* Recieved Split Comp Error */ -#define TSI148_PCFS_PCIXSTAT_DMCRS_M   (7<<26)	/* max Cumulative Read Size */ -#define TSI148_PCFS_PCIXSTAT_DMOST_M   (7<<23)	/* max outstanding Split Trans -						 */ -#define TSI148_PCFS_PCIXSTAT_DMMRC_M   (3<<21)	/* max mem read byte count */ -#define TSI148_PCFS_PCIXSTAT_DC        (1<<20)	/* Device Complexity */ -#define TSI148_PCFS_PCIXSTAT_USC       (1<<19)	/* Unexpected Split comp */ -#define TSI148_PCFS_PCIXSTAT_SCD       (1<<18)	/* Split completion discard */ -#define TSI148_PCFS_PCIXSTAT_133C      (1<<17)	/* 133MHz capable */ -#define TSI148_PCFS_PCIXSTAT_64D       (1<<16)	/* 64 bit device */ -#define TSI148_PCFS_PCIXSTAT_BN_M      (0xFF<<8)	/* Bus number */ -#define TSI148_PCFS_PCIXSTAT_DN_M      (0x1F<<3)	/* Device number */ -#define TSI148_PCFS_PCIXSTAT_FN_M      (7<<0)	/* Function Number */ - -/* - *  LCSR Registers - */ - -/* - *  Outbound Translation Starting Address Lower - */ -#define TSI148_LCSR_OTSAL_M            (0xFFFF<<16)	/* Mask */ - -/* - *  Outbound Translation Ending Address Lower - */ -#define TSI148_LCSR_OTEAL_M            (0xFFFF<<16)	/* Mask */ - -/* - *  Outbound Translation Offset Lower - */ -#define TSI148_LCSR_OTOFFL_M           (0xFFFF<<16)	/* Mask */ - -/* - *  Outbound Translation 2eSST Broadcast Select - */ -#define TSI148_LCSR_OTBS_M             (0xFFFFF<<0)	/* Mask */ - -/* - *  Outbound Translation Attribute - */ -#define TSI148_LCSR_OTAT_EN            (1<<31)	/* Window Enable */ -#define TSI148_LCSR_OTAT_MRPFD         (1<<18)	/* Prefetch Disable */ - -#define TSI148_LCSR_OTAT_PFS_M         (3<<16)	/* Prefetch Size Mask */ -#define TSI148_LCSR_OTAT_PFS_2         (0<<16)	/* 2 Cache Lines P Size */ -#define TSI148_LCSR_OTAT_PFS_4         (1<<16)	/* 4 Cache Lines P Size */ -#define TSI148_LCSR_OTAT_PFS_8         (2<<16)	/* 8 Cache Lines P Size */ -#define TSI148_LCSR_OTAT_PFS_16        (3<<16)	/* 16 Cache Lines P Size */ - -#define TSI148_LCSR_OTAT_2eSSTM_M      (7<<11)	/* 2eSST Xfer Rate Mask */ -#define TSI148_LCSR_OTAT_2eSSTM_160    (0<<11)	/* 160MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_OTAT_2eSSTM_267    (1<<11)	/* 267MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_OTAT_2eSSTM_320    (2<<11)	/* 320MB/s 2eSST Xfer Rate */ - -#define TSI148_LCSR_OTAT_TM_M          (7<<8)	/* Xfer Protocol Mask */ -#define TSI148_LCSR_OTAT_TM_SCT        (0<<8)	/* SCT Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_BLT        (1<<8)	/* BLT Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_MBLT       (2<<8)	/* MBLT Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_2eVME      (3<<8)	/* 2eVME Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_2eSST      (4<<8)	/* 2eSST Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_2eSSTB     (5<<8)	/* 2eSST Bcast Xfer Protocol */ - -#define TSI148_LCSR_OTAT_DBW_M         (3<<6)	/* Max Data Width */ -#define TSI148_LCSR_OTAT_DBW_16        (0<<6)	/* 16-bit Data Width */ -#define TSI148_LCSR_OTAT_DBW_32        (1<<6)	/* 32-bit Data Width */ - -#define TSI148_LCSR_OTAT_SUP           (1<<5)	/* Supervisory Access */ -#define TSI148_LCSR_OTAT_PGM           (1<<4)	/* Program Access */ - -#define TSI148_LCSR_OTAT_AMODE_M       (0xf<<0)	/* Address Mode Mask */ -#define TSI148_LCSR_OTAT_AMODE_A16     (0<<0)	/* A16 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_A24     (1<<0)	/* A24 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_A32     (2<<0)	/* A32 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_A64     (4<<0)	/* A32 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_CRCSR   (5<<0)	/* CR/CSR Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER1   (8<<0)	/* User1 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER2   (9<<0)	/* User2 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER3   (10<<0)	/* User3 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER4   (11<<0)	/* User4 Address Space */ - -/* - *  VME Master Control Register  CRG+$234 - */ -#define TSI148_LCSR_VMCTRL_VSA         (1<<27)	/* VMEbus Stop Ack */ -#define TSI148_LCSR_VMCTRL_VS          (1<<26)	/* VMEbus Stop */ -#define TSI148_LCSR_VMCTRL_DHB         (1<<25)	/* Device Has Bus */ -#define TSI148_LCSR_VMCTRL_DWB         (1<<24)	/* Device Wants Bus */ - -#define TSI148_LCSR_VMCTRL_RMWEN       (1<<20)	/* RMW Enable */ - -#define TSI148_LCSR_VMCTRL_ATO_M       (7<<16)	/* Master Access Time-out Mask -						 */ -#define TSI148_LCSR_VMCTRL_ATO_32      (0<<16)	/* 32 us */ -#define TSI148_LCSR_VMCTRL_ATO_128     (1<<16)	/* 128 us */ -#define TSI148_LCSR_VMCTRL_ATO_512     (2<<16)	/* 512 us */ -#define TSI148_LCSR_VMCTRL_ATO_2M      (3<<16)	/* 2 ms */ -#define TSI148_LCSR_VMCTRL_ATO_8M      (4<<16)	/* 8 ms */ -#define TSI148_LCSR_VMCTRL_ATO_32M     (5<<16)	/* 32 ms */ -#define TSI148_LCSR_VMCTRL_ATO_128M    (6<<16)	/* 128 ms */ -#define TSI148_LCSR_VMCTRL_ATO_DIS     (7<<16)	/* Disabled */ - -#define TSI148_LCSR_VMCTRL_VTOFF_M     (7<<12)	/* VMEbus Master Time off */ -#define TSI148_LCSR_VMCTRL_VTOFF_0     (0<<12)	/* 0us */ -#define TSI148_LCSR_VMCTRL_VTOFF_1     (1<<12)	/* 1us */ -#define TSI148_LCSR_VMCTRL_VTOFF_2     (2<<12)	/* 2us */ -#define TSI148_LCSR_VMCTRL_VTOFF_4     (3<<12)	/* 4us */ -#define TSI148_LCSR_VMCTRL_VTOFF_8     (4<<12)	/* 8us */ -#define TSI148_LCSR_VMCTRL_VTOFF_16    (5<<12)	/* 16us */ -#define TSI148_LCSR_VMCTRL_VTOFF_32    (6<<12)	/* 32us */ -#define TSI148_LCSR_VMCTRL_VTOFF_64    (7<<12)	/* 64us */ - -#define TSI148_LCSR_VMCTRL_VTON_M      (7<<8)	/* VMEbus Master Time On */ -#define TSI148_LCSR_VMCTRL_VTON_4      (0<<8)	/* 8us */ -#define TSI148_LCSR_VMCTRL_VTON_8      (1<<8)	/* 8us */ -#define TSI148_LCSR_VMCTRL_VTON_16     (2<<8)	/* 16us */ -#define TSI148_LCSR_VMCTRL_VTON_32     (3<<8)	/* 32us */ -#define TSI148_LCSR_VMCTRL_VTON_64     (4<<8)	/* 64us */ -#define TSI148_LCSR_VMCTRL_VTON_128    (5<<8)	/* 128us */ -#define TSI148_LCSR_VMCTRL_VTON_256    (6<<8)	/* 256us */ -#define TSI148_LCSR_VMCTRL_VTON_512    (7<<8)	/* 512us */ - -#define TSI148_LCSR_VMCTRL_VREL_M      (3<<3)	/* VMEbus Master Rel Mode Mask -						 */ -#define TSI148_LCSR_VMCTRL_VREL_T_D    (0<<3)	/* Time on or Done */ -#define TSI148_LCSR_VMCTRL_VREL_T_R_D  (1<<3)	/* Time on and REQ or Done */ -#define TSI148_LCSR_VMCTRL_VREL_T_B_D  (2<<3)	/* Time on and BCLR or Done */ -#define TSI148_LCSR_VMCTRL_VREL_T_D_R  (3<<3)	/* Time on or Done and REQ */ - -#define TSI148_LCSR_VMCTRL_VFAIR       (1<<2)	/* VMEbus Master Fair Mode */ -#define TSI148_LCSR_VMCTRL_VREQL_M     (3<<0)	/* VMEbus Master Req Level Mask -						 */ - -/* - *  VMEbus Control Register CRG+$238 - */ -#define TSI148_LCSR_VCTRL_LRE          (1<<31)	/* Late Retry Enable */ - -#define TSI148_LCSR_VCTRL_DLT_M        (0xF<<24)	/* Deadlock Timer */ -#define TSI148_LCSR_VCTRL_DLT_OFF      (0<<24)	/* Deadlock Timer Off */ -#define TSI148_LCSR_VCTRL_DLT_16       (1<<24)	/* 16 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_32       (2<<24)	/* 32 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_64       (3<<24)	/* 64 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_128      (4<<24)	/* 128 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_256      (5<<24)	/* 256 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_512      (6<<24)	/* 512 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_1024     (7<<24)	/* 1024 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_2048     (8<<24)	/* 2048 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_4096     (9<<24)	/* 4096 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_8192     (0xA<<24)	/* 8192 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_16384    (0xB<<24)	/* 16384 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_32768    (0xC<<24)	/* 32768 VCLKS */ - -#define TSI148_LCSR_VCTRL_NERBB        (1<<20)	/* No Early Release of Bus Busy -						 */ - -#define TSI148_LCSR_VCTRL_SRESET       (1<<17)	/* System Reset */ -#define TSI148_LCSR_VCTRL_LRESET       (1<<16)	/* Local Reset */ - -#define TSI148_LCSR_VCTRL_SFAILAI      (1<<15)	/* SYSFAIL Auto Slot ID */ -#define TSI148_LCSR_VCTRL_BID_M        (0x1F<<8)	/* Broadcast ID Mask */ - -#define TSI148_LCSR_VCTRL_ATOEN        (1<<7)	/* Arbiter Time-out Enable */ -#define TSI148_LCSR_VCTRL_ROBIN        (1<<6)	/* VMEbus Round Robin */ - -#define TSI148_LCSR_VCTRL_GTO_M        (7<<0)	/* VMEbus Global Time-out Mask -						 */ -#define TSI148_LCSR_VCTRL_GTO_8	      (0<<0)	/* 8 us */ -#define TSI148_LCSR_VCTRL_GTO_16	      (1<<0)	/* 16 us */ -#define TSI148_LCSR_VCTRL_GTO_32	      (2<<0)	/* 32 us */ -#define TSI148_LCSR_VCTRL_GTO_64	      (3<<0)	/* 64 us */ -#define TSI148_LCSR_VCTRL_GTO_128      (4<<0)	/* 128 us */ -#define TSI148_LCSR_VCTRL_GTO_256      (5<<0)	/* 256 us */ -#define TSI148_LCSR_VCTRL_GTO_512      (6<<0)	/* 512 us */ -#define TSI148_LCSR_VCTRL_GTO_DIS      (7<<0)	/* Disabled */ - -/* - *  VMEbus Status Register  CRG + $23C - */ -#define TSI148_LCSR_VSTAT_CPURST       (1<<15)	/* Clear power up reset */ -#define TSI148_LCSR_VSTAT_BRDFL        (1<<14)	/* Board fail */ -#define TSI148_LCSR_VSTAT_PURSTS       (1<<12)	/* Power up reset status */ -#define TSI148_LCSR_VSTAT_BDFAILS      (1<<11)	/* Board Fail Status */ -#define TSI148_LCSR_VSTAT_SYSFAILS     (1<<10)	/* System Fail Status */ -#define TSI148_LCSR_VSTAT_ACFAILS      (1<<9)	/* AC fail status */ -#define TSI148_LCSR_VSTAT_SCONS        (1<<8)	/* System Cont Status */ -#define TSI148_LCSR_VSTAT_GAP          (1<<5)	/* Geographic Addr Parity */ -#define TSI148_LCSR_VSTAT_GA_M         (0x1F<<0)  /* Geographic Addr Mask */ - -/* - *  PCI Configuration Status Register CRG+$240 - */ -#define TSI148_LCSR_PSTAT_REQ64S       (1<<6)	/* Request 64 status set */ -#define TSI148_LCSR_PSTAT_M66ENS       (1<<5)	/* M66ENS 66Mhz enable */ -#define TSI148_LCSR_PSTAT_FRAMES       (1<<4)	/* Frame Status */ -#define TSI148_LCSR_PSTAT_IRDYS        (1<<3)	/* IRDY status */ -#define TSI148_LCSR_PSTAT_DEVSELS      (1<<2)	/* DEVL status */ -#define TSI148_LCSR_PSTAT_STOPS        (1<<1)	/* STOP status */ -#define TSI148_LCSR_PSTAT_TRDYS        (1<<0)	/* TRDY status */ - -/* - *  VMEbus Exception Attributes Register  CRG + $268 - */ -#define TSI148_LCSR_VEAT_VES           (1<<31)	/* Status */ -#define TSI148_LCSR_VEAT_VEOF          (1<<30)	/* Overflow */ -#define TSI148_LCSR_VEAT_VESCL         (1<<29)	/* Status Clear */ -#define TSI148_LCSR_VEAT_2EOT          (1<<21)	/* 2e Odd Termination */ -#define TSI148_LCSR_VEAT_2EST          (1<<20)	/* 2e Slave terminated */ -#define TSI148_LCSR_VEAT_BERR          (1<<19)	/* Bus Error */ -#define TSI148_LCSR_VEAT_LWORD         (1<<18)	/* LWORD_ signal state */ -#define TSI148_LCSR_VEAT_WRITE         (1<<17)	/* WRITE_ signal state */ -#define TSI148_LCSR_VEAT_IACK          (1<<16)	/* IACK_ signal state */ -#define TSI148_LCSR_VEAT_DS1           (1<<15)	/* DS1_ signal state */ -#define TSI148_LCSR_VEAT_DS0           (1<<14)	/* DS0_ signal state */ -#define TSI148_LCSR_VEAT_AM_M          (0x3F<<8)	/* Address Mode Mask */ -#define TSI148_LCSR_VEAT_XAM_M         (0xFF<<0)	/* Master AMode Mask */ - - -/* - * VMEbus PCI Error Diagnostics PCI/X Attributes Register  CRG + $280 - */ -#define TSI148_LCSR_EDPAT_EDPCL        (1<<29) - -/* - *  Inbound Translation Starting Address Lower - */ -#define TSI148_LCSR_ITSAL6432_M        (0xFFFF<<16)	/* Mask */ -#define TSI148_LCSR_ITSAL24_M          (0x00FFF<<12)	/* Mask */ -#define TSI148_LCSR_ITSAL16_M          (0x0000FFF<<4)	/* Mask */ - -/* - *  Inbound Translation Ending Address Lower - */ -#define TSI148_LCSR_ITEAL6432_M        (0xFFFF<<16)	/* Mask */ -#define TSI148_LCSR_ITEAL24_M          (0x00FFF<<12)	/* Mask */ -#define TSI148_LCSR_ITEAL16_M          (0x0000FFF<<4)	/* Mask */ - -/* - *  Inbound Translation Offset Lower - */ -#define TSI148_LCSR_ITOFFL6432_M       (0xFFFF<<16)	/* Mask */ -#define TSI148_LCSR_ITOFFL24_M         (0xFFFFF<<12)	/* Mask */ -#define TSI148_LCSR_ITOFFL16_M         (0xFFFFFFF<<4)	/* Mask */ - -/* - *  Inbound Translation Attribute - */ -#define TSI148_LCSR_ITAT_EN            (1<<31)	/* Window Enable */ -#define TSI148_LCSR_ITAT_TH            (1<<18)	/* Prefetch Threshold */ - -#define TSI148_LCSR_ITAT_VFS_M         (3<<16)	/* Virtual FIFO Size Mask */ -#define TSI148_LCSR_ITAT_VFS_64        (0<<16)	/* 64 bytes Virtual FIFO Size */ -#define TSI148_LCSR_ITAT_VFS_128       (1<<16)	/* 128 bytes Virtual FIFO Sz */ -#define TSI148_LCSR_ITAT_VFS_256       (2<<16)	/* 256 bytes Virtual FIFO Sz */ -#define TSI148_LCSR_ITAT_VFS_512       (3<<16)	/* 512 bytes Virtual FIFO Sz */ - -#define TSI148_LCSR_ITAT_2eSSTM_M      (7<<12)	/* 2eSST Xfer Rate Mask */ -#define TSI148_LCSR_ITAT_2eSSTM_160    (0<<12)	/* 160MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_ITAT_2eSSTM_267    (1<<12)	/* 267MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_ITAT_2eSSTM_320    (2<<12)	/* 320MB/s 2eSST Xfer Rate */ - -#define TSI148_LCSR_ITAT_2eSSTB        (1<<11)	/* 2eSST Bcast Xfer Protocol */ -#define TSI148_LCSR_ITAT_2eSST         (1<<10)	/* 2eSST Xfer Protocol */ -#define TSI148_LCSR_ITAT_2eVME         (1<<9)	/* 2eVME Xfer Protocol */ -#define TSI148_LCSR_ITAT_MBLT          (1<<8)	/* MBLT Xfer Protocol */ -#define TSI148_LCSR_ITAT_BLT           (1<<7)	/* BLT Xfer Protocol */ - -#define TSI148_LCSR_ITAT_AS_M          (7<<4)	/* Address Space Mask */ -#define TSI148_LCSR_ITAT_AS_A16        (0<<4)	/* A16 Address Space */ -#define TSI148_LCSR_ITAT_AS_A24        (1<<4)	/* A24 Address Space */ -#define TSI148_LCSR_ITAT_AS_A32        (2<<4)	/* A32 Address Space */ -#define TSI148_LCSR_ITAT_AS_A64        (4<<4)	/* A64 Address Space */ - -#define TSI148_LCSR_ITAT_SUPR          (1<<3)	/* Supervisor Access */ -#define TSI148_LCSR_ITAT_NPRIV         (1<<2)	/* Non-Priv (User) Access */ -#define TSI148_LCSR_ITAT_PGM           (1<<1)	/* Program Access */ -#define TSI148_LCSR_ITAT_DATA          (1<<0)	/* Data Access */ - -/* - *  GCSR Base Address Lower Address  CRG +$404 - */ -#define TSI148_LCSR_GBAL_M             (0x7FFFFFF<<5)	/* Mask */ - -/* - *  GCSR Attribute Register CRG + $408 - */ -#define TSI148_LCSR_GCSRAT_EN          (1<<7)	/* Enable access to GCSR */ - -#define TSI148_LCSR_GCSRAT_AS_M        (7<<4)	/* Address Space Mask */ -#define TSI148_LCSR_GCSRAT_AS_A16       (0<<4)	/* Address Space 16 */ -#define TSI148_LCSR_GCSRAT_AS_A24       (1<<4)	/* Address Space 24 */ -#define TSI148_LCSR_GCSRAT_AS_A32       (2<<4)	/* Address Space 32 */ -#define TSI148_LCSR_GCSRAT_AS_A64       (4<<4)	/* Address Space 64 */ - -#define TSI148_LCSR_GCSRAT_SUPR        (1<<3)	/* Sup set -GCSR decoder */ -#define TSI148_LCSR_GCSRAT_NPRIV       (1<<2)	/* Non-Privliged set - CGSR */ -#define TSI148_LCSR_GCSRAT_PGM         (1<<1)	/* Program set - GCSR decoder */ -#define TSI148_LCSR_GCSRAT_DATA        (1<<0)	/* DATA set GCSR decoder */ - -/* - *  CRG Base Address Lower Address  CRG + $410 - */ -#define TSI148_LCSR_CBAL_M             (0xFFFFF<<12) - -/* - *  CRG Attribute Register  CRG + $414 - */ -#define TSI148_LCSR_CRGAT_EN           (1<<7)	/* Enable PRG Access */ - -#define TSI148_LCSR_CRGAT_AS_M         (7<<4)	/* Address Space */ -#define TSI148_LCSR_CRGAT_AS_A16       (0<<4)	/* Address Space 16 */ -#define TSI148_LCSR_CRGAT_AS_A24       (1<<4)	/* Address Space 24 */ -#define TSI148_LCSR_CRGAT_AS_A32       (2<<4)	/* Address Space 32 */ -#define TSI148_LCSR_CRGAT_AS_A64       (4<<4)	/* Address Space 64 */ - -#define TSI148_LCSR_CRGAT_SUPR         (1<<3)	/* Supervisor Access */ -#define TSI148_LCSR_CRGAT_NPRIV        (1<<2)	/* Non-Privliged(User) Access */ -#define TSI148_LCSR_CRGAT_PGM          (1<<1)	/* Program Access */ -#define TSI148_LCSR_CRGAT_DATA         (1<<0)	/* Data Access */ - -/* - *  CR/CSR Offset Lower Register  CRG + $41C - */ -#define TSI148_LCSR_CROL_M             (0x1FFF<<19)	/* Mask */ - -/* - *  CR/CSR Attribute register  CRG + $420 - */ -#define TSI148_LCSR_CRAT_EN            (1<<7)	/* Enable access to CR/CSR */ - -/* - *  Location Monitor base address lower register  CRG + $428 - */ -#define TSI148_LCSR_LMBAL_M            (0x7FFFFFF<<5)	/* Mask */ - -/* - *  Location Monitor Attribute Register  CRG + $42C - */ -#define TSI148_LCSR_LMAT_EN            (1<<7)	/* Enable Location Monitor */ - -#define TSI148_LCSR_LMAT_AS_M          (7<<4)	/* Address Space MASK  */ -#define TSI148_LCSR_LMAT_AS_A16        (0<<4)	/* A16 */ -#define TSI148_LCSR_LMAT_AS_A24        (1<<4)	/* A24 */ -#define TSI148_LCSR_LMAT_AS_A32        (2<<4)	/* A32 */ -#define TSI148_LCSR_LMAT_AS_A64        (4<<4)	/* A64 */ - -#define TSI148_LCSR_LMAT_SUPR          (1<<3)	/* Supervisor Access */ -#define TSI148_LCSR_LMAT_NPRIV         (1<<2)	/* Non-Priv (User) Access */ -#define TSI148_LCSR_LMAT_PGM           (1<<1)	/* Program Access */ -#define TSI148_LCSR_LMAT_DATA          (1<<0)	/* Data Access  */ - -/* - *  Broadcast Pulse Generator Timer Register  CRG + $438 - */ -#define TSI148_LCSR_BPGTR_BPGT_M       (0xFFFF<<0)	/* Mask */ - -/* - *  Broadcast Programmable Clock Timer Register  CRG + $43C - */ -#define TSI148_LCSR_BPCTR_BPCT_M       (0xFFFFFF<<0)	/* Mask */ - -/* - *  VMEbus Interrupt Control Register           CRG + $43C - */ -#define TSI148_LCSR_VICR_CNTS_M        (3<<22)	/* Cntr Source MASK */ -#define TSI148_LCSR_VICR_CNTS_DIS      (1<<22)	/* Cntr Disable */ -#define TSI148_LCSR_VICR_CNTS_IRQ1     (2<<22)	/* IRQ1 to Cntr */ -#define TSI148_LCSR_VICR_CNTS_IRQ2     (3<<22)	/* IRQ2 to Cntr */ - -#define TSI148_LCSR_VICR_EDGIS_M       (3<<20)	/* Edge interupt MASK */ -#define TSI148_LCSR_VICR_EDGIS_DIS     (1<<20)	/* Edge interupt Disable */ -#define TSI148_LCSR_VICR_EDGIS_IRQ1    (2<<20)	/* IRQ1 to Edge */ -#define TSI148_LCSR_VICR_EDGIS_IRQ2    (3<<20)	/* IRQ2 to Edge */ - -#define TSI148_LCSR_VICR_IRQIF_M       (3<<18)	/* IRQ1* Function MASK */ -#define TSI148_LCSR_VICR_IRQIF_NORM    (1<<18)	/* Normal */ -#define TSI148_LCSR_VICR_IRQIF_PULSE   (2<<18)	/* Pulse Generator */ -#define TSI148_LCSR_VICR_IRQIF_PROG    (3<<18)	/* Programmable Clock */ -#define TSI148_LCSR_VICR_IRQIF_1U      (4<<18)	/* 1us Clock */ - -#define TSI148_LCSR_VICR_IRQ2F_M       (3<<16)	/* IRQ2* Function MASK */ -#define TSI148_LCSR_VICR_IRQ2F_NORM    (1<<16)	/* Normal */ -#define TSI148_LCSR_VICR_IRQ2F_PULSE   (2<<16)	/* Pulse Generator */ -#define TSI148_LCSR_VICR_IRQ2F_PROG    (3<<16)	/* Programmable Clock */ -#define TSI148_LCSR_VICR_IRQ2F_1U      (4<<16)	/* 1us Clock */ - -#define TSI148_LCSR_VICR_BIP           (1<<15)	/* Broadcast Interrupt Pulse */ - -#define TSI148_LCSR_VICR_IRQC          (1<<12)	/* VMEbus IRQ Clear */ -#define TSI148_LCSR_VICR_IRQS          (1<<11)	/* VMEbus IRQ Status */ - -#define TSI148_LCSR_VICR_IRQL_M        (7<<8)	/* VMEbus SW IRQ Level Mask */ -#define TSI148_LCSR_VICR_IRQL_1        (1<<8)	/* VMEbus SW IRQ Level 1 */ -#define TSI148_LCSR_VICR_IRQL_2        (2<<8)	/* VMEbus SW IRQ Level 2 */ -#define TSI148_LCSR_VICR_IRQL_3        (3<<8)	/* VMEbus SW IRQ Level 3 */ -#define TSI148_LCSR_VICR_IRQL_4        (4<<8)	/* VMEbus SW IRQ Level 4 */ -#define TSI148_LCSR_VICR_IRQL_5        (5<<8)	/* VMEbus SW IRQ Level 5 */ -#define TSI148_LCSR_VICR_IRQL_6        (6<<8)	/* VMEbus SW IRQ Level 6 */ -#define TSI148_LCSR_VICR_IRQL_7        (7<<8)	/* VMEbus SW IRQ Level 7 */ - -static const int TSI148_LCSR_VICR_IRQL[8] = { 0, TSI148_LCSR_VICR_IRQL_1, -			TSI148_LCSR_VICR_IRQL_2, TSI148_LCSR_VICR_IRQL_3, -			TSI148_LCSR_VICR_IRQL_4, TSI148_LCSR_VICR_IRQL_5, -			TSI148_LCSR_VICR_IRQL_6, TSI148_LCSR_VICR_IRQL_7 }; - -#define TSI148_LCSR_VICR_STID_M        (0xFF<<0)	/* Status/ID Mask */ - -/* - *  Interrupt Enable Register   CRG + $440 - */ -#define TSI148_LCSR_INTEN_DMA1EN       (1<<25)	/* DMAC 1 */ -#define TSI148_LCSR_INTEN_DMA0EN       (1<<24)	/* DMAC 0 */ -#define TSI148_LCSR_INTEN_LM3EN        (1<<23)	/* Location Monitor 3 */ -#define TSI148_LCSR_INTEN_LM2EN        (1<<22)	/* Location Monitor 2 */ -#define TSI148_LCSR_INTEN_LM1EN        (1<<21)	/* Location Monitor 1 */ -#define TSI148_LCSR_INTEN_LM0EN        (1<<20)	/* Location Monitor 0 */ -#define TSI148_LCSR_INTEN_MB3EN        (1<<19)	/* Mail Box 3 */ -#define TSI148_LCSR_INTEN_MB2EN        (1<<18)	/* Mail Box 2 */ -#define TSI148_LCSR_INTEN_MB1EN        (1<<17)	/* Mail Box 1 */ -#define TSI148_LCSR_INTEN_MB0EN        (1<<16)	/* Mail Box 0 */ -#define TSI148_LCSR_INTEN_PERREN       (1<<13)	/* PCI/X Error */ -#define TSI148_LCSR_INTEN_VERREN       (1<<12)	/* VMEbus Error */ -#define TSI148_LCSR_INTEN_VIEEN        (1<<11)	/* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTEN_IACKEN       (1<<10)	/* IACK */ -#define TSI148_LCSR_INTEN_SYSFLEN      (1<<9)	/* System Fail */ -#define TSI148_LCSR_INTEN_ACFLEN       (1<<8)	/* AC Fail */ -#define TSI148_LCSR_INTEN_IRQ7EN       (1<<7)	/* IRQ7 */ -#define TSI148_LCSR_INTEN_IRQ6EN       (1<<6)	/* IRQ6 */ -#define TSI148_LCSR_INTEN_IRQ5EN       (1<<5)	/* IRQ5 */ -#define TSI148_LCSR_INTEN_IRQ4EN       (1<<4)	/* IRQ4 */ -#define TSI148_LCSR_INTEN_IRQ3EN       (1<<3)	/* IRQ3 */ -#define TSI148_LCSR_INTEN_IRQ2EN       (1<<2)	/* IRQ2 */ -#define TSI148_LCSR_INTEN_IRQ1EN       (1<<1)	/* IRQ1 */ - -static const int TSI148_LCSR_INTEN_LMEN[4] = { TSI148_LCSR_INTEN_LM0EN, -					TSI148_LCSR_INTEN_LM1EN, -					TSI148_LCSR_INTEN_LM2EN, -					TSI148_LCSR_INTEN_LM3EN }; - -static const int TSI148_LCSR_INTEN_IRQEN[7] = { TSI148_LCSR_INTEN_IRQ1EN, -					TSI148_LCSR_INTEN_IRQ2EN, -					TSI148_LCSR_INTEN_IRQ3EN, -					TSI148_LCSR_INTEN_IRQ4EN, -					TSI148_LCSR_INTEN_IRQ5EN, -					TSI148_LCSR_INTEN_IRQ6EN, -					TSI148_LCSR_INTEN_IRQ7EN }; - -/* - *  Interrupt Enable Out Register CRG + $444 - */ -#define TSI148_LCSR_INTEO_DMA1EO       (1<<25)	/* DMAC 1 */ -#define TSI148_LCSR_INTEO_DMA0EO       (1<<24)	/* DMAC 0 */ -#define TSI148_LCSR_INTEO_LM3EO        (1<<23)	/* Loc Monitor 3 */ -#define TSI148_LCSR_INTEO_LM2EO        (1<<22)	/* Loc Monitor 2 */ -#define TSI148_LCSR_INTEO_LM1EO        (1<<21)	/* Loc Monitor 1 */ -#define TSI148_LCSR_INTEO_LM0EO        (1<<20)	/* Location Monitor 0 */ -#define TSI148_LCSR_INTEO_MB3EO        (1<<19)	/* Mail Box 3 */ -#define TSI148_LCSR_INTEO_MB2EO        (1<<18)	/* Mail Box 2 */ -#define TSI148_LCSR_INTEO_MB1EO        (1<<17)	/* Mail Box 1 */ -#define TSI148_LCSR_INTEO_MB0EO        (1<<16)	/* Mail Box 0 */ -#define TSI148_LCSR_INTEO_PERREO       (1<<13)	/* PCI/X Error */ -#define TSI148_LCSR_INTEO_VERREO       (1<<12)	/* VMEbus Error */ -#define TSI148_LCSR_INTEO_VIEEO        (1<<11)	/* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTEO_IACKEO       (1<<10)	/* IACK */ -#define TSI148_LCSR_INTEO_SYSFLEO      (1<<9)	/* System Fail */ -#define TSI148_LCSR_INTEO_ACFLEO       (1<<8)	/* AC Fail */ -#define TSI148_LCSR_INTEO_IRQ7EO       (1<<7)	/* IRQ7 */ -#define TSI148_LCSR_INTEO_IRQ6EO       (1<<6)	/* IRQ6 */ -#define TSI148_LCSR_INTEO_IRQ5EO       (1<<5)	/* IRQ5 */ -#define TSI148_LCSR_INTEO_IRQ4EO       (1<<4)	/* IRQ4 */ -#define TSI148_LCSR_INTEO_IRQ3EO       (1<<3)	/* IRQ3 */ -#define TSI148_LCSR_INTEO_IRQ2EO       (1<<2)	/* IRQ2 */ -#define TSI148_LCSR_INTEO_IRQ1EO       (1<<1)	/* IRQ1 */ - -static const int TSI148_LCSR_INTEO_LMEO[4] = { TSI148_LCSR_INTEO_LM0EO, -					TSI148_LCSR_INTEO_LM1EO, -					TSI148_LCSR_INTEO_LM2EO, -					TSI148_LCSR_INTEO_LM3EO }; - -static const int TSI148_LCSR_INTEO_IRQEO[7] = { TSI148_LCSR_INTEO_IRQ1EO, -					TSI148_LCSR_INTEO_IRQ2EO, -					TSI148_LCSR_INTEO_IRQ3EO, -					TSI148_LCSR_INTEO_IRQ4EO, -					TSI148_LCSR_INTEO_IRQ5EO, -					TSI148_LCSR_INTEO_IRQ6EO, -					TSI148_LCSR_INTEO_IRQ7EO }; - -/* - *  Interrupt Status Register CRG + $448 - */ -#define TSI148_LCSR_INTS_DMA1S         (1<<25)	/* DMA 1 */ -#define TSI148_LCSR_INTS_DMA0S         (1<<24)	/* DMA 0 */ -#define TSI148_LCSR_INTS_LM3S          (1<<23)	/* Location Monitor 3 */ -#define TSI148_LCSR_INTS_LM2S          (1<<22)	/* Location Monitor 2 */ -#define TSI148_LCSR_INTS_LM1S          (1<<21)	/* Location Monitor 1 */ -#define TSI148_LCSR_INTS_LM0S          (1<<20)	/* Location Monitor 0 */ -#define TSI148_LCSR_INTS_MB3S          (1<<19)	/* Mail Box 3 */ -#define TSI148_LCSR_INTS_MB2S          (1<<18)	/* Mail Box 2 */ -#define TSI148_LCSR_INTS_MB1S          (1<<17)	/* Mail Box 1 */ -#define TSI148_LCSR_INTS_MB0S          (1<<16)	/* Mail Box 0 */ -#define TSI148_LCSR_INTS_PERRS         (1<<13)	/* PCI/X Error */ -#define TSI148_LCSR_INTS_VERRS         (1<<12)	/* VMEbus Error */ -#define TSI148_LCSR_INTS_VIES          (1<<11)	/* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTS_IACKS         (1<<10)	/* IACK */ -#define TSI148_LCSR_INTS_SYSFLS        (1<<9)	/* System Fail */ -#define TSI148_LCSR_INTS_ACFLS         (1<<8)	/* AC Fail */ -#define TSI148_LCSR_INTS_IRQ7S         (1<<7)	/* IRQ7 */ -#define TSI148_LCSR_INTS_IRQ6S         (1<<6)	/* IRQ6 */ -#define TSI148_LCSR_INTS_IRQ5S         (1<<5)	/* IRQ5 */ -#define TSI148_LCSR_INTS_IRQ4S         (1<<4)	/* IRQ4 */ -#define TSI148_LCSR_INTS_IRQ3S         (1<<3)	/* IRQ3 */ -#define TSI148_LCSR_INTS_IRQ2S         (1<<2)	/* IRQ2 */ -#define TSI148_LCSR_INTS_IRQ1S         (1<<1)	/* IRQ1 */ - -static const int TSI148_LCSR_INTS_LMS[4] = { TSI148_LCSR_INTS_LM0S, -					TSI148_LCSR_INTS_LM1S, -					TSI148_LCSR_INTS_LM2S, -					TSI148_LCSR_INTS_LM3S }; - -static const int TSI148_LCSR_INTS_MBS[4] = { TSI148_LCSR_INTS_MB0S, -					TSI148_LCSR_INTS_MB1S, -					TSI148_LCSR_INTS_MB2S, -					TSI148_LCSR_INTS_MB3S }; - -/* - *  Interrupt Clear Register CRG + $44C - */ -#define TSI148_LCSR_INTC_DMA1C         (1<<25)	/* DMA 1 */ -#define TSI148_LCSR_INTC_DMA0C         (1<<24)	/* DMA 0 */ -#define TSI148_LCSR_INTC_LM3C          (1<<23)	/* Location Monitor 3 */ -#define TSI148_LCSR_INTC_LM2C          (1<<22)	/* Location Monitor 2 */ -#define TSI148_LCSR_INTC_LM1C          (1<<21)	/* Location Monitor 1 */ -#define TSI148_LCSR_INTC_LM0C          (1<<20)	/* Location Monitor 0 */ -#define TSI148_LCSR_INTC_MB3C          (1<<19)	/* Mail Box 3 */ -#define TSI148_LCSR_INTC_MB2C          (1<<18)	/* Mail Box 2 */ -#define TSI148_LCSR_INTC_MB1C          (1<<17)	/* Mail Box 1 */ -#define TSI148_LCSR_INTC_MB0C          (1<<16)	/* Mail Box 0 */ -#define TSI148_LCSR_INTC_PERRC         (1<<13)	/* VMEbus Error */ -#define TSI148_LCSR_INTC_VERRC         (1<<12)	/* VMEbus Access Time-out */ -#define TSI148_LCSR_INTC_VIEC          (1<<11)	/* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTC_IACKC         (1<<10)	/* IACK */ -#define TSI148_LCSR_INTC_SYSFLC        (1<<9)	/* System Fail */ -#define TSI148_LCSR_INTC_ACFLC         (1<<8)	/* AC Fail */ - -static const int TSI148_LCSR_INTC_LMC[4] = { TSI148_LCSR_INTC_LM0C, -					TSI148_LCSR_INTC_LM1C, -					TSI148_LCSR_INTC_LM2C, -					TSI148_LCSR_INTC_LM3C }; - -static const int TSI148_LCSR_INTC_MBC[4] = { TSI148_LCSR_INTC_MB0C, -					TSI148_LCSR_INTC_MB1C, -					TSI148_LCSR_INTC_MB2C, -					TSI148_LCSR_INTC_MB3C }; - -/* - *  Interrupt Map Register 1 CRG + $458 - */ -#define TSI148_LCSR_INTM1_DMA1M_M      (3<<18)	/* DMA 1 */ -#define TSI148_LCSR_INTM1_DMA0M_M      (3<<16)	/* DMA 0 */ -#define TSI148_LCSR_INTM1_LM3M_M       (3<<14)	/* Location Monitor 3 */ -#define TSI148_LCSR_INTM1_LM2M_M       (3<<12)	/* Location Monitor 2 */ -#define TSI148_LCSR_INTM1_LM1M_M       (3<<10)	/* Location Monitor 1 */ -#define TSI148_LCSR_INTM1_LM0M_M       (3<<8)	/* Location Monitor 0 */ -#define TSI148_LCSR_INTM1_MB3M_M       (3<<6)	/* Mail Box 3 */ -#define TSI148_LCSR_INTM1_MB2M_M       (3<<4)	/* Mail Box 2 */ -#define TSI148_LCSR_INTM1_MB1M_M       (3<<2)	/* Mail Box 1 */ -#define TSI148_LCSR_INTM1_MB0M_M       (3<<0)	/* Mail Box 0 */ - -/* - *  Interrupt Map Register 2 CRG + $45C - */ -#define TSI148_LCSR_INTM2_PERRM_M      (3<<26)	/* PCI Bus Error */ -#define TSI148_LCSR_INTM2_VERRM_M      (3<<24)	/* VMEbus Error */ -#define TSI148_LCSR_INTM2_VIEM_M       (3<<22)	/* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTM2_IACKM_M      (3<<20)	/* IACK */ -#define TSI148_LCSR_INTM2_SYSFLM_M     (3<<18)	/* System Fail */ -#define TSI148_LCSR_INTM2_ACFLM_M      (3<<16)	/* AC Fail */ -#define TSI148_LCSR_INTM2_IRQ7M_M      (3<<14)	/* IRQ7 */ -#define TSI148_LCSR_INTM2_IRQ6M_M      (3<<12)	/* IRQ6 */ -#define TSI148_LCSR_INTM2_IRQ5M_M      (3<<10)	/* IRQ5 */ -#define TSI148_LCSR_INTM2_IRQ4M_M      (3<<8)	/* IRQ4 */ -#define TSI148_LCSR_INTM2_IRQ3M_M      (3<<6)	/* IRQ3 */ -#define TSI148_LCSR_INTM2_IRQ2M_M      (3<<4)	/* IRQ2 */ -#define TSI148_LCSR_INTM2_IRQ1M_M      (3<<2)	/* IRQ1 */ - -/* - *  DMA Control (0-1) Registers CRG + $500 - */ -#define TSI148_LCSR_DCTL_ABT           (1<<27)	/* Abort */ -#define TSI148_LCSR_DCTL_PAU           (1<<26)	/* Pause */ -#define TSI148_LCSR_DCTL_DGO           (1<<25)	/* DMA Go */ - -#define TSI148_LCSR_DCTL_MOD           (1<<23)	/* Mode */ - -#define TSI148_LCSR_DCTL_VBKS_M        (7<<12)	/* VMEbus block Size MASK */ -#define TSI148_LCSR_DCTL_VBKS_32       (0<<12)	/* VMEbus block Size 32 */ -#define TSI148_LCSR_DCTL_VBKS_64       (1<<12)	/* VMEbus block Size 64 */ -#define TSI148_LCSR_DCTL_VBKS_128      (2<<12)	/* VMEbus block Size 128 */ -#define TSI148_LCSR_DCTL_VBKS_256      (3<<12)	/* VMEbus block Size 256 */ -#define TSI148_LCSR_DCTL_VBKS_512      (4<<12)	/* VMEbus block Size 512 */ -#define TSI148_LCSR_DCTL_VBKS_1024     (5<<12)	/* VMEbus block Size 1024 */ -#define TSI148_LCSR_DCTL_VBKS_2048     (6<<12)	/* VMEbus block Size 2048 */ -#define TSI148_LCSR_DCTL_VBKS_4096     (7<<12)	/* VMEbus block Size 4096 */ - -#define TSI148_LCSR_DCTL_VBOT_M        (7<<8)	/* VMEbus back-off MASK */ -#define TSI148_LCSR_DCTL_VBOT_0        (0<<8)	/* VMEbus back-off  0us */ -#define TSI148_LCSR_DCTL_VBOT_1        (1<<8)	/* VMEbus back-off 1us */ -#define TSI148_LCSR_DCTL_VBOT_2        (2<<8)	/* VMEbus back-off 2us */ -#define TSI148_LCSR_DCTL_VBOT_4        (3<<8)	/* VMEbus back-off 4us */ -#define TSI148_LCSR_DCTL_VBOT_8        (4<<8)	/* VMEbus back-off 8us */ -#define TSI148_LCSR_DCTL_VBOT_16       (5<<8)	/* VMEbus back-off 16us */ -#define TSI148_LCSR_DCTL_VBOT_32       (6<<8)	/* VMEbus back-off 32us */ -#define TSI148_LCSR_DCTL_VBOT_64       (7<<8)	/* VMEbus back-off 64us */ - -#define TSI148_LCSR_DCTL_PBKS_M        (7<<4)	/* PCI block size MASK */ -#define TSI148_LCSR_DCTL_PBKS_32       (0<<4)	/* PCI block size 32 bytes */ -#define TSI148_LCSR_DCTL_PBKS_64       (1<<4)	/* PCI block size 64 bytes */ -#define TSI148_LCSR_DCTL_PBKS_128      (2<<4)	/* PCI block size 128 bytes */ -#define TSI148_LCSR_DCTL_PBKS_256      (3<<4)	/* PCI block size 256 bytes */ -#define TSI148_LCSR_DCTL_PBKS_512      (4<<4)	/* PCI block size 512 bytes */ -#define TSI148_LCSR_DCTL_PBKS_1024     (5<<4)	/* PCI block size 1024 bytes */ -#define TSI148_LCSR_DCTL_PBKS_2048     (6<<4)	/* PCI block size 2048 bytes */ -#define TSI148_LCSR_DCTL_PBKS_4096     (7<<4)	/* PCI block size 4096 bytes */ - -#define TSI148_LCSR_DCTL_PBOT_M        (7<<0)	/* PCI back off MASK */ -#define TSI148_LCSR_DCTL_PBOT_0        (0<<0)	/* PCI back off 0us */ -#define TSI148_LCSR_DCTL_PBOT_1        (1<<0)	/* PCI back off 1us */ -#define TSI148_LCSR_DCTL_PBOT_2        (2<<0)	/* PCI back off 2us */ -#define TSI148_LCSR_DCTL_PBOT_4        (3<<0)	/* PCI back off 3us */ -#define TSI148_LCSR_DCTL_PBOT_8        (4<<0)	/* PCI back off 4us */ -#define TSI148_LCSR_DCTL_PBOT_16       (5<<0)	/* PCI back off 8us */ -#define TSI148_LCSR_DCTL_PBOT_32       (6<<0)	/* PCI back off 16us */ -#define TSI148_LCSR_DCTL_PBOT_64       (7<<0)	/* PCI back off 32us */ - -/* - *  DMA Status Registers (0-1)  CRG + $504 - */ -#define TSI148_LCSR_DSTA_SMA           (1<<31)	/* PCI Signalled Master Abt */ -#define TSI148_LCSR_DSTA_RTA           (1<<30)	/* PCI Received Target Abt */ -#define TSI148_LCSR_DSTA_MRC           (1<<29)	/* PCI Max Retry Count */ -#define TSI148_LCSR_DSTA_VBE           (1<<28)	/* VMEbus error */ -#define TSI148_LCSR_DSTA_ABT           (1<<27)	/* Abort */ -#define TSI148_LCSR_DSTA_PAU           (1<<26)	/* Pause */ -#define TSI148_LCSR_DSTA_DON           (1<<25)	/* Done */ -#define TSI148_LCSR_DSTA_BSY           (1<<24)	/* Busy */ - -/* - *  DMA Current Link Address Lower (0-1) - */ -#define TSI148_LCSR_DCLAL_M            (0x3FFFFFF<<6)	/* Mask */ - -/* - *  DMA Source Attribute (0-1) Reg - */ -#define TSI148_LCSR_DSAT_TYP_M         (3<<28)	/* Source Bus Type */ -#define TSI148_LCSR_DSAT_TYP_PCI       (0<<28)	/* PCI Bus */ -#define TSI148_LCSR_DSAT_TYP_VME       (1<<28)	/* VMEbus */ -#define TSI148_LCSR_DSAT_TYP_PAT       (2<<28)	/* Data Pattern */ - -#define TSI148_LCSR_DSAT_PSZ           (1<<25)	/* Pattern Size */ -#define TSI148_LCSR_DSAT_NIN           (1<<24)	/* No Increment */ - -#define TSI148_LCSR_DSAT_2eSSTM_M      (3<<11)	/* 2eSST Trans Rate Mask */ -#define TSI148_LCSR_DSAT_2eSSTM_160    (0<<11)	/* 160 MB/s */ -#define TSI148_LCSR_DSAT_2eSSTM_267    (1<<11)	/* 267 MB/s */ -#define TSI148_LCSR_DSAT_2eSSTM_320    (2<<11)	/* 320 MB/s */ - -#define TSI148_LCSR_DSAT_TM_M          (7<<8)	/* Bus Transfer Protocol Mask */ -#define TSI148_LCSR_DSAT_TM_SCT        (0<<8)	/* SCT */ -#define TSI148_LCSR_DSAT_TM_BLT        (1<<8)	/* BLT */ -#define TSI148_LCSR_DSAT_TM_MBLT       (2<<8)	/* MBLT */ -#define TSI148_LCSR_DSAT_TM_2eVME      (3<<8)	/* 2eVME */ -#define TSI148_LCSR_DSAT_TM_2eSST      (4<<8)	/* 2eSST */ -#define TSI148_LCSR_DSAT_TM_2eSSTB     (5<<8)	/* 2eSST Broadcast */ - -#define TSI148_LCSR_DSAT_DBW_M         (3<<6)	/* Max Data Width MASK */ -#define TSI148_LCSR_DSAT_DBW_16        (0<<6)	/* 16 Bits */ -#define TSI148_LCSR_DSAT_DBW_32        (1<<6)	/* 32 Bits */ - -#define TSI148_LCSR_DSAT_SUP           (1<<5)	/* Supervisory Mode */ -#define TSI148_LCSR_DSAT_PGM           (1<<4)	/* Program Mode */ - -#define TSI148_LCSR_DSAT_AMODE_M       (0xf<<0)	/* Address Space Mask */ -#define TSI148_LCSR_DSAT_AMODE_A16     (0<<0)	/* A16 */ -#define TSI148_LCSR_DSAT_AMODE_A24     (1<<0)	/* A24 */ -#define TSI148_LCSR_DSAT_AMODE_A32     (2<<0)	/* A32 */ -#define TSI148_LCSR_DSAT_AMODE_A64     (4<<0)	/* A64 */ -#define TSI148_LCSR_DSAT_AMODE_CRCSR   (5<<0)	/* CR/CSR */ -#define TSI148_LCSR_DSAT_AMODE_USER1   (8<<0)	/* User1 */ -#define TSI148_LCSR_DSAT_AMODE_USER2   (9<<0)	/* User2 */ -#define TSI148_LCSR_DSAT_AMODE_USER3   (0xa<<0)	/* User3 */ -#define TSI148_LCSR_DSAT_AMODE_USER4   (0xb<<0)	/* User4 */ - -/* - *  DMA Destination Attribute Registers (0-1) - */ -#define TSI148_LCSR_DDAT_TYP_PCI       (0<<28)	/* Destination PCI Bus  */ -#define TSI148_LCSR_DDAT_TYP_VME       (1<<28)	/* Destination VMEbus */ - -#define TSI148_LCSR_DDAT_2eSSTM_M      (3<<11)	/* 2eSST Transfer Rate Mask */ -#define TSI148_LCSR_DDAT_2eSSTM_160    (0<<11)	/* 160 MB/s */ -#define TSI148_LCSR_DDAT_2eSSTM_267    (1<<11)	/* 267 MB/s */ -#define TSI148_LCSR_DDAT_2eSSTM_320    (2<<11)	/* 320 MB/s */ - -#define TSI148_LCSR_DDAT_TM_M          (7<<8)	/* Bus Transfer Protocol Mask */ -#define TSI148_LCSR_DDAT_TM_SCT        (0<<8)	/* SCT */ -#define TSI148_LCSR_DDAT_TM_BLT        (1<<8)	/* BLT */ -#define TSI148_LCSR_DDAT_TM_MBLT       (2<<8)	/* MBLT */ -#define TSI148_LCSR_DDAT_TM_2eVME      (3<<8)	/* 2eVME */ -#define TSI148_LCSR_DDAT_TM_2eSST      (4<<8)	/* 2eSST */ -#define TSI148_LCSR_DDAT_TM_2eSSTB     (5<<8)	/* 2eSST Broadcast */ - -#define TSI148_LCSR_DDAT_DBW_M         (3<<6)	/* Max Data Width MASK */ -#define TSI148_LCSR_DDAT_DBW_16        (0<<6)	/* 16 Bits */ -#define TSI148_LCSR_DDAT_DBW_32        (1<<6)	/* 32 Bits */ - -#define TSI148_LCSR_DDAT_SUP           (1<<5)	/* Supervisory/User Access */ -#define TSI148_LCSR_DDAT_PGM           (1<<4)	/* Program/Data Access */ - -#define TSI148_LCSR_DDAT_AMODE_M       (0xf<<0)	/* Address Space Mask */ -#define TSI148_LCSR_DDAT_AMODE_A16      (0<<0)	/* A16 */ -#define TSI148_LCSR_DDAT_AMODE_A24      (1<<0)	/* A24 */ -#define TSI148_LCSR_DDAT_AMODE_A32      (2<<0)	/* A32 */ -#define TSI148_LCSR_DDAT_AMODE_A64      (4<<0)	/* A64 */ -#define TSI148_LCSR_DDAT_AMODE_CRCSR   (5<<0)	/* CRC/SR */ -#define TSI148_LCSR_DDAT_AMODE_USER1   (8<<0)	/* User1 */ -#define TSI148_LCSR_DDAT_AMODE_USER2   (9<<0)	/* User2 */ -#define TSI148_LCSR_DDAT_AMODE_USER3   (0xa<<0)	/* User3 */ -#define TSI148_LCSR_DDAT_AMODE_USER4   (0xb<<0)	/* User4 */ - -/* - *  DMA Next Link Address Lower - */ -#define TSI148_LCSR_DNLAL_DNLAL_M      (0x3FFFFFF<<6)	/* Address Mask */ -#define TSI148_LCSR_DNLAL_LLA          (1<<0)  /* Last Link Address Indicator */ - -/* - *  DMA 2eSST Broadcast Select - */ -#define TSI148_LCSR_DBS_M              (0x1FFFFF<<0)	/* Mask */ - -/* - *  GCSR Register Group - */ - -/* - *  GCSR Control and Status Register  CRG + $604 - */ -#define TSI148_GCSR_GCTRL_LRST         (1<<15)	/* Local Reset */ -#define TSI148_GCSR_GCTRL_SFAILEN      (1<<14)	/* System Fail enable */ -#define TSI148_GCSR_GCTRL_BDFAILS      (1<<13)	/* Board Fail Status */ -#define TSI148_GCSR_GCTRL_SCON         (1<<12)	/* System Copntroller */ -#define TSI148_GCSR_GCTRL_MEN          (1<<11)	/* Module Enable (READY) */ - -#define TSI148_GCSR_GCTRL_LMI3S        (1<<7)	/* Loc Monitor 3 Int Status */ -#define TSI148_GCSR_GCTRL_LMI2S        (1<<6)	/* Loc Monitor 2 Int Status */ -#define TSI148_GCSR_GCTRL_LMI1S        (1<<5)	/* Loc Monitor 1 Int Status */ -#define TSI148_GCSR_GCTRL_LMI0S        (1<<4)	/* Loc Monitor 0 Int Status */ -#define TSI148_GCSR_GCTRL_MBI3S        (1<<3)	/* Mail box 3 Int Status */ -#define TSI148_GCSR_GCTRL_MBI2S        (1<<2)	/* Mail box 2 Int Status */ -#define TSI148_GCSR_GCTRL_MBI1S        (1<<1)	/* Mail box 1 Int Status */ -#define TSI148_GCSR_GCTRL_MBI0S        (1<<0)	/* Mail box 0 Int Status */ - -#define TSI148_GCSR_GAP                (1<<5)	/* Geographic Addr Parity */ -#define TSI148_GCSR_GA_M               (0x1F<<0)  /* Geographic Address Mask */ - -/* - *  CR/CSR Register Group - */ - -/* - *  CR/CSR Bit Clear Register CRG + $FF4 - */ -#define TSI148_CRCSR_CSRBCR_LRSTC      (1<<7)	/* Local Reset Clear */ -#define TSI148_CRCSR_CSRBCR_SFAILC     (1<<6)	/* System Fail Enable Clear */ -#define TSI148_CRCSR_CSRBCR_BDFAILS    (1<<5)	/* Board Fail Status */ -#define TSI148_CRCSR_CSRBCR_MENC       (1<<4)	/* Module Enable Clear */ -#define TSI148_CRCSR_CSRBCR_BERRSC     (1<<3)	/* Bus Error Status Clear */ - -/* - *  CR/CSR Bit Set Register CRG+$FF8 - */ -#define TSI148_CRCSR_CSRBSR_LISTS      (1<<7)	/* Local Reset Clear */ -#define TSI148_CRCSR_CSRBSR_SFAILS     (1<<6)	/* System Fail Enable Clear */ -#define TSI148_CRCSR_CSRBSR_BDFAILS    (1<<5)	/* Board Fail Status */ -#define TSI148_CRCSR_CSRBSR_MENS       (1<<4)	/* Module Enable Clear */ -#define TSI148_CRCSR_CSRBSR_BERRS      (1<<3)	/* Bus Error Status Clear */ - -/* - *  CR/CSR Base Address Register CRG + FFC - */ -#define TSI148_CRCSR_CBAR_M            (0x1F<<3)	/* Mask */ - -#endif				/* TSI148_H */ diff --git a/drivers/staging/vme/devices/Kconfig b/drivers/staging/vme/devices/Kconfig index ca5ba89e2d8..8e8bbb1dcd9 100644 --- a/drivers/staging/vme/devices/Kconfig +++ b/drivers/staging/vme/devices/Kconfig @@ -2,7 +2,21 @@ comment "VME Device Drivers"  config VME_USER  	tristate "VME user space access driver" +	depends on STAGING  	help  	  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/. +	  provided with the original driver at <http://www.vmelinux.org/>. + +config VME_PIO2 +	tristate "GE PIO2 VME" +	depends on STAGING && 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 459742a7528..172512cb5db 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 00000000000..d5d94c43c07 --- /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 pio2_gpio_init(struct pio2_card *); +void 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 00000000000..6335471faa3 --- /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 <linux/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 00000000000..fd19c257f53 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -0,0 +1,512 @@ +/* + * GE PIO2 6U VME I/O Driver + * + * Author: Martyn Welch <martyn.welch@ge.com> + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/device.h> +#include <linux/ctype.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/vme.h> + +#include "vme_pio2.h" + + +static const char driver_name[] = "pio2"; + +static int bus[PIO2_CARDS_MAX]; +static int bus_num; +static long base[PIO2_CARDS_MAX]; +static int base_num; +static int vector[PIO2_CARDS_MAX]; +static int vector_num; +static int level[PIO2_CARDS_MAX]; +static int level_num; +static char *variant[PIO2_CARDS_MAX]; +static int variant_num; + +static bool loopback; + +static int pio2_match(struct vme_dev *); +static int pio2_probe(struct vme_dev *); +static int pio2_remove(struct vme_dev *); + +static int pio2_get_led(struct pio2_card *card) +{ +	/* Can't read hardware, state saved in structure */ +	return card->led; +} + +static int pio2_set_led(struct pio2_card *card, int state) +{ +	u8 reg; +	int retval; + +	reg = card->irq_level; + +	/* Register state inverse of led state */ +	if (!state) +		reg |= PIO2_LED; + +	if (loopback) +		reg |= PIO2_LOOP; + +	retval = vme_master_write(card->window, ®, 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 = pio2_remove, +}; + + +static int __init pio2_init(void) +{ +	if (bus_num == 0) { +		pr_err("No cards, skipping registration\n"); +		return -ENODEV; +	} + +	if (bus_num > PIO2_CARDS_MAX) { +		pr_err("Driver only able to handle %d PIO2 Cards\n", +		       PIO2_CARDS_MAX); +		bus_num = PIO2_CARDS_MAX; +	} + +	/* Register the PIO2 driver */ +	return  vme_register_driver(&pio2_driver, bus_num); +} + +static int pio2_match(struct vme_dev *vdev) +{ + +	if (vdev->num >= bus_num) { +		dev_err(&vdev->dev, +			"The enumeration of the VMEbus to which the board is connected must be specified"); +		return 0; +	} + +	if (vdev->num >= base_num) { +		dev_err(&vdev->dev, +			"The VME address for the cards registers must be specified"); +		return 0; +	} + +	if (vdev->num >= vector_num) { +		dev_err(&vdev->dev, +			"The IRQ vector used by the card must be specified"); +		return 0; +	} + +	if (vdev->num >= level_num) { +		dev_err(&vdev->dev, +			"The IRQ level used by the card must be specified"); +		return 0; +	} + +	if (vdev->num >= variant_num) { +		dev_err(&vdev->dev, "The variant of the card must be specified"); +		return 0; +	} + +	return 1; +} + +static int pio2_probe(struct vme_dev *vdev) +{ +	struct pio2_card *card; +	int retval; +	int i; +	u8 reg; +	int vec; + +	card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL); +	if (card == NULL) { +		retval = -ENOMEM; +		goto err_struct; +	} + +	card->id = vdev->num; +	card->bus = bus[card->id]; +	card->base = base[card->id]; +	card->irq_vector = vector[card->id]; +	card->irq_level = level[card->id] & PIO2_VME_INT_MASK; +	strncpy(card->variant, variant[card->id], PIO2_VARIANT_LENGTH); +	card->vdev = vdev; + +	for (i = 0; i < PIO2_VARIANT_LENGTH; i++) { + +		if (isdigit(card->variant[i]) == 0) { +			dev_err(&card->vdev->dev, "Variant invalid\n"); +			retval = -EINVAL; +			goto err_variant; +		} +	} + +	/* +	 * Bottom 4 bits of VME interrupt vector used to determine source, +	 * provided vector should only use upper 4 bits. +	 */ +	if (card->irq_vector & ~PIO2_VME_VECTOR_MASK) { +		dev_err(&card->vdev->dev, +			"Invalid VME IRQ Vector, vector must not use lower 4 bits\n"); +		retval = -EINVAL; +		goto err_vector; +	} + +	/* +	 * There is no way to determine the build variant or whether each bank +	 * is input, output or both at run time. The inputs are also inverted +	 * if configured as both. +	 * +	 * We pass in the board variant and use that to determine the +	 * configuration of the banks. +	 */ +	for (i = 1; i < PIO2_VARIANT_LENGTH; i++) { +		switch (card->variant[i]) { +		case '0': +			card->bank[i-1].config = NOFIT; +			break; +		case '1': +		case '2': +		case '3': +		case '4': +			card->bank[i-1].config = INPUT; +			break; +		case '5': +			card->bank[i-1].config = OUTPUT; +			break; +		case '6': +		case '7': +		case '8': +		case '9': +			card->bank[i-1].config = BOTH; +			break; +		} +	} + +	/* Get a master window and position over regs */ +	card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16); +	if (card->window == NULL) { +		dev_err(&card->vdev->dev, +			"Unable to assign VME master resource\n"); +		retval = -EIO; +		goto err_window; +	} + +	retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24, +		(VME_SCT | VME_USER | VME_DATA), VME_D16); +	if (retval) { +		dev_err(&card->vdev->dev, +			"Unable to configure VME master resource\n"); +		goto err_set; +	} + +	/* +	 * There is also no obvious register which we can probe to determine +	 * whether the provided base is valid. If we can read the "ID Register" +	 * offset and the reset function doesn't error, assume we have a valid +	 * location. +	 */ +	retval = vme_master_read(card->window, ®, 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 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 00000000000..2a2d920d980 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -0,0 +1,229 @@ +/* + * 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/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 <linux/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 available 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 pio2_gpio_init(struct pio2_card *card) +{ +	int retval = 0; +	char *label; + +	label = kmalloc(PIO2_NUM_CHANNELS, GFP_KERNEL); +	if (label == NULL) +		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 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.c b/drivers/staging/vme/devices/vme_user.c index 71bbc526626..2d8497277aa 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -15,6 +15,8 @@   * option) any later version.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/cdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -27,24 +29,23 @@  #include <linux/module.h>  #include <linux/pagemap.h>  #include <linux/pci.h> -#include <linux/semaphore.h> +#include <linux/mutex.h>  #include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/syscalls.h> -#include <linux/mutex.h>  #include <linux/types.h>  #include <linux/io.h>  #include <linux/uaccess.h> +#include <linux/vme.h> -#include "../vme.h"  #include "vme_user.h"  static DEFINE_MUTEX(vme_user_mutex); -static char driver_name[] = "vme_user"; +static const char driver_name[] = "vme_user"; -static int bus[USER_BUS_MAX]; -static int bus_num; +static int bus[VME_USER_BUS_MAX]; +static unsigned int bus_num;  /* Currently Documentation/devices.txt defines the following for VME:   * @@ -65,13 +66,13 @@ static int bus_num;   *   * However the VME driver at http://www.vmelinux.org/ is rather old and doesn't   * even support the tsi148 chipset (which has 8 master and 8 slave windows). - * We'll run with this or now as far as possible, however it probably makes + * We'll run with this for now as far as possible, however it probably makes   * sense to get rid of the old mappings and just do everything dynamically.   *   * So for now, we'll restrict the driver to providing 4 masters and 4 slaves as   * defined above and try to support at least some of the interface from - * http://www.vmelinux.org/ as an alternative drive can be written providing a - * saner interface later. + * http://www.vmelinux.org/ as an alternative the driver can be written + * providing a saner interface later.   *   * The vmelinux.org driver never supported slave images, the devices reserved   * for slaves were repurposed to support all 8 master images on the UniverseII! @@ -91,32 +92,32 @@ static int bus_num;  /*   * Structure to handle image related parameters.   */ -typedef struct { -	void __iomem *kern_buf;	/* Buffer address in kernel space */ +struct image_desc { +	void *kern_buf;	/* Buffer address in kernel space */  	dma_addr_t pci_buf;	/* Buffer address in PCI address space */  	unsigned long long size_buf;	/* Buffer size */ -	struct semaphore sem;	/* Semaphore for locking image */ +	struct mutex mutex;	/* Mutex for locking image */  	struct device *device;	/* Sysfs device */  	struct vme_resource *resource;	/* VME resource */  	int users;		/* Number of current users */ -} image_desc_t; -static image_desc_t image[VME_DEVS]; +}; +static struct image_desc image[VME_DEVS]; -typedef struct { +struct driver_stats {  	unsigned long reads;  	unsigned long writes;  	unsigned long ioctls;  	unsigned long irqs;  	unsigned long berrs; -	unsigned long dmaErrors; +	unsigned long dmaerrors;  	unsigned long timeouts;  	unsigned long external; -} driver_stats_t; -static driver_stats_t statistics; +}; +static struct driver_stats statistics; -struct cdev *vme_user_cdev;		/* Character device */ -struct class *vme_user_sysfs_class;	/* Sysfs class */ -struct device *vme_user_bridge;		/* Pointer to the bridge device */ +static struct cdev *vme_user_cdev;		/* Character device */ +static struct class *vme_user_sysfs_class;	/* Sysfs class */ +static struct vme_dev *vme_user_bridge;		/* Pointer to user device */  static const int type[VME_DEVS] = {	MASTER_MINOR,	MASTER_MINOR, @@ -129,21 +130,24 @@ static const int type[VME_DEVS] = {	MASTER_MINOR,	MASTER_MINOR,  static int vme_user_open(struct inode *, struct file *);  static int vme_user_release(struct inode *, struct file *); -static ssize_t vme_user_read(struct file *, char *, size_t, loff_t *); -static ssize_t vme_user_write(struct file *, const char *, size_t, loff_t *); +static ssize_t vme_user_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t vme_user_write(struct file *, const char __user *, size_t, +	loff_t *);  static loff_t vme_user_llseek(struct file *, loff_t, int);  static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long); -static int __init vme_user_probe(struct device *, int, int); -static int __exit vme_user_remove(struct device *, int, int); +static int vme_user_match(struct vme_dev *); +static int vme_user_probe(struct vme_dev *); +static int vme_user_remove(struct vme_dev *); -static struct file_operations vme_user_fops = { +static const struct file_operations vme_user_fops = {  	.open = vme_user_open,  	.release = vme_user_release,  	.read = vme_user_read,  	.write = vme_user_write,  	.llseek = vme_user_llseek,  	.unlocked_ioctl = vme_user_unlocked_ioctl, +	.compat_ioctl = vme_user_unlocked_ioctl,  }; @@ -157,7 +161,7 @@ static void reset_counters(void)  	statistics.ioctls = 0;  	statistics.irqs = 0;  	statistics.berrs = 0; -	statistics.dmaErrors = 0; +	statistics.dmaerrors = 0;  	statistics.timeouts = 0;  } @@ -166,10 +170,10 @@ static int vme_user_open(struct inode *inode, struct file *file)  	int err;  	unsigned int minor = MINOR(inode->i_rdev); -	down(&image[minor].sem); -	/* Only allow device to be opened if a resource is allocated */ -	if (image[minor].resource == NULL) { -		printk(KERN_ERR "No resources allocated for device\n"); +	mutex_lock(&image[minor].mutex); +	/* Allow device to be opened if a resource is needed and allocated. */ +	if (minor < CONTROL_MINOR && image[minor].resource == NULL) { +		pr_err("No resources allocated for device\n");  		err = -EINVAL;  		goto err_res;  	} @@ -177,12 +181,12 @@ static int vme_user_open(struct inode *inode, struct file *file)  	/* Increment user count */  	image[minor].users++; -	up(&image[minor].sem); +	mutex_unlock(&image[minor].mutex);  	return 0;  err_res: -	up(&image[minor].sem); +	mutex_unlock(&image[minor].mutex);  	return err;  } @@ -191,12 +195,12 @@ static int vme_user_release(struct inode *inode, struct file *file)  {  	unsigned int minor = MINOR(inode->i_rdev); -	down(&image[minor].sem); +	mutex_lock(&image[minor].mutex);  	/* Decrement user count */  	image[minor].users--; -	up(&image[minor].sem); +	mutex_unlock(&image[minor].mutex);  	return 0;  } @@ -224,13 +228,13 @@ static ssize_t resource_to_user(int minor, char __user *buf, size_t count,  			(unsigned long)copied);  		if (retval != 0) {  			copied = (copied - retval); -			printk(KERN_INFO "User copy failed\n"); +			pr_info("User copy failed\n");  			return -EINVAL;  		}  	} else {  		/* XXX Need to write this */ -		printk(KERN_INFO "Currently don't support large transfers\n"); +		pr_info("Currently don't support large transfers\n");  		/* Map in pages from userspace */  		/* Call vme_master_read to do the transfer */ @@ -241,12 +245,12 @@ static ssize_t resource_to_user(int minor, char __user *buf, size_t count,  }  /* - * We are going ot alloc a page during init per window for small transfers. + * We are going to alloc a page during init per window for small transfers.   * Small transfers will go user space -> buffer -> VME. Larger (more than a   * page) transfers will lock the user space buffer into memory and then   * transfer the data directly from the user space buffers out to VME.   */ -static ssize_t resource_from_user(unsigned int minor, const char *buf, +static ssize_t resource_from_user(unsigned int minor, const char __user *buf,  	size_t count, loff_t *ppos)  {  	ssize_t retval; @@ -264,7 +268,7 @@ static ssize_t resource_from_user(unsigned int minor, const char *buf,  			image[minor].kern_buf, copied, *ppos);  	} else {  		/* XXX Need to write this */ -		printk(KERN_INFO "Currently don't support large transfers\n"); +		pr_info("Currently don't support large transfers\n");  		/* Map in pages from userspace */  		/* Call vme_master_write to do the transfer */ @@ -277,7 +281,7 @@ static ssize_t resource_from_user(unsigned int minor, const char *buf,  static ssize_t buffer_to_user(unsigned int minor, char __user *buf,  	size_t count, loff_t *ppos)  { -	void __iomem *image_ptr; +	void *image_ptr;  	ssize_t retval;  	image_ptr = image[minor].kern_buf + *ppos; @@ -285,7 +289,7 @@ static ssize_t buffer_to_user(unsigned int minor, char __user *buf,  	retval = __copy_to_user(buf, image_ptr, (unsigned long)count);  	if (retval != 0) {  		retval = (count - retval); -		printk(KERN_WARNING "Partial copy to userspace\n"); +		pr_warn("Partial copy to userspace\n");  	} else  		retval = count; @@ -293,10 +297,10 @@ static ssize_t buffer_to_user(unsigned int minor, char __user *buf,  	return retval;  } -static ssize_t buffer_from_user(unsigned int minor, const char *buf, +static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,  	size_t count, loff_t *ppos)  { -	void __iomem *image_ptr; +	void *image_ptr;  	size_t retval;  	image_ptr = image[minor].kern_buf + *ppos; @@ -304,7 +308,7 @@ static ssize_t buffer_from_user(unsigned int minor, const char *buf,  	retval = __copy_from_user(image_ptr, buf, (unsigned long)count);  	if (retval != 0) {  		retval = (count - retval); -		printk(KERN_WARNING "Partial copy to userspace\n"); +		pr_warn("Partial copy to userspace\n");  	} else  		retval = count; @@ -312,22 +316,25 @@ static ssize_t buffer_from_user(unsigned int minor, const char *buf,  	return retval;  } -static ssize_t vme_user_read(struct file *file, char *buf, size_t count, +static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,  			loff_t *ppos)  { -	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); +	unsigned int minor = MINOR(file_inode(file)->i_rdev);  	ssize_t retval;  	size_t image_size;  	size_t okcount; -	down(&image[minor].sem); +	if (minor == CONTROL_MINOR) +		return 0; + +	mutex_lock(&image[minor].mutex);  	/* XXX Do we *really* want this helper - we can use vme_*_get ? */  	image_size = vme_get_size(image[minor].resource);  	/* Ensure we are starting at a valid location */  	if ((*ppos < 0) || (*ppos > (image_size - 1))) { -		up(&image[minor].sem); +		mutex_unlock(&image[minor].mutex);  		return 0;  	} @@ -348,29 +355,31 @@ static ssize_t vme_user_read(struct file *file, char *buf, size_t count,  		retval = -EINVAL;  	} -	up(&image[minor].sem); - +	mutex_unlock(&image[minor].mutex);  	if (retval > 0)  		*ppos += retval;  	return retval;  } -static ssize_t vme_user_write(struct file *file, const char *buf, size_t count, -			 loff_t *ppos) +static ssize_t vme_user_write(struct file *file, const char __user *buf, +			size_t count, loff_t *ppos)  { -	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); +	unsigned int minor = MINOR(file_inode(file)->i_rdev);  	ssize_t retval;  	size_t image_size;  	size_t okcount; -	down(&image[minor].sem); +	if (minor == CONTROL_MINOR) +		return 0; + +	mutex_lock(&image[minor].mutex);  	image_size = vme_get_size(image[minor].resource);  	/* Ensure we are starting at a valid location */  	if ((*ppos < 0) || (*ppos > (image_size - 1))) { -		up(&image[minor].sem); +		mutex_unlock(&image[minor].mutex);  		return 0;  	} @@ -391,7 +400,7 @@ static ssize_t vme_user_write(struct file *file, const char *buf, size_t count,  		retval = -EINVAL;  	} -	up(&image[minor].sem); +	mutex_unlock(&image[minor].mutex);  	if (retval > 0)  		*ppos += retval; @@ -402,10 +411,13 @@ static ssize_t vme_user_write(struct file *file, const char *buf, size_t count,  static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)  {  	loff_t absolute = -1; -	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); +	unsigned int minor = MINOR(file_inode(file)->i_rdev);  	size_t image_size; -	down(&image[minor].sem); +	if (minor == CONTROL_MINOR) +		return -EINVAL; + +	mutex_lock(&image[minor].mutex);  	image_size = vme_get_size(image[minor].resource);  	switch (whence) { @@ -419,19 +431,19 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)  		absolute = image_size + off;  		break;  	default: -		up(&image[minor].sem); +		mutex_unlock(&image[minor].mutex);  		return -EINVAL;  		break;  	}  	if ((absolute < 0) || (absolute >= image_size)) { -		up(&image[minor].sem); +		mutex_unlock(&image[minor].mutex);  		return -EINVAL;  	}  	file->f_pos = absolute; -	up(&image[minor].sem); +	mutex_unlock(&image[minor].mutex);  	return absolute;  } @@ -451,15 +463,32 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,  {  	struct vme_master master;  	struct vme_slave slave; +	struct vme_irq_id irq_req;  	unsigned long copied;  	unsigned int minor = MINOR(inode->i_rdev);  	int retval;  	dma_addr_t pci_addr; +	void __user *argp = (void __user *)arg;  	statistics.ioctls++;  	switch (type[minor]) {  	case CONTROL_MINOR: +		switch (cmd) { +		case VME_IRQ_GEN: +			copied = copy_from_user(&irq_req, argp, +						sizeof(struct vme_irq_id)); +			if (copied != 0) { +				pr_warn("Partial copy from userspace\n"); +				return -EFAULT; +			} + +			retval = vme_irq_generate(vme_user_bridge, +						  irq_req.level, +						  irq_req.statid); + +			return retval; +		}  		break;  	case MASTER_MINOR:  		switch (cmd) { @@ -470,15 +499,14 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,  			 *	to userspace as they are  			 */  			retval = vme_master_get(image[minor].resource, -				&(master.enable), &(master.vme_addr), -				&(master.size), &(master.aspace), -				&(master.cycle), &(master.dwidth)); +				&master.enable, &master.vme_addr, +				&master.size, &master.aspace, +				&master.cycle, &master.dwidth); -			copied = copy_to_user((char *)arg, &master, +			copied = copy_to_user(argp, &master,  				sizeof(struct vme_master));  			if (copied != 0) { -				printk(KERN_WARNING "Partial copy to " -					"userspace\n"); +				pr_warn("Partial copy to userspace\n");  				return -EFAULT;  			} @@ -487,11 +515,9 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,  		case VME_SET_MASTER: -			copied = copy_from_user(&master, (char *)arg, -				sizeof(master)); +			copied = copy_from_user(&master, argp, sizeof(master));  			if (copied != 0) { -				printk(KERN_WARNING "Partial copy from " -					"userspace\n"); +				pr_warn("Partial copy from userspace\n");  				return -EFAULT;  			} @@ -514,15 +540,14 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,  			 *	to userspace as they are  			 */  			retval = vme_slave_get(image[minor].resource, -				&(slave.enable), &(slave.vme_addr), -				&(slave.size), &pci_addr, &(slave.aspace), -				&(slave.cycle)); +				&slave.enable, &slave.vme_addr, +				&slave.size, &pci_addr, &slave.aspace, +				&slave.cycle); -			copied = copy_to_user((char *)arg, &slave, +			copied = copy_to_user(argp, &slave,  				sizeof(struct vme_slave));  			if (copied != 0) { -				printk(KERN_WARNING "Partial copy to " -					"userspace\n"); +				pr_warn("Partial copy to userspace\n");  				return -EFAULT;  			} @@ -531,11 +556,9 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,  		case VME_SET_SLAVE: -			copied = copy_from_user(&slave, (char *)arg, -				sizeof(slave)); +			copied = copy_from_user(&slave, argp, sizeof(slave));  			if (copied != 0) { -				printk(KERN_WARNING "Partial copy from " -					"userspace\n"); +				pr_warn("Partial copy from userspace\n");  				return -EFAULT;  			} @@ -561,7 +584,7 @@ vme_user_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  	int ret;  	mutex_lock(&vme_user_mutex); -	ret = vme_user_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); +	ret = vme_user_ioctl(file_inode(file), file, cmd, arg);  	mutex_unlock(&vme_user_mutex);  	return ret; @@ -575,8 +598,8 @@ static void buf_unalloc(int num)  {  	if (image[num].kern_buf) {  #ifdef VME_DEBUG -		printk(KERN_DEBUG "UniverseII:Releasing buffer at %p\n", -			image[num].pci_buf); +		pr_debug("UniverseII:Releasing buffer at %p\n", +			 image[num].pci_buf);  #endif  		vme_free_consistent(image[num].resource, image[num].size_buf, @@ -588,13 +611,14 @@ static void buf_unalloc(int num)  #ifdef VME_DEBUG  	} else { -		printk(KERN_DEBUG "UniverseII: Buffer not allocated\n"); +		pr_debug("UniverseII: Buffer not allocated\n");  #endif  	}  }  static struct vme_driver vme_user_driver = {  	.name = driver_name, +	.match = vme_user_match,  	.probe = vme_user_probe,  	.remove = vme_user_remove,  }; @@ -603,87 +627,78 @@ static struct vme_driver vme_user_driver = {  static int __init vme_user_init(void)  {  	int retval = 0; -	int i; -	struct vme_device_id *ids; -	printk(KERN_INFO "VME User Space Access Driver\n"); +	pr_info("VME User Space Access Driver\n");  	if (bus_num == 0) { -		printk(KERN_ERR "%s: No cards, skipping registration\n", -			driver_name); +		pr_err("No cards, skipping registration\n"); +		retval = -ENODEV;  		goto err_nocard;  	}  	/* Let's start by supporting one bus, we can support more than one  	 * in future revisions if that ever becomes necessary.  	 */ -	if (bus_num > USER_BUS_MAX) { -		printk(KERN_ERR "%s: Driver only able to handle %d buses\n", -			driver_name, USER_BUS_MAX); -		bus_num = USER_BUS_MAX; +	if (bus_num > VME_USER_BUS_MAX) { +		pr_err("Driver only able to handle %d buses\n", +		       VME_USER_BUS_MAX); +		bus_num = VME_USER_BUS_MAX;  	} - -	/* Dynamically create the bind table based on module parameters */ -	ids = kmalloc(sizeof(struct vme_device_id) * (bus_num + 1), GFP_KERNEL); -	if (ids == NULL) { -		printk(KERN_ERR "%s: Unable to allocate ID table\n", -			driver_name); -		goto err_id; -	} - -	memset(ids, 0, (sizeof(struct vme_device_id) * (bus_num + 1))); - -	for (i = 0; i < bus_num; i++) { -		ids[i].bus = bus[i]; -		/* -		 * We register the driver against the slot occupied by *this* -		 * card, since it's really a low level way of controlling -		 * the VME bridge -		 */ -		ids[i].slot = VME_SLOT_CURRENT; -	} - -	vme_user_driver.bind_table = ids; - -	retval = vme_register_driver(&vme_user_driver); +	/* +	 * Here we just register the maximum number of devices we can and +	 * leave vme_user_match() to allow only 1 to go through to probe(). +	 * This way, if we later want to allow multiple user access devices, +	 * we just change the code in vme_user_match(). +	 */ +	retval = vme_register_driver(&vme_user_driver, VME_MAX_SLOTS);  	if (retval != 0)  		goto err_reg;  	return retval; -	vme_unregister_driver(&vme_user_driver);  err_reg: -	kfree(ids); -err_id:  err_nocard:  	return retval;  } +static int vme_user_match(struct vme_dev *vdev) +{ +	int i; + +	int cur_bus = vme_bus_num(vdev); +	int cur_slot = vme_slot_num(vdev); + +	for (i = 0; i < bus_num; i++) +		if ((cur_bus == bus[i]) && (cur_slot == vdev->num)) +			return 1; + +	return 0; +} +  /*   * In this simple access driver, the old behaviour is being preserved as much   * as practical. We will therefore reserve the buffers and request the images   * here so that we don't have to do it later.   */ -static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot) +static int vme_user_probe(struct vme_dev *vdev)  {  	int i, err; -	char name[12]; +	char *name;  	/* Save pointer to the bridge device */  	if (vme_user_bridge != NULL) { -		printk(KERN_ERR "%s: Driver can only be loaded for 1 device\n", -			driver_name); +		dev_err(&vdev->dev, "Driver can only be loaded for 1 device\n");  		err = -EINVAL;  		goto err_dev;  	} -	vme_user_bridge = dev; +	vme_user_bridge = vdev;  	/* Initialise descriptors */  	for (i = 0; i < VME_DEVS; i++) {  		image[i].kern_buf = NULL;  		image[i].pci_buf = 0; -		sema_init(&(image[i].sem), 1); +		mutex_init(&image[i].mutex);  		image[i].device = NULL;  		image[i].resource = NULL;  		image[i].users = 0; @@ -696,18 +711,22 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)  	err = register_chrdev_region(MKDEV(VME_MAJOR, 0), VME_DEVS,  		driver_name);  	if (err) { -		printk(KERN_WARNING "%s: Error getting Major Number %d for " -		"driver.\n", driver_name, VME_MAJOR); +		dev_warn(&vdev->dev, "Error getting Major Number %d for driver.\n", +			 VME_MAJOR);  		goto err_region;  	}  	/* Register the driver as a char device */  	vme_user_cdev = cdev_alloc(); +	if (!vme_user_cdev) { +		err = -ENOMEM; +		goto err_char; +	}  	vme_user_cdev->ops = &vme_user_fops;  	vme_user_cdev->owner = THIS_MODULE;  	err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS);  	if (err) { -		printk(KERN_WARNING "%s: cdev_all failed\n", driver_name); +		dev_warn(&vdev->dev, "cdev_all failed\n");  		goto err_char;  	} @@ -721,16 +740,17 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)  		image[i].resource = vme_slave_request(vme_user_bridge,  			VME_A24, VME_SCT);  		if (image[i].resource == NULL) { -			printk(KERN_WARNING "Unable to allocate slave " -				"resource\n"); +			dev_warn(&vdev->dev, +				 "Unable to allocate slave resource\n"); +			err = -ENOMEM;  			goto err_slave;  		}  		image[i].size_buf = PCI_BUF_SIZE;  		image[i].kern_buf = vme_alloc_consistent(image[i].resource, -			image[i].size_buf, &(image[i].pci_buf)); +			image[i].size_buf, &image[i].pci_buf);  		if (image[i].kern_buf == NULL) { -			printk(KERN_WARNING "Unable to allocate memory for " -				"buffer\n"); +			dev_warn(&vdev->dev, +				 "Unable to allocate memory for buffer\n");  			image[i].pci_buf = 0;  			vme_slave_free(image[i].resource);  			err = -ENOMEM; @@ -747,39 +767,41 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)  		image[i].resource = vme_master_request(vme_user_bridge,  			VME_A32, VME_SCT, VME_D32);  		if (image[i].resource == NULL) { -			printk(KERN_WARNING "Unable to allocate master " -				"resource\n"); +			dev_warn(&vdev->dev, +				 "Unable to allocate master resource\n"); +			err = -ENOMEM;  			goto err_master;  		}  		image[i].size_buf = PCI_BUF_SIZE;  		image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);  		if (image[i].kern_buf == NULL) { -			printk(KERN_WARNING "Unable to allocate memory for " -				"master window buffers\n");  			err = -ENOMEM; -			goto err_master_buf; +			vme_master_free(image[i].resource); +			goto err_master;  		}  	}  	/* Create sysfs entries - on udev systems this creates the dev files */  	vme_user_sysfs_class = class_create(THIS_MODULE, driver_name);  	if (IS_ERR(vme_user_sysfs_class)) { -		printk(KERN_ERR "Error creating vme_user class.\n"); +		dev_err(&vdev->dev, "Error creating vme_user class.\n");  		err = PTR_ERR(vme_user_sysfs_class);  		goto err_class;  	}  	/* Add sysfs Entries */  	for (i = 0; i < VME_DEVS; i++) { +		int num; +  		switch (type[i]) {  		case MASTER_MINOR: -			sprintf(name, "bus/vme/m%%d"); +			name = "bus/vme/m%d";  			break;  		case CONTROL_MINOR: -			sprintf(name, "bus/vme/ctl"); +			name = "bus/vme/ctl";  			break;  		case SLAVE_MINOR: -			sprintf(name, "bus/vme/s%%d"); +			name = "bus/vme/s%d";  			break;  		default:  			err = -EINVAL; @@ -787,13 +809,11 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)  			break;  		} -		image[i].device = -			device_create(vme_user_sysfs_class, NULL, -				MKDEV(VME_MAJOR, i), NULL, name, -				(type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i); +		num = (type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i; +		image[i].device = device_create(vme_user_sysfs_class, NULL, +					MKDEV(VME_MAJOR, i), NULL, name, num);  		if (IS_ERR(image[i].device)) { -			printk(KERN_INFO "%s: Error creating sysfs device\n", -				driver_name); +			dev_info(&vdev->dev, "Error creating sysfs device\n");  			err = PTR_ERR(image[i].device);  			goto err_sysfs;  		} @@ -801,8 +821,6 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)  	return 0; -	/* Ensure counter set correcty to destroy all sysfs devices */ -	i = VME_DEVS;  err_sysfs:  	while (i > 0) {  		i--; @@ -812,12 +830,10 @@ err_sysfs:  	/* Ensure counter set correcty to unalloc all master windows */  	i = MASTER_MAX + 1; -err_master_buf: -	for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) -		kfree(image[i].kern_buf);  err_master:  	while (i > MASTER_MINOR) {  		i--; +		kfree(image[i].kern_buf);  		vme_master_free(image[i].resource);  	} @@ -828,8 +844,8 @@ err_master:  err_slave:  	while (i > SLAVE_MINOR) {  		i--; -		vme_slave_free(image[i].resource);  		buf_unalloc(i); +		vme_slave_free(image[i].resource);  	}  err_class:  	cdev_del(vme_user_cdev); @@ -840,22 +856,26 @@ err_dev:  	return err;  } -static int __exit vme_user_remove(struct device *dev, int cur_bus, int cur_slot) +static int vme_user_remove(struct vme_dev *dev)  {  	int i;  	/* Remove sysfs Entries */ -	for (i = 0; i < VME_DEVS; i++) +	for (i = 0; i < VME_DEVS; i++) { +		mutex_destroy(&image[i].mutex);  		device_destroy(vme_user_sysfs_class, MKDEV(VME_MAJOR, i)); +	}  	class_destroy(vme_user_sysfs_class); -	for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) +	for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) {  		kfree(image[i].kern_buf); +		vme_master_free(image[i].resource); +	}  	for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {  		vme_slave_set(image[i].resource, 0, 0, 0, 0, VME_A32, 0); -		vme_slave_free(image[i].resource);  		buf_unalloc(i); +		vme_slave_free(image[i].resource);  	}  	/* Unregister device driver */ @@ -870,8 +890,6 @@ static int __exit vme_user_remove(struct device *dev, int cur_bus, int cur_slot)  static void __exit vme_user_exit(void)  {  	vme_unregister_driver(&vme_user_driver); - -	kfree(vme_user_driver.bind_table);  } diff --git a/drivers/staging/vme/devices/vme_user.h b/drivers/staging/vme/devices/vme_user.h index ede77d7e766..b8cc7bc78a7 100644 --- a/drivers/staging/vme/devices/vme_user.h +++ b/drivers/staging/vme/devices/vme_user.h @@ -1,24 +1,24 @@  #ifndef _VME_USER_H_  #define _VME_USER_H_ -#define USER_BUS_MAX                  1 +#define VME_USER_BUS_MAX	1  /*   * VMEbus Master Window Configuration Structure   */  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 enable;		/* State of Window */ +	__u64 vme_addr;		/* Starting Address on the VMEbus */ +	__u64 size;		/* Window Size */ +	__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) */ -	char wrPostEnable;		/* Write Post State */ +	char prefetchenable;		/* Prefetch Read Enable State */ +	int prefetchsize;		/* Prefetch Read Size (Cache Lines) */ +	char wrpostenable;		/* Write Post State */  #endif -}; +} __packed;  /* @@ -31,22 +31,28 @@ struct vme_master {  /* VMEbus Slave Window Configuration Structure */  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 enable;		/* State of Window */ +	__u64 vme_addr;		/* Starting Address on the VMEbus */ +	__u64 size;		/* Window Size */ +	__u32 aspace;		/* Address Space */ +	__u32 cycle;		/* Cycle properties */  #if 0 -	char wrPostEnable;		/* Write Post State */ -	char rmwLock;			/* Lock PCI during RMW Cycles */ -	char data64BitCapable;		/* non-VMEbus capable of 64-bit Data */ +	char wrpostenable;		/* Write Post State */ +	char rmwlock;			/* Lock PCI during RMW Cycles */ +	char data64bitcapable;		/* non-VMEbus capable of 64-bit Data */  #endif +} __packed; + +struct vme_irq_id { +	__u8 level; +	__u8 statid;  };  #define VME_GET_SLAVE _IOR(VME_IOC_MAGIC, 1, struct vme_slave)  #define VME_SET_SLAVE _IOW(VME_IOC_MAGIC, 2, struct vme_slave)  #define VME_GET_MASTER _IOR(VME_IOC_MAGIC, 3, struct vme_master)  #define VME_SET_MASTER _IOW(VME_IOC_MAGIC, 4, struct vme_master) +#define VME_IRQ_GEN _IOW(VME_IOC_MAGIC, 5, struct vme_irq_id)  #endif /* _VME_USER_H_ */ diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c deleted file mode 100644 index 093fbffbf55..00000000000 --- a/drivers/staging/vme/vme.c +++ /dev/null @@ -1,1539 +0,0 @@ -/* - * VME Bridge Framework - * - * Author: Martyn Welch <martyn.welch@ge.com> - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. - * - * Based on work by Tom Armistead and Ajit Prem - * Copyright 2004 Motorola 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/module.h> -#include <linux/moduleparam.h> -#include <linux/mm.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/poll.h> -#include <linux/highmem.h> -#include <linux/interrupt.h> -#include <linux/pagemap.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/syscalls.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <linux/slab.h> - -#include "vme.h" -#include "vme_bridge.h" - -/* Bitmask and mutex to keep track of bridge numbers */ -static unsigned int vme_bus_numbers; -static DEFINE_MUTEX(vme_bus_num_mtx); - -static void __exit vme_exit(void); -static int __init vme_init(void); - - -/* - * Find the bridge resource associated with a specific device resource - */ -static struct vme_bridge *dev_to_bridge(struct device *dev) -{ -	return dev->platform_data; -} - -/* - * Find the bridge that the resource is associated with. - */ -static struct vme_bridge *find_bridge(struct vme_resource *resource) -{ -	/* Get list to search */ -	switch (resource->type) { -	case VME_MASTER: -		return list_entry(resource->entry, struct vme_master_resource, -			list)->parent; -		break; -	case VME_SLAVE: -		return list_entry(resource->entry, struct vme_slave_resource, -			list)->parent; -		break; -	case VME_DMA: -		return list_entry(resource->entry, struct vme_dma_resource, -			list)->parent; -		break; -	case VME_LM: -		return list_entry(resource->entry, struct vme_lm_resource, -			list)->parent; -		break; -	default: -		printk(KERN_ERR "Unknown resource type\n"); -		return NULL; -		break; -	} -} - -/* - * Allocate a contiguous block of memory for use by the driver. This is used to - * create the buffers for the slave windows. - * - * XXX VME bridges could be available on buses other than PCI. At the momment - *     this framework only supports PCI devices. - */ -void *vme_alloc_consistent(struct vme_resource *resource, size_t size, -	dma_addr_t *dma) -{ -	struct vme_bridge *bridge; -	struct pci_dev *pdev; - -	if (resource == NULL) { -		printk(KERN_ERR "No resource\n"); -		return NULL; -	} - -	bridge = find_bridge(resource); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find bridge\n"); -		return NULL; -	} - -	/* Find pci_dev container of dev */ -	if (bridge->parent == NULL) { -		printk(KERN_ERR "Dev entry NULL\n"); -		return NULL; -	} -	pdev = container_of(bridge->parent, struct pci_dev, dev); - -	return pci_alloc_consistent(pdev, size, dma); -} -EXPORT_SYMBOL(vme_alloc_consistent); - -/* - * Free previously allocated contiguous block of memory. - * - * XXX VME bridges could be available on buses other than PCI. At the momment - *     this framework only supports PCI devices. - */ -void vme_free_consistent(struct vme_resource *resource, size_t size, -	void *vaddr, dma_addr_t dma) -{ -	struct vme_bridge *bridge; -	struct pci_dev *pdev; - -	if (resource == NULL) { -		printk(KERN_ERR "No resource\n"); -		return; -	} - -	bridge = find_bridge(resource); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find bridge\n"); -		return; -	} - -	/* Find pci_dev container of dev */ -	pdev = container_of(bridge->parent, struct pci_dev, dev); - -	pci_free_consistent(pdev, size, vaddr, dma); -} -EXPORT_SYMBOL(vme_free_consistent); - -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; - -	switch (resource->type) { -	case VME_MASTER: -		retval = vme_master_get(resource, &enabled, &base, &size, -			&aspace, &cycle, &dwidth); - -		return size; -		break; -	case VME_SLAVE: -		retval = vme_slave_get(resource, &enabled, &base, &size, -			&buf_base, &aspace, &cycle); - -		return size; -		break; -	case VME_DMA: -		return 0; -		break; -	default: -		printk(KERN_ERR "Unknown resource type\n"); -		return 0; -		break; -	} -} -EXPORT_SYMBOL(vme_get_size); - -static int vme_check_window(vme_address_t aspace, unsigned long long vme_base, -	unsigned long long size) -{ -	int retval = 0; - -	switch (aspace) { -	case VME_A16: -		if (((vme_base + size) > VME_A16_MAX) || -				(vme_base > VME_A16_MAX)) -			retval = -EFAULT; -		break; -	case VME_A24: -		if (((vme_base + size) > VME_A24_MAX) || -				(vme_base > VME_A24_MAX)) -			retval = -EFAULT; -		break; -	case VME_A32: -		if (((vme_base + size) > VME_A32_MAX) || -				(vme_base > VME_A32_MAX)) -			retval = -EFAULT; -		break; -	case VME_A64: -		/* -		 * Any value held in an unsigned long long can be used as the -		 * base -		 */ -		break; -	case VME_CRCSR: -		if (((vme_base + size) > VME_CRCSR_MAX) || -				(vme_base > VME_CRCSR_MAX)) -			retval = -EFAULT; -		break; -	case VME_USER1: -	case VME_USER2: -	case VME_USER3: -	case VME_USER4: -		/* User Defined */ -		break; -	default: -		printk(KERN_ERR "Invalid address space\n"); -		retval = -EINVAL; -		break; -	} - -	return retval; -} - -/* - * Request a slave image with specific attributes, return some unique - * identifier. - */ -struct vme_resource *vme_slave_request(struct device *dev, -	vme_address_t address, vme_cycle_t cycle) -{ -	struct vme_bridge *bridge; -	struct list_head *slave_pos = NULL; -	struct vme_slave_resource *allocated_image = NULL; -	struct vme_slave_resource *slave_image = NULL; -	struct vme_resource *resource = NULL; - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		goto err_bus; -	} - -	/* Loop through slave resources */ -	list_for_each(slave_pos, &(bridge->slave_resources)) { -		slave_image = list_entry(slave_pos, -			struct vme_slave_resource, list); - -		if (slave_image == NULL) { -			printk(KERN_ERR "Registered NULL Slave resource\n"); -			continue; -		} - -		/* Find an unlocked and compatible image */ -		mutex_lock(&(slave_image->mtx)); -		if (((slave_image->address_attr & address) == address) && -			((slave_image->cycle_attr & cycle) == cycle) && -			(slave_image->locked == 0)) { - -			slave_image->locked = 1; -			mutex_unlock(&(slave_image->mtx)); -			allocated_image = slave_image; -			break; -		} -		mutex_unlock(&(slave_image->mtx)); -	} - -	/* No free image */ -	if (allocated_image == NULL) -		goto err_image; - -	resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); -	if (resource == NULL) { -		printk(KERN_WARNING "Unable to allocate resource structure\n"); -		goto err_alloc; -	} -	resource->type = VME_SLAVE; -	resource->entry = &(allocated_image->list); - -	return resource; - -err_alloc: -	/* Unlock image */ -	mutex_lock(&(slave_image->mtx)); -	slave_image->locked = 0; -	mutex_unlock(&(slave_image->mtx)); -err_image: -err_bus: -	return NULL; -} -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) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_slave_resource *image; -	int retval; - -	if (resource->type != VME_SLAVE) { -		printk(KERN_ERR "Not a slave resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_slave_resource, list); - -	if (bridge->slave_set == NULL) { -		printk(KERN_ERR "Function not supported\n"); -		return -ENOSYS; -	} - -	if (!(((image->address_attr & aspace) == aspace) && -		((image->cycle_attr & cycle) == cycle))) { -		printk(KERN_ERR "Invalid attributes\n"); -		return -EINVAL; -	} - -	retval = vme_check_window(aspace, vme_base, size); -	if (retval) -		return retval; - -	return bridge->slave_set(image, enabled, vme_base, size, buf_base, -		aspace, cycle); -} -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) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_slave_resource *image; - -	if (resource->type != VME_SLAVE) { -		printk(KERN_ERR "Not a slave resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_slave_resource, list); - -	if (bridge->slave_get == NULL) { -		printk(KERN_ERR "vme_slave_get not supported\n"); -		return -EINVAL; -	} - -	return bridge->slave_get(image, enabled, vme_base, size, buf_base, -		aspace, cycle); -} -EXPORT_SYMBOL(vme_slave_get); - -void vme_slave_free(struct vme_resource *resource) -{ -	struct vme_slave_resource *slave_image; - -	if (resource->type != VME_SLAVE) { -		printk(KERN_ERR "Not a slave resource\n"); -		return; -	} - -	slave_image = list_entry(resource->entry, struct vme_slave_resource, -		list); -	if (slave_image == NULL) { -		printk(KERN_ERR "Can't find slave resource\n"); -		return; -	} - -	/* Unlock image */ -	mutex_lock(&(slave_image->mtx)); -	if (slave_image->locked == 0) -		printk(KERN_ERR "Image is already free\n"); - -	slave_image->locked = 0; -	mutex_unlock(&(slave_image->mtx)); - -	/* Free up resource memory */ -	kfree(resource); -} -EXPORT_SYMBOL(vme_slave_free); - -/* - * Request a master image with specific attributes, return some unique - * identifier. - */ -struct vme_resource *vme_master_request(struct device *dev, -	vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth) -{ -	struct vme_bridge *bridge; -	struct list_head *master_pos = NULL; -	struct vme_master_resource *allocated_image = NULL; -	struct vme_master_resource *master_image = NULL; -	struct vme_resource *resource = NULL; - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		goto err_bus; -	} - -	/* Loop through master resources */ -	list_for_each(master_pos, &(bridge->master_resources)) { -		master_image = list_entry(master_pos, -			struct vme_master_resource, list); - -		if (master_image == NULL) { -			printk(KERN_WARNING "Registered NULL master resource\n"); -			continue; -		} - -		/* Find an unlocked and compatible image */ -		spin_lock(&(master_image->lock)); -		if (((master_image->address_attr & address) == address) && -			((master_image->cycle_attr & cycle) == cycle) && -			((master_image->width_attr & dwidth) == dwidth) && -			(master_image->locked == 0)) { - -			master_image->locked = 1; -			spin_unlock(&(master_image->lock)); -			allocated_image = master_image; -			break; -		} -		spin_unlock(&(master_image->lock)); -	} - -	/* Check to see if we found a resource */ -	if (allocated_image == NULL) { -		printk(KERN_ERR "Can't find a suitable resource\n"); -		goto err_image; -	} - -	resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); -	if (resource == NULL) { -		printk(KERN_ERR "Unable to allocate resource structure\n"); -		goto err_alloc; -	} -	resource->type = VME_MASTER; -	resource->entry = &(allocated_image->list); - -	return resource; - -	kfree(resource); -err_alloc: -	/* Unlock image */ -	spin_lock(&(master_image->lock)); -	master_image->locked = 0; -	spin_unlock(&(master_image->lock)); -err_image: -err_bus: -	return NULL; -} -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) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_master_resource *image; -	int retval; - -	if (resource->type != VME_MASTER) { -		printk(KERN_ERR "Not a master resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_master_resource, list); - -	if (bridge->master_set == NULL) { -		printk(KERN_WARNING "vme_master_set not supported\n"); -		return -EINVAL; -	} - -	if (!(((image->address_attr & aspace) == aspace) && -		((image->cycle_attr & cycle) == cycle) && -		((image->width_attr & dwidth) == dwidth))) { -		printk(KERN_WARNING "Invalid attributes\n"); -		return -EINVAL; -	} - -	retval = vme_check_window(aspace, vme_base, size); -	if (retval) -		return retval; - -	return bridge->master_set(image, enabled, vme_base, size, aspace, -		cycle, dwidth); -} -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) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_master_resource *image; - -	if (resource->type != VME_MASTER) { -		printk(KERN_ERR "Not a master resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_master_resource, list); - -	if (bridge->master_get == NULL) { -		printk(KERN_WARNING "vme_master_set not supported\n"); -		return -EINVAL; -	} - -	return bridge->master_get(image, enabled, vme_base, size, aspace, -		cycle, dwidth); -} -EXPORT_SYMBOL(vme_master_get); - -/* - * Read data out of VME space into a buffer. - */ -ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count, -	loff_t offset) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_master_resource *image; -	size_t length; - -	if (bridge->master_read == NULL) { -		printk(KERN_WARNING "Reading from resource not supported\n"); -		return -EINVAL; -	} - -	if (resource->type != VME_MASTER) { -		printk(KERN_ERR "Not a master resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_master_resource, list); - -	length = vme_get_size(resource); - -	if (offset > length) { -		printk(KERN_WARNING "Invalid Offset\n"); -		return -EFAULT; -	} - -	if ((offset + count) > length) -		count = length - offset; - -	return bridge->master_read(image, buf, count, offset); - -} -EXPORT_SYMBOL(vme_master_read); - -/* - * Write data out to VME space from a buffer. - */ -ssize_t vme_master_write(struct vme_resource *resource, void *buf, -	size_t count, loff_t offset) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_master_resource *image; -	size_t length; - -	if (bridge->master_write == NULL) { -		printk(KERN_WARNING "Writing to resource not supported\n"); -		return -EINVAL; -	} - -	if (resource->type != VME_MASTER) { -		printk(KERN_ERR "Not a master resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_master_resource, list); - -	length = vme_get_size(resource); - -	if (offset > length) { -		printk(KERN_WARNING "Invalid Offset\n"); -		return -EFAULT; -	} - -	if ((offset + count) > length) -		count = length - offset; - -	return bridge->master_write(image, buf, count, offset); -} -EXPORT_SYMBOL(vme_master_write); - -/* - * Perform RMW cycle to provided location. - */ -unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask, -	unsigned int compare, unsigned int swap, loff_t offset) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_master_resource *image; - -	if (bridge->master_rmw == NULL) { -		printk(KERN_WARNING "Writing to resource not supported\n"); -		return -EINVAL; -	} - -	if (resource->type != VME_MASTER) { -		printk(KERN_ERR "Not a master resource\n"); -		return -EINVAL; -	} - -	image = list_entry(resource->entry, struct vme_master_resource, list); - -	return bridge->master_rmw(image, mask, compare, swap, offset); -} -EXPORT_SYMBOL(vme_master_rmw); - -void vme_master_free(struct vme_resource *resource) -{ -	struct vme_master_resource *master_image; - -	if (resource->type != VME_MASTER) { -		printk(KERN_ERR "Not a master resource\n"); -		return; -	} - -	master_image = list_entry(resource->entry, struct vme_master_resource, -		list); -	if (master_image == NULL) { -		printk(KERN_ERR "Can't find master resource\n"); -		return; -	} - -	/* Unlock image */ -	spin_lock(&(master_image->lock)); -	if (master_image->locked == 0) -		printk(KERN_ERR "Image is already free\n"); - -	master_image->locked = 0; -	spin_unlock(&(master_image->lock)); - -	/* Free up resource memory */ -	kfree(resource); -} -EXPORT_SYMBOL(vme_master_free); - -/* - * Request a DMA controller with specific attributes, return some unique - * identifier. - */ -struct vme_resource *vme_dma_request(struct device *dev, vme_dma_route_t route) -{ -	struct vme_bridge *bridge; -	struct list_head *dma_pos = NULL; -	struct vme_dma_resource *allocated_ctrlr = NULL; -	struct vme_dma_resource *dma_ctrlr = NULL; -	struct vme_resource *resource = NULL; - -	/* XXX Not checking resource attributes */ -	printk(KERN_ERR "No VME resource Attribute tests done\n"); - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		goto err_bus; -	} - -	/* Loop through DMA resources */ -	list_for_each(dma_pos, &(bridge->dma_resources)) { -		dma_ctrlr = list_entry(dma_pos, -			struct vme_dma_resource, list); - -		if (dma_ctrlr == NULL) { -			printk(KERN_ERR "Registered NULL DMA resource\n"); -			continue; -		} - -		/* Find an unlocked and compatible controller */ -		mutex_lock(&(dma_ctrlr->mtx)); -		if (((dma_ctrlr->route_attr & route) == route) && -			(dma_ctrlr->locked == 0)) { - -			dma_ctrlr->locked = 1; -			mutex_unlock(&(dma_ctrlr->mtx)); -			allocated_ctrlr = dma_ctrlr; -			break; -		} -		mutex_unlock(&(dma_ctrlr->mtx)); -	} - -	/* Check to see if we found a resource */ -	if (allocated_ctrlr == NULL) -		goto err_ctrlr; - -	resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); -	if (resource == NULL) { -		printk(KERN_WARNING "Unable to allocate resource structure\n"); -		goto err_alloc; -	} -	resource->type = VME_DMA; -	resource->entry = &(allocated_ctrlr->list); - -	return resource; - -err_alloc: -	/* Unlock image */ -	mutex_lock(&(dma_ctrlr->mtx)); -	dma_ctrlr->locked = 0; -	mutex_unlock(&(dma_ctrlr->mtx)); -err_ctrlr: -err_bus: -	return NULL; -} -EXPORT_SYMBOL(vme_dma_request); - -/* - * Start new list - */ -struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) -{ -	struct vme_dma_resource *ctrlr; -	struct vme_dma_list *dma_list; - -	if (resource->type != VME_DMA) { -		printk(KERN_ERR "Not a DMA resource\n"); -		return NULL; -	} - -	ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); - -	dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL); -	if (dma_list == NULL) { -		printk(KERN_ERR "Unable to allocate memory for new dma list\n"); -		return NULL; -	} -	INIT_LIST_HEAD(&(dma_list->entries)); -	dma_list->parent = ctrlr; -	mutex_init(&(dma_list->mtx)); - -	return dma_list; -} -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 *attributes; -	struct vme_dma_pattern *pattern_attr; - -	attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); -	if (attributes == NULL) { -		printk(KERN_ERR "Unable to allocate memory for attributes " -			"structure\n"); -		goto err_attr; -	} - -	pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL); -	if (pattern_attr == NULL) { -		printk(KERN_ERR "Unable to allocate memory for pattern " -			"attributes\n"); -		goto err_pat; -	} - -	attributes->type = VME_DMA_PATTERN; -	attributes->private = (void *)pattern_attr; - -	pattern_attr->pattern = pattern; -	pattern_attr->type = type; - -	return attributes; - -	kfree(pattern_attr); -err_pat: -	kfree(attributes); -err_attr: -	return NULL; -} -EXPORT_SYMBOL(vme_dma_pattern_attribute); - -/* - * Create "PCI" type attributes - */ -struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address) -{ -	struct vme_dma_attr *attributes; -	struct vme_dma_pci *pci_attr; - -	/* XXX Run some sanity checks here */ - -	attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); -	if (attributes == NULL) { -		printk(KERN_ERR "Unable to allocate memory for attributes " -			"structure\n"); -		goto err_attr; -	} - -	pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL); -	if (pci_attr == NULL) { -		printk(KERN_ERR "Unable to allocate memory for pci " -			"attributes\n"); -		goto err_pci; -	} - - - -	attributes->type = VME_DMA_PCI; -	attributes->private = (void *)pci_attr; - -	pci_attr->address = address; - -	return attributes; - -	kfree(pci_attr); -err_pci: -	kfree(attributes); -err_attr: -	return NULL; -} -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) -{ -	struct vme_dma_attr *attributes; -	struct vme_dma_vme *vme_attr; - -	attributes = kmalloc( -		sizeof(struct vme_dma_attr), GFP_KERNEL); -	if (attributes == NULL) { -		printk(KERN_ERR "Unable to allocate memory for attributes " -			"structure\n"); -		goto err_attr; -	} - -	vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL); -	if (vme_attr == NULL) { -		printk(KERN_ERR "Unable to allocate memory for vme " -			"attributes\n"); -		goto err_vme; -	} - -	attributes->type = VME_DMA_VME; -	attributes->private = (void *)vme_attr; - -	vme_attr->address = address; -	vme_attr->aspace = aspace; -	vme_attr->cycle = cycle; -	vme_attr->dwidth = dwidth; - -	return attributes; - -	kfree(vme_attr); -err_vme: -	kfree(attributes); -err_attr: -	return NULL; -} -EXPORT_SYMBOL(vme_dma_vme_attribute); - -/* - * Free attribute - */ -void vme_dma_free_attribute(struct vme_dma_attr *attributes) -{ -	kfree(attributes->private); -	kfree(attributes); -} -EXPORT_SYMBOL(vme_dma_free_attribute); - -int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, -	struct vme_dma_attr *dest, size_t count) -{ -	struct vme_bridge *bridge = list->parent->parent; -	int retval; - -	if (bridge->dma_list_add == NULL) { -		printk(KERN_WARNING "Link List DMA generation not supported\n"); -		return -EINVAL; -	} - -	if (!mutex_trylock(&(list->mtx))) { -		printk(KERN_ERR "Link List already submitted\n"); -		return -EINVAL; -	} - -	retval = bridge->dma_list_add(list, src, dest, count); - -	mutex_unlock(&(list->mtx)); - -	return retval; -} -EXPORT_SYMBOL(vme_dma_list_add); - -int vme_dma_list_exec(struct vme_dma_list *list) -{ -	struct vme_bridge *bridge = list->parent->parent; -	int retval; - -	if (bridge->dma_list_exec == NULL) { -		printk(KERN_ERR "Link List DMA execution not supported\n"); -		return -EINVAL; -	} - -	mutex_lock(&(list->mtx)); - -	retval = bridge->dma_list_exec(list); - -	mutex_unlock(&(list->mtx)); - -	return retval; -} -EXPORT_SYMBOL(vme_dma_list_exec); - -int vme_dma_list_free(struct vme_dma_list *list) -{ -	struct vme_bridge *bridge = list->parent->parent; -	int retval; - -	if (bridge->dma_list_empty == NULL) { -		printk(KERN_WARNING "Emptying of Link Lists not supported\n"); -		return -EINVAL; -	} - -	if (!mutex_trylock(&(list->mtx))) { -		printk(KERN_ERR "Link List in use\n"); -		return -EINVAL; -	} - -	/* -	 * Empty out all of the entries from the dma list. We need to go to the -	 * low level driver as dma entries are driver specific. -	 */ -	retval = bridge->dma_list_empty(list); -	if (retval) { -		printk(KERN_ERR "Unable to empty link-list entries\n"); -		mutex_unlock(&(list->mtx)); -		return retval; -	} -	mutex_unlock(&(list->mtx)); -	kfree(list); - -	return retval; -} -EXPORT_SYMBOL(vme_dma_list_free); - -int vme_dma_free(struct vme_resource *resource) -{ -	struct vme_dma_resource *ctrlr; - -	if (resource->type != VME_DMA) { -		printk(KERN_ERR "Not a DMA resource\n"); -		return -EINVAL; -	} - -	ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); - -	if (!mutex_trylock(&(ctrlr->mtx))) { -		printk(KERN_ERR "Resource busy, can't free\n"); -		return -EBUSY; -	} - -	if (!(list_empty(&(ctrlr->pending)) && list_empty(&(ctrlr->running)))) { -		printk(KERN_WARNING "Resource still processing transfers\n"); -		mutex_unlock(&(ctrlr->mtx)); -		return -EBUSY; -	} - -	ctrlr->locked = 0; - -	mutex_unlock(&(ctrlr->mtx)); - -	return 0; -} -EXPORT_SYMBOL(vme_dma_free); - -void vme_irq_handler(struct vme_bridge *bridge, int level, int statid) -{ -	void (*call)(int, int, void *); -	void *priv_data; - -	call = bridge->irq[level - 1].callback[statid].func; -	priv_data = bridge->irq[level - 1].callback[statid].priv_data; - -	if (call != NULL) -		call(level, statid, priv_data); -	else -		printk(KERN_WARNING "Spurilous VME interrupt, level:%x, " -			"vector:%x\n", level, statid); -} -EXPORT_SYMBOL(vme_irq_handler); - -int vme_irq_request(struct device *dev, int level, int statid, -	void (*callback)(int, int, void *), -	void *priv_data) -{ -	struct vme_bridge *bridge; - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		return -EINVAL; -	} - -	if ((level < 1) || (level > 7)) { -		printk(KERN_ERR "Invalid interrupt level\n"); -		return -EINVAL; -	} - -	if (bridge->irq_set == NULL) { -		printk(KERN_ERR "Configuring interrupts not supported\n"); -		return -EINVAL; -	} - -	mutex_lock(&(bridge->irq_mtx)); - -	if (bridge->irq[level - 1].callback[statid].func) { -		mutex_unlock(&(bridge->irq_mtx)); -		printk(KERN_WARNING "VME Interrupt already taken\n"); -		return -EBUSY; -	} - -	bridge->irq[level - 1].count++; -	bridge->irq[level - 1].callback[statid].priv_data = priv_data; -	bridge->irq[level - 1].callback[statid].func = callback; - -	/* Enable IRQ level */ -	bridge->irq_set(bridge, level, 1, 1); - -	mutex_unlock(&(bridge->irq_mtx)); - -	return 0; -} -EXPORT_SYMBOL(vme_irq_request); - -void vme_irq_free(struct device *dev, int level, int statid) -{ -	struct vme_bridge *bridge; - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		return; -	} - -	if ((level < 1) || (level > 7)) { -		printk(KERN_ERR "Invalid interrupt level\n"); -		return; -	} - -	if (bridge->irq_set == NULL) { -		printk(KERN_ERR "Configuring interrupts not supported\n"); -		return; -	} - -	mutex_lock(&(bridge->irq_mtx)); - -	bridge->irq[level - 1].count--; - -	/* Disable IRQ level if no more interrupts attached at this level*/ -	if (bridge->irq[level - 1].count == 0) -		bridge->irq_set(bridge, level, 0, 1); - -	bridge->irq[level - 1].callback[statid].func = NULL; -	bridge->irq[level - 1].callback[statid].priv_data = NULL; - -	mutex_unlock(&(bridge->irq_mtx)); -} -EXPORT_SYMBOL(vme_irq_free); - -int vme_irq_generate(struct device *dev, int level, int statid) -{ -	struct vme_bridge *bridge; - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		return -EINVAL; -	} - -	if ((level < 1) || (level > 7)) { -		printk(KERN_WARNING "Invalid interrupt level\n"); -		return -EINVAL; -	} - -	if (bridge->irq_generate == NULL) { -		printk(KERN_WARNING "Interrupt generation not supported\n"); -		return -EINVAL; -	} - -	return bridge->irq_generate(bridge, level, statid); -} -EXPORT_SYMBOL(vme_irq_generate); - -/* - * Request the location monitor, return resource or NULL - */ -struct vme_resource *vme_lm_request(struct device *dev) -{ -	struct vme_bridge *bridge; -	struct list_head *lm_pos = NULL; -	struct vme_lm_resource *allocated_lm = NULL; -	struct vme_lm_resource *lm = NULL; -	struct vme_resource *resource = NULL; - -	bridge = dev_to_bridge(dev); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		goto err_bus; -	} - -	/* Loop through DMA resources */ -	list_for_each(lm_pos, &(bridge->lm_resources)) { -		lm = list_entry(lm_pos, -			struct vme_lm_resource, list); - -		if (lm == NULL) { -			printk(KERN_ERR "Registered NULL Location Monitor " -				"resource\n"); -			continue; -		} - -		/* Find an unlocked controller */ -		mutex_lock(&(lm->mtx)); -		if (lm->locked == 0) { -			lm->locked = 1; -			mutex_unlock(&(lm->mtx)); -			allocated_lm = lm; -			break; -		} -		mutex_unlock(&(lm->mtx)); -	} - -	/* Check to see if we found a resource */ -	if (allocated_lm == NULL) -		goto err_lm; - -	resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); -	if (resource == NULL) { -		printk(KERN_ERR "Unable to allocate resource structure\n"); -		goto err_alloc; -	} -	resource->type = VME_LM; -	resource->entry = &(allocated_lm->list); - -	return resource; - -err_alloc: -	/* Unlock image */ -	mutex_lock(&(lm->mtx)); -	lm->locked = 0; -	mutex_unlock(&(lm->mtx)); -err_lm: -err_bus: -	return NULL; -} -EXPORT_SYMBOL(vme_lm_request); - -int vme_lm_count(struct vme_resource *resource) -{ -	struct vme_lm_resource *lm; - -	if (resource->type != VME_LM) { -		printk(KERN_ERR "Not a Location Monitor resource\n"); -		return -EINVAL; -	} - -	lm = list_entry(resource->entry, struct vme_lm_resource, list); - -	return lm->monitors; -} -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) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_lm_resource *lm; - -	if (resource->type != VME_LM) { -		printk(KERN_ERR "Not a Location Monitor resource\n"); -		return -EINVAL; -	} - -	lm = list_entry(resource->entry, struct vme_lm_resource, list); - -	if (bridge->lm_set == NULL) { -		printk(KERN_ERR "vme_lm_set not supported\n"); -		return -EINVAL; -	} - -	return bridge->lm_set(lm, lm_base, aspace, cycle); -} -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) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_lm_resource *lm; - -	if (resource->type != VME_LM) { -		printk(KERN_ERR "Not a Location Monitor resource\n"); -		return -EINVAL; -	} - -	lm = list_entry(resource->entry, struct vme_lm_resource, list); - -	if (bridge->lm_get == NULL) { -		printk(KERN_ERR "vme_lm_get not supported\n"); -		return -EINVAL; -	} - -	return bridge->lm_get(lm, lm_base, aspace, cycle); -} -EXPORT_SYMBOL(vme_lm_get); - -int vme_lm_attach(struct vme_resource *resource, int monitor, -	void (*callback)(int)) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_lm_resource *lm; - -	if (resource->type != VME_LM) { -		printk(KERN_ERR "Not a Location Monitor resource\n"); -		return -EINVAL; -	} - -	lm = list_entry(resource->entry, struct vme_lm_resource, list); - -	if (bridge->lm_attach == NULL) { -		printk(KERN_ERR "vme_lm_attach not supported\n"); -		return -EINVAL; -	} - -	return bridge->lm_attach(lm, monitor, callback); -} -EXPORT_SYMBOL(vme_lm_attach); - -int vme_lm_detach(struct vme_resource *resource, int monitor) -{ -	struct vme_bridge *bridge = find_bridge(resource); -	struct vme_lm_resource *lm; - -	if (resource->type != VME_LM) { -		printk(KERN_ERR "Not a Location Monitor resource\n"); -		return -EINVAL; -	} - -	lm = list_entry(resource->entry, struct vme_lm_resource, list); - -	if (bridge->lm_detach == NULL) { -		printk(KERN_ERR "vme_lm_detach not supported\n"); -		return -EINVAL; -	} - -	return bridge->lm_detach(lm, monitor); -} -EXPORT_SYMBOL(vme_lm_detach); - -void vme_lm_free(struct vme_resource *resource) -{ -	struct vme_lm_resource *lm; - -	if (resource->type != VME_LM) { -		printk(KERN_ERR "Not a Location Monitor resource\n"); -		return; -	} - -	lm = list_entry(resource->entry, struct vme_lm_resource, list); - -	mutex_lock(&(lm->mtx)); - -	/* XXX -	 * Check to see that there aren't any callbacks still attached, if -	 * there are we should probably be detaching them! -	 */ - -	lm->locked = 0; - -	mutex_unlock(&(lm->mtx)); - -	kfree(resource); -} -EXPORT_SYMBOL(vme_lm_free); - -int vme_slot_get(struct device *bus) -{ -	struct vme_bridge *bridge; - -	bridge = dev_to_bridge(bus); -	if (bridge == NULL) { -		printk(KERN_ERR "Can't find VME bus\n"); -		return -EINVAL; -	} - -	if (bridge->slot_get == NULL) { -		printk(KERN_WARNING "vme_slot_get not supported\n"); -		return -EINVAL; -	} - -	return bridge->slot_get(bridge); -} -EXPORT_SYMBOL(vme_slot_get); - - -/* - Bridge Registration --------------------------------------------------- */ - -static int vme_alloc_bus_num(void) -{ -	int i; - -	mutex_lock(&vme_bus_num_mtx); -	for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { -		if (((vme_bus_numbers >> i) & 0x1) == 0) { -			vme_bus_numbers |= (0x1 << i); -			break; -		} -	} -	mutex_unlock(&vme_bus_num_mtx); - -	return i; -} - -static void vme_free_bus_num(int bus) -{ -	mutex_lock(&vme_bus_num_mtx); -	vme_bus_numbers |= ~(0x1 << bus); -	mutex_unlock(&vme_bus_num_mtx); -} - -int vme_register_bridge(struct vme_bridge *bridge) -{ -	struct device *dev; -	int retval; -	int i; - -	bridge->num = vme_alloc_bus_num(); - -	/* This creates 32 vme "slot" devices. This equates to a slot for each -	 * ID available in a system conforming to the ANSI/VITA 1-1994 -	 * specification. -	 */ -	for (i = 0; i < VME_SLOTS_MAX; i++) { -		dev = &(bridge->dev[i]); -		memset(dev, 0, sizeof(struct device)); - -		dev->parent = bridge->parent; -		dev->bus = &(vme_bus_type); -		/* -		 * We save a pointer to the bridge in platform_data so that we -		 * can get to it later. We keep driver_data for use by the -		 * driver that binds against the slot -		 */ -		dev->platform_data = bridge; -		dev_set_name(dev, "vme-%x.%x", bridge->num, i + 1); - -		retval = device_register(dev); -		if (retval) -			goto err_reg; -	} - -	return retval; - -	i = VME_SLOTS_MAX; -err_reg: -	while (i > -1) { -		dev = &(bridge->dev[i]); -		device_unregister(dev); -	} -	vme_free_bus_num(bridge->num); -	return retval; -} -EXPORT_SYMBOL(vme_register_bridge); - -void vme_unregister_bridge(struct vme_bridge *bridge) -{ -	int i; -	struct device *dev; - - -	for (i = 0; i < VME_SLOTS_MAX; i++) { -		dev = &(bridge->dev[i]); -		device_unregister(dev); -	} -	vme_free_bus_num(bridge->num); -} -EXPORT_SYMBOL(vme_unregister_bridge); - - -/* - Driver Registration --------------------------------------------------- */ - -int vme_register_driver(struct vme_driver *drv) -{ -	drv->driver.name = drv->name; -	drv->driver.bus = &vme_bus_type; - -	return driver_register(&drv->driver); -} -EXPORT_SYMBOL(vme_register_driver); - -void vme_unregister_driver(struct vme_driver *drv) -{ -	driver_unregister(&drv->driver); -} -EXPORT_SYMBOL(vme_unregister_driver); - -/* - Bus Registration ------------------------------------------------------ */ - -static int vme_calc_slot(struct device *dev) -{ -	struct vme_bridge *bridge; -	int num; - -	bridge = dev_to_bridge(dev); - -	/* Determine slot number */ -	num = 0; -	while (num < VME_SLOTS_MAX) { -		if (&(bridge->dev[num]) == dev) -			break; - -		num++; -	} -	if (num == VME_SLOTS_MAX) { -		dev_err(dev, "Failed to identify slot\n"); -		num = 0; -		goto err_dev; -	} -	num++; - -err_dev: -	return num; -} - -static struct vme_driver *dev_to_vme_driver(struct device *dev) -{ -	if (dev->driver == NULL) -		printk(KERN_ERR "Bugger dev->driver is NULL\n"); - -	return container_of(dev->driver, struct vme_driver, driver); -} - -static int vme_bus_match(struct device *dev, struct device_driver *drv) -{ -	struct vme_bridge *bridge; -	struct vme_driver *driver; -	int i, num; - -	bridge = dev_to_bridge(dev); -	driver = container_of(drv, struct vme_driver, driver); - -	num = vme_calc_slot(dev); -	if (!num) -		goto err_dev; - -	if (driver->bind_table == NULL) { -		dev_err(dev, "Bind table NULL\n"); -		goto err_table; -	} - -	i = 0; -	while ((driver->bind_table[i].bus != 0) || -		(driver->bind_table[i].slot != 0)) { - -		if (bridge->num == driver->bind_table[i].bus) { -			if (num == driver->bind_table[i].slot) -				return 1; - -			if (driver->bind_table[i].slot == VME_SLOT_ALL) -				return 1; - -			if ((driver->bind_table[i].slot == VME_SLOT_CURRENT) && -				(num == vme_slot_get(dev))) -				return 1; -		} -		i++; -	} - -err_dev: -err_table: -	return 0; -} - -static int vme_bus_probe(struct device *dev) -{ -	struct vme_bridge *bridge; -	struct vme_driver *driver; -	int retval = -ENODEV; - -	driver = dev_to_vme_driver(dev); -	bridge = dev_to_bridge(dev); - -	if (driver->probe != NULL) -		retval = driver->probe(dev, bridge->num, vme_calc_slot(dev)); - -	return retval; -} - -static int vme_bus_remove(struct device *dev) -{ -	struct vme_bridge *bridge; -	struct vme_driver *driver; -	int retval = -ENODEV; - -	driver = dev_to_vme_driver(dev); -	bridge = dev_to_bridge(dev); - -	if (driver->remove != NULL) -		retval = driver->remove(dev, bridge->num, vme_calc_slot(dev)); - -	return retval; -} - -struct bus_type vme_bus_type = { -	.name = "vme", -	.match = vme_bus_match, -	.probe = vme_bus_probe, -	.remove = vme_bus_remove, -}; -EXPORT_SYMBOL(vme_bus_type); - -static int __init vme_init(void) -{ -	return bus_register(&vme_bus_type); -} - -static void __exit vme_exit(void) -{ -	bus_unregister(&vme_bus_type); -} - -MODULE_DESCRIPTION("VME bridge driver framework"); -MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); -MODULE_LICENSE("GPL"); - -module_init(vme_init); -module_exit(vme_exit); diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h deleted file mode 100644 index 48768ca97e1..00000000000 --- a/drivers/staging/vme/vme.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef _VME_H_ -#define _VME_H_ - -/* Resource Type */ -enum vme_resource_type { -	VME_MASTER, -	VME_SLAVE, -	VME_DMA, -	VME_LM -}; - -/* VME Address Spaces */ -typedef u32 vme_address_t; -#define VME_A16		0x1 -#define VME_A24		0x2 -#define	VME_A32		0x4 -#define VME_A64		0x8 -#define VME_CRCSR	0x10 -#define VME_USER1	0x20 -#define VME_USER2	0x40 -#define VME_USER3	0x80 -#define VME_USER4	0x100 - -#define VME_A16_MAX	0x10000ULL -#define VME_A24_MAX	0x1000000ULL -#define VME_A32_MAX	0x100000000ULL -#define VME_A64_MAX	0x10000000000000000ULL -#define VME_CRCSR_MAX	0x1000000ULL - - -/* VME Cycle Types */ -typedef u32 vme_cycle_t; -#define VME_SCT		0x1 -#define VME_BLT		0x2 -#define VME_MBLT	0x4 -#define VME_2eVME	0x8 -#define VME_2eSST	0x10 -#define VME_2eSSTB	0x20 - -#define VME_2eSST160	0x100 -#define VME_2eSST267	0x200 -#define VME_2eSST320	0x400 - -#define	VME_SUPER	0x1000 -#define	VME_USER	0x2000 -#define	VME_PROG	0x4000 -#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) -#define VME_DMA_MEM_TO_MEM		(1<<3) -#define VME_DMA_PATTERN_TO_VME		(1<<4) -#define VME_DMA_PATTERN_TO_MEM		(1<<5) - -struct vme_dma_attr { -	vme_dma_t type; -	void *private; -}; - -struct vme_resource { -	enum vme_resource_type type; -	struct list_head *entry; -}; - -extern struct bus_type vme_bus_type; - -#define VME_SLOT_CURRENT	-1 -#define VME_SLOT_ALL		-2 - -struct vme_device_id { -	int bus; -	int slot; -}; - -struct vme_driver { -	struct list_head node; -	char *name; -	const struct vme_device_id *bind_table; -	int (*probe)  (struct device *, int, int); -	int (*remove) (struct device *, int, int); -	void (*shutdown) (void); -	struct device_driver    driver; -}; - -void *vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *); -void vme_free_consistent(struct vme_resource *, size_t,  void *, -	dma_addr_t); - -size_t vme_get_size(struct vme_resource *); - -struct vme_resource *vme_slave_request(struct device *, vme_address_t, -	vme_cycle_t); -int vme_slave_set(struct vme_resource *, int, unsigned long long, -	unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t); -int vme_slave_get(struct vme_resource *, int *, unsigned long long *, -	unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *); -void vme_slave_free(struct vme_resource *); - -struct vme_resource *vme_master_request(struct device *, vme_address_t, -	vme_cycle_t, vme_width_t); -int vme_master_set(struct vme_resource *, int, unsigned long long, -	unsigned long long, vme_address_t, vme_cycle_t, vme_width_t); -int vme_master_get(struct vme_resource *, int *, unsigned long long *, -	unsigned long long *, vme_address_t *, vme_cycle_t *, vme_width_t *); -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 device *, vme_dma_route_t); -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_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); -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); -int vme_dma_list_exec(struct vme_dma_list *); -int vme_dma_list_free(struct vme_dma_list *); -int vme_dma_free(struct vme_resource *); - -int vme_irq_request(struct device *, int, int, -	void (*callback)(int, int, void *), void *); -void vme_irq_free(struct device *, int, int); -int vme_irq_generate(struct device *, int, int); - -struct vme_resource * vme_lm_request(struct device *); -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_attach(struct vme_resource *, int, void (*callback)(int)); -int vme_lm_detach(struct vme_resource *, int); -void vme_lm_free(struct vme_resource *); - -int vme_slot_get(struct device *); - -int vme_register_driver(struct vme_driver *); -void vme_unregister_driver(struct vme_driver *); - - -#endif /* _VME_H_ */ - diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt deleted file mode 100644 index a910a0c4388..00000000000 --- a/drivers/staging/vme/vme_api.txt +++ /dev/null @@ -1,383 +0,0 @@ -			VME Device Driver API -			===================== - -Driver registration -=================== - -As with other subsystems within the Linux kernel, VME device drivers register -with the VME subsystem, typically called from the devices init routine.  This is -achieved via a call to the follwoing function: - -	int vme_register_driver (struct vme_driver *driver); - -If driver registration is successful this function returns zero, if an error -occurred a negative error code will be returned. - -A pointer to a structure of type 'vme_driver' must be provided to the -registration function. The structure is as follows: - -	struct vme_driver { -		struct list_head node; -		char *name; -		const struct vme_device_id *bind_table; -		int (*probe)  (struct device *, int, int); -		int (*remove) (struct device *, int, int); -		void (*shutdown) (void); -		struct device_driver    driver; -	}; - -At the minimum, the '.name', '.probe' and '.bind_table' elements of this -structure should be correctly set. The '.name' element is a pointer to a string -holding the device driver's name. The '.probe' element should contain a pointer -to the probe routine. - -The arguments of the probe routine are as follows: - -	probe(struct device *dev, int bus, int slot); - -The '.bind_table' is a pointer to an array of type 'vme_device_id': - -	struct vme_device_id { -		int bus; -		int slot; -	}; - -Each structure in this array should provide a bus and slot number where the core -should probe, using the driver's probe routine, for a device on the specified -VME bus. - -The VME subsystem supports a single VME driver per 'slot'. There are considered -to be 32 slots per bus, one for each slot-ID as defined in the ANSI/VITA 1-1994 -specification and are analogious to the physical slots on the VME backplane. - -A function is also provided to unregister the driver from the VME core and is -usually called from the device driver's exit routine: - -	void vme_unregister_driver (struct vme_driver *driver); - - -Resource management -=================== - -Once a driver has registered with the VME core the provided probe routine will -be called for each of the bus/slot combination that becomes valid as VME buses -are themselves registered.  The probe routine is passed a pointer to the devices -device structure. This pointer should be saved, it will be required for -requesting VME resources. - -The driver can request ownership of one or more master windows, slave windows -and/or dma channels. Rather than allowing the device driver to request a -specific window or DMA channel (which may be used by a different driver) this -driver allows a resource to be assigned based on the required attributes of the -driver in question: - -	struct vme_resource * vme_master_request(struct device *dev, -		vme_address_t aspace, vme_cycle_t cycle, vme_width_t width); - -	struct vme_resource * vme_slave_request(struct device *dev, -		vme_address_t aspace, vme_cycle_t cycle); - -	struct vme_resource *vme_dma_request(struct device *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. - -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 -during resource allocation: - -	void vme_master_free(struct vme_resource *res); - -	void vme_slave_free(struct vme_resource *res); - -	void vme_dma_free(struct vme_resource *res); - - -Master windows -============== - -Master windows provide access from the local processor[s] out onto the VME bus. -The number of windows available and the available access modes is dependant on -the underlying chipset. A window must be configured before it can be used. - - -Master window configuration ---------------------------- - -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); - -	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); - -The address spaces, transfer widths and cycle types are the same as described -under resource management, however some of the options are mutually exclusive. -For example, only one address space may be specified. - -These functions return 0 on success or an error code should the call fail. - - -Master window access --------------------- - -The following functions can be used to read from and write to configured master -windows. These functions return the number of bytes copied: - -	ssize_t vme_master_read(struct vme_resource *res, void *buf, -		size_t count, loff_t offset); - -	ssize_t vme_master_write(struct vme_resource *res, void *buf, -		size_t count, loff_t offset); - -In addition to simple reads and writes, a function is provided to do a -read-modify-write transaction. This function returns the original value of the -VME bus location : - -	unsigned int vme_master_rmw (struct vme_resource *res, -		unsigned int mask, unsigned int compare, unsigned int swap, -		loff_t offset); - -This functions by reading the offset, applying the mask. If the bits selected in -the mask match with the values of the corresponding bits in the compare field, -the value of swap is written the specified offset. - - -Slave windows -============= - -Slave windows provide devices on the VME bus access into mapped portions of the -local memory. The number of windows available and the access modes that can be -used is dependant on the underlying chipset. A window must be configured before -it can be used. - - -Slave window configuration --------------------------- - -Once a slave window has been assigned the following functions can be used to -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); - -	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); - -The address spaces, transfer widths and cycle types are the same as described -under resource management, however some of the options are mutually exclusive. -For example, only one address space may be specified. - -These functions return 0 on success or an error code should the call fail. - - -Slave window buffer allocation ------------------------------- - -Functions are provided to allow the user to allocate and free a contiguous -buffers which will be accessible by the VME bridge. These functions do not have -to be used, other methods can be used to allocate a buffer, though care must be -taken to ensure that they are contiguous and accessible by the VME bridge: - -	void * vme_alloc_consistent(struct vme_resource *res, size_t size, -		dma_addr_t *mem); - -	void vme_free_consistent(struct vme_resource *res, size_t size, -		void *virt,	dma_addr_t mem); - - -Slave window access -------------------- - -Slave windows map local memory onto the VME bus, the standard methods for -accessing memory should be used. - - -DMA channels -============ - -The VME DMA transfer provides the ability to run link-list DMA transfers. The -API introduces the concept of DMA lists. Each DMA list is a link-list which can -be passed to a DMA controller. Multiple lists can be created, extended, -executed, reused and destroyed. - - -List Management ---------------- - -The following functions are provided to create and destroy DMA lists. Execution -of a list will not automatically destroy the list, thus enabling a list to be -reused for repetitive tasks: - -	struct vme_dma_list *vme_new_dma_list(struct vme_resource *res); - -	int vme_dma_list_free(struct vme_dma_list *list); - - -List Population ---------------- - -An item can be added to a list using the following function ( the source and -destination attributes need to be created before calling this function, this is -covered under "Transfer Attributes"): - -	int vme_dma_list_add(struct vme_dma_list *list, -		struct vme_dma_attr *src, struct vme_dma_attr *dest, -		size_t count); - -NOTE:	The detailed attributes of the transfers source and destination -	are not checked until an entry is added to a DMA list, the request -	for a DMA channel purely checks the directions in which the -	controller is expected to transfer data. As a result it is -	possible for this call to return an error, for example if the -	source or destination is in an unsupported VME address space. - -Transfer Attributes -------------------- - -The attributes for the source and destination are handled separately from adding -an item to a list. This is due to the diverse attributes required for each type -of source and destination. There are functions to create attributes for PCI, VME -and pattern sources and destinations (where appropriate): - -Pattern source: - -	struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, -		vme_pattern_t type); - -PCI source or destination: - -	struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t mem); - -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); - -The following function should be used to free an attribute: - -	void vme_dma_free_attribute(struct vme_dma_attr *attr); - - -List Execution --------------- - -The following function queues a list for execution. The function will return -once the list has been executed: - -	int vme_dma_list_exec(struct vme_dma_list *list); - - -Interrupts -========== - -The VME API provides functions to attach and detach callbacks to specific VME -level and status ID combinations and for the generation of VME interrupts with -specific VME level and status IDs. - - -Attaching Interrupt Handlers ----------------------------- - -The following functions can be used to attach and free a specific VME level and -status ID combination. Any given combination can only be assigned a single -callback function. A void pointer parameter is provided, the value of which is -passed to the callback function, the use of this pointer is user undefined: - -	int vme_irq_request(struct device *dev, int level, int statid, -		void (*callback)(int, int, void *), void *priv); - -	void vme_irq_free(struct device *dev, int level, int statid); - -The callback parameters are as follows. Care must be taken in writing a callback -function, callback functions run in interrupt context: - -	void callback(int level, int statid, void *priv); - - -Interrupt Generation --------------------- - -The following function can be used to generate a VME interrupt at a given VME -level and VME status ID: - -	int vme_irq_generate(struct device *dev, int level, int statid); - - -Location monitors -================= - -The VME API provides the following functionality to configure the location -monitor. - - -Location Monitor Management ---------------------------- - -The following functions are provided to request the use of a block of location -monitors and to free them after they are no longer required: - -	struct vme_resource * vme_lm_request(struct device *dev); - -	void vme_lm_free(struct vme_resource * res); - -Each block may provide a number of location monitors, monitoring adjacent -locations. The following function can be used to determine how many locations -are provided: - -	int vme_lm_count(struct vme_resource * res); - - -Location Monitor Configuration ------------------------------- - -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); - -	int vme_lm_get(struct vme_resource *res, unsigned long long *base, -		vme_address_t *aspace, vme_cycle_t *cycle); - - -Location Monitor Use --------------------- - -The following functions allow a callback to be attached and detached from each -location monitor location. Each location monitor can monitor a number of -adjacent locations: - -	int vme_lm_attach(struct vme_resource *res, int num, -		void (*callback)(int)); - -	int vme_lm_detach(struct vme_resource *res, int num); - -The callback function is declared as follows. - -	void callback(int num); - - -Slot Detection -============== - -This function returns the slot ID of the provided bridge. - -	int vme_slot_get(struct device *dev); diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h deleted file mode 100644 index b653ec02e1f..00000000000 --- a/drivers/staging/vme/vme_bridge.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef _VME_BRIDGE_H_ -#define _VME_BRIDGE_H_ - -#define VME_CRCSR_BUF_SIZE (508*1024) -#define VME_SLOTS_MAX 32 -/* - * Resource structures - */ -struct vme_master_resource { -	struct list_head list; -	struct vme_bridge *parent; -	/* -	 * We are likely to need to access the VME bus in interrupt context, so -	 * protect master routines with a spinlock rather than a mutex. -	 */ -	spinlock_t lock; -	int locked; -	int number; -	vme_address_t address_attr; -	vme_cycle_t cycle_attr; -	vme_width_t width_attr; -	struct resource bus_resource; -	void *kern_base; -}; - -struct vme_slave_resource { -	struct list_head list; -	struct vme_bridge *parent; -	struct mutex mtx; -	int locked; -	int number; -	vme_address_t address_attr; -	vme_cycle_t cycle_attr; -}; - -struct vme_dma_pattern { -	u32 pattern; -	vme_pattern_t type; -}; - -struct vme_dma_pci { -	dma_addr_t address; -}; - -struct vme_dma_vme { -	unsigned long long address; -	vme_address_t aspace; -	vme_cycle_t cycle; -	vme_width_t dwidth; -}; - -struct vme_dma_list { -	struct list_head list; -	struct vme_dma_resource *parent; -	struct list_head entries; -	struct mutex mtx; -}; - -struct vme_dma_resource { -	struct list_head list; -	struct vme_bridge *parent; -	struct mutex mtx; -	int locked; -	int number; -	struct list_head pending; -	struct list_head running; -	vme_dma_route_t route_attr; -}; - -struct vme_lm_resource { -	struct list_head list; -	struct vme_bridge *parent; -	struct mutex mtx; -	int locked; -	int number; -	int monitors; -}; - -struct vme_bus_error { -	struct list_head list; -	unsigned long long address; -	u32 attributes; -}; - -struct vme_callback { -	void (*func)(int, int, void*); -	void *priv_data; -}; - -struct vme_irq { -	int count; -	struct vme_callback callback[255]; -}; - -/* Allow 16 characters for name (including null character) */ -#define VMENAMSIZ 16 - -/* This structure stores all the information about one bridge - * The structure should be dynamically allocated by the driver and one instance - * of the structure should be present for each VME chip present in the system. - * - * Currently we assume that all chips are PCI-based - */ -struct vme_bridge { -	char name[VMENAMSIZ]; -	int num; -	struct list_head master_resources; -	struct list_head slave_resources; -	struct list_head dma_resources; -	struct list_head lm_resources; - -	struct list_head vme_errors;	/* List for errors generated on VME */ - -	/* Bridge Info - XXX Move to private structure? */ -	struct device *parent;	/* Generic device struct (pdev->dev for PCI) */ -	void *driver_priv;	/* Private pointer for the bridge driver */ - -	struct device dev[VME_SLOTS_MAX];	/* Device registered with -						 * device model on VME bus -						 */ - -	/* Interrupt callbacks */ -	struct vme_irq irq[7]; -	/* Locking for VME irq callback configuration */ -	struct mutex irq_mtx; - -	/* 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 *); -	int (*slave_set) (struct vme_slave_resource *, int, unsigned long long, -		unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t); - -	/* 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 *); -	int (*master_set) (struct vme_master_resource *, int, -		unsigned long long, unsigned long long,  vme_address_t, -		vme_cycle_t, vme_width_t); -	ssize_t (*master_read) (struct vme_master_resource *, void *, size_t, -		loff_t); -	ssize_t (*master_write) (struct vme_master_resource *, void *, size_t, -		loff_t); -	unsigned int (*master_rmw) (struct vme_master_resource *, unsigned int, -		unsigned int, unsigned int, loff_t); - -	/* DMA Functions */ -	int (*dma_list_add) (struct vme_dma_list *, struct vme_dma_attr *, -		struct vme_dma_attr *, size_t); -	int (*dma_list_exec) (struct vme_dma_list *); -	int (*dma_list_empty) (struct vme_dma_list *); - -	/* Interrupt Functions */ -	void (*irq_set) (struct vme_bridge *, int, int, int); -	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_attach) (struct vme_lm_resource *, int, void (*callback)(int)); -	int (*lm_detach) (struct vme_lm_resource *, int); - -	/* CR/CSR space functions */ -	int (*slot_get) (struct vme_bridge *); -}; - -void vme_irq_handler(struct vme_bridge *, int, int); - -int vme_register_bridge(struct vme_bridge *); -void vme_unregister_bridge(struct vme_bridge *); - -#endif /* _VME_BRIDGE_H_ */  | 
