vme_ca91cx42.c revision 7c0ace54887872ebd99fefdfe85d273295a09426
160479690af6d559d4202bed139db90323386bd2bMartyn Welch/* 260479690af6d559d4202bed139db90323386bd2bMartyn Welch * Support for the Tundra Universe I/II VME-PCI Bridge Chips 360479690af6d559d4202bed139db90323386bd2bMartyn Welch * 466bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com> 566bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 660479690af6d559d4202bed139db90323386bd2bMartyn Welch * 760479690af6d559d4202bed139db90323386bd2bMartyn Welch * Based on work by Tom Armistead and Ajit Prem 860479690af6d559d4202bed139db90323386bd2bMartyn Welch * Copyright 2004 Motorola Inc. 960479690af6d559d4202bed139db90323386bd2bMartyn Welch * 1060479690af6d559d4202bed139db90323386bd2bMartyn Welch * Derived from ca91c042.c by Michael Wyrick 1160479690af6d559d4202bed139db90323386bd2bMartyn Welch * 1260479690af6d559d4202bed139db90323386bd2bMartyn Welch * This program is free software; you can redistribute it and/or modify it 1360479690af6d559d4202bed139db90323386bd2bMartyn Welch * under the terms of the GNU General Public License as published by the 1460479690af6d559d4202bed139db90323386bd2bMartyn Welch * Free Software Foundation; either version 2 of the License, or (at your 1560479690af6d559d4202bed139db90323386bd2bMartyn Welch * option) any later version. 1660479690af6d559d4202bed139db90323386bd2bMartyn Welch */ 1760479690af6d559d4202bed139db90323386bd2bMartyn Welch 1860479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/module.h> 1960479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/mm.h> 2060479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/types.h> 2160479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/errno.h> 2260479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/pci.h> 2360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/dma-mapping.h> 2460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/poll.h> 2560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/interrupt.h> 2660479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/spinlock.h> 276af783c8ba3418a8ffc50f1266d9b1e35a3322dbGreg Kroah-Hartman#include <linux/sched.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 297946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/time.h> 307946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/io.h> 317946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/uaccess.h> 3260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme.h" 3460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme_bridge.h" 3560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "vme_ca91cx42.h" 3660479690af6d559d4202bed139db90323386bd2bMartyn Welch 373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void); 383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); 393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_remove(struct pci_dev *); 403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void); 4160479690af6d559d4202bed139db90323386bd2bMartyn Welch 4212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch/* Module parameters */ 4312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchstatic int geoid; 4412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic char driver_name[] = "vme_ca91cx42"; 4660479690af6d559d4202bed139db90323386bd2bMartyn Welch 4713ac58dac0c6b1edeb060102049b07ebceea9a40Németh Mártonstatic const struct pci_device_id 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{ 6129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 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{ 8529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 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{ 9229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch wake_up(&(bridge->iack_queue)); 9360479690af6d559d4202bed139db90323386bd2bMartyn Welch 943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_SW_IACK; 9560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 9660479690af6d559d4202bed139db90323386bd2bMartyn Welch 9748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 ca91cx42_VERR_irqhandler(struct vme_bridge *ca91cx42_bridge) 9860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 9960479690af6d559d4202bed139db90323386bd2bMartyn Welch int val; 10048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct ca91cx42_driver *bridge; 10148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 10248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 10360479690af6d559d4202bed139db90323386bd2bMartyn Welch 10429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch val = ioread32(bridge->base + DGCS); 10560479690af6d559d4202bed139db90323386bd2bMartyn Welch 10660479690af6d559d4202bed139db90323386bd2bMartyn Welch if (!(val & 0x00000800)) { 10748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "ca91cx42_VERR_irqhandler DMA " 10848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Read Error DGCS=%08X\n", val); 10960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 1103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_VERR; 11260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 11360479690af6d559d4202bed139db90323386bd2bMartyn Welch 11448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 ca91cx42_LERR_irqhandler(struct vme_bridge *ca91cx42_bridge) 11560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 11660479690af6d559d4202bed139db90323386bd2bMartyn Welch int val; 11748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct ca91cx42_driver *bridge; 11860479690af6d559d4202bed139db90323386bd2bMartyn Welch 11948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 12060479690af6d559d4202bed139db90323386bd2bMartyn Welch 12148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch val = ioread32(bridge->base + DGCS); 12260479690af6d559d4202bed139db90323386bd2bMartyn Welch 12348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch if (!(val & 0x00000800)) 12448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "ca91cx42_LERR_irqhandler DMA " 12548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Read Error DGCS=%08X\n", val); 12660479690af6d559d4202bed139db90323386bd2bMartyn Welch 1273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_LERR; 12860479690af6d559d4202bed139db90323386bd2bMartyn Welch} 12960479690af6d559d4202bed139db90323386bd2bMartyn Welch 1303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 13129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge, 13229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int stat) 13360479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 1343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int vec, i, serviced = 0; 13529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 13629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 13729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 13829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 13960479690af6d559d4202bed139db90323386bd2bMartyn Welch 14060479690af6d559d4202bed139db90323386bd2bMartyn Welch for (i = 7; i > 0; i--) { 1413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (1 << i)) { 14229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vec = ioread32(bridge->base + 1433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_V_STATID[i]) & 0xff; 1443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 145c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch vme_irq_handler(ca91cx42_bridge, i, vec); 1463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch serviced |= (1 << i); 14860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 14960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 1503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return serviced; 15260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 15360479690af6d559d4202bed139db90323386bd2bMartyn Welch 15429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic irqreturn_t ca91cx42_irqhandler(int irq, void *ptr) 15560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 1563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 stat, enable, serviced = 0; 15729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 15829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 15960479690af6d559d4202bed139db90323386bd2bMartyn Welch 16029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = ptr; 16160479690af6d559d4202bed139db90323386bd2bMartyn Welch 16229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 16329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch enable = ioread32(bridge->base + LINT_EN); 16529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch stat = ioread32(bridge->base + LINT_STAT); 16660479690af6d559d4202bed139db90323386bd2bMartyn Welch 1673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only look at unmasked interrupts */ 1683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch stat &= enable; 1693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (unlikely(!stat)) 1713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return IRQ_NONE; 1723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_DMA) 17429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_DMA_irqhandler(bridge); 1753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 1763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_LM3)) 17729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_LM_irqhandler(bridge, stat); 1783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_MBOX) 17929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_MB_irqhandler(bridge, stat); 1803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_SW_IACK) 18129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_IACK_irqhandler(bridge); 1823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_VERR) 18348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= ca91cx42_VERR_irqhandler(ca91cx42_bridge); 1843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_LERR) 18548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= ca91cx42_LERR_irqhandler(ca91cx42_bridge); 1863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | 1873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | 1883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | 1893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ7)) 19029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat); 1913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear serviced interrupts */ 19329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(stat, bridge->base + LINT_STAT); 19460479690af6d559d4202bed139db90323386bd2bMartyn Welch 19560479690af6d559d4202bed139db90323386bd2bMartyn Welch return IRQ_HANDLED; 19660479690af6d559d4202bed139db90323386bd2bMartyn Welch} 19760479690af6d559d4202bed139db90323386bd2bMartyn Welch 19829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) 19960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int result, tmp; 2013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 20229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 20329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 20429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 20560479690af6d559d4202bed139db90323386bd2bMartyn Welch 2063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need pdev */ 20729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 20860479690af6d559d4202bed139db90323386bd2bMartyn Welch 2093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialise list for VME bus errors */ 21029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch INIT_LIST_HEAD(&(ca91cx42_bridge->vme_errors)); 21160479690af6d559d4202bed139db90323386bd2bMartyn Welch 21229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch mutex_init(&(ca91cx42_bridge->irq_mtx)); 213c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable interrupts from PCI to VME */ 2153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + VINT_EN); 21660479690af6d559d4202bed139db90323386bd2bMartyn Welch 2173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable PCI interrupts */ 2183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_EN); 2193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear Any Pending PCI Interrupts */ 2203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); 22160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, 22329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch driver_name, ca91cx42_bridge); 2243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (result) { 2253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", 2263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev->irq); 2273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return result; 22860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 22960479690af6d559d4202bed139db90323386bd2bMartyn Welch 2303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Ensure all interrupts are mapped to PCI Interrupt 0 */ 2313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP0); 2323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP1); 2333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP2); 2343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable DMA, mailbox & LM Interrupts */ 2363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | 2373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | 2383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; 2393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 24160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 24360479690af6d559d4202bed139db90323386bd2bMartyn Welch} 24460479690af6d559d4202bed139db90323386bd2bMartyn Welch 24529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, 24629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 24760479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable interrupts from PCI to VME */ 24929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VINT_EN); 25060479690af6d559d4202bed139db90323386bd2bMartyn Welch 2513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable PCI interrupts */ 25229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 2533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear Any Pending PCI Interrupts */ 25429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); 25560479690af6d559d4202bed139db90323386bd2bMartyn Welch 2563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch free_irq(pdev->irq, pdev); 2573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 25860479690af6d559d4202bed139db90323386bd2bMartyn Welch 2593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 2603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Set up an VME interrupt 2613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 26229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchvoid ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, int state, 26329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int sync) 264c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 266c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch struct pci_dev *pdev; 2673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 26829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 26929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 27029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 27160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable IRQ level */ 27329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + LINT_EN); 2743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 275c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (state == 0) 2763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_LINT_VIRQ[level]; 277c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch else 278c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tmp |= CA91CX42_LINT_VIRQ[level]; 27960479690af6d559d4202bed139db90323386bd2bMartyn Welch 28029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 281c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 282c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if ((state == 0) && (sync != 0)) { 2833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, 2843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev); 2853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch synchronize_irq(pdev->irq); 28760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 28860479690af6d559d4202bed139db90323386bd2bMartyn Welch} 28960479690af6d559d4202bed139db90323386bd2bMartyn Welch 29029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchint ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, 29129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int statid) 29260479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 29429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 29529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 29629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 29760479690af6d559d4202bed139db90323386bd2bMartyn Welch 2983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Universe can only generate even vectors */ 2993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (statid & 1) 3003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 30160479690af6d559d4202bed139db90323386bd2bMartyn Welch 30229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch mutex_lock(&(bridge->vme_int)); 30360479690af6d559d4202bed139db90323386bd2bMartyn Welch 30429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 30560479690af6d559d4202bed139db90323386bd2bMartyn Welch 3063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Set Status/ID */ 30729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(statid << 24, bridge->base + STATID); 3083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Assert VMEbus IRQ */ 3103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp | (1 << (level + 24)); 31129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 31260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Wait for IACK */ 31429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch wait_event_interruptible(bridge->iack_queue, 0); 3153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Return interrupt to low state */ 31729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 3183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp & ~(1 << (level + 24)); 31929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 3203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 32129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch mutex_unlock(&(bridge->vme_int)); 3223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 32460479690af6d559d4202bed139db90323386bd2bMartyn Welch} 32560479690af6d559d4202bed139db90323386bd2bMartyn Welch 3263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, 3273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 3283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) 32960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 33021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, addr = 0, granularity; 3313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 3323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int vme_bound, pci_offset; 33348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 33429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 33529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 33648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 33748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 33848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 33960479690af6d559d4202bed139db90323386bd2bMartyn Welch 3403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 34160479690af6d559d4202bed139db90323386bd2bMartyn Welch 3423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 3433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A16: 3443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A16; 3453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A24: 3473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A24; 3483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A32: 3503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A32; 3513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER1: 3533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER1; 3543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER2: 3563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER2; 3573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 3593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 3603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 3613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 3623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 36348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 3643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 36660479690af6d559d4202bed139db90323386bd2bMartyn Welch } 36760479690af6d559d4202bed139db90323386bd2bMartyn Welch 3683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 3693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 3703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * accordingly 3713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 37221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch vme_bound = vme_base + size; 3733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_offset = pci_base - vme_base; 3743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 3763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 3773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 3783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 3793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_base & (granularity - 1)) { 38148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME base " 38248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 3853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_bound & (granularity - 1)) { 38648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME bound " 38748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 3903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (pci_offset & (granularity - 1)) { 39148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " 39248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 39460479690af6d559d4202bed139db90323386bd2bMartyn Welch } 39560479690af6d559d4202bed139db90323386bd2bMartyn Welch 3963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 39729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 3983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_EN; 39929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 40060479690af6d559d4202bed139db90323386bd2bMartyn Welch 4013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 40229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); 40329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); 40429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); 4053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 4073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; 4083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= addr; 4093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 4113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); 4123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 4133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; 4143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_USER) 4153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; 4163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 4173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; 4183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_DATA) 4193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; 4203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 42229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 4253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_EN; 4263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 42729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 43060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 43160479690af6d559d4202bed139db90323386bd2bMartyn Welch 4323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, 4333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 4343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) 43560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 4363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, granularity = 0, ctl = 0; 4373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_bound, pci_offset; 43829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 43929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 44029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 4413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 44360479690af6d559d4202bed139db90323386bd2bMartyn Welch 4443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 4453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 4463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 4473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 4483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Read Registers */ 45029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 4513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 45229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); 45329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); 45429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); 4553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *pci_base = (dma_addr_t)vme_base + pci_offset; 4573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *size = (unsigned long long)((vme_bound - *vme_base) + granularity); 4583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 4603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 4613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 4623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_EN) 4643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 4653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) 4673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 4683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) 4693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 4703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) 4713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 4723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) 4733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 4743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) 4753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 4763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) 4783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 4793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) 4803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 4813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_PGM) 4823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_PROG; 4833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_DATA) 4843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_DATA; 4853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 4873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 4883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 4903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Allocate and map PCI Resource 4913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 4923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_alloc_resource(struct vme_master_resource *image, 4933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long size) 4943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 4953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long existing_size; 4963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 4973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 49829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 49929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 50029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = image->parent; 5013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Find pci_dev container of dev */ 5033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge->parent == NULL) { 50448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); 5053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 5063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 5083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5098fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch existing_size = (unsigned long long)(image->bus_resource.end - 5108fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start); 5113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* If the existing size is OK, return */ 5133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size == (size - 1)) 5143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size != 0) { 5173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 5198fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name != NULL) 5208fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 5218fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch release_resource(&(image->bus_resource)); 5228fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch memset(&(image->bus_resource), 0, sizeof(struct resource)); 5233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5258fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 5260aa3f139cd5123ffb8f397b91d777635e9761c24Julia Lawall image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); 5278fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 52848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate " 52948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "memory for resource name\n"); 5303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_name; 5323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 53360479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5358fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch sprintf((char *)image->bus_resource.name, "%s.%d", 5363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->name, image->number); 5373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5388fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start = 0; 5398fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.end = (unsigned long)size; 5408fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.flags = IORESOURCE_MEM; 5413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_bus_alloc_resource(pdev->bus, 5438fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch &(image->bus_resource), size, size, PCIBIOS_MIN_MEM, 5443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 0, NULL, NULL); 5453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 54648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " 54748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "resource for window %d size 0x%lx start 0x%lx\n", 5483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->number, (unsigned long)size, 5498fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch (unsigned long)image->bus_resource.start); 5503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 55160479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = ioremap_nocache( 5548fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start, size); 5553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (image->kern_base == NULL) { 55648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); 5573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 55960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 56060479690af6d559d4202bed139db90323386bd2bMartyn Welch 5613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 5653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 5668fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch release_resource(&(image->bus_resource)); 5673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 5688fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 5698fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch memset(&(image->bus_resource), 0, sizeof(struct resource)); 5703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_name: 5713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 5723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 5754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Free and unmap PCI Resource 5764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 5773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_free_resource(struct vme_master_resource *image) 5783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 5818fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch release_resource(&(image->bus_resource)); 5828fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 5838fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch memset(&(image->bus_resource), 0, sizeof(struct resource)); 5843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_master_set(struct vme_master_resource *image, int enabled, 5883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 5893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) 5903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 59221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, granularity = 0; 5933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 5943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_bound, vme_offset, pci_base; 59548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 59629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 59729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 59848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 59948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 60048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 6013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 60221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch i = image->number; 60321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 60421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if ((i == 0) || (i == 4)) 60521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x1000; 60621e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch else 60721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x10000; 60821e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 6093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Verify input data */ 61021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (vme_base & (granularity - 1)) { 61148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 61248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 61621e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (size & (granularity - 1)) { 61748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 61848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_lock(&(image->lock)); 6243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Let's allocate the resource here rather than further up the stack as 6273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * it avoids pushing loads of bus dependant stuff up the stack 6283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 6293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_alloc_resource(image, size); 6303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 6313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 63248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " 63348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "for resource name\n"); 6343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 6353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_res; 6363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6388fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch pci_base = (unsigned long long)image->bus_resource.start; 6393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 6423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * according to window granularity. 6433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 64421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch pci_bound = pci_base + size; 6453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_offset = vme_base - pci_base; 6463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 64829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 6493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_EN; 65029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 6513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 6533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; 6543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_BLT) 6553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; 6563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_MBLT) 6573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; 6583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 6603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; 6613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (dwidth) { 6623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D8: 6633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; 6643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D16: 6663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; 6673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D32: 6693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; 6703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D64: 6723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; 6733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 6753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 67648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); 6773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dwidth; 6793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 68060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 6813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 6833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; 6843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 68560479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A16: 6863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; 68760479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 68860479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A24: 6893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; 69060479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 69160479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A32: 6923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; 6933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 6953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; 69660479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 69760479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER1: 6983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; 69960479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 70060479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER2: 7013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; 7023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 7043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 7053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 7063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 7073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 70848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 7093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 7103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_aspace; 71160479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 71260479690af6d559d4202bed139db90323386bd2bMartyn Welch } 71360479690af6d559d4202bed139db90323386bd2bMartyn Welch 7143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); 7153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 7163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; 7173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 7183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; 71960479690af6d559d4202bed139db90323386bd2bMartyn Welch 7203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 72129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); 72229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); 72329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); 7243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 72629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 7293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_EN; 7303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 73129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 7343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 7353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_aspace: 7373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dwidth: 7383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_free_resource(image); 7393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_res: 7403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_window: 7413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 7423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 7433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint __ca91cx42_master_get(struct vme_master_resource *image, int *enabled, 7453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 7463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 7473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 7483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, ctl; 7493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_base, pci_bound, vme_offset; 75029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 75129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 75229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 7533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 7553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 75629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 7573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 75829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); 75929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); 76029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); 7613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *vme_base = pci_base + vme_offset; 76321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch *size = (unsigned long long)(pci_bound - pci_base); 7643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 7663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 7673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 7683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = 0; 7693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_EN) 7713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 7723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 7743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VAS_M) { 7753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A16: 7763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 7773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A24: 7793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 7803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A32: 7823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 7833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_CRCSR: 7853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_CRCSR; 7863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER1: 7883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 7893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER2: 7913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 7923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 7943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* XXX Not sure howto check for MBLT */ 7963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 7973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_VCT_BLT) 7983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_BLT; 7993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SCT; 8013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) 8033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 8043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 8063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_PGM_PGM) 8083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_PROG; 8093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_DATA; 8113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 8133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VDW_M) { 8143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D8: 8153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D8; 8163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D16: 8183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D16; 8193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D32: 8213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D32; 8223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D64: 8243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D64; 8253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 8273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 8293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_master_get(struct vme_master_resource *image, int *enabled, 8323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 8333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 8343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 8353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval; 8363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_lock(&(image->lock)); 8383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, 8403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch cycle, dwidth); 8413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 8433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 8453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf, 8483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch size_t count, loff_t offset) 8493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 85021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch ssize_t retval; 85160479690af6d559d4202bed139db90323386bd2bMartyn Welch 8523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_lock(&(image->lock)); 85360479690af6d559d4202bed139db90323386bd2bMartyn Welch 8543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); 8553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = count; 85660479690af6d559d4202bed139db90323386bd2bMartyn Welch 8573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 8583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 86060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 86160479690af6d559d4202bed139db90323386bd2bMartyn Welch 8623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf, 8633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch size_t count, loff_t offset) 86460479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 8653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 86660479690af6d559d4202bed139db90323386bd2bMartyn Welch 8673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_lock(&(image->lock)); 86860479690af6d559d4202bed139db90323386bd2bMartyn Welch 8693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); 8703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = count; 8713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_unlock(&(image->lock)); 8733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 87560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 87660479690af6d559d4202bed139db90323386bd2bMartyn Welch 87704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welchunsigned int ca91cx42_master_rmw(struct vme_master_resource *image, 87804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch unsigned int mask, unsigned int compare, unsigned int swap, 87904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch loff_t offset) 88004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch{ 88104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch u32 pci_addr, result; 88204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch int i; 88304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct ca91cx42_driver *bridge; 88404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct device *dev; 88504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 88604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch bridge = image->parent->driver_priv; 88704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev = image->parent->parent; 88804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 88904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Find the PCI address that maps to the desired VME address */ 89004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch i = image->number; 89104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 89204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Locking as we can only do one of these at a time */ 89304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch mutex_lock(&(bridge->vme_rmw)); 89404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 89504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Lock image */ 89604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch spin_lock(&(image->lock)); 89704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 89804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch pci_addr = (u32)image->kern_base + offset; 89904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 90004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Address must be 4-byte aligned */ 90104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch if (pci_addr & 0x3) { 90204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev_err(dev, "RMW Address not 4-byte aligned\n"); 9037c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall result = -EINVAL; 9047c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall goto out; 90504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch } 90604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 90704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Ensure RMW Disabled whilst configuring */ 90804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 90904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 91004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Configure registers */ 91104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(mask, bridge->base + SCYC_EN); 91204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(compare, bridge->base + SCYC_CMP); 91304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(swap, bridge->base + SCYC_SWP); 91404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(pci_addr, bridge->base + SCYC_ADDR); 91504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 91604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Enable RMW */ 91704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); 91804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 91904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Kick process off with a read to the required address. */ 92004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch result = ioread32(image->kern_base + offset); 92104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 92204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Disable RMW */ 92304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 92404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 9257c0ace54887872ebd99fefdfe85d273295a09426Julia Lawallout: 92604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch spin_unlock(&(image->lock)); 92704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 92804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch mutex_unlock(&(bridge->vme_rmw)); 92904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 93004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch return result; 93104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch} 93204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 9334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchint ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, 9344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_attr *dest, size_t count) 9354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 9364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry, *prev; 9374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_pci *pci_attr; 9384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_vme *vme_attr; 9394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t desc_ptr; 9404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 94148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 94248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 94348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = list->parent->parent->parent; 9444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX descriptor must be aligned on 64-bit boundaries */ 946324148788bf3744d90fb6894ec5744eb0ca91b74Julia Lawall entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); 9474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (entry == NULL) { 94848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Failed to allocate memory for dma resource " 9494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "structure\n"); 9504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -ENOMEM; 9514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_mem; 9524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 9534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Test descriptor alignment */ 9554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((unsigned long)&(entry->descriptor) & CA91CX42_DCPP_M) { 95648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Descriptor not aligned to 16 byte boundary as " 9574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "required: %p\n", &(entry->descriptor)); 9584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 9594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_align; 9604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 9614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch memset(&(entry->descriptor), 0, sizeof(struct ca91cx42_dma_descriptor)); 9634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (dest->type == VME_DMA_VME) { 9654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_L2V; 9664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch vme_attr = (struct vme_dma_vme *)dest->private; 9674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch pci_attr = (struct vme_dma_pci *)src->private; 9684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 9694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch vme_attr = (struct vme_dma_vme *)src->private; 9704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch pci_attr = (struct vme_dma_pci *)dest->private; 9714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 9724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Check we can do fullfill required attributes */ 9744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | 9754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_USER2)) != 0) { 9764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 97748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 9784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 9794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_aspace; 9804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 9814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | 9834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_PROG | VME_DATA)) != 0) { 9844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 98548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 9864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 9874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_cycle; 9884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 9894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 9904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Check to see if we can fullfill source and destination */ 9914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || 9924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { 9934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 99448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Cannot perform transfer with this " 9954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "source-destination combination\n"); 9964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 9974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_direct; 9984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 9994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup cycle types */ 10014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_BLT) 10024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; 10034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup data width */ 10054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->dwidth) { 10064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D8: 10074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; 10084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D16: 10104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; 10114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D32: 10134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; 10144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D64: 10164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; 10174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 101948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid data width\n"); 10204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 10214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup address space */ 10244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->aspace) { 10254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A16: 10264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; 10274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A24: 10294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; 10304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A32: 10324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; 10334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER1: 10354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; 10364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER2: 10384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; 10394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 104148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid address space\n"); 10424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 10434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 10444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_SUPER) 10474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; 10484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_PROG) 10494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; 10504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dtbc = count; 10524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dla = pci_attr->address; 10534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dva = vme_attr->address; 10544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dcpp = CA91CX42_DCPP_NULL; 10554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Add to list */ 10574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_add_tail(&(entry->list), &(list->entries)); 10584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Fill out previous descriptors "Next Address" */ 10604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (entry->list.prev != &(list->entries)) { 10614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, 10624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 10634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* We need the bus address for the pointer */ 10644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch desc_ptr = virt_to_bus(&(entry->descriptor)); 10654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; 10664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 10694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_cycle: 10714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_aspace: 10724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_direct: 10734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_align: 10744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 10754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_mem: 10764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 10774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 10784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchstatic int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) 10804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 10814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 tmp; 10824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 10834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ca91cx42_bridge->driver_priv; 10854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch tmp = ioread32(bridge->base + DGCS); 10874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (tmp & CA91CX42_DGCS_ACT) 10894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 10904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch else 10914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 1; 10924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 10934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchint ca91cx42_dma_list_exec(struct vme_dma_list *list) 10954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 10964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_resource *ctrlr; 10974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 10984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 10994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t bus_addr; 11004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 val; 110148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 11024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ctrlr = list->parent; 11054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ctrlr->parent->driver_priv; 110748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = ctrlr->parent->parent; 11084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch mutex_lock(&(ctrlr->mtx)); 11104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (!(list_empty(&(ctrlr->running)))) { 11124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 11134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * XXX We have an active DMA transfer and currently haven't 11144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * sorted out the mechanism for "pending" DMA transfers. 11154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Return busy. 11164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 11174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Need to add to pending here */ 11184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch mutex_unlock(&(ctrlr->mtx)); 11194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EBUSY; 11204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 11214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_add(&(list->list), &(ctrlr->running)); 11224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Get first bus address and write into registers */ 11254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry = list_first_entry(&(list->entries), struct ca91cx42_dma_entry, 11264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 11274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bus_addr = virt_to_bus(&(entry->descriptor)); 11294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch mutex_unlock(&(ctrlr->mtx)); 11314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(0, bridge->base + DTBC); 11334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); 11344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Start the operation */ 11364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 11374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX Could set VMEbus On and Off Counters here */ 11394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); 11404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | 11424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 11434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR); 11444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 11464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= CA91CX42_DGCS_GO; 11484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 11504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch wait_event_interruptible(bridge->dma_queue, 11524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ca91cx42_dma_busy(ctrlr->parent)); 11534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 11554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Read status register, this register is valid until we kick off a 11564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * new transfer. 11574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 11584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 11594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 11614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR)) { 11624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 116348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); 11644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DCTL); 11654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Remove list from running list */ 11684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch mutex_lock(&(ctrlr->mtx)); 11694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_del(&(list->list)); 11704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch mutex_unlock(&(ctrlr->mtx)); 11714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 11734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchint ca91cx42_dma_list_empty(struct vme_dma_list *list) 11774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct list_head *pos, *temp; 11794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 11804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* detach and free each entry */ 11824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_for_each_safe(pos, temp, &(list->entries)) { 11834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_del(pos); 11844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry = list_entry(pos, struct ca91cx42_dma_entry, list); 11854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 11864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 11922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * All 4 location monitors reside at the same base - this is therefore a 11932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * system wide configuration. 11942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 11952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * This does not enable the LM monitor - that should be done when the first 11962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * callback is attached and disabled when the last callback is removed. 11972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 11982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, 11992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch vme_address_t aspace, vme_cycle_t cycle) 12002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 12012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 temp_base, lm_ctl = 0; 12022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch int i; 12032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 12042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 12052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 12072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 12082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check the alignment of the location monitor */ 12102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch temp_base = (u32)lm_base; 12112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (temp_base & 0xffff) { 12122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor must be aligned to 64KB " 12132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "boundary"); 12142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 12152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 12162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_lock(&(lm->mtx)); 12182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If we already have a callback attached, we can't move it! */ 12202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch for (i = 0; i < lm->monitors; i++) { 12212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[i] != NULL) { 12222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 12232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor callback attached, " 12242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "can't reset\n"); 12252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 12262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 12272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 12282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch switch (aspace) { 12302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A16: 12312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A16; 12322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 12332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A24: 12342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A24; 12352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 12362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A32: 12372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A32; 12382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 12392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch default: 12402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 12412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Invalid address space\n"); 12422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 12432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 12442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 12452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_SUPER) 12472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_SUPR; 12482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_USER) 12492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_NPRIV; 12502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_PROG) 12512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_PGM; 12522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_DATA) 12532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_DATA; 12542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_base, bridge->base + LM_BS); 12562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 12572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 12592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 12612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 12622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* Get configuration of the callback monitor and return whether it is enabled 12642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * or disabled. 12652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 12662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base, 12672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch vme_address_t *aspace, vme_cycle_t *cycle) 12682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 12692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, enabled = 0; 12702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 12712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 12732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_lock(&(lm->mtx)); 12752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); 12772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 12782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_EN) 12802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch enabled = 1; 12812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) 12832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A16; 12842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) 12852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A24; 12862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) 12872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A32; 12882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle = 0; 12902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_SUPR) 12912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_SUPER; 12922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_NPRIV) 12932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_USER; 12942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_PGM) 12952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_PROG; 12962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_DATA) 12972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_DATA; 12982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 12992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 13002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return enabled; 13022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 13052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Attach a callback to a specific location monitor. 13062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 13072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Callback will be passed the monitor triggered. 13082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 13092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, 13102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch void (*callback)(int)) 13112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 13122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, tmp; 13132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 13152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 13182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_lock(&(lm->mtx)); 13202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that the location monitor is configured - need PGM or DATA */ 13222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 13232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { 13242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 13252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor not properly configured\n"); 13262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 13272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check that a callback isn't already attached */ 13302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[monitor] != NULL) { 13312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 13322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Existing callback attached\n"); 13332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 13342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Attach callback */ 13372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = callback; 13382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Enable Location Monitor interrupt */ 13402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 13412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp |= CA91CX42_LINT_LM[monitor]; 13422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 13432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that global Location Monitor Enable set */ 13452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { 13462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_EN; 13472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 13482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 13512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 13532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 13562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Detach a callback function forn a specific location monitor. 13572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 13582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) 13592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 13602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 tmp; 13612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_lock(&(lm->mtx)); 13662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Disable Location Monitor and ensure previous interrupts are clear */ 13682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 13692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LINT_LM[monitor]; 13702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 13712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(CA91CX42_LINT_LM[monitor], 13732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->base + LINT_STAT); 13742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Detach callback */ 13762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = NULL; 13772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If all location monitors disabled, disable global Location Monitor */ 13792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 13802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch CA91CX42_LINT_LM3)) == 0) { 13812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LM_CTL); 13822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LM_CTL_EN; 13832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LM_CTL); 13842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch mutex_unlock(&(lm->mtx)); 13872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 13892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 139129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchint ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) 139260479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 13933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 slot = 0; 139429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 139529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 139629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 139760479690af6d559d4202bed139db90323386bd2bMartyn Welch 139812b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch if (!geoid) { 139929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ioread32(bridge->base + VCSR_BS); 140012b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); 140112b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch } else 140212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = geoid; 140312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 14043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return (int)slot; 14053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 14073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void) 14093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 14103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return pci_register_driver(&ca91cx42_driver); 14113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 14123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 14143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Configure CR/CSR space 14153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * 14163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Access to the CR/CSR can be configured at power-up. The location of the 14173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * CR/CSR registers in the CR/CSR address space is determined by the boards 14183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Auto-ID or Geographic address. This function ensures that the window is 14193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * enabled at an offset consistent with the boards geopgraphic address. 14203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 142129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, 142229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 14233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 14243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int crcsr_addr; 14253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int tmp, slot; 142629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 142729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 142829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 14293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 143029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ca91cx42_slot_get(ca91cx42_bridge); 143125331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 143225331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch /* Write CSR Base Address if slot ID is supplied as a module param */ 143325331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch if (geoid) 143425331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch iowrite32(geoid << 27, bridge->base + VCSR_BS); 143525331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 14363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); 14373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slot == 0) { 14383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Slot number is unset, not configuring " 14393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "CR/CSR space\n"); 14403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 144160479690af6d559d4202bed139db90323386bd2bMartyn Welch } 14423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Allocate mem for CR/CSR image */ 144429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, 144529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch &(bridge->crcsr_bus)); 144629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->crcsr_kernel == NULL) { 14473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " 14483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "image\n"); 14493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -ENOMEM; 145060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 145160479690af6d559d4202bed139db90323386bd2bMartyn Welch 145229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); 145360479690af6d559d4202bed139db90323386bd2bMartyn Welch 14543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch crcsr_addr = slot * (512 * 1024); 145529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); 145660479690af6d559d4202bed139db90323386bd2bMartyn Welch 145729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 14583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp |= CA91CX42_VCSR_CTL_EN; 145929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 146060479690af6d559d4202bed139db90323386bd2bMartyn Welch 14613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 146260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 146360479690af6d559d4202bed139db90323386bd2bMartyn Welch 146429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, 146529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 146660479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 14673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 146829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 146929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 147029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 147160479690af6d559d4202bed139db90323386bd2bMartyn Welch 14723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off CR/CSR space */ 147329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 14743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_VCSR_CTL_EN; 147529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 147660479690af6d559d4202bed139db90323386bd2bMartyn Welch 14773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Free image */ 147829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VCSR_TO); 147960479690af6d559d4202bed139db90323386bd2bMartyn Welch 148029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, 148129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_bus); 14823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 148360479690af6d559d4202bed139db90323386bd2bMartyn Welch 14843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) 14853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 14863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval, i; 14873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 data; 14883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 148929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 149029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *ca91cx42_device; 14913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 14923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 14933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 14943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 14953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 14963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* We want to support more than one of each bridge so we need to 14973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * dynamically allocate the bridge structure 14983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 14997a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); 15003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge == NULL) { 15023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 15033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "structure\n"); 15043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 15053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_struct; 15063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15087a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); 150929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 151029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (ca91cx42_device == NULL) { 151129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 151229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch "structure\n"); 151329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch retval = -ENOMEM; 151429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch goto err_driver; 151529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch } 151629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 151729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge->driver_priv = ca91cx42_device; 151829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 15193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable the device */ 15203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_enable_device(pdev); 15213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 15223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to enable device\n"); 15233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_enable; 15243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Map Registers */ 15273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_request_regions(pdev, driver_name); 15283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 15293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to reserve resources\n"); 15303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 15313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* map registers in BAR 0 */ 153429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), 15353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4096); 153629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (!ca91cx42_device->base) { 15373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to remap CRG region\n"); 15383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 15393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 15403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Check to see if the mapping worked out */ 154329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; 15443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (data != PCI_VENDOR_ID_TUNDRA) { 15453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "PCI_ID check failed\n"); 15463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 15473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_test; 15483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialize wait queues & mutual exclusion flags */ 155129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch init_waitqueue_head(&(ca91cx42_device->dma_queue)); 155229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch init_waitqueue_head(&(ca91cx42_device->iack_queue)); 155329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch mutex_init(&(ca91cx42_device->vme_int)); 155429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch mutex_init(&(ca91cx42_device->vme_rmw)); 15553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->parent = &(pdev->dev); 15573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch strcpy(ca91cx42_bridge->name, driver_name); 15583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup IRQ */ 15603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_irq_init(ca91cx42_bridge); 15613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 15623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Initialization failed.\n"); 15633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_irq; 15643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add master windows to list */ 15673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch INIT_LIST_HEAD(&(ca91cx42_bridge->master_resources)); 15683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_MASTER; i++) { 15693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = kmalloc(sizeof(struct vme_master_resource), 15703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 15713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (master_image == NULL) { 15723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 15733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "master resource structure\n"); 15743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 15753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_master; 15763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->parent = ca91cx42_bridge; 15783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch spin_lock_init(&(master_image->lock)); 15793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->locked = 0; 15803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->number = i; 15813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | 15823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_CRCSR | VME_USER1 | VME_USER2; 15833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 15843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 15853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; 15868fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch memset(&(master_image->bus_resource), 0, 15873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch sizeof(struct resource)); 15883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->kern_base = NULL; 15893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_add_tail(&(master_image->list), 15903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch &(ca91cx42_bridge->master_resources)); 15913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 15923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add slave windows to list */ 15943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch INIT_LIST_HEAD(&(ca91cx42_bridge->slave_resources)); 15953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_SLAVE; i++) { 15963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = kmalloc(sizeof(struct vme_slave_resource), 15973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 15983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slave_image == NULL) { 15993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "slave resource structure\n"); 16013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_slave; 16033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->parent = ca91cx42_bridge; 16053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch mutex_init(&(slave_image->mtx)); 16063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->locked = 0; 16073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->number = i; 16083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | 16093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_USER2; 16103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only windows 0 and 4 support A16 */ 16123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (i == 0 || i == 4) 16133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr |= VME_A16; 16143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 16163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 16173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_add_tail(&(slave_image->list), 16183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch &(ca91cx42_bridge->slave_resources)); 16193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 16213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add dma engines to list */ 16223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources)); 16233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_DMA; i++) { 16243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), 16253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 16263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (dma_ctrlr == NULL) { 16273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "dma resource structure\n"); 16293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dma; 16313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->parent = ca91cx42_bridge; 16333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch mutex_init(&(dma_ctrlr->mtx)); 16343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->locked = 0; 16353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->number = i; 16364f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | 16374f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_MEM_TO_VME; 16383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch INIT_LIST_HEAD(&(dma_ctrlr->pending)); 16393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch INIT_LIST_HEAD(&(dma_ctrlr->running)); 16403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_add_tail(&(dma_ctrlr->list), 16413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch &(ca91cx42_bridge->dma_resources)); 16423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 16443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add location monitor to list */ 16453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources)); 16463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); 16473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (lm == NULL) { 16483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "location monitor resource structure\n"); 16503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_lm; 16523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->parent = ca91cx42_bridge; 16543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch mutex_init(&(lm->mtx)); 16553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->locked = 0; 16563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->number = 1; 16573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->monitors = 4; 16583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_add_tail(&(lm->list), &(ca91cx42_bridge->lm_resources)); 16593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_get = ca91cx42_slave_get; 16613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_set = ca91cx42_slave_set; 16623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_get = ca91cx42_master_get; 16633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_set = ca91cx42_master_set; 16643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_read = ca91cx42_master_read; 16653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_write = ca91cx42_master_write; 16663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; 16673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; 16683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; 16693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; 1670c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_set = ca91cx42_irq_set; 1671c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; 16723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_set = ca91cx42_lm_set; 16733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_get = ca91cx42_lm_get; 16743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; 16753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; 16763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slot_get = ca91cx42_slot_get; 16773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 167829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + MISC_CTL); 16793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "Board is%s the VME system controller\n", 16803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); 168129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_info(&pdev->dev, "Slot ID is %d\n", 168229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_slot_get(ca91cx42_bridge)); 16833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16847946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) 16853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); 168660479690af6d559d4202bed139db90323386bd2bMartyn Welch 16873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need to save ca91cx42_bridge pointer locally in link list for use in 16883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * ca91cx42_remove() 16893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 16903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = vme_register_bridge(ca91cx42_bridge); 16913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 16923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Registration failed.\n"); 16933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_reg; 16943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 169629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_set_drvdata(pdev, ca91cx42_bridge); 169729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 16993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_unregister_bridge(ca91cx42_bridge); 17013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_reg: 170229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 17033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_lm: 17043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 17053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { 17063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 17073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 17093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dma: 17113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 17123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { 17133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 17143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 171660479690af6d559d4202bed139db90323386bd2bMartyn Welch } 17173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_slave: 17183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 17193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { 17203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 17213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 17233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_master: 17253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 17263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->master_resources)) { 17273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 17283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 17293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 17313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 173329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(ca91cx42_device, pdev); 17343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_irq: 17353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_test: 173629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(ca91cx42_device->base); 17373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 17383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 17393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 17403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 17413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_enable: 174229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kfree(ca91cx42_device); 174329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welcherr_driver: 17443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 17453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_struct: 17463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 174760479690af6d559d4202bed139db90323386bd2bMartyn Welch 174860479690af6d559d4202bed139db90323386bd2bMartyn Welch} 174960479690af6d559d4202bed139db90323386bd2bMartyn Welch 17503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchvoid ca91cx42_remove(struct pci_dev *pdev) 175160479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 17523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 17533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 17543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 17553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 17563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 175729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 175829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); 175929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 176029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 176129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 176260479690af6d559d4202bed139db90323386bd2bMartyn Welch 17633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off Ints */ 176429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 17653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off the windows */ 176729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI0_CTL); 176829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI1_CTL); 176929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI2_CTL); 177029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI3_CTL); 177129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI4_CTL); 177229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI5_CTL); 177329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI6_CTL); 177429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI7_CTL); 177529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI0_CTL); 177629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI1_CTL); 177729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI2_CTL); 177829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI3_CTL); 177929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI4_CTL); 178029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI5_CTL); 178129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI6_CTL); 178229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI7_CTL); 17833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_unregister_bridge(ca91cx42_bridge); 1785bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 1786bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 1787bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 17883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 17893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { 17903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 17913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 179360479690af6d559d4202bed139db90323386bd2bMartyn Welch } 17943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 17963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { 17973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 17983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 17993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 180060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 180160479690af6d559d4202bed139db90323386bd2bMartyn Welch 18023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 18033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { 18043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 18053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 18073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 180860479690af6d559d4202bed139db90323386bd2bMartyn Welch 18093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 18103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_for_each(pos, &(ca91cx42_bridge->master_resources)) { 18113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 18123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 18133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 18153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 181660479690af6d559d4202bed139db90323386bd2bMartyn Welch 181729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(bridge, pdev); 181860479690af6d559d4202bed139db90323386bd2bMartyn Welch 181929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(bridge->base); 182060479690af6d559d4202bed139db90323386bd2bMartyn Welch 18213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 182260479690af6d559d4202bed139db90323386bd2bMartyn Welch 18233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 18243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 182660479690af6d559d4202bed139db90323386bd2bMartyn Welch} 182760479690af6d559d4202bed139db90323386bd2bMartyn Welch 18283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void) 182960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 18303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_unregister_driver(&ca91cx42_driver); 18313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 183260479690af6d559d4202bed139db90323386bd2bMartyn Welch 183312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn WelchMODULE_PARM_DESC(geoid, "Override geographical addressing"); 183412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchmodule_param(geoid, int, 0); 183512b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 18363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); 18373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_LICENSE("GPL"); 183860479690af6d559d4202bed139db90323386bd2bMartyn Welch 18393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_init(ca91cx42_init); 18403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_exit(ca91cx42_exit); 1841