vme_ca91cx42.c revision 794a8946ba2339af09dd1f39c8462c3611bebf77
160479690af6d559d4202bed139db90323386bd2bMartyn Welch/* 260479690af6d559d4202bed139db90323386bd2bMartyn Welch * Support for the Tundra Universe I/II VME-PCI Bridge Chips 360479690af6d559d4202bed139db90323386bd2bMartyn Welch * 466bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com> 566bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 660479690af6d559d4202bed139db90323386bd2bMartyn Welch * 760479690af6d559d4202bed139db90323386bd2bMartyn Welch * Based on work by Tom Armistead and Ajit Prem 860479690af6d559d4202bed139db90323386bd2bMartyn Welch * Copyright 2004 Motorola Inc. 960479690af6d559d4202bed139db90323386bd2bMartyn Welch * 1060479690af6d559d4202bed139db90323386bd2bMartyn Welch * Derived from ca91c042.c by Michael Wyrick 1160479690af6d559d4202bed139db90323386bd2bMartyn Welch * 1260479690af6d559d4202bed139db90323386bd2bMartyn Welch * This program is free software; you can redistribute it and/or modify it 1360479690af6d559d4202bed139db90323386bd2bMartyn Welch * under the terms of the GNU General Public License as published by the 1460479690af6d559d4202bed139db90323386bd2bMartyn Welch * Free Software Foundation; either version 2 of the License, or (at your 1560479690af6d559d4202bed139db90323386bd2bMartyn Welch * option) any later version. 1660479690af6d559d4202bed139db90323386bd2bMartyn Welch */ 1760479690af6d559d4202bed139db90323386bd2bMartyn Welch 1860479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/module.h> 1960479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/mm.h> 2060479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/types.h> 2160479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/errno.h> 2260479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/pci.h> 2360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/dma-mapping.h> 2460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/poll.h> 2560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/interrupt.h> 2660479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/spinlock.h> 276af783c8ba3418a8ffc50f1266d9b1e35a3322dbGreg Kroah-Hartman#include <linux/sched.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 297946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/time.h> 307946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/io.h> 317946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/uaccess.h> 3260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme.h" 3460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme_bridge.h" 3560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "vme_ca91cx42.h" 3660479690af6d559d4202bed139db90323386bd2bMartyn Welch 373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void); 383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); 393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_remove(struct pci_dev *); 403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void); 4160479690af6d559d4202bed139db90323386bd2bMartyn Welch 4212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch/* Module parameters */ 4312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchstatic int geoid; 4412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic char driver_name[] = "vme_ca91cx42"; 4660479690af6d559d4202bed139db90323386bd2bMartyn Welch 472cea0cf284048b03a06e4370709cd751ddb9354eNamhyung Kimstatic DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = { 483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, 493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch { }, 5060479690af6d559d4202bed139db90323386bd2bMartyn Welch}; 5160479690af6d559d4202bed139db90323386bd2bMartyn Welch 523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic struct pci_driver ca91cx42_driver = { 533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .name = driver_name, 543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .id_table = ca91cx42_ids, 553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .probe = ca91cx42_probe, 563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .remove = ca91cx42_remove, 5760479690af6d559d4202bed139db90323386bd2bMartyn Welch}; 5860479690af6d559d4202bed139db90323386bd2bMartyn Welch 5929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge) 6060479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 61886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->dma_queue); 6260479690af6d559d4202bed139db90323386bd2bMartyn Welch 633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_DMA; 643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 6560479690af6d559d4202bed139db90323386bd2bMartyn Welch 6629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat) 673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int i; 693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 serviced = 0; 7060479690af6d559d4202bed139db90323386bd2bMartyn Welch 713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < 4; i++) { 723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_LM[i]) { 733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* We only enable interrupts if the callback is set */ 7429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->lm_callback[i](i); 753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch serviced |= CA91CX42_LINT_LM[i]; 7660479690af6d559d4202bed139db90323386bd2bMartyn Welch } 7760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 7860479690af6d559d4202bed139db90323386bd2bMartyn Welch 793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return serviced; 803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8160479690af6d559d4202bed139db90323386bd2bMartyn Welch 823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX This needs to be split into 4 queues */ 8329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask) 843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 85886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->mbox_queue); 8660479690af6d559d4202bed139db90323386bd2bMartyn Welch 873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_MBOX; 883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8960479690af6d559d4202bed139db90323386bd2bMartyn Welch 9029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge) 913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 92886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->iack_queue); 9360479690af6d559d4202bed139db90323386bd2bMartyn Welch 943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_SW_IACK; 9560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 9660479690af6d559d4202bed139db90323386bd2bMartyn Welch 9748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 ca91cx42_VERR_irqhandler(struct vme_bridge *ca91cx42_bridge) 9860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 9960479690af6d559d4202bed139db90323386bd2bMartyn Welch int val; 10048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct ca91cx42_driver *bridge; 10148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 10248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 10360479690af6d559d4202bed139db90323386bd2bMartyn Welch 10429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch val = ioread32(bridge->base + DGCS); 10560479690af6d559d4202bed139db90323386bd2bMartyn Welch 10660479690af6d559d4202bed139db90323386bd2bMartyn Welch if (!(val & 0x00000800)) { 10748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "ca91cx42_VERR_irqhandler DMA " 10848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Read Error DGCS=%08X\n", val); 10960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 1103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_VERR; 11260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 11360479690af6d559d4202bed139db90323386bd2bMartyn Welch 11448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 ca91cx42_LERR_irqhandler(struct vme_bridge *ca91cx42_bridge) 11560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 11660479690af6d559d4202bed139db90323386bd2bMartyn Welch int val; 11748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct ca91cx42_driver *bridge; 11860479690af6d559d4202bed139db90323386bd2bMartyn Welch 11948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 12060479690af6d559d4202bed139db90323386bd2bMartyn Welch 12148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch val = ioread32(bridge->base + DGCS); 12260479690af6d559d4202bed139db90323386bd2bMartyn Welch 12348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch if (!(val & 0x00000800)) 12448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "ca91cx42_LERR_irqhandler DMA " 12548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Read Error DGCS=%08X\n", val); 12660479690af6d559d4202bed139db90323386bd2bMartyn Welch 1273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_LERR; 12860479690af6d559d4202bed139db90323386bd2bMartyn Welch} 12960479690af6d559d4202bed139db90323386bd2bMartyn Welch 1303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 13129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge, 13229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int stat) 13360479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 1343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int vec, i, serviced = 0; 13529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 13629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 13729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 13829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 13960479690af6d559d4202bed139db90323386bd2bMartyn Welch 14060479690af6d559d4202bed139db90323386bd2bMartyn Welch for (i = 7; i > 0; i--) { 1413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (1 << i)) { 14229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vec = ioread32(bridge->base + 1433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_V_STATID[i]) & 0xff; 1443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 145c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch vme_irq_handler(ca91cx42_bridge, i, vec); 1463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch serviced |= (1 << i); 14860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 14960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 1503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return serviced; 15260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 15360479690af6d559d4202bed139db90323386bd2bMartyn Welch 15429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic irqreturn_t ca91cx42_irqhandler(int irq, void *ptr) 15560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 1563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 stat, enable, serviced = 0; 15729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 15829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 15960479690af6d559d4202bed139db90323386bd2bMartyn Welch 16029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = ptr; 16160479690af6d559d4202bed139db90323386bd2bMartyn Welch 16229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 16329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch enable = ioread32(bridge->base + LINT_EN); 16529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch stat = ioread32(bridge->base + LINT_STAT); 16660479690af6d559d4202bed139db90323386bd2bMartyn Welch 1673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only look at unmasked interrupts */ 1683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch stat &= enable; 1693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (unlikely(!stat)) 1713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return IRQ_NONE; 1723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_DMA) 17429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_DMA_irqhandler(bridge); 1753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 1763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_LM3)) 17729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_LM_irqhandler(bridge, stat); 1783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_MBOX) 17929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_MB_irqhandler(bridge, stat); 1803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_SW_IACK) 18129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_IACK_irqhandler(bridge); 1823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_VERR) 18348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= ca91cx42_VERR_irqhandler(ca91cx42_bridge); 1843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_LERR) 18548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= ca91cx42_LERR_irqhandler(ca91cx42_bridge); 1863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | 1873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | 1883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | 1893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ7)) 19029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat); 1913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear serviced interrupts */ 19329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(stat, bridge->base + LINT_STAT); 19460479690af6d559d4202bed139db90323386bd2bMartyn Welch 19560479690af6d559d4202bed139db90323386bd2bMartyn Welch return IRQ_HANDLED; 19660479690af6d559d4202bed139db90323386bd2bMartyn Welch} 19760479690af6d559d4202bed139db90323386bd2bMartyn Welch 19829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) 19960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int result, tmp; 2013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 20229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 20329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 20429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 20560479690af6d559d4202bed139db90323386bd2bMartyn Welch 2063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need pdev */ 20729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 20860479690af6d559d4202bed139db90323386bd2bMartyn Welch 2093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialise list for VME bus errors */ 210886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->vme_errors); 21160479690af6d559d4202bed139db90323386bd2bMartyn Welch 212886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_bridge->irq_mtx); 213c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable interrupts from PCI to VME */ 2153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + VINT_EN); 21660479690af6d559d4202bed139db90323386bd2bMartyn Welch 2173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable PCI interrupts */ 2183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_EN); 2193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear Any Pending PCI Interrupts */ 2203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); 22160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, 22329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch driver_name, ca91cx42_bridge); 2243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (result) { 2253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", 2263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev->irq); 2273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return result; 22860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 22960479690af6d559d4202bed139db90323386bd2bMartyn Welch 2303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Ensure all interrupts are mapped to PCI Interrupt 0 */ 2313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP0); 2323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP1); 2333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP2); 2343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable DMA, mailbox & LM Interrupts */ 2363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | 2373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | 2383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; 2393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 24160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 24360479690af6d559d4202bed139db90323386bd2bMartyn Welch} 24460479690af6d559d4202bed139db90323386bd2bMartyn Welch 24529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, 24629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 24760479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable interrupts from PCI to VME */ 24929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VINT_EN); 25060479690af6d559d4202bed139db90323386bd2bMartyn Welch 2513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable PCI interrupts */ 25229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 2533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear Any Pending PCI Interrupts */ 25429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); 25560479690af6d559d4202bed139db90323386bd2bMartyn Welch 2563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch free_irq(pdev->irq, pdev); 2573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 25860479690af6d559d4202bed139db90323386bd2bMartyn Welch 2593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 2603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Set up an VME interrupt 2613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 262efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, 263efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota int state, int sync) 264c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 266c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch struct pci_dev *pdev; 2673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 26829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 26929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 27029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 27160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable IRQ level */ 27329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + LINT_EN); 2743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 275c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (state == 0) 2763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_LINT_VIRQ[level]; 277c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch else 278c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tmp |= CA91CX42_LINT_VIRQ[level]; 27960479690af6d559d4202bed139db90323386bd2bMartyn Welch 28029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 281c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 282c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if ((state == 0) && (sync != 0)) { 2833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, 2843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev); 2853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch synchronize_irq(pdev->irq); 28760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 28860479690af6d559d4202bed139db90323386bd2bMartyn Welch} 28960479690af6d559d4202bed139db90323386bd2bMartyn Welch 290efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, 29129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int statid) 29260479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 29429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 29529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 29629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 29760479690af6d559d4202bed139db90323386bd2bMartyn Welch 2983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Universe can only generate even vectors */ 2993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (statid & 1) 3003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 30160479690af6d559d4202bed139db90323386bd2bMartyn Welch 302886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_int); 30360479690af6d559d4202bed139db90323386bd2bMartyn Welch 30429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 30560479690af6d559d4202bed139db90323386bd2bMartyn Welch 3063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Set Status/ID */ 30729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(statid << 24, bridge->base + STATID); 3083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Assert VMEbus IRQ */ 3103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp | (1 << (level + 24)); 31129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 31260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Wait for IACK */ 31429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch wait_event_interruptible(bridge->iack_queue, 0); 3153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Return interrupt to low state */ 31729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 3183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp & ~(1 << (level + 24)); 31929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 3203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 321886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_int); 3223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 32460479690af6d559d4202bed139db90323386bd2bMartyn Welch} 32560479690af6d559d4202bed139db90323386bd2bMartyn Welch 326efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, 3273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 3283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) 32960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 33021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, addr = 0, granularity; 3313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 3323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int vme_bound, pci_offset; 33348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 33429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 33529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 33648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 33748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 33848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 33960479690af6d559d4202bed139db90323386bd2bMartyn Welch 3403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 34160479690af6d559d4202bed139db90323386bd2bMartyn Welch 3423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 3433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A16: 3443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A16; 3453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A24: 3473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A24; 3483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A32: 3503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A32; 3513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER1: 3533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER1; 3543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER2: 3563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER2; 3573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 3593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 3603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 3613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 3623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 36348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 3643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 36660479690af6d559d4202bed139db90323386bd2bMartyn Welch } 36760479690af6d559d4202bed139db90323386bd2bMartyn Welch 3683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 3693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 3703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * accordingly 3713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 37221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch vme_bound = vme_base + size; 3733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_offset = pci_base - vme_base; 3743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 3763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 3773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 3783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 3793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_base & (granularity - 1)) { 38148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME base " 38248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 3853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_bound & (granularity - 1)) { 38648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME bound " 38748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 3903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (pci_offset & (granularity - 1)) { 39148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " 39248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 39460479690af6d559d4202bed139db90323386bd2bMartyn Welch } 39560479690af6d559d4202bed139db90323386bd2bMartyn Welch 3963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 39729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 3983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_EN; 39929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 40060479690af6d559d4202bed139db90323386bd2bMartyn Welch 4013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 40229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); 40329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); 40429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); 4053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 4073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; 4083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= addr; 4093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 4113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); 4123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 4133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; 4143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_USER) 4153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; 4163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 4173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; 4183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_DATA) 4193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; 4203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 42229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 4253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_EN; 4263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 42729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 43060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 43160479690af6d559d4202bed139db90323386bd2bMartyn Welch 432efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, 4333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 4343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) 43560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 4363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, granularity = 0, ctl = 0; 4373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_bound, pci_offset; 43829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 43929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 44029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 4413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 44360479690af6d559d4202bed139db90323386bd2bMartyn Welch 4443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 4453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 4463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 4473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 4483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Read Registers */ 45029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 4513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 45229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); 45329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); 45429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); 4553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *pci_base = (dma_addr_t)vme_base + pci_offset; 4573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *size = (unsigned long long)((vme_bound - *vme_base) + granularity); 4583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 4603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 4613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 4623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_EN) 4643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 4653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) 4673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 4683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) 4693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 4703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) 4713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 4723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) 4733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 4743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) 4753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 4763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) 4783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 4793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) 4803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 4813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_PGM) 4823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_PROG; 4833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_DATA) 4843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_DATA; 4853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 4873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 4883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 4903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Allocate and map PCI Resource 4913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 4923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_alloc_resource(struct vme_master_resource *image, 4933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long size) 4943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 4953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long existing_size; 4963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 4973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 49829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 49929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 50029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = image->parent; 5013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Find pci_dev container of dev */ 5033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge->parent == NULL) { 50448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); 5053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 5063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 5083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5098fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch existing_size = (unsigned long long)(image->bus_resource.end - 5108fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start); 5113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* If the existing size is OK, return */ 5133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size == (size - 1)) 5143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size != 0) { 5173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 519794a8946ba2339af09dd1f39c8462c3611bebf77Ilia Mirkin kfree(image->bus_resource.name); 520886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 521886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5248fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 5250aa3f139cd5123ffb8f397b91d777635e9761c24Julia Lawall image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); 5268fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 52748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate " 52848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "memory for resource name\n"); 5293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_name; 5313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 53260479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5348fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch sprintf((char *)image->bus_resource.name, "%s.%d", 5353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->name, image->number); 5363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5378fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start = 0; 5388fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.end = (unsigned long)size; 5398fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.flags = IORESOURCE_MEM; 5403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_bus_alloc_resource(pdev->bus, 542886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &image->bus_resource, size, size, PCIBIOS_MIN_MEM, 5433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 0, NULL, NULL); 5443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 54548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " 54648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "resource for window %d size 0x%lx start 0x%lx\n", 5473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->number, (unsigned long)size, 5488fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch (unsigned long)image->bus_resource.start); 5493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 55060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = ioremap_nocache( 5538fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start, size); 5543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (image->kern_base == NULL) { 55548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); 5563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 55860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 55960479690af6d559d4202bed139db90323386bd2bMartyn Welch 5603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 563886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 5643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 5658fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 566886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_name: 5683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 5693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 5724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Free and unmap PCI Resource 5734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 5743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_free_resource(struct vme_master_resource *image) 5753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 578886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 5798fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 580886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 584efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_master_set(struct vme_master_resource *image, int enabled, 5853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 5863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) 5873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 58921e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, granularity = 0; 5903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 5913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_bound, vme_offset, pci_base; 59248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 59329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 59429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 59548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 59648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 59748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 5983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 59921e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch i = image->number; 60021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 60121e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if ((i == 0) || (i == 4)) 60221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x1000; 60321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch else 60421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x10000; 60521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 6063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Verify input data */ 60721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (vme_base & (granularity - 1)) { 60848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 60948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 61321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (size & (granularity - 1)) { 61448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 61548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 620886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 6213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Let's allocate the resource here rather than further up the stack as 6243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * it avoids pushing loads of bus dependant stuff up the stack 6253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 6263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_alloc_resource(image, size); 6273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 628886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 62948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " 63048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "for resource name\n"); 6313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 6323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_res; 6333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6358fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch pci_base = (unsigned long long)image->bus_resource.start; 6363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 6393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * according to window granularity. 6403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 64121e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch pci_bound = pci_base + size; 6423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_offset = vme_base - pci_base; 6433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 64529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 6463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_EN; 64729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 6483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 6503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; 6513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_BLT) 6523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; 6533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_MBLT) 6543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; 6553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 6573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; 6583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (dwidth) { 6593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D8: 6603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; 6613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D16: 6633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; 6643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D32: 6663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; 6673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D64: 6693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; 6703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 672886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 67348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); 6743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dwidth; 6763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 67760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 6783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 6803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; 6813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 68260479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A16: 6833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; 68460479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 68560479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A24: 6863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; 68760479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 68860479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A32: 6893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; 6903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 6923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; 69360479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 69460479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER1: 6953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; 69660479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 69760479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER2: 6983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; 6993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 7013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 7023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 7033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 704886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 70548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 7063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 7073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_aspace; 70860479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 70960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 71060479690af6d559d4202bed139db90323386bd2bMartyn Welch 7113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); 7123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 7133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; 7143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 7153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; 71660479690af6d559d4202bed139db90323386bd2bMartyn Welch 7173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 71829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); 71929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); 72029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); 7213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 72329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 7263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_EN; 7273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 72829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 730886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 7313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 7323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_aspace: 7343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dwidth: 7353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_free_resource(image); 7363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_res: 7373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_window: 7383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 7393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 7403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 741efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int __ca91cx42_master_get(struct vme_master_resource *image, 742efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota int *enabled, unsigned long long *vme_base, unsigned long long *size, 7433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 7443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 7453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, ctl; 7463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_base, pci_bound, vme_offset; 74729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 74829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 74929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 7503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 7523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 75329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 7543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 75529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); 75629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); 75729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); 7583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *vme_base = pci_base + vme_offset; 76021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch *size = (unsigned long long)(pci_bound - pci_base); 7613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 7633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 7643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 7653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = 0; 7663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_EN) 7683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 7693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 7713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VAS_M) { 7723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A16: 7733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 7743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A24: 7763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 7773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A32: 7793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 7803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_CRCSR: 7823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_CRCSR; 7833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER1: 7853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 7863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER2: 7883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 7893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 7913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* XXX Not sure howto check for MBLT */ 7933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 7943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_VCT_BLT) 7953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_BLT; 7963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 7973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SCT; 7983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) 8003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 8013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 8033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_PGM_PGM) 8053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_PROG; 8063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_DATA; 8083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 8103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VDW_M) { 8113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D8: 8123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D8; 8133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D16: 8153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D16; 8163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D32: 8183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D32; 8193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D64: 8213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D64; 8223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 8243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 8263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 828efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, 8293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 8303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 8313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 8323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval; 8333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 834886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 8353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, 8373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch cycle, dwidth); 8383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 839886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 8403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 8423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 844efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic ssize_t ca91cx42_master_read(struct vme_master_resource *image, 845efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota void *buf, size_t count, loff_t offset) 8463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 84721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch ssize_t retval; 84853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov void *addr = image->kern_base + offset; 84953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int done = 0; 85053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int count32; 85153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 85253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count == 0) 85353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov return 0; 85460479690af6d559d4202bed139db90323386bd2bMartyn Welch 855886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 85660479690af6d559d4202bed139db90323386bd2bMartyn Welch 85753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov /* The following code handles VME address alignment problem 85853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * in order to assure the maximal data width cycle. 85953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * We cannot use memcpy_xxx directly here because it 86053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * may cut data transfer in 8-bits cycles, thus making 86153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * D16 cycle impossible. 86253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * From the other hand, the bridge itself assures that 86353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * maximal configured data cycle is used and splits it 86453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * automatically for non-aligned addresses. 86553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov */ 86653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x1) { 86753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)buf = ioread8(addr); 86853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 86953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (done == count) 87053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 87153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 87253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x2) { 87353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) < 2) { 87453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)(buf + done) = ioread8(addr + done); 87553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 87653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 87753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } else { 87853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u16 *)(buf + done) = ioread16(addr + done); 87953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 88053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 88153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 88260479690af6d559d4202bed139db90323386bd2bMartyn Welch 88353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov count32 = (count - done) & ~0x3; 88453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count32 > 0) { 88553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov memcpy_fromio(buf + done, addr + done, (unsigned int)count); 88653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += count32; 88753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 88853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 88953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x2) { 89053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u16 *)(buf + done) = ioread16(addr + done); 89153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 89253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 89353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x1) { 89453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)(buf + done) = ioread8(addr + done); 89553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 89653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 89753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilovout: 89853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov retval = count; 899886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 9003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 9013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 90260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 90360479690af6d559d4202bed139db90323386bd2bMartyn Welch 904efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic ssize_t ca91cx42_master_write(struct vme_master_resource *image, 905efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota void *buf, size_t count, loff_t offset) 90660479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 90753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov ssize_t retval; 90853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov void *addr = image->kern_base + offset; 90953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int done = 0; 91053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int count32; 91153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 91253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count == 0) 91353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov return 0; 91460479690af6d559d4202bed139db90323386bd2bMartyn Welch 915886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 91660479690af6d559d4202bed139db90323386bd2bMartyn Welch 91753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov /* Here we apply for the same strategy we do in master_read 91853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * function in order to assure D16 cycle when required. 91953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov */ 92053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x1) { 92153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)buf, addr); 92253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 92353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (done == count) 92453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 92553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 92653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x2) { 92753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) < 2) { 92853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)(buf + done), addr + done); 92953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 93053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 93153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } else { 93253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite16(*(u16 *)(buf + done), addr + done); 93353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 93453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 93553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 93653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 93753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov count32 = (count - done) & ~0x3; 93853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count32 > 0) { 93953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov memcpy_toio(addr + done, buf + done, count32); 94053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += count32; 94153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 94253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 94353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x2) { 94453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite16(*(u16 *)(buf + done), addr + done); 94553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 94653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 94753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x1) { 94853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)(buf + done), addr + done); 94953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 95053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 95153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilovout: 9523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = count; 9533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 954886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 955886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota 9563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 95760479690af6d559d4202bed139db90323386bd2bMartyn Welch} 95860479690af6d559d4202bed139db90323386bd2bMartyn Welch 959efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, 96004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch unsigned int mask, unsigned int compare, unsigned int swap, 96104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch loff_t offset) 96204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch{ 96304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch u32 pci_addr, result; 96404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch int i; 96504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct ca91cx42_driver *bridge; 96604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct device *dev; 96704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 96804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch bridge = image->parent->driver_priv; 96904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev = image->parent->parent; 97004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 97104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Find the PCI address that maps to the desired VME address */ 97204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch i = image->number; 97304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 97404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Locking as we can only do one of these at a time */ 975886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_rmw); 97604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 97704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Lock image */ 978886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 97904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch pci_addr = (u32)image->kern_base + offset; 98104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Address must be 4-byte aligned */ 98304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch if (pci_addr & 0x3) { 98404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev_err(dev, "RMW Address not 4-byte aligned\n"); 9857c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall result = -EINVAL; 9867c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall goto out; 98704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch } 98804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Ensure RMW Disabled whilst configuring */ 99004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 99104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Configure registers */ 99304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(mask, bridge->base + SCYC_EN); 99404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(compare, bridge->base + SCYC_CMP); 99504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(swap, bridge->base + SCYC_SWP); 99604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(pci_addr, bridge->base + SCYC_ADDR); 99704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Enable RMW */ 99904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); 100004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 100104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Kick process off with a read to the required address. */ 100204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch result = ioread32(image->kern_base + offset); 100304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 100404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Disable RMW */ 100504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 100604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 10077c0ace54887872ebd99fefdfe85d273295a09426Julia Lawallout: 1008886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 100904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 1010886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_rmw); 101104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch return result; 101304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch} 101404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 1015efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_add(struct vme_dma_list *list, 1016efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) 10174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 10184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry, *prev; 10194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_pci *pci_attr; 10204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_vme *vme_attr; 10214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t desc_ptr; 10224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 102348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 102448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 102548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = list->parent->parent->parent; 10264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX descriptor must be aligned on 64-bit boundaries */ 1028324148788bf3744d90fb6894ec5744eb0ca91b74Julia Lawall entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); 10294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (entry == NULL) { 103048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Failed to allocate memory for dma resource " 10314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "structure\n"); 10324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -ENOMEM; 10334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_mem; 10344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Test descriptor alignment */ 1037886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if ((unsigned long)&entry->descriptor & CA91CX42_DCPP_M) { 103848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Descriptor not aligned to 16 byte boundary as " 1039886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota "required: %p\n", &entry->descriptor); 10404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_align; 10424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1044886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&entry->descriptor, 0, sizeof(struct ca91cx42_dma_descriptor)); 10454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (dest->type == VME_DMA_VME) { 10474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_L2V; 1048feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy vme_attr = dest->private; 1049feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy pci_attr = src->private; 10504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 1051feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy vme_attr = src->private; 1052feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy pci_attr = dest->private; 10534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Check we can do fullfill required attributes */ 10564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | 10574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_USER2)) != 0) { 10584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 105948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 10604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_aspace; 10624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | 10654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_PROG | VME_DATA)) != 0) { 10664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 106748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 10684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_cycle; 10704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Check to see if we can fullfill source and destination */ 10734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || 10744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { 10754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 107648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Cannot perform transfer with this " 10774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "source-destination combination\n"); 10784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_direct; 10804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup cycle types */ 10834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_BLT) 10844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; 10854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup data width */ 10874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->dwidth) { 10884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D8: 10894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; 10904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D16: 10924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; 10934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D32: 10954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; 10964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D64: 10984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; 10994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 110148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid data width\n"); 11024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 11034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup address space */ 11064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->aspace) { 11074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A16: 11084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; 11094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A24: 11114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; 11124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A32: 11144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; 11154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER1: 11174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; 11184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER2: 11204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; 11214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 112348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid address space\n"); 11244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 11254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_SUPER) 11294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; 11304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_PROG) 11314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; 11324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dtbc = count; 11344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dla = pci_attr->address; 11354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dva = vme_attr->address; 11364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dcpp = CA91CX42_DCPP_NULL; 11374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Add to list */ 1139886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&entry->list, &list->entries); 11404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Fill out previous descriptors "Next Address" */ 1142886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (entry->list.prev != &list->entries) { 11434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, 11444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 11454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* We need the bus address for the pointer */ 1146886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota desc_ptr = virt_to_bus(&entry->descriptor); 11474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; 11484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_cycle: 11534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_aspace: 11544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_direct: 11554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_align: 11564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 11574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_mem: 11584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 11594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchstatic int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) 11624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 tmp; 11644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ca91cx42_bridge->driver_priv; 11674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch tmp = ioread32(bridge->base + DGCS); 11694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (tmp & CA91CX42_DGCS_ACT) 11714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch else 11734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 1; 11744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1176efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_exec(struct vme_dma_list *list) 11774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_resource *ctrlr; 11794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 11804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 11814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t bus_addr; 11824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 val; 118348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 11844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ctrlr = list->parent; 11874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ctrlr->parent->driver_priv; 118948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = ctrlr->parent->parent; 11904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1191886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 11924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1193886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!(list_empty(&ctrlr->running))) { 11944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 11954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * XXX We have an active DMA transfer and currently haven't 11964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * sorted out the mechanism for "pending" DMA transfers. 11974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Return busy. 11984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 11994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Need to add to pending here */ 1200886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EBUSY; 12024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 1203886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add(&list->list, &ctrlr->running); 12044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Get first bus address and write into registers */ 1207886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota entry = list_first_entry(&list->entries, struct ca91cx42_dma_entry, 12084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 12094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1210886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota bus_addr = virt_to_bus(&entry->descriptor); 12114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1212886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(0, bridge->base + DTBC); 12154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); 12164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Start the operation */ 12184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 12194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX Could set VMEbus On and Off Counters here */ 12214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); 12224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | 12244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 12254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR); 12264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 12284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= CA91CX42_DGCS_GO; 12304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 12324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch wait_event_interruptible(bridge->dma_queue, 12344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ca91cx42_dma_busy(ctrlr->parent)); 12354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 12374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Read status register, this register is valid until we kick off a 12384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * new transfer. 12394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 12404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 12414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 12434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR)) { 12444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 124548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); 12464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DCTL); 12474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Remove list from running list */ 1250886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 1251886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_del(&list->list); 1252886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 12554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 12574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1258efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_empty(struct vme_dma_list *list) 12594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 12604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct list_head *pos, *temp; 12614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 12624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* detach and free each entry */ 1264886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each_safe(pos, temp, &list->entries) { 12654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_del(pos); 12664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry = list_entry(pos, struct ca91cx42_dma_entry, list); 12674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 12684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 12714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 12724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 12742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * All 4 location monitors reside at the same base - this is therefore a 12752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * system wide configuration. 12762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 12772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * This does not enable the LM monitor - that should be done when the first 12782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * callback is attached and disabled when the last callback is removed. 12792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1280efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_set(struct vme_lm_resource *lm, 1281efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota unsigned long long lm_base, vme_address_t aspace, vme_cycle_t cycle) 12822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 12832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 temp_base, lm_ctl = 0; 12842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch int i; 12852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 12862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 12872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 12892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 12902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check the alignment of the location monitor */ 12922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch temp_base = (u32)lm_base; 12932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (temp_base & 0xffff) { 12942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor must be aligned to 64KB " 12952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "boundary"); 12962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 12972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 12982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1299886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 13002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If we already have a callback attached, we can't move it! */ 13022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch for (i = 0; i < lm->monitors; i++) { 13032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[i] != NULL) { 1304886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor callback attached, " 13062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "can't reset\n"); 13072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 13082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch switch (aspace) { 13122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A16: 13132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A16; 13142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A24: 13162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A24; 13172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A32: 13192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A32; 13202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch default: 1322886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Invalid address space\n"); 13242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 13252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_SUPER) 13292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_SUPR; 13302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_USER) 13312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_NPRIV; 13322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_PROG) 13332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_PGM; 13342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_DATA) 13352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_DATA; 13362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_base, bridge->base + LM_BS); 13382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 13392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1340886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 13432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* Get configuration of the callback monitor and return whether it is enabled 13462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * or disabled. 13472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1348efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_get(struct vme_lm_resource *lm, 1349efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle) 13502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 13512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, enabled = 0; 13522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1356886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 13572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); 13592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 13602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_EN) 13622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch enabled = 1; 13632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) 13652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A16; 13662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) 13672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A24; 13682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) 13692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A32; 13702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle = 0; 13722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_SUPR) 13732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_SUPER; 13742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_NPRIV) 13752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_USER; 13762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_PGM) 13772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_PROG; 13782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_DATA) 13792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_DATA; 13802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1381886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return enabled; 13842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 13872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Attach a callback to a specific location monitor. 13882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 13892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Callback will be passed the monitor triggered. 13902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1391efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, 13922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch void (*callback)(int)) 13932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 13942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, tmp; 13952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 13972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 14002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1401886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 14022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that the location monitor is configured - need PGM or DATA */ 14042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 14052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { 1406886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor not properly configured\n"); 14082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 14092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check that a callback isn't already attached */ 14122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[monitor] != NULL) { 1413886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Existing callback attached\n"); 14152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 14162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Attach callback */ 14192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = callback; 14202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Enable Location Monitor interrupt */ 14222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 14232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp |= CA91CX42_LINT_LM[monitor]; 14242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 14252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that global Location Monitor Enable set */ 14272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { 14282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_EN; 14292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 14302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1432886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 14352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 14362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 14382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Detach a callback function forn a specific location monitor. 14392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1440efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) 14412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 14422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 tmp; 14432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 14442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 14462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1447886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 14482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Disable Location Monitor and ensure previous interrupts are clear */ 14502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 14512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LINT_LM[monitor]; 14522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 14532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(CA91CX42_LINT_LM[monitor], 14552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->base + LINT_STAT); 14562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Detach callback */ 14582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = NULL; 14592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If all location monitors disabled, disable global Location Monitor */ 14612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 14622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch CA91CX42_LINT_LM3)) == 0) { 14632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LM_CTL); 14642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LM_CTL_EN; 14652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LM_CTL); 14662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1468886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 14712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 14722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1473efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) 147460479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 14753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 slot = 0; 147629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 147729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 147829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 147960479690af6d559d4202bed139db90323386bd2bMartyn Welch 148012b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch if (!geoid) { 148129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ioread32(bridge->base + VCSR_BS); 148212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); 148312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch } else 148412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = geoid; 148512b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 14863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return (int)slot; 14873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 14893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void) 14913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 14923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return pci_register_driver(&ca91cx42_driver); 14933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 14943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 14963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Configure CR/CSR space 14973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * 14983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Access to the CR/CSR can be configured at power-up. The location of the 14993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * CR/CSR registers in the CR/CSR address space is determined by the boards 15003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Auto-ID or Geographic address. This function ensures that the window is 15013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * enabled at an offset consistent with the boards geopgraphic address. 15023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 150329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, 150429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 15053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int crcsr_addr; 15073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int tmp, slot; 150829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 150929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 151029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 15113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 151229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ca91cx42_slot_get(ca91cx42_bridge); 151325331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 151425331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch /* Write CSR Base Address if slot ID is supplied as a module param */ 151525331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch if (geoid) 151625331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch iowrite32(geoid << 27, bridge->base + VCSR_BS); 151725331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 15183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); 15193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slot == 0) { 15203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Slot number is unset, not configuring " 15213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "CR/CSR space\n"); 15223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 152360479690af6d559d4202bed139db90323386bd2bMartyn Welch } 15243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Allocate mem for CR/CSR image */ 152629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, 1527886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &bridge->crcsr_bus); 152829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->crcsr_kernel == NULL) { 15293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " 15303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "image\n"); 15313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -ENOMEM; 153260479690af6d559d4202bed139db90323386bd2bMartyn Welch } 153360479690af6d559d4202bed139db90323386bd2bMartyn Welch 153429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); 153560479690af6d559d4202bed139db90323386bd2bMartyn Welch 15363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch crcsr_addr = slot * (512 * 1024); 153729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); 153860479690af6d559d4202bed139db90323386bd2bMartyn Welch 153929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 15403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp |= CA91CX42_VCSR_CTL_EN; 154129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 154260479690af6d559d4202bed139db90323386bd2bMartyn Welch 15433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 154460479690af6d559d4202bed139db90323386bd2bMartyn Welch} 154560479690af6d559d4202bed139db90323386bd2bMartyn Welch 154629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, 154729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 154860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 15493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 155029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 155129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 155229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 155360479690af6d559d4202bed139db90323386bd2bMartyn Welch 15543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off CR/CSR space */ 155529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 15563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_VCSR_CTL_EN; 155729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 155860479690af6d559d4202bed139db90323386bd2bMartyn Welch 15593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Free image */ 156029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VCSR_TO); 156160479690af6d559d4202bed139db90323386bd2bMartyn Welch 156229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, 156329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_bus); 15643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 156560479690af6d559d4202bed139db90323386bd2bMartyn Welch 15663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) 15673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval, i; 15693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 data; 15703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 157129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 157229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *ca91cx42_device; 15733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 15743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 15753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 15763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 15773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* We want to support more than one of each bridge so we need to 15793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * dynamically allocate the bridge structure 15803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 15817a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); 15823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge == NULL) { 15843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 15853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "structure\n"); 15863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 15873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_struct; 15883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15907a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); 159129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 159229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (ca91cx42_device == NULL) { 159329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 159429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch "structure\n"); 159529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch retval = -ENOMEM; 159629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch goto err_driver; 159729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch } 159829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 159929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge->driver_priv = ca91cx42_device; 160029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable the device */ 16023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_enable_device(pdev); 16033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 16043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to enable device\n"); 16053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_enable; 16063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Map Registers */ 16093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_request_regions(pdev, driver_name); 16103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 16113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to reserve resources\n"); 16123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 16133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* map registers in BAR 0 */ 161629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), 16173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4096); 161829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (!ca91cx42_device->base) { 16193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to remap CRG region\n"); 16203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 16213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 16223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Check to see if the mapping worked out */ 162529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; 16263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (data != PCI_VENDOR_ID_TUNDRA) { 16273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "PCI_ID check failed\n"); 16283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 16293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_test; 16303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialize wait queues & mutual exclusion flags */ 1633886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&ca91cx42_device->dma_queue); 1634886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&ca91cx42_device->iack_queue); 1635886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_device->vme_int); 1636886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_device->vme_rmw); 16373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1638886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota ca91cx42_bridge->parent = &pdev->dev; 16393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch strcpy(ca91cx42_bridge->name, driver_name); 16403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup IRQ */ 16423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_irq_init(ca91cx42_bridge); 16433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 16443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Initialization failed.\n"); 16453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_irq; 16463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add master windows to list */ 1649886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->master_resources); 16503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_MASTER; i++) { 16513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = kmalloc(sizeof(struct vme_master_resource), 16523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 16533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (master_image == NULL) { 16543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "master resource structure\n"); 16563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_master; 16583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->parent = ca91cx42_bridge; 1660886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock_init(&master_image->lock); 16613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->locked = 0; 16623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->number = i; 16633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | 16643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_CRCSR | VME_USER1 | VME_USER2; 16653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 16663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 16673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; 1668886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&master_image->bus_resource, 0, 16693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch sizeof(struct resource)); 16703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->kern_base = NULL; 1671886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&master_image->list, 1672886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->master_resources); 16733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add slave windows to list */ 1676886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->slave_resources); 16773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_SLAVE; i++) { 16783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = kmalloc(sizeof(struct vme_slave_resource), 16793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 16803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slave_image == NULL) { 16813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "slave resource structure\n"); 16833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_slave; 16853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->parent = ca91cx42_bridge; 1687886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&slave_image->mtx); 16883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->locked = 0; 16893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->number = i; 16903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | 16913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_USER2; 16923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only windows 0 and 4 support A16 */ 16943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (i == 0 || i == 4) 16953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr |= VME_A16; 16963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 16983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 1699886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&slave_image->list, 1700886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->slave_resources); 17013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 17033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add dma engines to list */ 1704886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->dma_resources); 17053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_DMA; i++) { 17063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), 17073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 17083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (dma_ctrlr == NULL) { 17093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "dma resource structure\n"); 17113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dma; 17133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->parent = ca91cx42_bridge; 1715886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&dma_ctrlr->mtx); 17163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->locked = 0; 17173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->number = i; 17184f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | 17194f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_MEM_TO_VME; 1720886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->pending); 1721886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->running); 1722886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&dma_ctrlr->list, 1723886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->dma_resources); 17243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 17263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add location monitor to list */ 1727886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->lm_resources); 17283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); 17293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (lm == NULL) { 17303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "location monitor resource structure\n"); 17323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_lm; 17343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->parent = ca91cx42_bridge; 1736886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&lm->mtx); 17373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->locked = 0; 17383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->number = 1; 17393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->monitors = 4; 1740886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&lm->list, &ca91cx42_bridge->lm_resources); 17413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_get = ca91cx42_slave_get; 17433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_set = ca91cx42_slave_set; 17443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_get = ca91cx42_master_get; 17453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_set = ca91cx42_master_set; 17463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_read = ca91cx42_master_read; 17473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_write = ca91cx42_master_write; 17483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; 17493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; 17503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; 17513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; 1752c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_set = ca91cx42_irq_set; 1753c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; 17543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_set = ca91cx42_lm_set; 17553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_get = ca91cx42_lm_get; 17563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; 17573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; 17583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slot_get = ca91cx42_slot_get; 17593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 176029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + MISC_CTL); 17613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "Board is%s the VME system controller\n", 17623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); 176329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_info(&pdev->dev, "Slot ID is %d\n", 176429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_slot_get(ca91cx42_bridge)); 17653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17667946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) 17673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); 176860479690af6d559d4202bed139db90323386bd2bMartyn Welch 17693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need to save ca91cx42_bridge pointer locally in link list for use in 17703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * ca91cx42_remove() 17713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 17723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = vme_register_bridge(ca91cx42_bridge); 17733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 17743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Registration failed.\n"); 17753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_reg; 17763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 177829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_set_drvdata(pdev, ca91cx42_bridge); 177929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 17803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 17813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_reg: 178329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 17843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_lm: 17853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1786886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->lm_resources) { 17873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 17883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 17903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dma: 17923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1793886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->dma_resources) { 17943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 17953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 179760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 17983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_slave: 17993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1800886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->slave_resources) { 18013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 18023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 18043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_master: 18063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1807886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->master_resources) { 18083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 18093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 18103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 18123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 181429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(ca91cx42_device, pdev); 18153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_irq: 18163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_test: 181729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(ca91cx42_device->base); 18183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 18193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 18203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 18213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 18223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_enable: 182329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kfree(ca91cx42_device); 182429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welcherr_driver: 18253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 18263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_struct: 18273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 182860479690af6d559d4202bed139db90323386bd2bMartyn Welch 182960479690af6d559d4202bed139db90323386bd2bMartyn Welch} 183060479690af6d559d4202bed139db90323386bd2bMartyn Welch 1831efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic void ca91cx42_remove(struct pci_dev *pdev) 183260479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 18333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 18343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 18353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 18363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 18373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 183829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 183929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); 184029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 184129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 184229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 184360479690af6d559d4202bed139db90323386bd2bMartyn Welch 18443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off Ints */ 184529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 18463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off the windows */ 184829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI0_CTL); 184929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI1_CTL); 185029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI2_CTL); 185129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI3_CTL); 185229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI4_CTL); 185329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI5_CTL); 185429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI6_CTL); 185529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI7_CTL); 185629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI0_CTL); 185729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI1_CTL); 185829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI2_CTL); 185929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI3_CTL); 186029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI4_CTL); 186129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI5_CTL); 186229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI6_CTL); 186329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI7_CTL); 18643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_unregister_bridge(ca91cx42_bridge); 1866bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 1867bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 1868bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 18693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1870886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->lm_resources) { 18713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 18723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 187460479690af6d559d4202bed139db90323386bd2bMartyn Welch } 18753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1877886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->dma_resources) { 18783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 18793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 188160479690af6d559d4202bed139db90323386bd2bMartyn Welch } 188260479690af6d559d4202bed139db90323386bd2bMartyn Welch 18833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1884886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->slave_resources) { 18853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 18863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 18883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 188960479690af6d559d4202bed139db90323386bd2bMartyn Welch 18903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1891886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->master_resources) { 18923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 18933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 18943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 18963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 189760479690af6d559d4202bed139db90323386bd2bMartyn Welch 189829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(bridge, pdev); 189960479690af6d559d4202bed139db90323386bd2bMartyn Welch 190029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(bridge->base); 190160479690af6d559d4202bed139db90323386bd2bMartyn Welch 19023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 190360479690af6d559d4202bed139db90323386bd2bMartyn Welch 19043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 19053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 19063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 190760479690af6d559d4202bed139db90323386bd2bMartyn Welch} 190860479690af6d559d4202bed139db90323386bd2bMartyn Welch 19093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void) 191060479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 19113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_unregister_driver(&ca91cx42_driver); 19123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 191360479690af6d559d4202bed139db90323386bd2bMartyn Welch 191412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn WelchMODULE_PARM_DESC(geoid, "Override geographical addressing"); 191512b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchmodule_param(geoid, int, 0); 191612b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 19173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); 19183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_LICENSE("GPL"); 191960479690af6d559d4202bed139db90323386bd2bMartyn Welch 19203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_init(ca91cx42_init); 19213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_exit(ca91cx42_exit); 1922