160479690af6d559d4202bed139db90323386bd2bMartyn Welch/* 260479690af6d559d4202bed139db90323386bd2bMartyn Welch * Support for the Tundra Universe I/II VME-PCI Bridge Chips 360479690af6d559d4202bed139db90323386bd2bMartyn Welch * 466bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com> 566bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 660479690af6d559d4202bed139db90323386bd2bMartyn Welch * 760479690af6d559d4202bed139db90323386bd2bMartyn Welch * Based on work by Tom Armistead and Ajit Prem 860479690af6d559d4202bed139db90323386bd2bMartyn Welch * Copyright 2004 Motorola Inc. 960479690af6d559d4202bed139db90323386bd2bMartyn Welch * 1060479690af6d559d4202bed139db90323386bd2bMartyn Welch * Derived from ca91c042.c by Michael Wyrick 1160479690af6d559d4202bed139db90323386bd2bMartyn Welch * 1260479690af6d559d4202bed139db90323386bd2bMartyn Welch * This program is free software; you can redistribute it and/or modify it 1360479690af6d559d4202bed139db90323386bd2bMartyn Welch * under the terms of the GNU General Public License as published by the 1460479690af6d559d4202bed139db90323386bd2bMartyn Welch * Free Software Foundation; either version 2 of the License, or (at your 1560479690af6d559d4202bed139db90323386bd2bMartyn Welch * option) any later version. 1660479690af6d559d4202bed139db90323386bd2bMartyn Welch */ 1760479690af6d559d4202bed139db90323386bd2bMartyn Welch 1860479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/module.h> 1960479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/mm.h> 2060479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/types.h> 2160479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/errno.h> 2260479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/pci.h> 2360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/dma-mapping.h> 2460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/poll.h> 2560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/interrupt.h> 2660479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/spinlock.h> 276af783c8ba3418a8ffc50f1266d9b1e35a3322dbGreg Kroah-Hartman#include <linux/sched.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 297946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/time.h> 307946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/io.h> 317946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch#include <linux/uaccess.h> 3260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme.h" 3460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme_bridge.h" 3560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "vme_ca91cx42.h" 3660479690af6d559d4202bed139db90323386bd2bMartyn Welch 373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void); 383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); 393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_remove(struct pci_dev *); 403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void); 4160479690af6d559d4202bed139db90323386bd2bMartyn Welch 4212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch/* Module parameters */ 4312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchstatic int geoid; 4412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 45584721cab2bdd26f63bfeca60c83f5e6b8eee7d0Vincent Bossierstatic const char driver_name[] = "vme_ca91cx42"; 4660479690af6d559d4202bed139db90323386bd2bMartyn Welch 472cea0cf284048b03a06e4370709cd751ddb9354eNamhyung Kimstatic DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = { 483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, 493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch { }, 5060479690af6d559d4202bed139db90323386bd2bMartyn Welch}; 5160479690af6d559d4202bed139db90323386bd2bMartyn Welch 523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic struct pci_driver ca91cx42_driver = { 533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .name = driver_name, 543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .id_table = ca91cx42_ids, 553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .probe = ca91cx42_probe, 563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch .remove = ca91cx42_remove, 5760479690af6d559d4202bed139db90323386bd2bMartyn Welch}; 5860479690af6d559d4202bed139db90323386bd2bMartyn Welch 5929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge) 6060479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 61886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->dma_queue); 6260479690af6d559d4202bed139db90323386bd2bMartyn Welch 633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_DMA; 643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 6560479690af6d559d4202bed139db90323386bd2bMartyn Welch 6629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat) 673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int i; 693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 serviced = 0; 7060479690af6d559d4202bed139db90323386bd2bMartyn Welch 713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < 4; i++) { 723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_LM[i]) { 733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* We only enable interrupts if the callback is set */ 7429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->lm_callback[i](i); 753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch serviced |= CA91CX42_LINT_LM[i]; 7660479690af6d559d4202bed139db90323386bd2bMartyn Welch } 7760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 7860479690af6d559d4202bed139db90323386bd2bMartyn Welch 793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return serviced; 803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8160479690af6d559d4202bed139db90323386bd2bMartyn Welch 823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX This needs to be split into 4 queues */ 8329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask) 843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 85886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->mbox_queue); 8660479690af6d559d4202bed139db90323386bd2bMartyn Welch 873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_MBOX; 883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8960479690af6d559d4202bed139db90323386bd2bMartyn Welch 9029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge) 913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 92886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->iack_queue); 9360479690af6d559d4202bed139db90323386bd2bMartyn Welch 943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_SW_IACK; 9560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 9660479690af6d559d4202bed139db90323386bd2bMartyn Welch 9748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 ca91cx42_VERR_irqhandler(struct vme_bridge *ca91cx42_bridge) 9860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 9960479690af6d559d4202bed139db90323386bd2bMartyn Welch int val; 10048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct ca91cx42_driver *bridge; 10148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 10248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 10360479690af6d559d4202bed139db90323386bd2bMartyn Welch 10429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch val = ioread32(bridge->base + DGCS); 10560479690af6d559d4202bed139db90323386bd2bMartyn Welch 10660479690af6d559d4202bed139db90323386bd2bMartyn Welch if (!(val & 0x00000800)) { 10748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "ca91cx42_VERR_irqhandler DMA " 10848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Read Error DGCS=%08X\n", val); 10960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 1103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_VERR; 11260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 11360479690af6d559d4202bed139db90323386bd2bMartyn Welch 11448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 ca91cx42_LERR_irqhandler(struct vme_bridge *ca91cx42_bridge) 11560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 11660479690af6d559d4202bed139db90323386bd2bMartyn Welch int val; 11748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct ca91cx42_driver *bridge; 11860479690af6d559d4202bed139db90323386bd2bMartyn Welch 11948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 12060479690af6d559d4202bed139db90323386bd2bMartyn Welch 12148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch val = ioread32(bridge->base + DGCS); 12260479690af6d559d4202bed139db90323386bd2bMartyn Welch 12348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch if (!(val & 0x00000800)) 12448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "ca91cx42_LERR_irqhandler DMA " 12548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Read Error DGCS=%08X\n", val); 12660479690af6d559d4202bed139db90323386bd2bMartyn Welch 1273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return CA91CX42_LINT_LERR; 12860479690af6d559d4202bed139db90323386bd2bMartyn Welch} 12960479690af6d559d4202bed139db90323386bd2bMartyn Welch 1303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 13129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge, 13229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int stat) 13360479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 1343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int vec, i, serviced = 0; 13529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 13629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 13729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 13829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 13960479690af6d559d4202bed139db90323386bd2bMartyn Welch 14060479690af6d559d4202bed139db90323386bd2bMartyn Welch for (i = 7; i > 0; i--) { 1413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (1 << i)) { 14229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vec = ioread32(bridge->base + 1433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_V_STATID[i]) & 0xff; 1443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 145c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch vme_irq_handler(ca91cx42_bridge, i, vec); 1463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch serviced |= (1 << i); 14860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 14960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 1503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return serviced; 15260479690af6d559d4202bed139db90323386bd2bMartyn Welch} 15360479690af6d559d4202bed139db90323386bd2bMartyn Welch 15429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic irqreturn_t ca91cx42_irqhandler(int irq, void *ptr) 15560479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 1563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 stat, enable, serviced = 0; 15729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 15829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 15960479690af6d559d4202bed139db90323386bd2bMartyn Welch 16029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = ptr; 16160479690af6d559d4202bed139db90323386bd2bMartyn Welch 16229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 16329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch enable = ioread32(bridge->base + LINT_EN); 16529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch stat = ioread32(bridge->base + LINT_STAT); 16660479690af6d559d4202bed139db90323386bd2bMartyn Welch 1673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only look at unmasked interrupts */ 1683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch stat &= enable; 1693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (unlikely(!stat)) 1713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return IRQ_NONE; 1723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_DMA) 17429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_DMA_irqhandler(bridge); 1753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 1763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_LM3)) 17729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_LM_irqhandler(bridge, stat); 1783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_MBOX) 17929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_MB_irqhandler(bridge, stat); 1803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_SW_IACK) 18129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_IACK_irqhandler(bridge); 1823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_VERR) 18348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= ca91cx42_VERR_irqhandler(ca91cx42_bridge); 1843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & CA91CX42_LINT_LERR) 18548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= ca91cx42_LERR_irqhandler(ca91cx42_bridge); 1863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | 1873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | 1883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | 1893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VIRQ7)) 19029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat); 1913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear serviced interrupts */ 19356fc508186dbec9aca46cd034ef12358fc044ac1Vincent Bossier iowrite32(serviced, bridge->base + LINT_STAT); 19460479690af6d559d4202bed139db90323386bd2bMartyn Welch 19560479690af6d559d4202bed139db90323386bd2bMartyn Welch return IRQ_HANDLED; 19660479690af6d559d4202bed139db90323386bd2bMartyn Welch} 19760479690af6d559d4202bed139db90323386bd2bMartyn Welch 19829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) 19960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int result, tmp; 2013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 20229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 20329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 20429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 20560479690af6d559d4202bed139db90323386bd2bMartyn Welch 2063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need pdev */ 20729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 20860479690af6d559d4202bed139db90323386bd2bMartyn Welch 2093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialise list for VME bus errors */ 210886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->vme_errors); 21160479690af6d559d4202bed139db90323386bd2bMartyn Welch 212886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_bridge->irq_mtx); 213c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable interrupts from PCI to VME */ 2153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + VINT_EN); 21660479690af6d559d4202bed139db90323386bd2bMartyn Welch 2173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable PCI interrupts */ 2183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_EN); 2193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear Any Pending PCI Interrupts */ 2203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); 22160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, 22329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch driver_name, ca91cx42_bridge); 2243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (result) { 2253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", 2263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev->irq); 2273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return result; 22860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 22960479690af6d559d4202bed139db90323386bd2bMartyn Welch 2303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Ensure all interrupts are mapped to PCI Interrupt 0 */ 2313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP0); 2323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP1); 2333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(0, bridge->base + LINT_MAP2); 2343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable DMA, mailbox & LM Interrupts */ 2363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | 2373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | 2383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; 2393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 24160479690af6d559d4202bed139db90323386bd2bMartyn Welch 2423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 24360479690af6d559d4202bed139db90323386bd2bMartyn Welch} 24460479690af6d559d4202bed139db90323386bd2bMartyn Welch 24529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, 24629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 24760479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 2483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable interrupts from PCI to VME */ 24929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VINT_EN); 25060479690af6d559d4202bed139db90323386bd2bMartyn Welch 2513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable PCI interrupts */ 25229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 2533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Clear Any Pending PCI Interrupts */ 25429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); 25560479690af6d559d4202bed139db90323386bd2bMartyn Welch 2563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch free_irq(pdev->irq, pdev); 2573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 25860479690af6d559d4202bed139db90323386bd2bMartyn Welch 25954b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossierstatic int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level) 26054b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier{ 26154b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier u32 tmp; 26254b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier 26354b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier tmp = ioread32(bridge->base + LINT_STAT); 26454b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier 26554b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier if (tmp & (1 << level)) 26654b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier return 0; 26754b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier else 26854b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier return 1; 26954b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier} 27054b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier 2713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 2723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Set up an VME interrupt 2733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 274efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, 275efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota int state, int sync) 276c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 2773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 278c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch struct pci_dev *pdev; 2793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 28029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 28129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 28229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 28360479690af6d559d4202bed139db90323386bd2bMartyn Welch 2843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable IRQ level */ 28529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + LINT_EN); 2863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 287c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (state == 0) 2883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_LINT_VIRQ[level]; 289c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch else 290c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tmp |= CA91CX42_LINT_VIRQ[level]; 29160479690af6d559d4202bed139db90323386bd2bMartyn Welch 29229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + LINT_EN); 293c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 294c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if ((state == 0) && (sync != 0)) { 2953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, 2963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev); 2973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 2983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch synchronize_irq(pdev->irq); 29960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 30060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 30160479690af6d559d4202bed139db90323386bd2bMartyn Welch 302efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, 30329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int statid) 30460479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 3053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 30629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 30729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 30829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 30960479690af6d559d4202bed139db90323386bd2bMartyn Welch 3103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Universe can only generate even vectors */ 3113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (statid & 1) 3123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 31360479690af6d559d4202bed139db90323386bd2bMartyn Welch 314886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_int); 31560479690af6d559d4202bed139db90323386bd2bMartyn Welch 31629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 31760479690af6d559d4202bed139db90323386bd2bMartyn Welch 3183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Set Status/ID */ 31929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(statid << 24, bridge->base + STATID); 3203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Assert VMEbus IRQ */ 3223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp | (1 << (level + 24)); 32329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 32460479690af6d559d4202bed139db90323386bd2bMartyn Welch 3253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Wait for IACK */ 32654b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier wait_event_interruptible(bridge->iack_queue, 32754b4a779c9565c475a17cc1254a38f293a5ba3efVincent Bossier ca91cx42_iack_received(bridge, level)); 3283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Return interrupt to low state */ 33029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VINT_EN); 3313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp = tmp & ~(1 << (level + 24)); 33229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VINT_EN); 3333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 334886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_int); 3353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 33760479690af6d559d4202bed139db90323386bd2bMartyn Welch} 33860479690af6d559d4202bed139db90323386bd2bMartyn Welch 339efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, 3403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_base, unsigned long long size, 3416af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch dma_addr_t pci_base, u32 aspace, u32 cycle) 34260479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 34321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, addr = 0, granularity; 3443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 3453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int vme_bound, pci_offset; 34648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 34729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 34829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 34948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 35048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 35148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 35260479690af6d559d4202bed139db90323386bd2bMartyn Welch 3533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 35460479690af6d559d4202bed139db90323386bd2bMartyn Welch 3553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 3563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A16: 3573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A16; 3583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A24: 3603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A24; 3613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A32: 3633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_A32; 3643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER1: 3663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER1; 3673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER2: 3693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch addr |= CA91CX42_VSI_CTL_VAS_USER2; 3703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 3713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 3723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 3733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 3743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 3753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 37648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 3773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 37960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 38060479690af6d559d4202bed139db90323386bd2bMartyn Welch 3813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 3823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 3833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * accordingly 3843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 38521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch vme_bound = vme_base + size; 3863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_offset = pci_base - vme_base; 3873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 3893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 3903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 3913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 3923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 3933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_base & (granularity - 1)) { 39448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME base " 39548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 3963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 3973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 3983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (vme_bound & (granularity - 1)) { 39948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME bound " 40048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 4013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 4023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 4033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (pci_offset & (granularity - 1)) { 40448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " 40548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 4063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 40760479690af6d559d4202bed139db90323386bd2bMartyn Welch } 40860479690af6d559d4202bed139db90323386bd2bMartyn Welch 4093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 41029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 4113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_EN; 41229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 41360479690af6d559d4202bed139db90323386bd2bMartyn Welch 4143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 41529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); 41629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); 41729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); 4183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 4203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; 4213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= addr; 4223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 4243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); 4253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 4263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; 4273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_USER) 4283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; 4293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 4303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; 4313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_DATA) 4323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; 4333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 43529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 4383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_VSI_CTL_EN; 4393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 44029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); 4413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 44360479690af6d559d4202bed139db90323386bd2bMartyn Welch} 44460479690af6d559d4202bed139db90323386bd2bMartyn Welch 445efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, 4463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long *vme_base, unsigned long long *size, 4476af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch dma_addr_t *pci_base, u32 *aspace, u32 *cycle) 44860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 4493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, granularity = 0, ctl = 0; 4503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long vme_bound, pci_offset; 45129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 45229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 45329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 4543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 45660479690af6d559d4202bed139db90323386bd2bMartyn Welch 4573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((i == 0) || (i == 4)) 4583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x1000; 4593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 4603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch granularity = 0x10000; 4613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Read Registers */ 46329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); 4643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 46529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); 46629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); 46729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); 4683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *pci_base = (dma_addr_t)vme_base + pci_offset; 4703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *size = (unsigned long long)((vme_bound - *vme_base) + granularity); 4713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 4733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 4743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 4753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_EN) 4773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 4783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) 4803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 4813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) 4823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 4833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) 4843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 4853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) 4863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 4873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) 4883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 4893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) 4913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 4923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) 4933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 4943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_PGM) 4953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_PROG; 4963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_VSI_CTL_PGM_DATA) 4973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_DATA; 4983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 5033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Allocate and map PCI Resource 5043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 5053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_alloc_resource(struct vme_master_resource *image, 5063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long size) 5073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long existing_size; 5093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 5103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct pci_dev *pdev; 51129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 51229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 51329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge = image->parent; 5143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Find pci_dev container of dev */ 5163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge->parent == NULL) { 51748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); 5183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 5193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); 5213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5228fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch existing_size = (unsigned long long)(image->bus_resource.end - 5238fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start); 5243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* If the existing size is OK, return */ 5263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size == (size - 1)) 5273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (existing_size != 0) { 5303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 532794a8946ba2339af09dd1f39c8462c3611bebf77Ilia Mirkin kfree(image->bus_resource.name); 533886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 534886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 5363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5378fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 5380aa3f139cd5123ffb8f397b91d777635e9761c24Julia Lawall image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); 5398fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 54048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate " 54148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "memory for resource name\n"); 5423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_name; 5443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 54560479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5478fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch sprintf((char *)image->bus_resource.name, "%s.%d", 5483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->name, image->number); 5493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5508fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start = 0; 5518fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.end = (unsigned long)size; 5528fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.flags = IORESOURCE_MEM; 5533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_bus_alloc_resource(pdev->bus, 555886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &image->bus_resource, size, size, PCIBIOS_MIN_MEM, 5563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 0, NULL, NULL); 5573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 55848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " 55948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "resource for window %d size 0x%lx start 0x%lx\n", 5603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->number, (unsigned long)size, 5618fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch (unsigned long)image->bus_resource.start); 5623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 56360479690af6d559d4202bed139db90323386bd2bMartyn Welch } 5643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = ioremap_nocache( 5668fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start, size); 5673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (image->kern_base == NULL) { 56848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); 5693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 5703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 57160479690af6d559d4202bed139db90323386bd2bMartyn Welch } 57260479690af6d559d4202bed139db90323386bd2bMartyn Welch 5733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 5743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 576886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 5773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 5788fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 579886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_name: 5813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 5823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 5854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Free and unmap PCI Resource 5864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 5873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_free_resource(struct vme_master_resource *image) 5883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 5893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch iounmap(image->kern_base); 5903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch image->kern_base = NULL; 591886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 5928fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 593886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 5943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 5953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 5963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 597efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_master_set(struct vme_master_resource *image, int enabled, 5986af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long vme_base, unsigned long long size, u32 aspace, 5996af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 cycle, u32 dwidth) 6003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 6013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval = 0; 60221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch unsigned int i, granularity = 0; 6033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int temp_ctl = 0; 6043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_bound, vme_offset, pci_base; 60548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *ca91cx42_bridge; 60629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 60729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 60848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ca91cx42_bridge = image->parent; 60948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 61048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = ca91cx42_bridge->driver_priv; 6113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 61221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch i = image->number; 61321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 61421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if ((i == 0) || (i == 4)) 61521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x1000; 61621e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch else 61721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch granularity = 0x10000; 61821e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch 6193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Verify input data */ 62021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (vme_base & (granularity - 1)) { 62148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 62248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 62621e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch if (size & (granularity - 1)) { 62748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid VME Window " 62848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 6293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_window; 6313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 633886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 6343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Let's allocate the resource here rather than further up the stack as 63725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * it avoids pushing loads of bus dependent stuff up the stack 6383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 6393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_alloc_resource(image, size); 6403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 641886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 64248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " 64348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "for resource name\n"); 6443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 6453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_res; 6463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 6473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6488fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch pci_base = (unsigned long long)image->bus_resource.start; 6493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* 6513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Bound address is a valid address for the window, adjust 6523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * according to window granularity. 6533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 65421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch pci_bound = pci_base + size; 6553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_offset = vme_base - pci_base; 6563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Disable while we are mucking around */ 65829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 6593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_EN; 66029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 6613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 6633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; 6643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_BLT) 6653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; 6663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_MBLT) 6673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; 6683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 6703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; 6713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (dwidth) { 6723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D8: 6733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; 6743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D16: 6763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; 6773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D32: 6793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; 6803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_D64: 6823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; 6833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 6843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 685886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 68648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); 6873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 6883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dwidth; 6893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 69060479690af6d559d4202bed139db90323386bd2bMartyn Welch } 6913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 6923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 6933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; 6943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (aspace) { 69560479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A16: 6963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; 69760479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 69860479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A24: 6993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; 70060479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 70160479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_A32: 7023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; 7033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_CRCSR: 7053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; 70660479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 70760479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER1: 7083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; 70960479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 71060479690af6d559d4202bed139db90323386bd2bMartyn Welch case VME_USER2: 7113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; 7123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_A64: 7143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER3: 7153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case VME_USER4: 7163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch default: 717886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 71848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); 7193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EINVAL; 7203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_aspace; 72160479690af6d559d4202bed139db90323386bd2bMartyn Welch break; 72260479690af6d559d4202bed139db90323386bd2bMartyn Welch } 72360479690af6d559d4202bed139db90323386bd2bMartyn Welch 7243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); 7253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_SUPER) 7263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; 7273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (cycle & VME_PROG) 7283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; 72960479690af6d559d4202bed139db90323386bd2bMartyn Welch 7303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup mapping */ 73129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); 73229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); 73329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); 7343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Write ctl reg without enable */ 73629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (enabled) 7393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch temp_ctl |= CA91CX42_LSI_CTL_EN; 7403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 74129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); 7423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 743886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 7443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 7453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_aspace: 7473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dwidth: 7483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_free_resource(image); 7493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_res: 7503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_window: 7513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 7523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 7533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 754efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int __ca91cx42_master_get(struct vme_master_resource *image, 755efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota int *enabled, unsigned long long *vme_base, unsigned long long *size, 7566af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 *aspace, u32 *cycle, u32 *dwidth) 7573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 7583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int i, ctl; 7593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned long long pci_base, pci_bound, vme_offset; 76029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 76129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 76229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 7633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch i = image->number; 7653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 76629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); 7673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 76829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); 76929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); 77029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); 7713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *vme_base = pci_base + vme_offset; 77321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch *size = (unsigned long long)(pci_bound - pci_base); 7743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 0; 7763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = 0; 7773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = 0; 7783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = 0; 7793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_EN) 7813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *enabled = 1; 7823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 7833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup address space */ 7843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VAS_M) { 7853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A16: 7863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A16; 7873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A24: 7893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A24; 7903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_A32: 7923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_A32; 7933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_CRCSR: 7953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_CRCSR; 7963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 7973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER1: 7983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER1; 7993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VAS_USER2: 8013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *aspace = VME_USER2; 8023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 8043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* XXX Not sure howto check for MBLT */ 8063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup cycle types */ 8073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_VCT_BLT) 8083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_BLT; 8093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SCT; 8113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) 8133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_SUPER; 8143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle |= VME_USER; 8163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ctl & CA91CX42_LSI_CTL_PGM_PGM) 8183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_PROG; 8193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch else 8203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *cycle = VME_DATA; 8213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup data width */ 8233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch switch (ctl & CA91CX42_LSI_CTL_VDW_M) { 8243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D8: 8253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D8; 8263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D16: 8283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D16; 8293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D32: 8313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D32; 8323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch case CA91CX42_LSI_CTL_VDW_D64: 8343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *dwidth = VME_D64; 8353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch break; 8363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 8373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 8393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 841efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, 8426af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long *vme_base, unsigned long long *size, u32 *aspace, 8436af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 *cycle, u32 *dwidth) 8443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 8453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval; 8463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 847886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 8483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, 8503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch cycle, dwidth); 8513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 852886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 8533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 8543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 8553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 8563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 857efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic ssize_t ca91cx42_master_read(struct vme_master_resource *image, 858efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota void *buf, size_t count, loff_t offset) 8593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 86021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch ssize_t retval; 86153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov void *addr = image->kern_base + offset; 86253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int done = 0; 86353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int count32; 86453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 86553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count == 0) 86653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov return 0; 86760479690af6d559d4202bed139db90323386bd2bMartyn Welch 868886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 86960479690af6d559d4202bed139db90323386bd2bMartyn Welch 87053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov /* The following code handles VME address alignment problem 87153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * in order to assure the maximal data width cycle. 87253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * We cannot use memcpy_xxx directly here because it 87353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * may cut data transfer in 8-bits cycles, thus making 87453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * D16 cycle impossible. 87553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * From the other hand, the bridge itself assures that 87653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * maximal configured data cycle is used and splits it 87753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * automatically for non-aligned addresses. 87853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov */ 879b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga if ((uintptr_t)addr & 0x1) { 88053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)buf = ioread8(addr); 88153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 88253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (done == count) 88353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 88453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 885b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga if ((uintptr_t)addr & 0x2) { 88653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) < 2) { 88753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)(buf + done) = ioread8(addr + done); 88853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 88953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 89053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } else { 89153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u16 *)(buf + done) = ioread16(addr + done); 89253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 89353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 89453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 89560479690af6d559d4202bed139db90323386bd2bMartyn Welch 89653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov count32 = (count - done) & ~0x3; 89753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count32 > 0) { 89853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov memcpy_fromio(buf + done, addr + done, (unsigned int)count); 89953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += count32; 90053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 90153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 90253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x2) { 90353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u16 *)(buf + done) = ioread16(addr + done); 90453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 90553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 90653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x1) { 90753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov *(u8 *)(buf + done) = ioread8(addr + done); 90853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 90953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 91053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilovout: 91153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov retval = count; 912886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 9133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 9143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 91560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 91660479690af6d559d4202bed139db90323386bd2bMartyn Welch 917efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic ssize_t ca91cx42_master_write(struct vme_master_resource *image, 918efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota void *buf, size_t count, loff_t offset) 91960479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 92053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov ssize_t retval; 92153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov void *addr = image->kern_base + offset; 92253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int done = 0; 92353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov unsigned int count32; 92453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 92553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count == 0) 92653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov return 0; 92760479690af6d559d4202bed139db90323386bd2bMartyn Welch 928886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 92960479690af6d559d4202bed139db90323386bd2bMartyn Welch 93053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov /* Here we apply for the same strategy we do in master_read 93153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov * function in order to assure D16 cycle when required. 93253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov */ 933b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga if ((uintptr_t)addr & 0x1) { 93453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)buf, addr); 93553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 93653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (done == count) 93753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 93853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 939b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga if ((uintptr_t)addr & 0x2) { 94053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) < 2) { 94153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)(buf + done), addr + done); 94253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 94353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov goto out; 94453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } else { 94553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite16(*(u16 *)(buf + done), addr + done); 94653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 94753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 94853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 94953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 95053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov count32 = (count - done) & ~0x3; 95153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if (count32 > 0) { 95253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov memcpy_toio(addr + done, buf + done, count32); 95353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += count32; 95453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 95553059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov 95653059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x2) { 95753059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite16(*(u16 *)(buf + done), addr + done); 95853059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 2; 95953059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 96053059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov if ((count - done) & 0x1) { 96153059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov iowrite8(*(u8 *)(buf + done), addr + done); 96253059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov done += 1; 96353059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilov } 96453059aa05988761a738fa8bc082bbf3c5d4462d1Arthur Benilovout: 9653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = count; 9663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 967886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 968886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota 9693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 97060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 97160479690af6d559d4202bed139db90323386bd2bMartyn Welch 972efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, 97304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch unsigned int mask, unsigned int compare, unsigned int swap, 97404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch loff_t offset) 97504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch{ 976b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga u32 result; 977b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga uintptr_t pci_addr; 97804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch int i; 97904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct ca91cx42_driver *bridge; 98004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch struct device *dev; 98104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch bridge = image->parent->driver_priv; 98304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev = image->parent->parent; 98404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Find the PCI address that maps to the desired VME address */ 98604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch i = image->number; 98704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 98804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Locking as we can only do one of these at a time */ 989886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_rmw); 99004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Lock image */ 992886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 99304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 994b91a9363bbdf71324c80bdf0baac09b94c02c52aManohar Vanga pci_addr = (uintptr_t)image->kern_base + offset; 99504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 99604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Address must be 4-byte aligned */ 99704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch if (pci_addr & 0x3) { 99804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch dev_err(dev, "RMW Address not 4-byte aligned\n"); 9997c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall result = -EINVAL; 10007c0ace54887872ebd99fefdfe85d273295a09426Julia Lawall goto out; 100104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch } 100204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 100304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Ensure RMW Disabled whilst configuring */ 100404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 100504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 100604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Configure registers */ 100704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(mask, bridge->base + SCYC_EN); 100804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(compare, bridge->base + SCYC_CMP); 100904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(swap, bridge->base + SCYC_SWP); 101004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(pci_addr, bridge->base + SCYC_ADDR); 101104e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101204e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Enable RMW */ 101304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); 101404e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Kick process off with a read to the required address. */ 101604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch result = ioread32(image->kern_base + offset); 101704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 101804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch /* Disable RMW */ 101904e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch iowrite32(0, bridge->base + SCYC_CTL); 102004e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 10217c0ace54887872ebd99fefdfe85d273295a09426Julia Lawallout: 1022886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 102304e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 1024886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_rmw); 102504e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 102604e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch return result; 102704e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch} 102804e10e15f9509d08c5e2194ea2ae680c013d5b63Martyn Welch 1029efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_add(struct vme_dma_list *list, 1030efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cota struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) 10314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 10324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry, *prev; 10334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_pci *pci_attr; 10344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_vme *vme_attr; 10354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t desc_ptr; 10364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 103748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 103848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 103948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = list->parent->parent->parent; 10404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX descriptor must be aligned on 64-bit boundaries */ 1042324148788bf3744d90fb6894ec5744eb0ca91b74Julia Lawall entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); 10434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (entry == NULL) { 104448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Failed to allocate memory for dma resource " 10454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "structure\n"); 10464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -ENOMEM; 10474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_mem; 10484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Test descriptor alignment */ 1051886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if ((unsigned long)&entry->descriptor & CA91CX42_DCPP_M) { 105248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Descriptor not aligned to 16 byte boundary as " 1053886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota "required: %p\n", &entry->descriptor); 10544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_align; 10564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1058886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&entry->descriptor, 0, sizeof(struct ca91cx42_dma_descriptor)); 10594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (dest->type == VME_DMA_VME) { 10614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_L2V; 1062feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy vme_attr = dest->private; 1063feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy pci_attr = src->private; 10644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 1065feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy vme_attr = src->private; 1066feffce47678375a6422d5356a379e407f007d424Kulikov Vasiliy pci_attr = dest->private; 10674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 106925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Check we can do fulfill required attributes */ 10704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | 10714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_USER2)) != 0) { 10724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 107348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 10744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_aspace; 10764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | 10794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch VME_PROG | VME_DATA)) != 0) { 10804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 108148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Unsupported cycle type\n"); 10824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_cycle; 10844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 108625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Check to see if we can fulfill source and destination */ 10874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || 10884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { 10894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 109048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Cannot perform transfer with this " 10914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch "source-destination combination\n"); 10924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch retval = -EINVAL; 10934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch goto err_direct; 10944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 10954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 10964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup cycle types */ 10974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_BLT) 10984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; 10994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup data width */ 11014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->dwidth) { 11024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D8: 11034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; 11044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D16: 11064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; 11074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D32: 11094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; 11104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_D64: 11124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; 11134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 111548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid data width\n"); 11164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 11174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Setup address space */ 11204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch switch (vme_attr->aspace) { 11214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A16: 11224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; 11234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A24: 11254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; 11264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_A32: 11284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; 11294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER1: 11314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; 11324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch case VME_USER2: 11344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; 11354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch default: 113748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid address space\n"); 11384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EINVAL; 11394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch break; 11404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_SUPER) 11434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; 11444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (vme_attr->cycle & VME_PROG) 11454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; 11464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dtbc = count; 11484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dla = pci_attr->address; 11494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dva = vme_attr->address; 11504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry->descriptor.dcpp = CA91CX42_DCPP_NULL; 11514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Add to list */ 1153886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&entry->list, &list->entries); 11544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Fill out previous descriptors "Next Address" */ 1156886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (entry->list.prev != &list->entries) { 11574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, 11584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 11594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* We need the bus address for the pointer */ 1160886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota desc_ptr = virt_to_bus(&entry->descriptor); 11614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; 11624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 11634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_cycle: 11674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_aspace: 11684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_direct: 11694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_align: 11704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 11714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_mem: 11724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 11734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchstatic int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) 11764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 tmp; 11784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ca91cx42_bridge->driver_priv; 11814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch tmp = ioread32(bridge->base + DGCS); 11834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 11844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (tmp & CA91CX42_DGCS_ACT) 11854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 11864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch else 11874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 1; 11884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 11894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1190efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_exec(struct vme_dma_list *list) 11914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 11924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct vme_dma_resource *ctrlr; 11934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 11944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch int retval = 0; 11954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch dma_addr_t bus_addr; 11964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch u32 val; 119748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct device *dev; 11984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_driver *bridge; 11994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ctrlr = list->parent; 12014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch bridge = ctrlr->parent->driver_priv; 120348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev = ctrlr->parent->parent; 12044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1205886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 12064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1207886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!(list_empty(&ctrlr->running))) { 12084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 12094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * XXX We have an active DMA transfer and currently haven't 12104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * sorted out the mechanism for "pending" DMA transfers. 12114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Return busy. 12124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 12134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Need to add to pending here */ 1214886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return -EBUSY; 12164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } else { 1217886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add(&list->list, &ctrlr->running); 12184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Get first bus address and write into registers */ 1221886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota entry = list_first_entry(&list->entries, struct ca91cx42_dma_entry, 12224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list); 12234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1224886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota bus_addr = virt_to_bus(&entry->descriptor); 12254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1226886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(0, bridge->base + DTBC); 12294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); 12304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Start the operation */ 12324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 12334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* XXX Could set VMEbus On and Off Counters here */ 12354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); 12364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | 12384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 12394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR); 12404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 12424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val |= CA91CX42_DGCS_GO; 12444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch iowrite32(val, bridge->base + DGCS); 12464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch wait_event_interruptible(bridge->dma_queue, 12484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch ca91cx42_dma_busy(ctrlr->parent)); 12494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* 12514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Read status register, this register is valid until we kick off a 12524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * new transfer. 12534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */ 12544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DGCS); 12554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | 12574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch CA91CX42_DGCS_PERR)) { 12584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 125948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); 12604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch val = ioread32(bridge->base + DCTL); 12614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* Remove list from running list */ 1264886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 1265886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_del(&list->list); 1266886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 12674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return retval; 12694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 12714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 1272efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_dma_list_empty(struct vme_dma_list *list) 12734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{ 12744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct list_head *pos, *temp; 12754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch struct ca91cx42_dma_entry *entry; 12764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch /* detach and free each entry */ 1278886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each_safe(pos, temp, &list->entries) { 12794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch list_del(pos); 12804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch entry = list_entry(pos, struct ca91cx42_dma_entry, list); 12814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch kfree(entry); 12824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch } 12834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch return 0; 12854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch} 12864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 12872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 12882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * All 4 location monitors reside at the same base - this is therefore a 12892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * system wide configuration. 12902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 12912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * This does not enable the LM monitor - that should be done when the first 12922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * callback is attached and disabled when the last callback is removed. 12932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1294efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_set(struct vme_lm_resource *lm, 12956af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long lm_base, u32 aspace, u32 cycle) 12962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 12972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 temp_base, lm_ctl = 0; 12982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch int i; 12992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 13012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 13042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check the alignment of the location monitor */ 13062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch temp_base = (u32)lm_base; 13072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (temp_base & 0xffff) { 13082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor must be aligned to 64KB " 13092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "boundary"); 13102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 13112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1313886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 13142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If we already have a callback attached, we can't move it! */ 13162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch for (i = 0; i < lm->monitors; i++) { 13172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[i] != NULL) { 1318886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor callback attached, " 13202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch "can't reset\n"); 13212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 13222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch switch (aspace) { 13262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A16: 13272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A16; 13282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A24: 13302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A24; 13312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch case VME_A32: 13332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_AS_A32; 13342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch default: 1336886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Invalid address space\n"); 13382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 13392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch break; 13402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 13412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_SUPER) 13432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_SUPR; 13442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_USER) 13452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_NPRIV; 13462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_PROG) 13472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_PGM; 13482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (cycle & VME_DATA) 13492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_DATA; 13502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_base, bridge->base + LM_BS); 13522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 13532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1354886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 13572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* Get configuration of the callback monitor and return whether it is enabled 13602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * or disabled. 13612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1362efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_get(struct vme_lm_resource *lm, 13636af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long *lm_base, u32 *aspace, u32 *cycle) 13642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 13652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, enabled = 0; 13662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 13672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 13692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1370886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 13712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); 13732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 13742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_EN) 13762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch enabled = 1; 13772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) 13792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A16; 13802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) 13812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A24; 13822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) 13832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *aspace = VME_A32; 13842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle = 0; 13862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_SUPR) 13872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_SUPER; 13882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_NPRIV) 13892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_USER; 13902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_PGM) 13912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_PROG; 13922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (lm_ctl & CA91CX42_LM_CTL_DATA) 13932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *cycle |= VME_DATA; 13942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1395886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 13962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 13972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return enabled; 13982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 13992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 14012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Attach a callback to a specific location monitor. 14022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * 14032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Callback will be passed the monitor triggered. 14042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1405efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, 14062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch void (*callback)(int)) 14072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 14082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 lm_ctl, tmp; 14092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 14102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct device *dev; 14112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 14132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev = lm->parent->parent; 14142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1415886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 14162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that the location monitor is configured - need PGM or DATA */ 14182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl = ioread32(bridge->base + LM_CTL); 14192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { 1420886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Location monitor not properly configured\n"); 14222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EINVAL; 14232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Check that a callback isn't already attached */ 14262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if (bridge->lm_callback[monitor] != NULL) { 1427886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch dev_err(dev, "Existing callback attached\n"); 14292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return -EBUSY; 14302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Attach callback */ 14332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = callback; 14342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Enable Location Monitor interrupt */ 14362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 14372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp |= CA91CX42_LINT_LM[monitor]; 14382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 14392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Ensure that global Location Monitor Enable set */ 14412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { 14422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch lm_ctl |= CA91CX42_LM_CTL_EN; 14432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(lm_ctl, bridge->base + LM_CTL); 14442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1446886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 14492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 14502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* 14522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Detach a callback function forn a specific location monitor. 14532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */ 1454efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) 14552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{ 14562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch u32 tmp; 14572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch struct ca91cx42_driver *bridge; 14582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge = lm->parent->driver_priv; 14602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1461886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 14622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Disable Location Monitor and ensure previous interrupts are clear */ 14642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LINT_EN); 14652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LINT_LM[monitor]; 14662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LINT_EN); 14672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(CA91CX42_LINT_LM[monitor], 14692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->base + LINT_STAT); 14702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* Detach callback */ 14722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch bridge->lm_callback[monitor] = NULL; 14732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch /* If all location monitors disabled, disable global Location Monitor */ 14752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | 14762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch CA91CX42_LINT_LM3)) == 0) { 14772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp = ioread32(bridge->base + LM_CTL); 14782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch tmp &= ~CA91CX42_LM_CTL_EN; 14792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch iowrite32(tmp, bridge->base + LM_CTL); 14802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch } 14812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1482886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 14832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 14842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch return 0; 14852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch} 14862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch 1487efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) 148860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 14893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 slot = 0; 149029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 149129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 149229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 149360479690af6d559d4202bed139db90323386bd2bMartyn Welch 149412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch if (!geoid) { 149529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ioread32(bridge->base + VCSR_BS); 149612b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); 149712b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch } else 149812b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch slot = geoid; 149912b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 15003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return (int)slot; 15013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 15033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15047f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vangavoid *ca91cx42_alloc_consistent(struct device *parent, size_t size, 15057f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga dma_addr_t *dma) 15067f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga{ 15077f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga struct pci_dev *pdev; 15087f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 15097f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga /* Find pci_dev container of dev */ 15107f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga pdev = container_of(parent, struct pci_dev, dev); 15117f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 15127f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga return pci_alloc_consistent(pdev, size, dma); 15137f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga} 15147f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 15157f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vangavoid ca91cx42_free_consistent(struct device *parent, size_t size, void *vaddr, 15167f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga dma_addr_t dma) 15177f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga{ 15187f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga struct pci_dev *pdev; 15197f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 15207f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga /* Find pci_dev container of dev */ 15217f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga pdev = container_of(parent, struct pci_dev, dev); 15227f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 15237f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga pci_free_consistent(pdev, size, vaddr, dma); 15247f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga} 15257f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 15263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void) 15273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return pci_register_driver(&ca91cx42_driver); 15293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 15303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* 15323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Configure CR/CSR space 15333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * 15343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Access to the CR/CSR can be configured at power-up. The location of the 15353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * CR/CSR registers in the CR/CSR address space is determined by the boards 15363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Auto-ID or Geographic address. This function ensures that the window is 15373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * enabled at an offset consistent with the boards geopgraphic address. 15383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 153929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, 154029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 15413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 15423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch unsigned int crcsr_addr; 15433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int tmp, slot; 154429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 154529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 154629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 15473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 154829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ca91cx42_slot_get(ca91cx42_bridge); 154925331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 155025331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch /* Write CSR Base Address if slot ID is supplied as a module param */ 155125331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch if (geoid) 155225331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch iowrite32(geoid << 27, bridge->base + VCSR_BS); 155325331ba2f8e36abe77211765fa879106cdbc43e6Martyn Welch 15543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); 15553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slot == 0) { 15563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Slot number is unset, not configuring " 15573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "CR/CSR space\n"); 15583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -EINVAL; 155960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 15603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 15613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Allocate mem for CR/CSR image */ 156229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, 1563886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &bridge->crcsr_bus); 156429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->crcsr_kernel == NULL) { 15653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " 15663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "image\n"); 15673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return -ENOMEM; 156860479690af6d559d4202bed139db90323386bd2bMartyn Welch } 156960479690af6d559d4202bed139db90323386bd2bMartyn Welch 157029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); 157160479690af6d559d4202bed139db90323386bd2bMartyn Welch 15723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch crcsr_addr = slot * (512 * 1024); 157329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); 157460479690af6d559d4202bed139db90323386bd2bMartyn Welch 157529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 15763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp |= CA91CX42_VCSR_CTL_EN; 157729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 157860479690af6d559d4202bed139db90323386bd2bMartyn Welch 15793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 158060479690af6d559d4202bed139db90323386bd2bMartyn Welch} 158160479690af6d559d4202bed139db90323386bd2bMartyn Welch 158229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, 158329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 158460479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 15853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 tmp; 158629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 158729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 158829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 158960479690af6d559d4202bed139db90323386bd2bMartyn Welch 15903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off CR/CSR space */ 159129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32(bridge->base + VCSR_CTL); 15923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch tmp &= ~CA91CX42_VCSR_CTL_EN; 159329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(tmp, bridge->base + VCSR_CTL); 159460479690af6d559d4202bed139db90323386bd2bMartyn Welch 15953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Free image */ 159629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + VCSR_TO); 159760479690af6d559d4202bed139db90323386bd2bMartyn Welch 159829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, 159929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_bus); 16003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 160160479690af6d559d4202bed139db90323386bd2bMartyn Welch 16023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) 16033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{ 16043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch int retval, i; 16053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch u32 data; 16063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 160729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge; 160829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *ca91cx42_device; 16093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 16103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 16113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 16123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 16133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* We want to support more than one of each bridge so we need to 16153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * dynamically allocate the bridge structure 16163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 16177a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); 16183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (ca91cx42_bridge == NULL) { 16203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 16213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "structure\n"); 16223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_struct; 16243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16267a6cb0d5497418599d2125b670926b75e673861cJulia Lawall ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); 162729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 162829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (ca91cx42_device == NULL) { 162929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 163029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch "structure\n"); 163129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch retval = -ENOMEM; 163229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch goto err_driver; 163329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch } 163429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 163529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_bridge->driver_priv = ca91cx42_device; 163629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 16373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Enable the device */ 16383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_enable_device(pdev); 16393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 16403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to enable device\n"); 16413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_enable; 16423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Map Registers */ 16453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = pci_request_regions(pdev, driver_name); 16463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval) { 16473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to reserve resources\n"); 16483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_resource; 16493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* map registers in BAR 0 */ 165229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), 16533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 4096); 165429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (!ca91cx42_device->base) { 16553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Unable to remap CRG region\n"); 16563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 16573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_remap; 16583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Check to see if the mapping worked out */ 166129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; 16623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (data != PCI_VENDOR_ID_TUNDRA) { 16633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "PCI_ID check failed\n"); 16643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -EIO; 16653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_test; 16663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Initialize wait queues & mutual exclusion flags */ 1669886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&ca91cx42_device->dma_queue); 1670886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&ca91cx42_device->iack_queue); 1671886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_device->vme_int); 1672886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&ca91cx42_device->vme_rmw); 16733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 1674886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota ca91cx42_bridge->parent = &pdev->dev; 16753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch strcpy(ca91cx42_bridge->name, driver_name); 16763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Setup IRQ */ 16783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = ca91cx42_irq_init(ca91cx42_bridge); 16793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 16803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Initialization failed.\n"); 16813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_irq; 16823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 16843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add master windows to list */ 1685886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->master_resources); 16863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_MASTER; i++) { 16873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = kmalloc(sizeof(struct vme_master_resource), 16883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 16893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (master_image == NULL) { 16903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 16913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "master resource structure\n"); 16923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 16933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_master; 16943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 16953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->parent = ca91cx42_bridge; 1696886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock_init(&master_image->lock); 16973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->locked = 0; 16983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->number = i; 16993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | 17003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_CRCSR | VME_USER1 | VME_USER2; 17013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 17023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 17033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; 1704886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&master_image->bus_resource, 0, 17053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch sizeof(struct resource)); 17063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image->kern_base = NULL; 1707886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&master_image->list, 1708886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->master_resources); 17093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add slave windows to list */ 1712886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->slave_resources); 17133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_SLAVE; i++) { 17143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = kmalloc(sizeof(struct vme_slave_resource), 17153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 17163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (slave_image == NULL) { 17173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "slave resource structure\n"); 17193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_slave; 17213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->parent = ca91cx42_bridge; 1723886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&slave_image->mtx); 17243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->locked = 0; 17253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->number = i; 17263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | 17273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_USER2; 17283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Only windows 0 and 4 support A16 */ 17303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (i == 0 || i == 4) 17313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->address_attr |= VME_A16; 17323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 17343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch VME_SUPER | VME_USER | VME_PROG | VME_DATA; 1735886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&slave_image->list, 1736886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->slave_resources); 17373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 17393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add dma engines to list */ 1740886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->dma_resources); 17413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch for (i = 0; i < CA91C142_MAX_DMA; i++) { 17423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), 17433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch GFP_KERNEL); 17443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (dma_ctrlr == NULL) { 17453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "dma resource structure\n"); 17473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_dma; 17493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->parent = ca91cx42_bridge; 1751886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&dma_ctrlr->mtx); 17523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->locked = 0; 17533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr->number = i; 17544f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | 17554f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_MEM_TO_VME; 1756886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->pending); 1757886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->running); 1758886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&dma_ctrlr->list, 1759886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &ca91cx42_bridge->dma_resources); 17603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch 17623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Add location monitor to list */ 1763886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&ca91cx42_bridge->lm_resources); 17643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); 17653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (lm == NULL) { 17663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 17673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch "location monitor resource structure\n"); 17683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = -ENOMEM; 17693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_lm; 17703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 17713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->parent = ca91cx42_bridge; 1772886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&lm->mtx); 17733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->locked = 0; 17743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->number = 1; 17753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm->monitors = 4; 1776886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&lm->list, &ca91cx42_bridge->lm_resources); 17773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 17783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_get = ca91cx42_slave_get; 17793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slave_set = ca91cx42_slave_set; 17803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_get = ca91cx42_master_get; 17813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_set = ca91cx42_master_set; 17823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_read = ca91cx42_master_read; 17833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_write = ca91cx42_master_write; 17843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; 17853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; 17863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; 17873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; 1788c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_set = ca91cx42_irq_set; 1789c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; 17903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_set = ca91cx42_lm_set; 17913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_get = ca91cx42_lm_get; 17923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; 17933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; 17943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch ca91cx42_bridge->slot_get = ca91cx42_slot_get; 17957f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga ca91cx42_bridge->alloc_consistent = ca91cx42_alloc_consistent; 17967f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga ca91cx42_bridge->free_consistent = ca91cx42_free_consistent; 17973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 179829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(ca91cx42_device->base + MISC_CTL); 17993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_info(&pdev->dev, "Board is%s the VME system controller\n", 18003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); 180129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_info(&pdev->dev, "Slot ID is %d\n", 180229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_slot_get(ca91cx42_bridge)); 18033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18047946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) 18053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); 180660479690af6d559d4202bed139db90323386bd2bMartyn Welch 18073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Need to save ca91cx42_bridge pointer locally in link list for use in 18083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * ca91cx42_remove() 18093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */ 18103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch retval = vme_register_bridge(ca91cx42_bridge); 18113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch if (retval != 0) { 18123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dev_err(&pdev->dev, "Chip Registration failed.\n"); 18133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch goto err_reg; 18143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 181629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_set_drvdata(pdev, ca91cx42_bridge); 181729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 18183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return 0; 18193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_reg: 182129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 18223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_lm: 18233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1824886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->lm_resources) { 18253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 18263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 18283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dma: 18303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1831886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->dma_resources) { 18323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 18333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 183560479690af6d559d4202bed139db90323386bd2bMartyn Welch } 18363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_slave: 18373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1838886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->slave_resources) { 18393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 18403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 18423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_master: 18443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1845886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->master_resources) { 18463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 18473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 18483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 18493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 18503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 18513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 185229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(ca91cx42_device, pdev); 18533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_irq: 18543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_test: 185529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(ca91cx42_device->base); 18563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap: 18573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 18583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource: 18593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 18603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_enable: 186129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kfree(ca91cx42_device); 186229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welcherr_driver: 18633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 18643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_struct: 18653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch return retval; 186660479690af6d559d4202bed139db90323386bd2bMartyn Welch 186760479690af6d559d4202bed139db90323386bd2bMartyn Welch} 186860479690af6d559d4202bed139db90323386bd2bMartyn Welch 1869efbb979d1b31638a95d76b5acf65cf00a3213fe4Emilio G. Cotastatic void ca91cx42_remove(struct pci_dev *pdev) 187060479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 18713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct list_head *pos = NULL; 18723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_master_resource *master_image; 18733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_slave_resource *slave_image; 18743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_dma_resource *dma_ctrlr; 18753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch struct vme_lm_resource *lm; 187629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct ca91cx42_driver *bridge; 187729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); 187829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 187929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = ca91cx42_bridge->driver_priv; 188029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 188160479690af6d559d4202bed139db90323386bd2bMartyn Welch 18823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off Ints */ 188329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0, bridge->base + LINT_EN); 18843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 18853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* Turn off the windows */ 188629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI0_CTL); 188729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI1_CTL); 188829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI2_CTL); 188929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI3_CTL); 189029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI4_CTL); 189129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI5_CTL); 189229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI6_CTL); 189329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00800000, bridge->base + LSI7_CTL); 189429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI0_CTL); 189529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI1_CTL); 189629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI2_CTL); 189729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI3_CTL); 189829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI4_CTL); 189929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI5_CTL); 190029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI6_CTL); 190129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32(0x00F00000, bridge->base + VSI7_CTL); 19023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 19033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch vme_unregister_bridge(ca91cx42_bridge); 1904bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 1905bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); 1906bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch 19073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1908886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->lm_resources) { 19093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 19103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 19113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(lm); 191260479690af6d559d4202bed139db90323386bd2bMartyn Welch } 19133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 19143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1915886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->dma_resources) { 19163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 19173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 19183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(dma_ctrlr); 191960479690af6d559d4202bed139db90323386bd2bMartyn Welch } 192060479690af6d559d4202bed139db90323386bd2bMartyn Welch 19213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1922886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->slave_resources) { 19233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 19243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 19253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(slave_image); 19263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 192760479690af6d559d4202bed139db90323386bd2bMartyn Welch 19283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch /* resources are stored in link list */ 1929886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &ca91cx42_bridge->master_resources) { 19303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch master_image = list_entry(pos, struct vme_master_resource, 19313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list); 19323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch list_del(pos); 19333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(master_image); 19343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch } 193560479690af6d559d4202bed139db90323386bd2bMartyn Welch 193629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ca91cx42_irq_exit(bridge, pdev); 193760479690af6d559d4202bed139db90323386bd2bMartyn Welch 193829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(bridge->base); 193960479690af6d559d4202bed139db90323386bd2bMartyn Welch 19403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_release_regions(pdev); 194160479690af6d559d4202bed139db90323386bd2bMartyn Welch 19423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_disable_device(pdev); 19433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch 19443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch kfree(ca91cx42_bridge); 194560479690af6d559d4202bed139db90323386bd2bMartyn Welch} 194660479690af6d559d4202bed139db90323386bd2bMartyn Welch 19473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void) 194860479690af6d559d4202bed139db90323386bd2bMartyn Welch{ 19493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch pci_unregister_driver(&ca91cx42_driver); 19503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch} 195160479690af6d559d4202bed139db90323386bd2bMartyn Welch 195212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn WelchMODULE_PARM_DESC(geoid, "Override geographical addressing"); 195312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchmodule_param(geoid, int, 0); 195412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch 19553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); 19563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_LICENSE("GPL"); 195760479690af6d559d4202bed139db90323386bd2bMartyn Welch 19583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_init(ca91cx42_init); 19593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_exit(ca91cx42_exit); 1960