vme_ca91cx42.c revision 54b4a779c9565c475a17cc1254a38f293a5ba3ef
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 45584721cab2bdd26f63bfeca60c83f5e6b8eee7d0Vincent Bossierstatic const 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 */ 19356fc508186dbec9aca46cd034ef12358fc044ac1Vincent Bossier iowrite32(serviced, 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 25954b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossierstatic int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level) 26054b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier{ 26154b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier u32 tmp; 26254b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier 26354b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier tmp = ioread32(bridge->base + LINT_STAT); 26454b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier 26554b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier if (tmp & (1 << level)) 26654b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier return 0; 26754b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier else 26854b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier return 1; 26954b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier} 27054b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier 2713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 2723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Set up an VME interrupt 2733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 274efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, 275efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota int state, int sync) 276c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 278c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch struct pci_dev *pdev; 2793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 28029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 28129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 28229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 28360479690af6d559d4202bed139db90323386bd2bMartyn Welch 2843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable IRQ level */ 28529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + LINT_EN); 2863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 287c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (state == 0) 2883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_LINT_VIRQ[level]; 289c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch else 290c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tmp |= CA91CX42_LINT_VIRQ[level]; 29160479690af6d559d4202bed139db90323386bd2bMartyn Welch 29229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 293c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 294c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if ((state == 0) && (sync != 0)) { 2953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, 2963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev); 2973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch synchronize_irq(pdev->irq); 29960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 30060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 30160479690af6d559d4202bed139db90323386bd2bMartyn Welch 302efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, 30329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int statid) 30460479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 3053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 30629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 30729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 30829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 30960479690af6d559d4202bed139db90323386bd2bMartyn Welch 3103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Universe can only generate even vectors */ 3113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (statid & 1) 3123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 31360479690af6d559d4202bed139db90323386bd2bMartyn Welch 314886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_int); 31560479690af6d559d4202bed139db90323386bd2bMartyn Welch 31629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 31760479690af6d559d4202bed139db90323386bd2bMartyn Welch 3183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Set Status/ID */ 31929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(statid << 24, bridge->base + STATID); 3203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Assert VMEbus IRQ */ 3223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp | (1 << (level + 24)); 32329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 32460479690af6d559d4202bed139db90323386bd2bMartyn Welch 3253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Wait for IACK */ 32654b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier wait_event_interruptible(bridge->iack_queue, 32754b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier ca91cx42_iack_received(bridge, level)); 3283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Return interrupt to low state */ 33029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 3313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp & ~(1 << (level + 24)); 33229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 3333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 334886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_int); 3353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 33760479690af6d559d4202bed139db90323386bd2bMartyn Welch} 33860479690af6d559d4202bed139db90323386bd2bMartyn Welch 339efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, 3403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 3413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) 34260479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 34321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, addr = 0, granularity; 3443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 3453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int vme_bound, pci_offset; 34648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 34729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 34829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 34948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 35048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 35148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 35260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 35460479690af6d559d4202bed139db90323386bd2bMartyn Welch 3553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 3563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A16: 3573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A16; 3583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A24: 3603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A24; 3613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A32: 3633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A32; 3643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER1: 3663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER1; 3673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER2: 3693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER2; 3703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 3723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 3733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 3743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 3753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 37648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 3773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 37960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 38060479690af6d559d4202bed139db90323386bd2bMartyn Welch 3813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 3823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 3833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * accordingly 3843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 38521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch vme_bound = vme_base + size; 3863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_offset = pci_base - vme_base; 3873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 3893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 3903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 3913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 3923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_base & (granularity - 1)) { 39448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME base " 39548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 3983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_bound & (granularity - 1)) { 39948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME bound " 40048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 4013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 4023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 4033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (pci_offset & (granularity - 1)) { 40448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " 40548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 4063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 40760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 40860479690af6d559d4202bed139db90323386bd2bMartyn Welch 4093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 41029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 4113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_EN; 41229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 41360479690af6d559d4202bed139db90323386bd2bMartyn Welch 4143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 41529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); 41629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); 41729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); 4183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 4203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; 4213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= addr; 4223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 4243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); 4253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 4263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; 4273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_USER) 4283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; 4293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 4303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; 4313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_DATA) 4323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; 4333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 43529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 4383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_EN; 4393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 44029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 44360479690af6d559d4202bed139db90323386bd2bMartyn Welch} 44460479690af6d559d4202bed139db90323386bd2bMartyn Welch 445efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, 4463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 4473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) 44860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 4493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, granularity = 0, ctl = 0; 4503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_bound, pci_offset; 45129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 45229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 45329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 4543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 45660479690af6d559d4202bed139db90323386bd2bMartyn Welch 4573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 4583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 4593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 4603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 4613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Read Registers */ 46329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 4643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 46529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); 46629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); 46729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); 4683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *pci_base = (dma_addr_t)vme_base + pci_offset; 4703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *size = (unsigned long long)((vme_bound - *vme_base) + granularity); 4713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 4733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 4743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 4753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_EN) 4773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 4783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) 4803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 4813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) 4823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 4833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) 4843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 4853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) 4863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 4873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) 4883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 4893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) 4913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 4923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) 4933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 4943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_PGM) 4953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_PROG; 4963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_DATA) 4973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_DATA; 4983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 5033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Allocate and map PCI Resource 5043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 5053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_alloc_resource(struct vme_master_resource *image, 5063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long size) 5073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long existing_size; 5093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 5103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 51129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 51229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 51329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = image->parent; 5143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Find pci_dev container of dev */ 5163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge->parent == NULL) { 51748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); 5183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 5193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 5213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5228fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch existing_size = (unsigned long long)(image->bus_resource.end - 5238fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start); 5243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* If the existing size is OK, return */ 5263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size == (size - 1)) 5273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size != 0) { 5303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 532794a8946ba2339af09dd1f39c8462c3611bebf77Ilia Mirkin kfree(image->bus_resource.name); 533886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 534886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5378fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 5380aa3f139cd5123ffb8f397b91d777635e9761c24Julia Lawall image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); 5398fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 54048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate " 54148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "memory for resource name\n"); 5423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_name; 5443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 54560479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5478fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch sprintf((char *)image->bus_resource.name, "%s.%d", 5483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->name, image->number); 5493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5508fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start = 0; 5518fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.end = (unsigned long)size; 5528fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.flags = IORESOURCE_MEM; 5533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_bus_alloc_resource(pdev->bus, 555886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &image->bus_resource, size, size, PCIBIOS_MIN_MEM, 5563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 0, NULL, NULL); 5573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 55848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " 55948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "resource for window %d size 0x%lx start 0x%lx\n", 5603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->number, (unsigned long)size, 5618fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch (unsigned long)image->bus_resource.start); 5623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 56360479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = ioremap_nocache( 5668fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start, size); 5673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (image->kern_base == NULL) { 56848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); 5693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 57160479690af6d559d4202bed139db90323386bd2bMartyn Welch } 57260479690af6d559d4202bed139db90323386bd2bMartyn Welch 5733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 576886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 5773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 5788fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 579886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_name: 5813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 5823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 5854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Free and unmap PCI Resource 5864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 5873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_free_resource(struct vme_master_resource *image) 5883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 591886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 5928fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 593886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 597efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_master_set(struct vme_master_resource *image, int enabled, 5983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 5993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) 6003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 6013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 60221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, granularity = 0; 6033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 6043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_bound, vme_offset, pci_base; 60548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 60629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 60729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 60848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 60948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 61048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 6113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 61221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch i = image->number; 61321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 61421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if ((i == 0) || (i == 4)) 61521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x1000; 61621e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch else 61721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x10000; 61821e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 6193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Verify input data */ 62021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (vme_base & (granularity - 1)) { 62148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 62248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 62621e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (size & (granularity - 1)) { 62748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 62848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 633886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 6343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Let's allocate the resource here rather than further up the stack as 63725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * it avoids pushing loads of bus dependent stuff up the stack 6383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 6393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_alloc_resource(image, size); 6403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 641886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 64248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " 64348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "for resource name\n"); 6443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 6453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_res; 6463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6488fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch pci_base = (unsigned long long)image->bus_resource.start; 6493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 6523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * according to window granularity. 6533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 65421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch pci_bound = pci_base + size; 6553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_offset = vme_base - pci_base; 6563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 65829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 6593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_EN; 66029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 6613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 6633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; 6643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_BLT) 6653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; 6663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_MBLT) 6673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; 6683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 6703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; 6713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (dwidth) { 6723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D8: 6733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; 6743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D16: 6763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; 6773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D32: 6793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; 6803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D64: 6823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; 6833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 685886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 68648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); 6873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dwidth; 6893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 69060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 6913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 6933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; 6943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 69560479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A16: 6963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; 69760479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 69860479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A24: 6993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; 70060479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 70160479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A32: 7023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; 7033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 7053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; 70660479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 70760479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER1: 7083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; 70960479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 71060479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER2: 7113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; 7123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 7143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 7153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 7163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 717886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 71848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 7193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 7203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_aspace; 72160479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 72260479690af6d559d4202bed139db90323386bd2bMartyn Welch } 72360479690af6d559d4202bed139db90323386bd2bMartyn Welch 7243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); 7253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 7263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; 7273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 7283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; 72960479690af6d559d4202bed139db90323386bd2bMartyn Welch 7303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 73129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); 73229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); 73329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); 7343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 73629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 7393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_EN; 7403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 74129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 743886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 7443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 7453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_aspace: 7473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dwidth: 7483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_free_resource(image); 7493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_res: 7503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_window: 7513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 7523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 7533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 754efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int __ca91cx42_master_get(struct vme_master_resource *image, 755efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota int *enabled, unsigned long long *vme_base, unsigned long long *size, 7563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 7573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 7583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, ctl; 7593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_base, pci_bound, vme_offset; 76029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 76129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 76229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 7633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 7653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 76629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 7673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 76829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); 76929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); 77029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); 7713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *vme_base = pci_base + vme_offset; 77321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch *size = (unsigned long long)(pci_bound - pci_base); 7743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 7763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 7773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 7783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = 0; 7793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_EN) 7813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 7823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 7843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VAS_M) { 7853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A16: 7863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 7873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A24: 7893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 7903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A32: 7923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 7933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_CRCSR: 7953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_CRCSR; 7963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER1: 7983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 7993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER2: 8013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 8023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 8043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* XXX Not sure howto check for MBLT */ 8063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 8073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_VCT_BLT) 8083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_BLT; 8093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SCT; 8113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) 8133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 8143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 8163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_PGM_PGM) 8183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_PROG; 8193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_DATA; 8213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 8233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VDW_M) { 8243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D8: 8253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D8; 8263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D16: 8283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D16; 8293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D32: 8313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D32; 8323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D64: 8343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D64; 8353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 8373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 8393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 841efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, 8423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 8433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 8443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 8453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval; 8463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 847886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 8483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, 8503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch cycle, dwidth); 8513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 852886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 8533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 8553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 857efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic ssize_t ca91cx42_master_read(struct vme_master_resource *image, 858efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota void *buf, size_t count, loff_t offset) 8593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 86021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch ssize_t retval; 86153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov void *addr = image->kern_base + offset; 86253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int done = 0; 86353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int count32; 86453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 86553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count == 0) 86653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov return 0; 86760479690af6d559d4202bed139db90323386bd2bMartyn Welch 868886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 86960479690af6d559d4202bed139db90323386bd2bMartyn Welch 87053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov /* The following code handles VME address alignment problem 87153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * in order to assure the maximal data width cycle. 87253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * We cannot use memcpy_xxx directly here because it 87353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * may cut data transfer in 8-bits cycles, thus making 87453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * D16 cycle impossible. 87553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * From the other hand, the bridge itself assures that 87653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * maximal configured data cycle is used and splits it 87753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * automatically for non-aligned addresses. 87853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov */ 87953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x1) { 88053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)buf = ioread8(addr); 88153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 88253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (done == count) 88353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 88453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 88553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x2) { 88653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) < 2) { 88753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)(buf + done) = ioread8(addr + done); 88853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 88953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 89053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } else { 89153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u16 *)(buf + done) = ioread16(addr + done); 89253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 89353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 89453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 89560479690af6d559d4202bed139db90323386bd2bMartyn Welch 89653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov count32 = (count - done) & ~0x3; 89753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count32 > 0) { 89853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov memcpy_fromio(buf + done, addr + done, (unsigned int)count); 89953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += count32; 90053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 90153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 90253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x2) { 90353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u16 *)(buf + done) = ioread16(addr + done); 90453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 90553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 90653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x1) { 90753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)(buf + done) = ioread8(addr + done); 90853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 90953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 91053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilovout: 91153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov retval = count; 912886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 9133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 9143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 91560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 91660479690af6d559d4202bed139db90323386bd2bMartyn Welch 917efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic ssize_t ca91cx42_master_write(struct vme_master_resource *image, 918efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota void *buf, size_t count, loff_t offset) 91960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 92053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov ssize_t retval; 92153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov void *addr = image->kern_base + offset; 92253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int done = 0; 92353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int count32; 92453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 92553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count == 0) 92653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov return 0; 92760479690af6d559d4202bed139db90323386bd2bMartyn Welch 928886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 92960479690af6d559d4202bed139db90323386bd2bMartyn Welch 93053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov /* Here we apply for the same strategy we do in master_read 93153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * function in order to assure D16 cycle when required. 93253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov */ 93353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x1) { 93453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)buf, addr); 93553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 93653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (done == count) 93753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 93853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 93953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((int)addr & 0x2) { 94053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) < 2) { 94153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)(buf + done), addr + done); 94253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 94353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 94453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } else { 94553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite16(*(u16 *)(buf + done), addr + done); 94653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 94753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 94853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 94953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 95053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov count32 = (count - done) & ~0x3; 95153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count32 > 0) { 95253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov memcpy_toio(addr + done, buf + done, count32); 95353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += count32; 95453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 95553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 95653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x2) { 95753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite16(*(u16 *)(buf + done), addr + done); 95853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 95953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 96053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x1) { 96153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)(buf + done), addr + done); 96253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 96353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 96453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilovout: 9653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = count; 9663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 967886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 968886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota 9693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 97060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 97160479690af6d559d4202bed139db90323386bd2bMartyn Welch 972efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, 97304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch unsigned int mask, unsigned int compare, unsigned int swap, 97404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch loff_t offset) 97504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch{ 97604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch u32 pci_addr, result; 97704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch int i; 97804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct ca91cx42_driver *bridge; 97904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct device *dev; 98004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch bridge = image->parent->driver_priv; 98204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev = image->parent->parent; 98304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Find the PCI address that maps to the desired VME address */ 98504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch i = image->number; 98604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Locking as we can only do one of these at a time */ 988886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_rmw); 98904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Lock image */ 991886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 99204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch pci_addr = (u32)image->kern_base + offset; 99404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Address must be 4-byte aligned */ 99604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch if (pci_addr & 0x3) { 99704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev_err(dev, "RMW Address not 4-byte aligned\n"); 9987c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall result = -EINVAL; 9997c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall goto out; 100004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch } 100104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 100204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Ensure RMW Disabled whilst configuring */ 100304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 100404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 100504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Configure registers */ 100604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(mask, bridge->base + SCYC_EN); 100704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(compare, bridge->base + SCYC_CMP); 100804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(swap, bridge->base + SCYC_SWP); 100904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(pci_addr, bridge->base + SCYC_ADDR); 101004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Enable RMW */ 101204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); 101304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Kick process off with a read to the required address. */ 101504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch result = ioread32(image->kern_base + offset); 101604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Disable RMW */ 101804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 101904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 10207c0ace54887872ebd99fefdfe85d273295a09426Julia Lawallout: 1021886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 102204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 1023886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_rmw); 102404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 102504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch return result; 102604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch} 102704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 1028efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_add(struct vme_dma_list *list, 1029efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) 10304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 10314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry, *prev; 10324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_pci *pci_attr; 10334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_vme *vme_attr; 10344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t desc_ptr; 10354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 103648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 103748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 103848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = list->parent->parent->parent; 10394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX descriptor must be aligned on 64-bit boundaries */ 1041324148788bf3744d90fb6894ec5744eb0ca91b74Julia Lawall entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); 10424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (entry == NULL) { 104348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Failed to allocate memory for dma resource " 10444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "structure\n"); 10454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -ENOMEM; 10464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_mem; 10474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Test descriptor alignment */ 1050886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if ((unsigned long)&entry->descriptor & CA91CX42_DCPP_M) { 105148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Descriptor not aligned to 16 byte boundary as " 1052886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota "required: %p\n", &entry->descriptor); 10534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_align; 10554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1057886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&entry->descriptor, 0, sizeof(struct ca91cx42_dma_descriptor)); 10584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (dest->type == VME_DMA_VME) { 10604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_L2V; 1061feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy vme_attr = dest->private; 1062feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy pci_attr = src->private; 10634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 1064feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy vme_attr = src->private; 1065feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy pci_attr = dest->private; 10664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 106825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Check we can do fulfill required attributes */ 10694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | 10704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_USER2)) != 0) { 10714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 107248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 10734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_aspace; 10754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | 10784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_PROG | VME_DATA)) != 0) { 10794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 108048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 10814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_cycle; 10834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 108525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Check to see if we can fulfill source and destination */ 10864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || 10874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { 10884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 108948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Cannot perform transfer with this " 10904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "source-destination combination\n"); 10914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_direct; 10934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup cycle types */ 10964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_BLT) 10974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; 10984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup data width */ 11004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->dwidth) { 11014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D8: 11024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; 11034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D16: 11054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; 11064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D32: 11084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; 11094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D64: 11114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; 11124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 111448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid data width\n"); 11154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 11164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup address space */ 11194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->aspace) { 11204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A16: 11214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; 11224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A24: 11244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; 11254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A32: 11274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; 11284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER1: 11304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; 11314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER2: 11334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; 11344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 113648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid address space\n"); 11374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 11384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_SUPER) 11424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; 11434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_PROG) 11444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; 11454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dtbc = count; 11474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dla = pci_attr->address; 11484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dva = vme_attr->address; 11494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dcpp = CA91CX42_DCPP_NULL; 11504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Add to list */ 1152886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&entry->list, &list->entries); 11534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Fill out previous descriptors "Next Address" */ 1155886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (entry->list.prev != &list->entries) { 11564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, 11574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 11584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* We need the bus address for the pointer */ 1159886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota desc_ptr = virt_to_bus(&entry->descriptor); 11604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; 11614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_cycle: 11664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_aspace: 11674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_direct: 11684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_align: 11694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 11704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_mem: 11714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 11724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchstatic int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) 11754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 tmp; 11774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ca91cx42_bridge->driver_priv; 11804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch tmp = ioread32(bridge->base + DGCS); 11824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (tmp & CA91CX42_DGCS_ACT) 11844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch else 11864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 1; 11874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1189efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_exec(struct vme_dma_list *list) 11904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_resource *ctrlr; 11924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 11934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 11944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t bus_addr; 11954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 val; 119648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 11974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ctrlr = list->parent; 12004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ctrlr->parent->driver_priv; 120248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = ctrlr->parent->parent; 12034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1204886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 12054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1206886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!(list_empty(&ctrlr->running))) { 12074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 12084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * XXX We have an active DMA transfer and currently haven't 12094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * sorted out the mechanism for "pending" DMA transfers. 12104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Return busy. 12114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 12124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Need to add to pending here */ 1213886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EBUSY; 12154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 1216886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add(&list->list, &ctrlr->running); 12174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Get first bus address and write into registers */ 1220886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota entry = list_first_entry(&list->entries, struct ca91cx42_dma_entry, 12214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 12224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1223886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota bus_addr = virt_to_bus(&entry->descriptor); 12244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1225886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(0, bridge->base + DTBC); 12284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); 12294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Start the operation */ 12314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 12324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX Could set VMEbus On and Off Counters here */ 12344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); 12354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | 12374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 12384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR); 12394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 12414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= CA91CX42_DGCS_GO; 12434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 12454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch wait_event_interruptible(bridge->dma_queue, 12474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ca91cx42_dma_busy(ctrlr->parent)); 12484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 12504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Read status register, this register is valid until we kick off a 12514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * new transfer. 12524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 12534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 12544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 12564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR)) { 12574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 125848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); 12594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DCTL); 12604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Remove list from running list */ 1263886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 1264886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_del(&list->list); 1265886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 12684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 12704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1271efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_empty(struct vme_dma_list *list) 12724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 12734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct list_head *pos, *temp; 12744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 12754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* detach and free each entry */ 1277886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each_safe(pos, temp, &list->entries) { 12784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_del(pos); 12794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry = list_entry(pos, struct ca91cx42_dma_entry, list); 12804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 12814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 12844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 12854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 12872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * All 4 location monitors reside at the same base - this is therefore a 12882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * system wide configuration. 12892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 12902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * This does not enable the LM monitor - that should be done when the first 12912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * callback is attached and disabled when the last callback is removed. 12922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1293efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_set(struct vme_lm_resource *lm, 1294efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota unsigned long long lm_base, vme_address_t aspace, vme_cycle_t cycle) 12952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 12962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 temp_base, lm_ctl = 0; 12972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch int i; 12982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 12992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 13002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 13032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check the alignment of the location monitor */ 13052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch temp_base = (u32)lm_base; 13062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (temp_base & 0xffff) { 13072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor must be aligned to 64KB " 13082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "boundary"); 13092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 13102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1312886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 13132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If we already have a callback attached, we can't move it! */ 13152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch for (i = 0; i < lm->monitors; i++) { 13162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[i] != NULL) { 1317886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor callback attached, " 13192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "can't reset\n"); 13202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 13212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch switch (aspace) { 13252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A16: 13262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A16; 13272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A24: 13292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A24; 13302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A32: 13322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A32; 13332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch default: 1335886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Invalid address space\n"); 13372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 13382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_SUPER) 13422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_SUPR; 13432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_USER) 13442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_NPRIV; 13452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_PROG) 13462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_PGM; 13472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_DATA) 13482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_DATA; 13492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_base, bridge->base + LM_BS); 13512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 13522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1353886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 13562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* Get configuration of the callback monitor and return whether it is enabled 13592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * or disabled. 13602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1361efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_get(struct vme_lm_resource *lm, 1362efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle) 13632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 13642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, enabled = 0; 13652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1369886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 13702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); 13722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 13732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_EN) 13752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch enabled = 1; 13762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) 13782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A16; 13792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) 13802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A24; 13812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) 13822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A32; 13832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle = 0; 13852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_SUPR) 13862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_SUPER; 13872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_NPRIV) 13882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_USER; 13892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_PGM) 13902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_PROG; 13912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_DATA) 13922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_DATA; 13932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1394886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return enabled; 13972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 14002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Attach a callback to a specific location monitor. 14012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 14022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Callback will be passed the monitor triggered. 14032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1404efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, 14052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch void (*callback)(int)) 14062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 14072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, tmp; 14082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 14092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 14102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 14122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 14132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1414886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 14152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that the location monitor is configured - need PGM or DATA */ 14172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 14182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { 1419886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor not properly configured\n"); 14212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 14222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check that a callback isn't already attached */ 14252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[monitor] != NULL) { 1426886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Existing callback attached\n"); 14282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 14292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Attach callback */ 14322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = callback; 14332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Enable Location Monitor interrupt */ 14352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 14362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp |= CA91CX42_LINT_LM[monitor]; 14372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 14382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that global Location Monitor Enable set */ 14402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { 14412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_EN; 14422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 14432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1445886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 14482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 14492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 14512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Detach a callback function forn a specific location monitor. 14522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1453efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) 14542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 14552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 tmp; 14562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 14572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 14592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1460886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 14612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Disable Location Monitor and ensure previous interrupts are clear */ 14632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 14642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LINT_LM[monitor]; 14652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 14662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(CA91CX42_LINT_LM[monitor], 14682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->base + LINT_STAT); 14692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Detach callback */ 14712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = NULL; 14722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If all location monitors disabled, disable global Location Monitor */ 14742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 14752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch CA91CX42_LINT_LM3)) == 0) { 14762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LM_CTL); 14772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LM_CTL_EN; 14782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LM_CTL); 14792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1481886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 14842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 14852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1486efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) 148760479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 14883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 slot = 0; 148929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 149029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 149129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 149260479690af6d559d4202bed139db90323386bd2bMartyn Welch 149312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch if (!geoid) { 149429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ioread32(bridge->base + VCSR_BS); 149512b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); 149612b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch } else 149712b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = geoid; 149812b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 14993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return (int)slot; 15003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 15023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void) 15043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return pci_register_driver(&ca91cx42_driver); 15063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 15073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 15093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Configure CR/CSR space 15103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * 15113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Access to the CR/CSR can be configured at power-up. The location of the 15123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * CR/CSR registers in the CR/CSR address space is determined by the boards 15133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Auto-ID or Geographic address. This function ensures that the window is 15143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * enabled at an offset consistent with the boards geopgraphic address. 15153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 151629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, 151729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 15183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int crcsr_addr; 15203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int tmp, slot; 152129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 152229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 152329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 15243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 152529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ca91cx42_slot_get(ca91cx42_bridge); 152625331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 152725331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch /* Write CSR Base Address if slot ID is supplied as a module param */ 152825331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch if (geoid) 152925331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch iowrite32(geoid << 27, bridge->base + VCSR_BS); 153025331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 15313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); 15323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slot == 0) { 15333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Slot number is unset, not configuring " 15343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "CR/CSR space\n"); 15353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 153660479690af6d559d4202bed139db90323386bd2bMartyn Welch } 15373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Allocate mem for CR/CSR image */ 153929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, 1540886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &bridge->crcsr_bus); 154129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->crcsr_kernel == NULL) { 15423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " 15433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "image\n"); 15443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -ENOMEM; 154560479690af6d559d4202bed139db90323386bd2bMartyn Welch } 154660479690af6d559d4202bed139db90323386bd2bMartyn Welch 154729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); 154860479690af6d559d4202bed139db90323386bd2bMartyn Welch 15493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch crcsr_addr = slot * (512 * 1024); 155029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); 155160479690af6d559d4202bed139db90323386bd2bMartyn Welch 155229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 15533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp |= CA91CX42_VCSR_CTL_EN; 155429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 155560479690af6d559d4202bed139db90323386bd2bMartyn Welch 15563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 155760479690af6d559d4202bed139db90323386bd2bMartyn Welch} 155860479690af6d559d4202bed139db90323386bd2bMartyn Welch 155929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, 156029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 156160479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 15623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 156329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 156429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 156529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 156660479690af6d559d4202bed139db90323386bd2bMartyn Welch 15673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off CR/CSR space */ 156829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 15693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_VCSR_CTL_EN; 157029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 157160479690af6d559d4202bed139db90323386bd2bMartyn Welch 15723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Free image */ 157329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VCSR_TO); 157460479690af6d559d4202bed139db90323386bd2bMartyn Welch 157529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, 157629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_bus); 15773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 157860479690af6d559d4202bed139db90323386bd2bMartyn Welch 15793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) 15803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval, i; 15823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 data; 15833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 158429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 158529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *ca91cx42_device; 15863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 15873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 15883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 15893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 15903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* We want to support more than one of each bridge so we need to 15923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * dynamically allocate the bridge structure 15933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 15947a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); 15953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge == NULL) { 15973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 15983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "structure\n"); 15993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_struct; 16013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16037a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); 160429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 160529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (ca91cx42_device == NULL) { 160629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 160729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch "structure\n"); 160829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch retval = -ENOMEM; 160929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch goto err_driver; 161029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch } 161129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 161229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge->driver_priv = ca91cx42_device; 161329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable the device */ 16153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_enable_device(pdev); 16163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 16173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to enable device\n"); 16183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_enable; 16193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Map Registers */ 16223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_request_regions(pdev, driver_name); 16233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 16243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to reserve resources\n"); 16253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 16263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* map registers in BAR 0 */ 162929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), 16303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4096); 163129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (!ca91cx42_device->base) { 16323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to remap CRG region\n"); 16333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 16343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 16353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Check to see if the mapping worked out */ 163829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; 16393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (data != PCI_VENDOR_ID_TUNDRA) { 16403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "PCI_ID check failed\n"); 16413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 16423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_test; 16433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialize wait queues & mutual exclusion flags */ 1646886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&ca91cx42_device->dma_queue); 1647886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&ca91cx42_device->iack_queue); 1648886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_device->vme_int); 1649886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_device->vme_rmw); 16503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1651886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota ca91cx42_bridge->parent = &pdev->dev; 16523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch strcpy(ca91cx42_bridge->name, driver_name); 16533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup IRQ */ 16553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_irq_init(ca91cx42_bridge); 16563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 16573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Initialization failed.\n"); 16583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_irq; 16593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add master windows to list */ 1662886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->master_resources); 16633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_MASTER; i++) { 16643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = kmalloc(sizeof(struct vme_master_resource), 16653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 16663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (master_image == NULL) { 16673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "master resource structure\n"); 16693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_master; 16713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->parent = ca91cx42_bridge; 1673886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock_init(&master_image->lock); 16743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->locked = 0; 16753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->number = i; 16763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | 16773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_CRCSR | VME_USER1 | VME_USER2; 16783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 16793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 16803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; 1681886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&master_image->bus_resource, 0, 16823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch sizeof(struct resource)); 16833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->kern_base = NULL; 1684886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&master_image->list, 1685886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->master_resources); 16863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add slave windows to list */ 1689886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->slave_resources); 16903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_SLAVE; i++) { 16913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = kmalloc(sizeof(struct vme_slave_resource), 16923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 16933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slave_image == NULL) { 16943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "slave resource structure\n"); 16963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_slave; 16983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->parent = ca91cx42_bridge; 1700886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&slave_image->mtx); 17013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->locked = 0; 17023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->number = i; 17033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | 17043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_USER2; 17053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only windows 0 and 4 support A16 */ 17073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (i == 0 || i == 4) 17083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr |= VME_A16; 17093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 17113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 1712886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&slave_image->list, 1713886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->slave_resources); 17143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 17163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add dma engines to list */ 1717886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->dma_resources); 17183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_DMA; i++) { 17193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), 17203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 17213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (dma_ctrlr == NULL) { 17223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "dma resource structure\n"); 17243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dma; 17263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->parent = ca91cx42_bridge; 1728886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&dma_ctrlr->mtx); 17293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->locked = 0; 17303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->number = i; 17314f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | 17324f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_MEM_TO_VME; 1733886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->pending); 1734886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->running); 1735886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&dma_ctrlr->list, 1736886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->dma_resources); 17373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 17393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add location monitor to list */ 1740886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->lm_resources); 17413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); 17423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (lm == NULL) { 17433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "location monitor resource structure\n"); 17453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_lm; 17473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->parent = ca91cx42_bridge; 1749886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&lm->mtx); 17503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->locked = 0; 17513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->number = 1; 17523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->monitors = 4; 1753886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&lm->list, &ca91cx42_bridge->lm_resources); 17543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_get = ca91cx42_slave_get; 17563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_set = ca91cx42_slave_set; 17573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_get = ca91cx42_master_get; 17583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_set = ca91cx42_master_set; 17593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_read = ca91cx42_master_read; 17603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_write = ca91cx42_master_write; 17613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; 17623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; 17633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; 17643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; 1765c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_set = ca91cx42_irq_set; 1766c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; 17673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_set = ca91cx42_lm_set; 17683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_get = ca91cx42_lm_get; 17693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; 17703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; 17713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slot_get = ca91cx42_slot_get; 17723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 177329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + MISC_CTL); 17743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "Board is%s the VME system controller\n", 17753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); 177629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_info(&pdev->dev, "Slot ID is %d\n", 177729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_slot_get(ca91cx42_bridge)); 17783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17797946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) 17803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); 178160479690af6d559d4202bed139db90323386bd2bMartyn Welch 17823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need to save ca91cx42_bridge pointer locally in link list for use in 17833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * ca91cx42_remove() 17843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 17853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = vme_register_bridge(ca91cx42_bridge); 17863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 17873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Registration failed.\n"); 17883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_reg; 17893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 179129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_set_drvdata(pdev, ca91cx42_bridge); 179229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 17933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 17943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_reg: 179629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 17973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_lm: 17983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1799886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->lm_resources) { 18003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 18013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 18033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dma: 18053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1806886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->dma_resources) { 18073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 18083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 181060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 18113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_slave: 18123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1813886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->slave_resources) { 18143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 18153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 18173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_master: 18193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1820886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->master_resources) { 18213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 18223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 18233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 18253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 182729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(ca91cx42_device, pdev); 18283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_irq: 18293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_test: 183029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(ca91cx42_device->base); 18313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 18323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 18333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 18343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 18353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_enable: 183629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kfree(ca91cx42_device); 183729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welcherr_driver: 18383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 18393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_struct: 18403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 184160479690af6d559d4202bed139db90323386bd2bMartyn Welch 184260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 184360479690af6d559d4202bed139db90323386bd2bMartyn Welch 1844efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic void ca91cx42_remove(struct pci_dev *pdev) 184560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 18463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 18473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 18483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 18493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 18503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 185129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 185229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); 185329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 185429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 185529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 185660479690af6d559d4202bed139db90323386bd2bMartyn Welch 18573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off Ints */ 185829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 18593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off the windows */ 186129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI0_CTL); 186229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI1_CTL); 186329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI2_CTL); 186429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI3_CTL); 186529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI4_CTL); 186629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI5_CTL); 186729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI6_CTL); 186829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI7_CTL); 186929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI0_CTL); 187029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI1_CTL); 187129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI2_CTL); 187229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI3_CTL); 187329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI4_CTL); 187429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI5_CTL); 187529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI6_CTL); 187629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI7_CTL); 18773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_unregister_bridge(ca91cx42_bridge); 1879bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 1880bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 1881bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 18823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1883886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->lm_resources) { 18843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 18853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 188760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 18883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1890886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->dma_resources) { 18913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 18923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 189460479690af6d559d4202bed139db90323386bd2bMartyn Welch } 189560479690af6d559d4202bed139db90323386bd2bMartyn Welch 18963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1897886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->slave_resources) { 18983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 18993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 19003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 19013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 190260479690af6d559d4202bed139db90323386bd2bMartyn Welch 19033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1904886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->master_resources) { 19053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 19063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 19073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 19083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 19093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 191060479690af6d559d4202bed139db90323386bd2bMartyn Welch 191129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(bridge, pdev); 191260479690af6d559d4202bed139db90323386bd2bMartyn Welch 191329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(bridge->base); 191460479690af6d559d4202bed139db90323386bd2bMartyn Welch 19153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 191660479690af6d559d4202bed139db90323386bd2bMartyn Welch 19173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 19183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 19193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 192060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 192160479690af6d559d4202bed139db90323386bd2bMartyn Welch 19223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void) 192360479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 19243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_unregister_driver(&ca91cx42_driver); 19253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 192660479690af6d559d4202bed139db90323386bd2bMartyn Welch 192712b2d5c0895a03e941e7c145d9d23a45908a857bMartyn WelchMODULE_PARM_DESC(geoid, "Override geographical addressing"); 192812b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchmodule_param(geoid, int, 0); 192912b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 19303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); 19313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_LICENSE("GPL"); 193260479690af6d559d4202bed139db90323386bd2bMartyn Welch 19333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_init(ca91cx42_init); 19343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_exit(ca91cx42_exit); 1935