1d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 2d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Support for the Tundra TSI148 VME-PCI Bridge Chip 3d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 466bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com> 566bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 6d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 7d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Based on work by Tom Armistead and Ajit Prem 8d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Copyright 2004 Motorola Inc. 9d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 10d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * This program is free software; you can redistribute it and/or modify it 11d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * under the terms of the GNU General Public License as published by the 12d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Free Software Foundation; either version 2 of the License, or (at your 13d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * option) any later version. 14d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 15d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 16d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/module.h> 17d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/moduleparam.h> 18d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/mm.h> 19d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/types.h> 20d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/errno.h> 21d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/proc_fs.h> 22d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/pci.h> 23d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/poll.h> 24d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/dma-mapping.h> 25d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include <linux/interrupt.h> 26d22b8ed9a3b0a157b732580258ec16b729265953Martyn 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> 32d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 33d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include "../vme.h" 34d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include "../vme_bridge.h" 35d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch#include "vme_tsi148.h" 36d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 37d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic int __init tsi148_init(void); 38d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic int tsi148_probe(struct pci_dev *, const struct pci_device_id *); 39d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void tsi148_remove(struct pci_dev *); 40d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void __exit tsi148_exit(void); 41d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 42d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 4329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch/* Module parameter */ 4490ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool err_chk; 45638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welchstatic int geoid; 46d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 47584721cab2bdd26f63bfeca60c83f5e6b8eee7d0Vincent Bossierstatic const char driver_name[] = "vme_tsi148"; 48d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 49270b64bb4cf27a2ad7819bad89d8c9d8a66ba1b8Namhyung Kimstatic DEFINE_PCI_DEVICE_TABLE(tsi148_ids) = { 50d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) }, 51d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch { }, 52d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch}; 53d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 54d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic struct pci_driver tsi148_driver = { 55d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch .name = driver_name, 56d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch .id_table = tsi148_ids, 57d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch .probe = tsi148_probe, 58d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch .remove = tsi148_remove, 59d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch}; 60d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 61d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void reg_join(unsigned int high, unsigned int low, 62d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long *variable) 63d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 64d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *variable = (unsigned long long)high << 32; 65d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *variable |= (unsigned long long)low; 66d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 67d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 68d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void reg_split(unsigned long long variable, unsigned int *high, 69d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int *low) 70d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 71d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *low = (unsigned int)variable & 0xFFFFFFFF; 72d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *high = (unsigned int)(variable >> 32); 73d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 74d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 75d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 76d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Wakes up DMA queue. 77d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 7829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge, 7929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int channel_mask) 80d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 81d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 serviced = 0; 82d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 83d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (channel_mask & TSI148_LCSR_INTS_DMA0S) { 84886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->dma_queue[0]); 85d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch serviced |= TSI148_LCSR_INTC_DMA0C; 86d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 87d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (channel_mask & TSI148_LCSR_INTS_DMA1S) { 88886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->dma_queue[1]); 89d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch serviced |= TSI148_LCSR_INTC_DMA1C; 90d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 91d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 92d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return serviced; 93d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 94d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 95d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 96d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Wake up location monitor queue 97d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 9829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat) 99d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 100d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int i; 101d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 serviced = 0; 102d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 103d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 0; i < 4; i++) { 1047946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (stat & TSI148_LCSR_INTS_LMS[i]) { 105d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* We only enable interrupts if the callback is set */ 10629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->lm_callback[i](i); 107d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch serviced |= TSI148_LCSR_INTC_LMC[i]; 108d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 109d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 110d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 111d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return serviced; 112d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 113d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 114d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 115d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Wake up mail box queue. 116d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 117d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * XXX This functionality is not exposed up though API. 118d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 11948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 tsi148_MB_irqhandler(struct vme_bridge *tsi148_bridge, u32 stat) 120d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 121d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int i; 122d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 val; 123d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 serviced = 0; 12448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct tsi148_driver *bridge; 12548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 12648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 127d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 128d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 0; i < 4; i++) { 1297946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (stat & TSI148_LCSR_INTS_MBS[i]) { 13029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch val = ioread32be(bridge->base + TSI148_GCSR_MBOX[i]); 13148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "VME Mailbox %d received" 13248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ": 0x%x\n", i, val); 133d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch serviced |= TSI148_LCSR_INTC_MBC[i]; 134d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 135d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 136d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 137d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return serviced; 138d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 139d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 140d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 141d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Display error & status message when PERR (PCI) exception interrupt occurs. 142d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 14348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic u32 tsi148_PERR_irqhandler(struct vme_bridge *tsi148_bridge) 144d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 14548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct tsi148_driver *bridge; 14648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 14748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 14848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 14948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "PCI Exception at address: 0x%08x:%08x, " 15048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "attributes: %08x\n", 15129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ioread32be(bridge->base + TSI148_LCSR_EDPAU), 15229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ioread32be(bridge->base + TSI148_LCSR_EDPAL), 15348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ioread32be(bridge->base + TSI148_LCSR_EDPAT)); 15448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 15548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "PCI-X attribute reg: %08x, PCI-X split " 15648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "completion reg: %08x\n", 15729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ioread32be(bridge->base + TSI148_LCSR_EDPXA), 15848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch ioread32be(bridge->base + TSI148_LCSR_EDPXS)); 159d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 16029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT); 161d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 162d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return TSI148_LCSR_INTC_PERRC; 163d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 164d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 165d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 166d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Save address and status when VME error interrupt occurs. 167d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 16829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) 169d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 170d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int error_addr_high, error_addr_low; 171d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long error_addr; 172d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 error_attrib; 173d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_bus_error *error; 17429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 17529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 17629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 177d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 17829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU); 17929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL); 18029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT); 181d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 182d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(error_addr_high, error_addr_low, &error_addr); 183d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 184d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Check for exception register overflow (we have lost error data) */ 1857946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (error_attrib & TSI148_LCSR_VEAT_VEOF) { 18648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "VME Bus Exception Overflow " 18748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Occurred\n"); 188d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 189d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1907946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); 191d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (error) { 192d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch error->address = error_addr; 193d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch error->attributes = error_attrib; 194886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&error->list, &tsi148_bridge->vme_errors); 195d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } else { 19648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Unable to alloc memory for " 19748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "VMEbus Error reporting\n"); 19848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "VME Bus Error at address: " 19948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "0x%llx, attributes: %08x\n", error_addr, error_attrib); 200d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 201d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 202d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Clear Status */ 20329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT); 204d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 205d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return TSI148_LCSR_INTC_VERRC; 206d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 207d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 208d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 209d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Wake up IACK queue. 210d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 21129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge) 212d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 213886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota wake_up(&bridge->iack_queue); 214d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 215d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return TSI148_LCSR_INTC_IACKC; 216d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 217d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 218d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 219d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Calling VME bus interrupt callback if provided. 220d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 22129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge, 22229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch u32 stat) 223d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 224d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int vec, i, serviced = 0; 22529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 22629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 22729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 228d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 229d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 7; i > 0; i--) { 230d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & (1 << i)) { 231d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2327946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch * Note: Even though the registers are defined as 2337946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch * 32-bits in the spec, we only want to issue 8-bit 2347946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch * IACK cycles on the bus, read from offset 3. 235d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 23629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3); 237d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 238c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch vme_irq_handler(tsi148_bridge, i, vec); 239d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 240d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch serviced |= (1 << i); 241d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 242d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 243d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 244d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return serviced; 245d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 246d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 247d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 248d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Top level interrupt handler. Clears appropriate interrupt status bits and 249d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * then calls appropriate sub handler(s). 250d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 25129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic irqreturn_t tsi148_irqhandler(int irq, void *ptr) 252d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 253d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 stat, enable, serviced = 0; 25429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *tsi148_bridge; 25529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 25629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 25729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_bridge = ptr; 25829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 25929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 260d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 261d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Determine which interrupts are unmasked and set */ 26229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch enable = ioread32be(bridge->base + TSI148_LCSR_INTEO); 26329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch stat = ioread32be(bridge->base + TSI148_LCSR_INTS); 264d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 265d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Only look at unmasked interrupts */ 266d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch stat &= enable; 267d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2687946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (unlikely(!stat)) 269d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return IRQ_NONE; 270d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 271d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Call subhandlers as appropriate */ 272d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* DMA irqs */ 273d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S)) 27429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= tsi148_DMA_irqhandler(bridge, stat); 275d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 276d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Location monitor irqs */ 277d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S | 278d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S)) 27929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= tsi148_LM_irqhandler(bridge, stat); 280d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 281d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Mail box irqs */ 282d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S | 283d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S)) 28448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= tsi148_MB_irqhandler(tsi148_bridge, stat); 285d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 286d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* PCI bus error */ 287d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & TSI148_LCSR_INTS_PERRS) 28848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch serviced |= tsi148_PERR_irqhandler(tsi148_bridge); 289d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 290d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* VME bus error */ 291d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & TSI148_LCSR_INTS_VERRS) 29229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= tsi148_VERR_irqhandler(tsi148_bridge); 293d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 294d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* IACK irq */ 295d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & TSI148_LCSR_INTS_IACKS) 29629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= tsi148_IACK_irqhandler(bridge); 297d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 298d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* VME bus irqs */ 299d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S | 300d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S | 301d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S | 302d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTS_IRQ1S)) 30329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat); 304d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 305d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Clear serviced interrupts */ 30629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC); 307d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 308d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return IRQ_HANDLED; 309d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 310d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 31129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int tsi148_irq_init(struct vme_bridge *tsi148_bridge) 312d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 313d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int result; 314d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int tmp; 315d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct pci_dev *pdev; 31629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 31729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 31829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); 319d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 32029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 321d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 322d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Initialise list for VME bus errors */ 323886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&tsi148_bridge->vme_errors); 324d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 325886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&tsi148_bridge->irq_mtx); 326c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 327d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch result = request_irq(pdev->irq, 328d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_irqhandler, 329d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch IRQF_SHARED, 33029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch driver_name, tsi148_bridge); 331d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (result) { 33248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Can't get assigned pci irq " 33348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "vector %02X\n", pdev->irq); 334d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return result; 335d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 336d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 337d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Enable and unmask interrupts */ 338d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp = TSI148_LCSR_INTEO_DMA1EO | TSI148_LCSR_INTEO_DMA0EO | 339d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTEO_MB3EO | TSI148_LCSR_INTEO_MB2EO | 340d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTEO_MB1EO | TSI148_LCSR_INTEO_MB0EO | 341d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO | 342d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTEO_IACKEO; 343d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 34429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch /* This leaves the following interrupts masked. 345d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_VIEEO 346d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_SYSFLEO 347d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_ACFLEO 348d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 349d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 350d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Don't enable Location Monitor interrupts here - they will be 351d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * enabled when the location monitors are properly configured and 352d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * a callback has been attached. 353d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_LM0EO 354d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_LM1EO 355d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_LM2EO 356d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_LM3EO 357d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 358d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 359d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Don't enable VME interrupts until we add a handler, else the board 360d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * will respond to it and we don't want that unless it knows how to 361d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * properly deal with it. 362d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ7EO 363d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ6EO 364d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ5EO 365d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ4EO 366d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ3EO 367d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ2EO 368d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * TSI148_LCSR_INTEO_IRQ1EO 369d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 370d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 371d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); 372d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); 373d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 374d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 375d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 376d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 377a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cotastatic void tsi148_irq_exit(struct vme_bridge *tsi148_bridge, 378a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cota struct pci_dev *pdev) 379d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 380a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cota struct tsi148_driver *bridge = tsi148_bridge->driver_priv; 381a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cota 382d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Turn off interrupts */ 38329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO); 38429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN); 385d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 386d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Clear all interrupts */ 38729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC); 388d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 389d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Detach interrupt handler */ 390a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cota free_irq(pdev->irq, tsi148_bridge); 391d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 392d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 393d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 394d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Check to see if an IACk has been received, return true (1) or false (0). 395d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 3965ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_iack_received(struct tsi148_driver *bridge) 397d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 398d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 tmp; 399d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 40029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); 401d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 402d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (tmp & TSI148_LCSR_VICR_IRQS) 403d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 404d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch else 405d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 1; 406d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 407d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 408d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 409c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch * Configure VME interrupt 410d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 4115ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, 41229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch int state, int sync) 413d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 41475155020c8dc3aa38f8cabc95f17ccd8389c37b6Martyn Welch struct pci_dev *pdev; 415c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch u32 tmp; 41629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 41729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 41829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 419d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 420c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch /* We need to do the ordering differently for enabling and disabling */ 421c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (state == 0) { 42229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); 423d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1]; 42429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); 425df45517536eb010ce2b3c4c7b75c1a02bdb10018Martyn Welch 42629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); 427df45517536eb010ce2b3c4c7b75c1a02bdb10018Martyn Welch tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1]; 42829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); 42975155020c8dc3aa38f8cabc95f17ccd8389c37b6Martyn Welch 430c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (sync != 0) { 431c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch pdev = container_of(tsi148_bridge->parent, 432c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch struct pci_dev, dev); 43375155020c8dc3aa38f8cabc95f17ccd8389c37b6Martyn Welch 434c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch synchronize_irq(pdev->irq); 435c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch } 436c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch } else { 43729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); 438c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; 43929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); 440df45517536eb010ce2b3c4c7b75c1a02bdb10018Martyn Welch 44129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); 442c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; 44329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); 444c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch } 445d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 446d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 447d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 448d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Generate a VME bus interrupt at the requested level & vector. Wait for 449d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * interrupt to be acked. 450d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 4515ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, 4525ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cota int statid) 453d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 454d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 tmp; 45529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 45629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 45729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 458d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 459886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_int); 460d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 461d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Read VICR register */ 46229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); 463d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 464d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Set Status/ID */ 465d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) | 466d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch (statid & TSI148_LCSR_VICR_STID_M); 46729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); 468d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 469d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Assert VMEbus IRQ */ 470d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp = tmp | TSI148_LCSR_VICR_IRQL[level]; 47129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); 472d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 473d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* XXX Consider implementing a timeout? */ 47429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch wait_event_interruptible(bridge->iack_queue, 47529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_iack_received(bridge)); 476d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 477886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_int); 478d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 479d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 480d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 481d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 482d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 483d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Find the first error in this address range 484d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 48529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge, 4866af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, unsigned long long address, size_t count) 487d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 488d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct list_head *err_pos; 489d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_bus_error *vme_err, *valid = NULL; 490d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long bound; 491d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 492d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch bound = address + count; 493d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 494d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 495d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * XXX We are currently not looking at the address space when parsing 496d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * for errors. This is because parsing the Address Modifier Codes 497d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * is going to be quite resource intensive to do properly. We 498d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * should be OK just looking at the addresses and this is certainly 499d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * much better than what we had before. 500d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 501d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch err_pos = NULL; 502d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Iterate through errors */ 503886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(err_pos, &tsi148_bridge->vme_errors) { 504d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch vme_err = list_entry(err_pos, struct vme_bus_error, list); 5057946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((vme_err->address >= address) && 5067946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch (vme_err->address < bound)) { 5077946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 508d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch valid = vme_err; 509d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 510d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 511d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 512d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 513d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return valid; 514d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 515d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 516d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 517d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Clear errors in the provided address range. 518d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 51929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void tsi148_clear_errors(struct vme_bridge *tsi148_bridge, 5206af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, unsigned long long address, size_t count) 521d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 522d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct list_head *err_pos, *temp; 523d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_bus_error *vme_err; 524d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long bound; 525d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 526d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch bound = address + count; 527d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 528d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 529d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * XXX We are currently not looking at the address space when parsing 530d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * for errors. This is because parsing the Address Modifier Codes 531d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * is going to be quite resource intensive to do properly. We 532d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * should be OK just looking at the addresses and this is certainly 533d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * much better than what we had before. 534d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 535d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch err_pos = NULL; 536d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Iterate through errors */ 537886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each_safe(err_pos, temp, &tsi148_bridge->vme_errors) { 538d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch vme_err = list_entry(err_pos, struct vme_bus_error, list); 539d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 5407946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((vme_err->address >= address) && 5417946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch (vme_err->address < bound)) { 5427946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 543d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(err_pos); 544d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(vme_err); 545d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 546d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 547d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 548d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 549d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 550d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Initialize a slave window with the requested attributes. 551d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 5525ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_slave_set(struct vme_slave_resource *image, int enabled, 553d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long vme_base, unsigned long long size, 5546af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch dma_addr_t pci_base, u32 aspace, u32 cycle) 555d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 556d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int i, addr = 0, granularity = 0; 557d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int temp_ctl = 0; 558d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int vme_base_low, vme_base_high; 559d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int vme_bound_low, vme_bound_high; 560d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_offset_low, pci_offset_high; 561d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long vme_bound, pci_offset; 56248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *tsi148_bridge; 56329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 56429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 56548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch tsi148_bridge = image->parent; 56648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 567d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 568d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch i = image->number; 569d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 570d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (aspace) { 571d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A16: 572d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x10; 573d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch addr |= TSI148_LCSR_ITAT_AS_A16; 574d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 575d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A24: 576d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x1000; 577d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch addr |= TSI148_LCSR_ITAT_AS_A24; 578d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 579d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A32: 580d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x10000; 581d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch addr |= TSI148_LCSR_ITAT_AS_A32; 582d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 583d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A64: 584d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x10000; 585d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch addr |= TSI148_LCSR_ITAT_AS_A64; 586d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 587d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_CRCSR: 588d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER1: 589d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER2: 590d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER3: 591d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER4: 592d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 59348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid address space\n"); 594d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 595d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 596d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 597d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 598d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Convert 64-bit variables to 2x 32-bit variables */ 599d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(vme_base, &vme_base_high, &vme_base_low); 600d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 601d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 602d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Bound address is a valid address for the window, adjust 603d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * accordingly 604d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 605d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch vme_bound = vme_base + size - granularity; 606d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(vme_bound, &vme_bound_high, &vme_bound_low); 607d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch pci_offset = (unsigned long long)pci_base - vme_base; 608d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(pci_offset, &pci_offset_high, &pci_offset_low); 609d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 610d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (vme_base_low & (granularity - 1)) { 61148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid VME base alignment\n"); 612d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 613d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 614d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (vme_bound_low & (granularity - 1)) { 61548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid VME bound alignment\n"); 616d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 617d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 618d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (pci_offset_low & (granularity - 1)) { 61948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid PCI Offset " 62048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 621d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 622d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 623d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 624d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Disable while we are mucking around */ 62529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 626d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITAT); 627d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_ITAT_EN; 62829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + 629d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITAT); 630d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 631d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup mapping */ 63229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] + 633d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITSAU); 63429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] + 635d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITSAL); 63629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] + 637d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITEAU); 63829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] + 639d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITEAL); 64029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] + 641d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITOFU); 64229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] + 643d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITOFL); 644d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 645d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup 2eSST speeds */ 646d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M; 647d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { 648d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST160: 649d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_160; 650d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 651d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST267: 652d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_267; 653d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 654d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST320: 655d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_320; 656d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 657d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 658d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 659d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup cycle types */ 660d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~(0x1F << 7); 661d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_BLT) 662d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_BLT; 663d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_MBLT) 664d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_MBLT; 665d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eVME) 666d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_2eVME; 667d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eSST) 668d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_2eSST; 669d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eSSTB) 670d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_2eSSTB; 671d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 672d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup address space */ 673d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_ITAT_AS_M; 674d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= addr; 675d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 676d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~0xF; 677d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_SUPER) 678d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_SUPR ; 679d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_USER) 680d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_NPRIV; 681d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_PROG) 682d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_PGM; 683d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_DATA) 684d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_DATA; 685d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 686d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Write ctl reg without enable */ 68729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + 688d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITAT); 689d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 690d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (enabled) 691d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_ITAT_EN; 692d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 69329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + 694d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITAT); 695d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 696d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 697d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 698d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 699d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 700d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Get slave window configuration. 701d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 7025ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, 703d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long *vme_base, unsigned long long *size, 7046af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch dma_addr_t *pci_base, u32 *aspace, u32 *cycle) 705d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 706d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int i, granularity = 0, ctl = 0; 707d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int vme_base_low, vme_base_high; 708d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int vme_bound_low, vme_bound_high; 709d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_offset_low, pci_offset_high; 710d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long vme_bound, pci_offset; 71129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 712d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 71329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 714d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 715d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch i = image->number; 716d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 717d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Read registers */ 71829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 719d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITAT); 720d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 72129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 722d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITSAU); 72329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 724d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITSAL); 72529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 726d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITEAU); 72729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 728d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITEAL); 72929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 730d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITOFU); 73129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + 732d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITOFL); 733d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 734d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Convert 64-bit variables to 2x 32-bit variables */ 735d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(vme_base_high, vme_base_low, vme_base); 736d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(vme_bound_high, vme_bound_low, &vme_bound); 737d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(pci_offset_high, pci_offset_low, &pci_offset); 738d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 739d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *pci_base = (dma_addr_t)vme_base + pci_offset; 740d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 741d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *enabled = 0; 742d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace = 0; 743d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle = 0; 744d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 745d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_EN) 746d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *enabled = 1; 747d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 748d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A16) { 749d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x10; 750d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A16; 751d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 752d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A24) { 753d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x1000; 754d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A24; 755d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 756d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A32) { 757d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x10000; 758d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A32; 759d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 760d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A64) { 761d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch granularity = 0x10000; 762d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A64; 763d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 764d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 765d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Need granularity before we set the size */ 766d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *size = (unsigned long long)((vme_bound - *vme_base) + granularity); 767d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 768d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 769d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_160) 770d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST160; 771d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_267) 772d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST267; 773d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_320) 774d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST320; 775d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 776d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_BLT) 777d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_BLT; 778d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_MBLT) 779d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_MBLT; 780d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_2eVME) 781d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eVME; 782d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_2eSST) 783d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST; 784d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_2eSSTB) 785d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSSTB; 786d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 787d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_SUPR) 788d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_SUPER; 789d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_NPRIV) 790d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_USER; 791d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_PGM) 792d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_PROG; 793d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_ITAT_DATA) 794d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_DATA; 795d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 796d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 797d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 798d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 799d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 800d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Allocate and map PCI Resource 801d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 802d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic int tsi148_alloc_resource(struct vme_master_resource *image, 803d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long size) 804d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 805d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long existing_size; 806d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval = 0; 807d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct pci_dev *pdev; 80829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *tsi148_bridge; 80929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 81029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_bridge = image->parent; 811d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 81248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); 813d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 8148fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch existing_size = (unsigned long long)(image->bus_resource.end - 8158fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start); 816d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 817d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* If the existing size is OK, return */ 81859c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch if ((size != 0) && (existing_size == (size - 1))) 819d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 820d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 821d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (existing_size != 0) { 822d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iounmap(image->kern_base); 823d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch image->kern_base = NULL; 824794a8946ba2339af09dd1f39c8462c3611bebf77Ilia Mirkin kfree(image->bus_resource.name); 825886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 826886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 827d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 828d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 82959c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch /* Exit here if size is zero */ 8307946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (size == 0) 83159c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch return 0; 83259c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch 8338fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 8340aa3f139cd5123ffb8f397b91d777635e9761c24Julia Lawall image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); 8358fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch if (image->bus_resource.name == NULL) { 83648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Unable to allocate " 83748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "memory for resource name\n"); 838d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 839d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_name; 840d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 841d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 842d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 8438fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name, 844d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch image->number); 845d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 8468fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start = 0; 8478fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.end = (unsigned long)size; 8488fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.flags = IORESOURCE_MEM; 849d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 850d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = pci_bus_alloc_resource(pdev->bus, 851886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &image->bus_resource, size, size, PCIBIOS_MIN_MEM, 852d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 0, NULL, NULL); 853d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval) { 85448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Failed to allocate mem " 85548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "resource for window %d size 0x%lx start 0x%lx\n", 856d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch image->number, (unsigned long)size, 8578fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch (unsigned long)image->bus_resource.start); 858d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_resource; 859d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 860d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 861d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch image->kern_base = ioremap_nocache( 8628fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch image->bus_resource.start, size); 863d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (image->kern_base == NULL) { 86448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); 865d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 866d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_remap; 867d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 868d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 869d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 870d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 871d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_remap: 872886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 873d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_resource: 8748fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 875886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 876d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_name: 877d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 878d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 879d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 880d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 881d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Free and unmap PCI Resource 882d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 883d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void tsi148_free_resource(struct vme_master_resource *image) 884d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 885d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iounmap(image->kern_base); 886d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch image->kern_base = NULL; 887886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota release_resource(&image->bus_resource); 8888fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch kfree(image->bus_resource.name); 889886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&image->bus_resource, 0, sizeof(struct resource)); 890d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 891d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 892d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 893d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Set the attributes of an outbound window. 894d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 8955ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_master_set(struct vme_master_resource *image, int enabled, 8966af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long vme_base, unsigned long long size, u32 aspace, 8976af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 cycle, u32 dwidth) 898d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 899d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval = 0; 900d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int i; 901d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int temp_ctl = 0; 902d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_base_low, pci_base_high; 903d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_bound_low, pci_bound_high; 904d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int vme_offset_low, vme_offset_high; 905d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long pci_bound, vme_offset, pci_base; 90648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *tsi148_bridge; 90729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 90829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 90948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch tsi148_bridge = image->parent; 91048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 91148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 912d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 913d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Verify input data */ 914d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (vme_base & 0xFFFF) { 91548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid VME Window " 91648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 917d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 918d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_window; 919d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 92059c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch 92159c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch if ((size == 0) && (enabled != 0)) { 92248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Size must be non-zero for " 92348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "enabled windows\n"); 924d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 925d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_window; 926d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 927d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 928886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 929d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 930d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Let's allocate the resource here rather than further up the stack as 93125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * it avoids pushing loads of bus dependent stuff up the stack. If size 93259c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch * is zero, any existing resource will be freed. 933d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 934d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = tsi148_alloc_resource(image, size); 935d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval) { 936886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 93748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Unable to allocate memory for " 93859c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch "resource\n"); 939d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_res; 940d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 941d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 94259c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch if (size == 0) { 94359c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch pci_base = 0; 94459c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch pci_bound = 0; 94559c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch vme_offset = 0; 94659c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch } else { 9478fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch pci_base = (unsigned long long)image->bus_resource.start; 94859c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch 94959c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch /* 95059c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch * Bound address is a valid address for the window, adjust 95159c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch * according to window granularity. 95259c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch */ 95359c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch pci_bound = pci_base + (size - 0x10000); 95459c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch vme_offset = vme_base - pci_base; 95559c2290428dd93a4117aa453fc4c2be38da288c0Martyn Welch } 956d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 957d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Convert 64-bit variables to 2x 32-bit variables */ 958d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(pci_base, &pci_base_high, &pci_base_low); 959d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(pci_bound, &pci_bound_high, &pci_bound_low); 960d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(vme_offset, &vme_offset_high, &vme_offset_low); 961d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 962d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (pci_base_low & 0xFFFF) { 963886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 96448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid PCI base alignment\n"); 965d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 966d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_gran; 967d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 968d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (pci_bound_low & 0xFFFF) { 969886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 97048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid PCI bound alignment\n"); 971d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 972d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_gran; 973d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 974d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (vme_offset_low & 0xFFFF) { 975886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 97648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid VME Offset " 97748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "alignment\n"); 978d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 979d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_gran; 980d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 981d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 982d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch i = image->number; 983d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 984d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Disable while we are mucking around */ 98529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 986d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTAT); 987d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_EN; 98829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + 989d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTAT); 990d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 991d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup 2eSST speeds */ 992d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M; 993d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { 994d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST160: 995d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_160; 996d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 997d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST267: 998d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_267; 999d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1000d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST320: 1001d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_320; 1002d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1003d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1004d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1005d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup cycle types */ 1006d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_BLT) { 1007d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; 1008d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_TM_BLT; 1009d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1010d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_MBLT) { 1011d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; 1012d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_TM_MBLT; 1013d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1014d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eVME) { 1015d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; 1016d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_TM_2eVME; 1017d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1018d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eSST) { 1019d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; 1020d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST; 1021d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1022d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eSSTB) { 102348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_warn(tsi148_bridge->parent, "Currently not setting " 102448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Broadcast Select Registers\n"); 1025d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; 1026d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB; 1027d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1028d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1029d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup data width */ 1030d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_DBW_M; 1031d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (dwidth) { 1032d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_D16: 1033d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_DBW_16; 1034d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1035d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_D32: 1036d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_DBW_32; 1037d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1038d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 1039886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 104048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid data width\n"); 1041d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 1042d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_dwidth; 1043d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1044d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1045d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup address space */ 1046d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~TSI148_LCSR_OTAT_AMODE_M; 1047d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (aspace) { 1048d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A16: 1049d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_A16; 1050d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1051d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A24: 1052d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_A24; 1053d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1054d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A32: 1055d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_A32; 1056d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1057d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A64: 1058d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_A64; 1059d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1060d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_CRCSR: 1061d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_CRCSR; 1062d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1063d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER1: 1064d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER1; 1065d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1066d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER2: 1067d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER2; 1068d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1069d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER3: 1070d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER3; 1071d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1072d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER4: 1073d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER4; 1074d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1075d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 1076886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 107748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid address space\n"); 1078d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 1079d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_aspace; 1080d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1081d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1082d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1083d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl &= ~(3<<4); 1084d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_SUPER) 1085d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_SUP; 1086d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_PROG) 1087d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_PGM; 1088d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1089d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup mapping */ 109029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] + 1091d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTSAU); 109229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] + 1093d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTSAL); 109429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] + 1095d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTEAU); 109629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] + 1097d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTEAL); 109829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] + 1099d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTOFU); 110029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] + 1101d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTOFL); 1102d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1103d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Write ctl reg without enable */ 110429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + 1105d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTAT); 1106d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1107d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (enabled) 1108d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch temp_ctl |= TSI148_LCSR_OTAT_EN; 1109d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 111029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + 1111d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTAT); 1112d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1113886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 1114d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1115d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1116d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_aspace: 1117d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_dwidth: 1118d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_gran: 1119d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_free_resource(image); 1120d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_res: 1121d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_window: 1122d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 1123d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1124d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1125d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1126d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1127d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Set the attributes of an outbound window. 1128d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 1129d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * XXX Not parsing prefetch information. 1130d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 11315ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int __tsi148_master_get(struct vme_master_resource *image, int *enabled, 11326af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long *vme_base, unsigned long long *size, u32 *aspace, 11336af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 *cycle, u32 *dwidth) 1134d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1135d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int i, ctl; 1136d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_base_low, pci_base_high; 1137d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_bound_low, pci_bound_high; 1138d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int vme_offset_low, vme_offset_high; 1139d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1140d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long pci_base, pci_bound, vme_offset; 114129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 114229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 114329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 1144d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1145d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch i = image->number; 1146d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 114729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1148d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTAT); 1149d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 115029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1151d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTSAU); 115229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1153d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTSAL); 115429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1155d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTEAU); 115629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1157d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTEAL); 115829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1159d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTOFU); 116029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1161d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTOFL); 1162d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1163d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Convert 64-bit variables to 2x 32-bit variables */ 1164d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(pci_base_high, pci_base_low, &pci_base); 1165d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(pci_bound_high, pci_bound_low, &pci_bound); 1166d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(vme_offset_high, vme_offset_low, &vme_offset); 1167d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1168d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *vme_base = pci_base + vme_offset; 1169d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *size = (unsigned long long)(pci_bound - pci_base) + 0x10000; 1170d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1171d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *enabled = 0; 1172d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace = 0; 1173d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle = 0; 1174d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *dwidth = 0; 1175d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1176d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_OTAT_EN) 1177d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *enabled = 1; 1178d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1179d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup address space */ 1180d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A16) 1181d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A16; 1182d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A24) 1183d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A24; 1184d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A32) 1185d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A32; 1186d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A64) 1187d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A64; 1188d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_CRCSR) 1189d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_CRCSR; 1190d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER1) 1191d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_USER1; 1192d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER2) 1193d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_USER2; 1194d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER3) 1195d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_USER3; 1196d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER4) 1197d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_USER4; 1198d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1199d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup 2eSST speeds */ 1200d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_160) 1201d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST160; 1202d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_267) 1203d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST267; 1204d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_320) 1205d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST320; 1206d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1207d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup cycle types */ 12087946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_SCT) 1209d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_SCT; 12107946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_BLT) 1211d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_BLT; 12127946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_MBLT) 1213d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_MBLT; 12147946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eVME) 1215d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eVME; 12167946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSST) 1217d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSST; 12187946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSSTB) 1219d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_2eSSTB; 1220d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1221d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_OTAT_SUP) 1222d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_SUPER; 1223d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch else 1224d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_USER; 1225d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1226d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (ctl & TSI148_LCSR_OTAT_PGM) 1227d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_PROG; 1228d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch else 1229d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_DATA; 1230d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1231d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup data width */ 1232d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_16) 1233d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *dwidth = VME_D16; 1234d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_32) 1235d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *dwidth = VME_D32; 1236d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1237d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1238d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1239d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1240d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 12415ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_master_get(struct vme_master_resource *image, int *enabled, 12426af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long *vme_base, unsigned long long *size, u32 *aspace, 12436af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 *cycle, u32 *dwidth) 1244d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1245d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval; 1246d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1247886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 1248d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1249d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = __tsi148_master_get(image, enabled, vme_base, size, aspace, 1250d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch cycle, dwidth); 1251d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1252886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 1253d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1254d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 1255d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1256d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 12575ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, 1258d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch size_t count, loff_t offset) 1259d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1260d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval, enabled; 1261d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long vme_base, size; 12626af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, cycle, dwidth; 1263d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_bus_error *vme_err = NULL; 126429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *tsi148_bridge; 126529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 126629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_bridge = image->parent; 1267d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1268886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 1269d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1270d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); 1271d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = count; 1272d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1273d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (!err_chk) 1274d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto skip_chk; 1275d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1276d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, 1277d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch &dwidth); 1278d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 127929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, 128029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch count); 12817946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (vme_err != NULL) { 1282d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(image->parent->parent, "First VME read error detected " 1283d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch "an at address 0x%llx\n", vme_err->address); 1284d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = vme_err->address - (vme_base + offset); 1285d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Clear down save errors in this address range */ 128629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, 128729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch count); 1288d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1289d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1290d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchskip_chk: 1291886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 1292d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1293d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 1294d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1295d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1296d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 12975ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, 1298d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch size_t count, loff_t offset) 1299d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1300d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval = 0, enabled; 1301d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long vme_base, size; 13026af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, cycle, dwidth; 1303d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1304d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_bus_error *vme_err = NULL; 130529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *tsi148_bridge; 130629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 130729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 130829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_bridge = image->parent; 130929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 131029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 1311d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1312886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 1313d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1314d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); 1315d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = count; 1316d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1317d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 1318d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Writes are posted. We need to do a read on the VME bus to flush out 131925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * all of the writes before we check for errors. We can't guarantee 1320d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * that reading the data we have just written is safe. It is believed 1321d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * that there isn't any read, write re-ordering, so we can read any 1322d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * location in VME space, so lets read the Device ID from the tsi148's 1323d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * own registers as mapped into CR/CSR space. 1324d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 1325d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * We check for saved errors in the written address range/space. 1326d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 1327d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1328d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (!err_chk) 1329d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto skip_chk; 1330d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1331d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 1332d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Get window info first, to maximise the time that the buffers may 1333d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * fluch on their own 1334d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 1335d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, 1336d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch &dwidth); 1337d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 133829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch ioread16(bridge->flush_image->kern_base + 0x7F000); 1339d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 134029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, 134129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch count); 13427946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (vme_err != NULL) { 134348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_warn(tsi148_bridge->parent, "First VME write error detected" 134448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch " an at address 0x%llx\n", vme_err->address); 1345d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = vme_err->address - (vme_base + offset); 1346d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Clear down save errors in this address range */ 134729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, 134829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch count); 1349d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1350d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1351d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchskip_chk: 1352886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 1353d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1354d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 1355d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1356d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1357d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1358d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Perform an RMW cycle on the VME bus. 1359d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 1360d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Requires a previously configured master window, returns final value. 1361d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 13625ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic unsigned int tsi148_master_rmw(struct vme_master_resource *image, 1363d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int mask, unsigned int compare, unsigned int swap, 1364d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch loff_t offset) 1365d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1366d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned long long pci_addr; 1367d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch unsigned int pci_addr_high, pci_addr_low; 1368d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 tmp, result; 1369d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int i; 137029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 1371d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 137229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = image->parent->driver_priv; 1373d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1374d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Find the PCI address that maps to the desired VME address */ 1375d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch i = image->number; 1376d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1377d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Locking as we can only do one of these at a time */ 1378886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->vme_rmw); 1379d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1380d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Lock image */ 1381886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&image->lock); 1382d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 138329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1384d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTSAU); 138529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + 1386d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTSAL); 1387d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1388d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(pci_addr_high, pci_addr_low, &pci_addr); 1389d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low); 1390d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1391d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Configure registers */ 139229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN); 139329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC); 139429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS); 139529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU); 139629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL); 1397d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1398d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Enable RMW */ 139929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); 1400d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp |= TSI148_LCSR_VMCTRL_RMWEN; 140129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); 1402d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1403d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Kick process off with a read to the required address. */ 1404d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch result = ioread32be(image->kern_base + offset); 1405d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1406d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Disable RMW */ 140729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); 1408d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp &= ~TSI148_LCSR_VMCTRL_RMWEN; 140929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); 1410d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1411886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&image->lock); 1412d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1413886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->vme_rmw); 1414d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1415d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return result; 1416d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1417d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 141848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic int tsi148_dma_set_vme_src_attributes(struct device *dev, u32 *attr, 14196af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, u32 cycle, u32 dwidth) 1420d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1421d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup 2eSST speeds */ 1422d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { 1423d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST160: 1424d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_2eSSTM_160; 1425d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1426d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST267: 1427d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_2eSSTM_267; 1428d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1429d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST320: 1430d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_2eSSTM_320; 1431d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1432d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1433d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1434d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup cycle types */ 14357946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_SCT) 1436d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_TM_SCT; 14377946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 14387946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_BLT) 1439d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_TM_BLT; 14407946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 14417946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_MBLT) 1442d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_TM_MBLT; 14437946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 14447946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_2eVME) 1445d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_TM_2eVME; 14467946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 14477946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_2eSST) 1448d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_TM_2eSST; 14497946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 1450d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eSSTB) { 145148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Currently not setting Broadcast Select " 145248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Registers\n"); 1453d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_TM_2eSSTB; 1454d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1455d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1456d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup data width */ 1457d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (dwidth) { 1458d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_D16: 1459d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_DBW_16; 1460d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1461d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_D32: 1462d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_DBW_32; 1463d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1464d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 146548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid data width\n"); 1466d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 1467d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1468d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1469d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup address space */ 1470d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (aspace) { 1471d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A16: 1472d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_A16; 1473d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1474d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A24: 1475d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_A24; 1476d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1477d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A32: 1478d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_A32; 1479d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1480d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A64: 1481d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_A64; 1482d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1483d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_CRCSR: 1484d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_CRCSR; 1485d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1486d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER1: 1487d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_USER1; 1488d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1489d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER2: 1490d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_USER2; 1491d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1492d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER3: 1493d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_USER3; 1494d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1495d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER4: 1496d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_AMODE_USER4; 1497d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1498d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 149948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid address space\n"); 1500d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 1501d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1502d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1503d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1504d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_SUPER) 1505d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_SUP; 1506d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_PROG) 1507d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DSAT_PGM; 1508d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1509d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1510d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1511d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 151248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welchstatic int tsi148_dma_set_vme_dest_attributes(struct device *dev, u32 *attr, 15136af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, u32 cycle, u32 dwidth) 1514d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1515d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup 2eSST speeds */ 1516d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { 1517d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST160: 1518d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_2eSSTM_160; 1519d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1520d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST267: 1521d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_2eSSTM_267; 1522d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1523d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_2eSST320: 1524d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_2eSSTM_320; 1525d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1526d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1527d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1528d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup cycle types */ 15297946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_SCT) 1530d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_TM_SCT; 15317946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 15327946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_BLT) 1533d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_TM_BLT; 15347946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 15357946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_MBLT) 1536d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_TM_MBLT; 15377946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 15387946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_2eVME) 1539d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_TM_2eVME; 15407946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 15417946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (cycle & VME_2eSST) 1542d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_TM_2eSST; 15437946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 1544d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_2eSSTB) { 154548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Currently not setting Broadcast Select " 154648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "Registers\n"); 1547d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_TM_2eSSTB; 1548d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1549d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1550d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup data width */ 1551d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (dwidth) { 1552d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_D16: 1553d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_DBW_16; 1554d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1555d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_D32: 1556d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_DBW_32; 1557d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1558d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 155948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid data width\n"); 1560d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 1561d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1562d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1563d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup address space */ 1564d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (aspace) { 1565d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A16: 1566d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_A16; 1567d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1568d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A24: 1569d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_A24; 1570d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1571d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A32: 1572d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_A32; 1573d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1574d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A64: 1575d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_A64; 1576d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1577d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_CRCSR: 1578d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_CRCSR; 1579d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1580d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER1: 1581d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_USER1; 1582d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1583d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER2: 1584d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_USER2; 1585d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1586d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER3: 1587d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_USER3; 1588d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1589d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_USER4: 1590d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_AMODE_USER4; 1591d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1592d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 159348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(dev, "Invalid address space\n"); 1594d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 1595d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1596d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1597d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1598d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_SUPER) 1599d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_SUP; 1600d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_PROG) 1601d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *attr |= TSI148_LCSR_DDAT_PGM; 1602d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1603d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1604d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1605d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1606d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1607d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Add a link list descriptor to the list 1608d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 16095ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_dma_list_add(struct vme_dma_list *list, 16105ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cota struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) 1611d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1612d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct tsi148_dma_entry *entry, *prev; 1613d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 address_high, address_low; 1614d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_dma_pattern *pattern_attr; 1615d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_dma_pci *pci_attr; 1616d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_dma_vme *vme_attr; 1617d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_addr_t desc_ptr; 1618d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval = 0; 161948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *tsi148_bridge; 162048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 162148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch tsi148_bridge = list->parent->parent; 1622d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1623bb9ea89ec8a3d80a835d53afc388ad5f67fd3cb3Martyn Welch /* Descriptor must be aligned on 64-bit boundaries */ 16247946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch entry = kmalloc(sizeof(struct tsi148_dma_entry), GFP_KERNEL); 1625d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (entry == NULL) { 162648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Failed to allocate memory for " 162748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "dma resource structure\n"); 1628d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 1629d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_mem; 1630d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1631d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1632d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Test descriptor alignment */ 1633886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if ((unsigned long)&entry->descriptor & 0x7) { 163448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Descriptor not aligned to 8 " 163548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "byte boundary as required: %p\n", 1636886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &entry->descriptor); 1637d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 1638d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_align; 1639d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1640d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1641d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Given we are going to fill out the structure, we probably don't 1642d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * need to zero it, but better safe than sorry for now. 1643d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 1644886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&entry->descriptor, 0, sizeof(struct tsi148_dma_descriptor)); 1645d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1646d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Fill out source part */ 1647d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (src->type) { 1648d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_DMA_PATTERN: 1649c4d82fbb458e6c6eebcff84653563c9c5e9a530dKulikov Vasiliy pattern_attr = src->private; 1650d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1651d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsal = pattern_attr->pattern; 1652d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PAT; 1653d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Default behaviour is 32 bit pattern */ 16547946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (pattern_attr->type & VME_DMA_PATTERN_BYTE) 1655d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsat |= TSI148_LCSR_DSAT_PSZ; 16567946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 1657d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* It seems that the default behaviour is to increment */ 16587946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0) 1659d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsat |= TSI148_LCSR_DSAT_NIN; 16607946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 1661d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1662d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_DMA_PCI: 1663c4d82fbb458e6c6eebcff84653563c9c5e9a530dKulikov Vasiliy pci_attr = src->private; 1664d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1665d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split((unsigned long long)pci_attr->address, &address_high, 1666d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch &address_low); 1667d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsau = address_high; 1668d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsal = address_low; 1669d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PCI; 1670d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1671d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_DMA_VME: 1672c4d82fbb458e6c6eebcff84653563c9c5e9a530dKulikov Vasiliy vme_attr = src->private; 1673d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1674d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split((unsigned long long)vme_attr->address, &address_high, 1675d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch &address_low); 1676d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsau = address_high; 1677d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsal = address_low; 1678d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_VME; 1679d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1680d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = tsi148_dma_set_vme_src_attributes( 1681886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota tsi148_bridge->parent, &entry->descriptor.dsat, 168248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); 16837946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (retval < 0) 1684d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_source; 1685d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1686d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 168748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid source type\n"); 1688d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 1689d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_source; 1690d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1691d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1692d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1693d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Assume last link - this will be over-written by adding another */ 1694d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dnlau = 0; 1695d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dnlal = TSI148_LCSR_DNLAL_LLA; 1696d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1697d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1698d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Fill out destination part */ 1699d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (dest->type) { 1700d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_DMA_PCI: 1701c4d82fbb458e6c6eebcff84653563c9c5e9a530dKulikov Vasiliy pci_attr = dest->private; 1702d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1703d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split((unsigned long long)pci_attr->address, &address_high, 1704d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch &address_low); 1705d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.ddau = address_high; 1706d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.ddal = address_low; 1707d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_PCI; 1708d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1709d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_DMA_VME: 1710c4d82fbb458e6c6eebcff84653563c9c5e9a530dKulikov Vasiliy vme_attr = dest->private; 1711d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1712d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split((unsigned long long)vme_attr->address, &address_high, 1713d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch &address_low); 1714d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.ddau = address_high; 1715d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.ddal = address_low; 1716d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_VME; 1717d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1718d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = tsi148_dma_set_vme_dest_attributes( 1719886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota tsi148_bridge->parent, &entry->descriptor.ddat, 172048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); 17217946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (retval < 0) 1722d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_dest; 1723d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1724d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 172548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid destination type\n"); 1726d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EINVAL; 1727d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_dest; 1728d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1729d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1730d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1731d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Fill out count */ 1732d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry->descriptor.dcnt = (u32)count; 1733d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1734d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Add to list */ 1735886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&entry->list, &list->entries); 1736d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1737d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Fill out previous descriptors "Next Address" */ 1738886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (entry->list.prev != &list->entries) { 1739d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch prev = list_entry(entry->list.prev, struct tsi148_dma_entry, 1740d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list); 1741d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* We need the bus address for the pointer */ 1742886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota desc_ptr = virt_to_bus(&entry->descriptor); 1743886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota reg_split(desc_ptr, &prev->descriptor.dnlau, 1744886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &prev->descriptor.dnlal); 1745d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1746d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1747d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1748d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1749d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_dest: 1750d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_source: 1751d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_align: 1752d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(entry); 1753d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_mem: 1754d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 1755d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1756d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1757d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1758d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Check to see if the provided DMA channel is busy. 1759d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 176029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel) 1761d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1762d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 tmp; 176329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 176429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 176529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 1766d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 176729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + 1768d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_DSTA); 1769d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1770d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (tmp & TSI148_LCSR_DSTA_BSY) 1771d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1772d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch else 1773d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 1; 1774d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1775d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1776d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1777d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1778d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Execute a previously generated link list 1779d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 1780d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * XXX Need to provide control register configuration. 1781d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 17825ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_dma_list_exec(struct vme_dma_list *list) 1783d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1784d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_dma_resource *ctrlr; 1785d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int channel, retval = 0; 1786d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct tsi148_dma_entry *entry; 1787d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_addr_t bus_addr; 1788d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 bus_addr_high, bus_addr_low; 1789d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 val, dctlreg = 0; 179048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *tsi148_bridge; 179129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 1792d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1793d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch ctrlr = list->parent; 1794d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 179548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch tsi148_bridge = ctrlr->parent; 179648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 179748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 179829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 1799886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 1800d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1801d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch channel = ctrlr->number; 1802d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1803886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!list_empty(&ctrlr->running)) { 1804d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 1805d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * XXX We have an active DMA transfer and currently haven't 1806d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * sorted out the mechanism for "pending" DMA transfers. 1807d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Return busy. 1808d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 1809d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Need to add to pending here */ 1810886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 1811d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EBUSY; 1812d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } else { 1813886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add(&list->list, &ctrlr->running); 1814d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1815d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1816d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Get first bus address and write into registers */ 1817886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota entry = list_first_entry(&list->entries, struct tsi148_dma_entry, 1818d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list); 1819d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1820886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota bus_addr = virt_to_bus(&entry->descriptor); 1821d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1822886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 1823d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1824d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(bus_addr, &bus_addr_high, &bus_addr_low); 1825d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 182629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(bus_addr_high, bridge->base + 1827d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU); 182829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(bus_addr_low, bridge->base + 1829d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL); 1830d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1831d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Start the operation */ 183229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base + 1833d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL); 1834d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 183529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch wait_event_interruptible(bridge->dma_queue[channel], 183629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_dma_busy(ctrlr->parent, channel)); 1837d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 1838d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Read status register, this register is valid until we kick off a 1839d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * new transfer. 1840d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 184129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + 1842d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_DSTA); 1843d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1844d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (val & TSI148_LCSR_DSTA_VBE) { 184548d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "DMA Error. DSTA=%08X\n", val); 1846d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EIO; 1847d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1848d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1849d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Remove list from running list */ 1850886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&ctrlr->mtx); 1851886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_del(&list->list); 1852886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 1853d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1854d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 1855d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1856d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1857d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1858d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Clean up a previously generated link list 1859d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 1860d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * We have a separate function, don't assume that the chain can't be reused. 1861d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 18625ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_dma_list_empty(struct vme_dma_list *list) 1863d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1864d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct list_head *pos, *temp; 18657946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch struct tsi148_dma_entry *entry; 1866d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1867d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* detach and free each entry */ 1868886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each_safe(pos, temp, &list->entries) { 1869d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 1870d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch entry = list_entry(pos, struct tsi148_dma_entry, list); 1871d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(entry); 1872d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1873d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 18747946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch return 0; 1875d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1876d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1877d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1878d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * All 4 location monitors reside at the same base - this is therefore a 1879d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * system wide configuration. 1880d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 1881d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * This does not enable the LM monitor - that should be done when the first 1882d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * callback is attached and disabled when the last callback is removed. 1883d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 18845ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, 18856af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, u32 cycle) 1886d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1887d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 lm_base_high, lm_base_low, lm_ctl = 0; 1888d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int i; 188948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *tsi148_bridge; 189029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 189129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 189248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch tsi148_bridge = lm->parent; 189348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 189448d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 1895d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1896886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 1897d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1898d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* If we already have a callback attached, we can't move it! */ 189942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch for (i = 0; i < lm->monitors; i++) { 190029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->lm_callback[i] != NULL) { 1901886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 190248d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Location monitor " 190348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "callback attached, can't reset\n"); 1904d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EBUSY; 1905d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1906d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1907d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1908d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch switch (aspace) { 1909d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A16: 1910d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_AS_A16; 1911d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1912d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A24: 1913d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_AS_A24; 1914d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1915d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A32: 1916d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_AS_A32; 1917d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1918d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch case VME_A64: 1919d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_AS_A64; 1920d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1921d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch default: 1922886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 192348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Invalid address space\n"); 1924d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 1925d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch break; 1926d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 1927d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1928d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_SUPER) 1929d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_SUPR ; 1930d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_USER) 1931d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_NPRIV; 1932d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_PROG) 1933d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_PGM; 1934d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cycle & VME_DATA) 1935d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_DATA; 1936d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1937d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_split(lm_base, &lm_base_high, &lm_base_low); 1938d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 193929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU); 194029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL); 194129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); 1942d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1943886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 1944d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1945d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 1946d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1947d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1948d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* Get configuration of the callback monitor and return whether it is enabled 1949d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * or disabled. 1950d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 19515ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_lm_get(struct vme_lm_resource *lm, 19526af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long *lm_base, u32 *aspace, u32 *cycle) 1953d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 1954d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0; 195529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 195629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 195729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = lm->parent->driver_priv; 1958d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1959886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 1960d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 196129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU); 196229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL); 196329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); 1964d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1965d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch reg_join(lm_base_high, lm_base_low, lm_base); 1966d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1967d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (lm_ctl & TSI148_LCSR_LMAT_EN) 1968d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch enabled = 1; 1969d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 19707946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A16) 1971d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A16; 19727946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 19737946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A24) 1974d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A24; 19757946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 19767946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A32) 1977d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A32; 19787946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 19797946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A64) 1980d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *aspace |= VME_A64; 19817946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch 1982d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1983d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (lm_ctl & TSI148_LCSR_LMAT_SUPR) 1984d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_SUPER; 1985d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (lm_ctl & TSI148_LCSR_LMAT_NPRIV) 1986d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_USER; 1987d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (lm_ctl & TSI148_LCSR_LMAT_PGM) 1988d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_PROG; 1989d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (lm_ctl & TSI148_LCSR_LMAT_DATA) 1990d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch *cycle |= VME_DATA; 1991d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1992886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 1993d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1994d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return enabled; 1995d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 1996d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 1997d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 1998d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Attach a callback to a specific location monitor. 1999d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 2000d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Callback will be passed the monitor triggered. 2001d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 20025ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor, 200342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch void (*callback)(int)) 2004d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2005d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 lm_ctl, tmp; 200648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch struct vme_bridge *tsi148_bridge; 200729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 200829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 200948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch tsi148_bridge = lm->parent; 201048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch 201148d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch bridge = tsi148_bridge->driver_priv; 2012d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2013886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 2014d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2015d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Ensure that the location monitor is configured - need PGM or DATA */ 201629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); 2017d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) { 2018886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 201948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Location monitor not properly " 202048d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "configured\n"); 2021d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EINVAL; 2022d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2023d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2024d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Check that a callback isn't already attached */ 202529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->lm_callback[monitor] != NULL) { 2026886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 202748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Existing callback attached\n"); 2028d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -EBUSY; 2029d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2030d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2031d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Attach callback */ 203229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->lm_callback[monitor] = callback; 2033d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2034d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Enable Location Monitor interrupt */ 203529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); 2036d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp |= TSI148_LCSR_INTEN_LMEN[monitor]; 203729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); 2038d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 203929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); 2040d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp |= TSI148_LCSR_INTEO_LMEO[monitor]; 204129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); 2042d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2043d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Ensure that global Location Monitor Enable set */ 2044d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) { 2045d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_ctl |= TSI148_LCSR_LMAT_EN; 204629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); 2047d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2048d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2049886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 2050d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2051d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 2052d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2053d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2054d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 2055d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Detach a callback function forn a specific location monitor. 2056d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 20575ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor) 2058d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2059d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 lm_en, tmp; 206029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 206129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 206229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = lm->parent->driver_priv; 2063d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2064886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 2065d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2066d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Disable Location Monitor and ensure previous interrupts are clear */ 206729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN); 2068d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor]; 206929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN); 2070d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 207129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); 2072d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor]; 207329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); 2074d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2075d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iowrite32be(TSI148_LCSR_INTC_LMC[monitor], 207629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->base + TSI148_LCSR_INTC); 2077d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2078d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Detach callback */ 207929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->lm_callback[monitor] = NULL; 2080d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2081d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* If all location monitors disabled, disable global Location Monitor */ 2082d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S | 2083d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) { 208429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT); 2085d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tmp &= ~TSI148_LCSR_LMAT_EN; 208629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT); 2087d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2088d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2089886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 2090d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2091d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 2092d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2093d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2094d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 2095d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Determine Geographical Addressing 2096d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 20975ade6c4d79377efc371ac89db07e4f6594d1286aEmilio G. Cotastatic int tsi148_slot_get(struct vme_bridge *tsi148_bridge) 2098d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 20997946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch u32 slot = 0; 210029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 210129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 210229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 2103d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2104638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch if (!geoid) { 210529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT); 2106638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch slot = slot & TSI148_LCSR_VSTAT_GA_M; 2107638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch } else 2108638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch slot = geoid; 2109638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch 2110d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return (int)slot; 2111d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2112d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 21137f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vangavoid *tsi148_alloc_consistent(struct device *parent, size_t size, 21147f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga dma_addr_t *dma) 21157f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga{ 21167f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga struct pci_dev *pdev; 21177f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 21187f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga /* Find pci_dev container of dev */ 21197f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga pdev = container_of(parent, struct pci_dev, dev); 21207f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 21217f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga return pci_alloc_consistent(pdev, size, dma); 21227f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga} 21237f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 21247f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vangavoid tsi148_free_consistent(struct device *parent, size_t size, void *vaddr, 21257f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga dma_addr_t dma) 21267f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga{ 21277f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga struct pci_dev *pdev; 21287f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 21297f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga /* Find pci_dev container of dev */ 21307f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga pdev = container_of(parent, struct pci_dev, dev); 21317f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 21327f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga pci_free_consistent(pdev, size, vaddr, dma); 21337f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga} 21347f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 2135d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic int __init tsi148_init(void) 2136d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2137d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return pci_register_driver(&tsi148_driver); 2138d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2139d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2140d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch/* 2141d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Configure CR/CSR space 2142d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 2143d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Access to the CR/CSR can be configured at power-up. The location of the 2144d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * CR/CSR registers in the CR/CSR address space is determined by the boards 2145d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Auto-ID or Geographic address. This function ensures that the window is 2146d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * enabled at an offset consistent with the boards geopgraphic address. 2147d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * 2148d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Each board has a 512kB window, with the highest 4kB being used for the 2149d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * boards registers, this means there is a fix length 508kB window which must 2150d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * be mapped onto PCI memory. 2151d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 215229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, 215329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 2154d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2155d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 cbar, crat, vstat; 2156d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 crcsr_bus_high, crcsr_bus_low; 2157d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval; 215829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 215929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 216029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 2161d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2162d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Allocate mem for CR/CSR image */ 216329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, 2164886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &bridge->crcsr_bus); 216529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (bridge->crcsr_kernel == NULL) { 216648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Failed to allocate memory for " 216748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch "CR/CSR image\n"); 2168d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return -ENOMEM; 2169d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2170d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 217129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); 2172d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 217329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low); 2174d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 217529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU); 217629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL); 2177d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2178d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Ensure that the CR/CSR is configured at the correct offset */ 217929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch cbar = ioread32be(bridge->base + TSI148_CBAR); 2180d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3; 2181d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 218229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch vstat = tsi148_slot_get(tsi148_bridge); 2183d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2184d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (cbar != vstat) { 2185638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch cbar = vstat; 218648d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_info(tsi148_bridge->parent, "Setting CR/CSR offset\n"); 218729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(cbar<<3, bridge->base + TSI148_CBAR); 2188d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 218948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar); 2190d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 219129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); 2192d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (crat & TSI148_LCSR_CRAT_EN) { 219348d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n"); 2194d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iowrite32be(crat | TSI148_LCSR_CRAT_EN, 219529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->base + TSI148_LCSR_CRAT); 2196d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } else 219748d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n"); 2198d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2199d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* If we want flushed, error-checked writes, set up a window 2200d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * over the CR/CSR registers. We read from here to safely flush 2201d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * through VME writes. 2202d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 22037946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (err_chk) { 220429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch retval = tsi148_master_set(bridge->flush_image, 1, 220529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch (vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT, 220629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch VME_D16); 2207d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval) 220848d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch dev_err(tsi148_bridge->parent, "Configuring flush image" 220948d9356e7750d3efa3156eb3a76e7a4439774b12Martyn Welch " failed\n"); 2210d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2211d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2212d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 2213d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2214d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2215d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 221629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge, 221729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct pci_dev *pdev) 2218d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2219d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 crat; 222029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 222129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 222229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 2223d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2224d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Turn off CR/CSR space */ 222529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); 2226d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch iowrite32be(crat & ~TSI148_LCSR_CRAT_EN, 222729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->base + TSI148_LCSR_CRAT); 2228d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2229d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Free image */ 223029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0, bridge->base + TSI148_LCSR_CROU); 223129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0, bridge->base + TSI148_LCSR_CROL); 2232d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 223329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, 223429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->crcsr_bus); 2235d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2236d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2237d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) 2238d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2239d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int retval, i, master_num; 2240d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch u32 data; 2241d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct list_head *pos = NULL; 224229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *tsi148_bridge; 224329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *tsi148_device; 2244d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_master_resource *master_image; 2245d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_slave_resource *slave_image; 2246d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_dma_resource *dma_ctrlr; 224742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 2248d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2249d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* If we want to support more than one of each bridge, we need to 2250d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * dynamically generate this so we get one per device 2251d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 22527a6cb0d5497418599d2125b670926b75e673861cJulia Lawall tsi148_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); 2253d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (tsi148_bridge == NULL) { 2254d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 2255d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch "structure\n"); 2256d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 2257d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_struct; 2258d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2259d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 22607a6cb0d5497418599d2125b670926b75e673861cJulia Lawall tsi148_device = kzalloc(sizeof(struct tsi148_driver), GFP_KERNEL); 226129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (tsi148_device == NULL) { 226229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for device " 226329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch "structure\n"); 226429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch retval = -ENOMEM; 226529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch goto err_driver; 226629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch } 226729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 226829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_bridge->driver_priv = tsi148_device; 226929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 2270d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Enable the device */ 2271d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = pci_enable_device(pdev); 2272d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval) { 2273d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Unable to enable device\n"); 2274d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_enable; 2275d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2276d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2277d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Map Registers */ 2278d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = pci_request_regions(pdev, driver_name); 2279d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval) { 2280d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Unable to reserve resources\n"); 2281d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_resource; 2282d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2283d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2284d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* map registers in BAR 0 */ 228529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0), 228629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 4096); 228729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (!tsi148_device->base) { 2288d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Unable to remap CRG region\n"); 2289d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EIO; 2290d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_remap; 2291d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2292d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2293d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Check to see if the mapping worked out */ 229429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF; 2295d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (data != PCI_VENDOR_ID_TUNDRA) { 2296d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "CRG region check failed\n"); 2297d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -EIO; 2298d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_test; 2299d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2300d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2301d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Initialize wait queues & mutual exclusion flags */ 2302886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&tsi148_device->dma_queue[0]); 2303886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&tsi148_device->dma_queue[1]); 2304886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota init_waitqueue_head(&tsi148_device->iack_queue); 2305886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&tsi148_device->vme_int); 2306886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&tsi148_device->vme_rmw); 2307d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2308886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota tsi148_bridge->parent = &pdev->dev; 2309d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch strcpy(tsi148_bridge->name, driver_name); 2310d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2311d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Setup IRQ */ 2312d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = tsi148_irq_init(tsi148_bridge); 2313d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval != 0) { 2314d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Chip Initialization failed.\n"); 2315d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_irq; 2316d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2317d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2318d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* If we are going to flush writes, we need to read from the VME bus. 2319d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * We need to do this safely, thus we read the devices own CR/CSR 2320d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * register. To do this we must set up a window in CR/CSR space and 2321d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * hence have one less master window resource available. 2322d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 2323d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_num = TSI148_MAX_MASTER; 23247946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch if (err_chk) { 2325d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_num--; 232629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 2327324148788bf3744d90fb6894ec5744eb0ca91b74Julia Lawall tsi148_device->flush_image = 232829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL); 232929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (tsi148_device->flush_image == NULL) { 2330d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 2331d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch "flush resource structure\n"); 2332d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 2333d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_master; 2334d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 233529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->parent = tsi148_bridge; 2336886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock_init(&tsi148_device->flush_image->lock); 233729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->locked = 1; 233829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->number = master_num; 233929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 | 234029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch VME_A32 | VME_A64; 234129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT | 234229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB | 234329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER | 234429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch VME_USER | VME_PROG | VME_DATA; 234529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->width_attr = VME_D16 | VME_D32; 2346886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&tsi148_device->flush_image->bus_resource, 0, 2347d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch sizeof(struct resource)); 234829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_device->flush_image->kern_base = NULL; 2349d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2350d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2351d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Add master windows to list */ 2352886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&tsi148_bridge->master_resources); 2353d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 0; i < master_num; i++) { 23547946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch master_image = kmalloc(sizeof(struct vme_master_resource), 23557946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch GFP_KERNEL); 2356d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (master_image == NULL) { 2357d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 2358d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch "master resource structure\n"); 2359d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 2360d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_master; 2361d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2362d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->parent = tsi148_bridge; 2363886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock_init(&master_image->lock); 2364d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->locked = 0; 2365d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->number = i; 2366d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | 2367d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_A64; 2368d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 2369d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | 2370d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | 2371d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_PROG | VME_DATA; 2372d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->width_attr = VME_D16 | VME_D32; 2373886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota memset(&master_image->bus_resource, 0, 2374d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch sizeof(struct resource)); 2375d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch master_image->kern_base = NULL; 2376886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&master_image->list, 2377886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &tsi148_bridge->master_resources); 2378d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2379d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2380d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Add slave windows to list */ 2381886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&tsi148_bridge->slave_resources); 2382d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 0; i < TSI148_MAX_SLAVE; i++) { 23837946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch slave_image = kmalloc(sizeof(struct vme_slave_resource), 23847946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch GFP_KERNEL); 2385d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (slave_image == NULL) { 2386d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 2387d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch "slave resource structure\n"); 2388d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 2389d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_slave; 2390d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2391d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image->parent = tsi148_bridge; 2392886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&slave_image->mtx); 2393d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image->locked = 0; 2394d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image->number = i; 2395d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 | 2396d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 | 2397d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_USER3 | VME_USER4; 2398d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | 2399d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | 2400d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | 2401d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch VME_PROG | VME_DATA; 2402886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&slave_image->list, 2403886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &tsi148_bridge->slave_resources); 2404d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2405d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2406d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Add dma engines to list */ 2407886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&tsi148_bridge->dma_resources); 2408d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 0; i < TSI148_MAX_DMA; i++) { 24097946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), 24107946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch GFP_KERNEL); 2411d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (dma_ctrlr == NULL) { 2412d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 2413d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch "dma resource structure\n"); 2414d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = -ENOMEM; 2415d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_dma; 2416d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2417d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_ctrlr->parent = tsi148_bridge; 2418886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&dma_ctrlr->mtx); 2419d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_ctrlr->locked = 0; 2420d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_ctrlr->number = i; 24214f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | 24224f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME | 24234f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME | 24244f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch VME_DMA_PATTERN_TO_MEM; 2425886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->pending); 2426886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_ctrlr->running); 2427886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&dma_ctrlr->list, 2428886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota &tsi148_bridge->dma_resources); 2429d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2430d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 243142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Add location monitor to list */ 2432886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&tsi148_bridge->lm_resources); 243342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); 243442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (lm == NULL) { 243542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch dev_err(&pdev->dev, "Failed to allocate memory for " 243642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch "location monitor resource structure\n"); 243742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch retval = -ENOMEM; 243842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_lm; 243942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 244042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->parent = tsi148_bridge; 2441886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&lm->mtx); 244242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 0; 244342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->number = 1; 244442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->monitors = 4; 2445886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_add_tail(&lm->list, &tsi148_bridge->lm_resources); 244642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 2447d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->slave_get = tsi148_slave_get; 2448d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->slave_set = tsi148_slave_set; 2449d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->master_get = tsi148_master_get; 2450d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->master_set = tsi148_master_set; 2451d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->master_read = tsi148_master_read; 2452d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->master_write = tsi148_master_write; 2453d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->master_rmw = tsi148_master_rmw; 2454d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->dma_list_add = tsi148_dma_list_add; 2455d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->dma_list_exec = tsi148_dma_list_exec; 2456d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->dma_list_empty = tsi148_dma_list_empty; 2457c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tsi148_bridge->irq_set = tsi148_irq_set; 2458c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch tsi148_bridge->irq_generate = tsi148_irq_generate; 2459d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->lm_set = tsi148_lm_set; 2460d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->lm_get = tsi148_lm_get; 2461d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->lm_attach = tsi148_lm_attach; 2462d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->lm_detach = tsi148_lm_detach; 2463d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch tsi148_bridge->slot_get = tsi148_slot_get; 24647f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga tsi148_bridge->alloc_consistent = tsi148_alloc_consistent; 24657f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga tsi148_bridge->free_consistent = tsi148_free_consistent; 2466d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 246729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); 2468d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_info(&pdev->dev, "Board is%s the VME system controller\n", 24697946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch (data & TSI148_LCSR_VSTAT_SCONS) ? "" : " not"); 247029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (!geoid) 2471638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch dev_info(&pdev->dev, "VME geographical address is %d\n", 2472638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch data & TSI148_LCSR_VSTAT_GA_M); 247329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch else 2474638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch dev_info(&pdev->dev, "VME geographical address is set to %d\n", 2475638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch geoid); 247629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 2477d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", 2478d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch err_chk ? "enabled" : "disabled"); 2479d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 24804839737b3b6af2a9b3b960584f08177fbc9bf118Martyn Welch if (tsi148_crcsr_init(tsi148_bridge, pdev)) { 2481d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); 2482d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_crcsr; 24834839737b3b6af2a9b3b960584f08177fbc9bf118Martyn Welch } 2484d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2485d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch retval = vme_register_bridge(tsi148_bridge); 2486d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch if (retval != 0) { 2487d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dev_err(&pdev->dev, "Chip Registration failed.\n"); 2488d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch goto err_reg; 2489d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2490d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 249129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch pci_set_drvdata(pdev, tsi148_bridge); 249229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 2493d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* Clear VME bus "board fail", and "power-up reset" lines */ 249429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); 2495d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch data &= ~TSI148_LCSR_VSTAT_BRDFL; 2496d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch data |= TSI148_LCSR_VSTAT_CPURST; 249729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT); 2498d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2499d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return 0; 2500d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2501d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_reg: 250229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_crcsr_exit(tsi148_bridge, pdev); 2503d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_crcsr: 250442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_lm: 250542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* resources are stored in link list */ 2506886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &tsi148_bridge->lm_resources) { 250742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(pos, struct vme_lm_resource, list); 250842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch list_del(pos); 250942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch kfree(lm); 251042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 2511d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_dma: 2512d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* resources are stored in link list */ 2513886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &tsi148_bridge->dma_resources) { 2514d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 2515d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 2516d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(dma_ctrlr); 2517d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2518d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_slave: 2519d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* resources are stored in link list */ 2520886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &tsi148_bridge->slave_resources) { 2521d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 2522d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 2523d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(slave_image); 2524d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2525d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_master: 2526d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* resources are stored in link list */ 2527886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(pos, &tsi148_bridge->master_resources) { 25287946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch master_image = list_entry(pos, struct vme_master_resource, 25297946328faf1dca9bfadf98f4579f95aafffaba0fMartyn Welch list); 2530d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 2531d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(master_image); 2532d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2533d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2534a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cota tsi148_irq_exit(tsi148_bridge, pdev); 2535d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_irq: 2536d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_test: 253729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(tsi148_device->base); 2538d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_remap: 2539d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch pci_release_regions(pdev); 2540d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_resource: 2541d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch pci_disable_device(pdev); 2542d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_enable: 254329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kfree(tsi148_device); 254429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welcherr_driver: 2545d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(tsi148_bridge); 2546d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welcherr_struct: 2547d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch return retval; 2548d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2549d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2550d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2551d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void tsi148_remove(struct pci_dev *pdev) 2552d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2553d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct list_head *pos = NULL; 2554b558ba2f356c28269de179c4f7f6f179a4fa6a1dEmilio G. Cota struct list_head *tmplist; 2555d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_master_resource *master_image; 2556d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_slave_resource *slave_image; 2557d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch struct vme_dma_resource *dma_ctrlr; 2558d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch int i; 255929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct tsi148_driver *bridge; 256029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev); 256129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 256229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge = tsi148_bridge->driver_priv; 2563d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2564d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 256529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch dev_dbg(&pdev->dev, "Driver is being unloaded.\n"); 2566d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2567d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2568d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Shutdown all inbound and outbound windows. 2569d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 2570d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch for (i = 0; i < 8; i++) { 257129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] + 2572d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_ITAT); 257329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] + 2574d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch TSI148_LCSR_OFFSET_OTAT); 2575d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2576d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2577d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2578d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Shutdown Location monitor. 2579d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 258029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0, bridge->base + TSI148_LCSR_LMAT); 2581d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2582d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2583d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Shutdown CRG map. 2584d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 258529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT); 2586d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2587d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2588d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Clear error status. 2589d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 259029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT); 259129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT); 259229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT); 2593d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2594d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2595d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Remove VIRQ interrupt (if any) 2596d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 259729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800) 259829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR); 2599d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2600d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* 2601d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch * Map all Interrupts to PCI INTA 2602d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch */ 260329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1); 260429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2); 2605d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2606a82ad05ecd9dbd909509a332d3aa5f4ac439a054Emilio G. Cota tsi148_irq_exit(tsi148_bridge, pdev); 2607d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2608d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch vme_unregister_bridge(tsi148_bridge); 2609d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 261029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch tsi148_crcsr_exit(tsi148_bridge, pdev); 2611d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2612d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* resources are stored in link list */ 2613b558ba2f356c28269de179c4f7f6f179a4fa6a1dEmilio G. Cota list_for_each_safe(pos, tmplist, &tsi148_bridge->dma_resources) { 2614d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); 2615d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 2616d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(dma_ctrlr); 2617d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2618d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2619d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* resources are stored in link list */ 2620b558ba2f356c28269de179c4f7f6f179a4fa6a1dEmilio G. Cota list_for_each_safe(pos, tmplist, &tsi148_bridge->slave_resources) { 2621d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch slave_image = list_entry(pos, struct vme_slave_resource, list); 2622d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 2623d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(slave_image); 2624d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2625d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2626d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch /* resources are stored in link list */ 2627b558ba2f356c28269de179c4f7f6f179a4fa6a1dEmilio G. Cota list_for_each_safe(pos, tmplist, &tsi148_bridge->master_resources) { 2628638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch master_image = list_entry(pos, struct vme_master_resource, 2629638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch list); 2630d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch list_del(pos); 2631d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(master_image); 2632d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch } 2633d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 263429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch iounmap(bridge->base); 2635d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2636d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch pci_release_regions(pdev); 2637d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2638d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch pci_disable_device(pdev); 2639d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 264029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch kfree(tsi148_bridge->driver_priv); 264129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch 2642d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch kfree(tsi148_bridge); 2643d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2644d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2645d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchstatic void __exit tsi148_exit(void) 2646d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch{ 2647d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch pci_unregister_driver(&tsi148_driver); 2648d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch} 2649d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2650d22b8ed9a3b0a157b732580258ec16b729265953Martyn WelchMODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes"); 2651d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchmodule_param(err_chk, bool, 0); 2652d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2653638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn WelchMODULE_PARM_DESC(geoid, "Override geographical addressing"); 2654638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welchmodule_param(geoid, int, 0); 2655638f199db463a8f2b1535c45ab27d04bb1a55bafMartyn Welch 2656d22b8ed9a3b0a157b732580258ec16b729265953Martyn WelchMODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge"); 2657d22b8ed9a3b0a157b732580258ec16b729265953Martyn WelchMODULE_LICENSE("GPL"); 2658d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welch 2659d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchmodule_init(tsi148_init); 2660d22b8ed9a3b0a157b732580258ec16b729265953Martyn Welchmodule_exit(tsi148_exit); 2661