vme_ca91cx42.c revision 21e0cf6d2e59e19f77096e73d83157734e7f7782
160479690af6d559d4202bed139db90323386bd2bMartyn Welch/*
260479690af6d559d4202bed139db90323386bd2bMartyn Welch * Support for the Tundra Universe I/II VME-PCI Bridge Chips
360479690af6d559d4202bed139db90323386bd2bMartyn Welch *
466bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com>
566bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
660479690af6d559d4202bed139db90323386bd2bMartyn Welch *
760479690af6d559d4202bed139db90323386bd2bMartyn Welch * Based on work by Tom Armistead and Ajit Prem
860479690af6d559d4202bed139db90323386bd2bMartyn Welch * Copyright 2004 Motorola Inc.
960479690af6d559d4202bed139db90323386bd2bMartyn Welch *
1060479690af6d559d4202bed139db90323386bd2bMartyn Welch * Derived from ca91c042.c by Michael Wyrick
1160479690af6d559d4202bed139db90323386bd2bMartyn Welch *
1260479690af6d559d4202bed139db90323386bd2bMartyn Welch * This program is free software; you can redistribute  it and/or modify it
1360479690af6d559d4202bed139db90323386bd2bMartyn Welch * under  the terms of  the GNU General  Public License as published by the
1460479690af6d559d4202bed139db90323386bd2bMartyn Welch * Free Software Foundation;  either version 2 of the  License, or (at your
1560479690af6d559d4202bed139db90323386bd2bMartyn Welch * option) any later version.
1660479690af6d559d4202bed139db90323386bd2bMartyn Welch */
1760479690af6d559d4202bed139db90323386bd2bMartyn Welch
1860479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/module.h>
1960479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/mm.h>
2060479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/types.h>
2160479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/errno.h>
2260479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/pci.h>
2360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/dma-mapping.h>
2460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/poll.h>
2560479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/interrupt.h>
2660479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <linux/spinlock.h>
276af783c8ba3418a8ffc50f1266d9b1e35a3322dbGreg Kroah-Hartman#include <linux/sched.h>
2860479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <asm/time.h>
2960479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <asm/io.h>
3060479690af6d559d4202bed139db90323386bd2bMartyn Welch#include <asm/uaccess.h>
3160479690af6d559d4202bed139db90323386bd2bMartyn Welch
3260479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme.h"
3360479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "../vme_bridge.h"
3460479690af6d559d4202bed139db90323386bd2bMartyn Welch#include "vme_ca91cx42.h"
3560479690af6d559d4202bed139db90323386bd2bMartyn Welch
363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void);
373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *);
383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_remove(struct pci_dev *);
393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void);
4060479690af6d559d4202bed139db90323386bd2bMartyn Welch
4112b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch/* Module parameters */
4212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchstatic int geoid;
4312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch
443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic char driver_name[] = "vme_ca91cx42";
4560479690af6d559d4202bed139db90323386bd2bMartyn Welch
4613ac58dac0c6b1edeb060102049b07ebceea9a40Németh Mártonstatic const struct pci_device_id ca91cx42_ids[] = {
473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) },
483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	{ },
4960479690af6d559d4202bed139db90323386bd2bMartyn Welch};
5060479690af6d559d4202bed139db90323386bd2bMartyn Welch
513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic struct pci_driver ca91cx42_driver = {
523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	.name = driver_name,
533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	.id_table = ca91cx42_ids,
543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	.probe = ca91cx42_probe,
553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	.remove = ca91cx42_remove,
5660479690af6d559d4202bed139db90323386bd2bMartyn Welch};
5760479690af6d559d4202bed139db90323386bd2bMartyn Welch
5829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge)
5960479690af6d559d4202bed139db90323386bd2bMartyn Welch{
6029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	wake_up(&(bridge->dma_queue));
6160479690af6d559d4202bed139db90323386bd2bMartyn Welch
623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return CA91CX42_LINT_DMA;
633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
6460479690af6d559d4202bed139db90323386bd2bMartyn Welch
6529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat)
663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int i;
683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 serviced = 0;
6960479690af6d559d4202bed139db90323386bd2bMartyn Welch
703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	for (i = 0; i < 4; i++) {
713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if (stat & CA91CX42_LINT_LM[i]) {
723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			/* We only enable interrupts if the callback is set */
7329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch			bridge->lm_callback[i](i);
743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			serviced |= CA91CX42_LINT_LM[i];
7560479690af6d559d4202bed139db90323386bd2bMartyn Welch		}
7660479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
7760479690af6d559d4202bed139db90323386bd2bMartyn Welch
783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return serviced;
793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
8060479690af6d559d4202bed139db90323386bd2bMartyn Welch
813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX This needs to be split into 4 queues */
8229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask)
833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
8429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	wake_up(&(bridge->mbox_queue));
8560479690af6d559d4202bed139db90323386bd2bMartyn Welch
863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return CA91CX42_LINT_MBOX;
873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
8860479690af6d559d4202bed139db90323386bd2bMartyn Welch
8929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge)
903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
9129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	wake_up(&(bridge->iack_queue));
9260479690af6d559d4202bed139db90323386bd2bMartyn Welch
933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return CA91CX42_LINT_SW_IACK;
9460479690af6d559d4202bed139db90323386bd2bMartyn Welch}
9560479690af6d559d4202bed139db90323386bd2bMartyn Welch
963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_bus_error_chk(int clrflag)
9860479690af6d559d4202bed139db90323386bd2bMartyn Welch{
9960479690af6d559d4202bed139db90323386bd2bMartyn Welch	int tmp;
10029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	tmp = ioread32(bridge->base + PCI_COMMAND);
1013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (tmp & 0x08000000) {	/* S_TA is Set */
10260479690af6d559d4202bed139db90323386bd2bMartyn Welch		if (clrflag)
1033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			iowrite32(tmp | 0x08000000,
10429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch			       bridge->base + PCI_COMMAND);
1053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return 1;
10660479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
1073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
10860479690af6d559d4202bed139db90323386bd2bMartyn Welch}
1093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
11060479690af6d559d4202bed139db90323386bd2bMartyn Welch
11129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_VERR_irqhandler(struct ca91cx42_driver *bridge)
11260479690af6d559d4202bed139db90323386bd2bMartyn Welch{
11360479690af6d559d4202bed139db90323386bd2bMartyn Welch	int val;
11460479690af6d559d4202bed139db90323386bd2bMartyn Welch
11529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	val = ioread32(bridge->base + DGCS);
11660479690af6d559d4202bed139db90323386bd2bMartyn Welch
11760479690af6d559d4202bed139db90323386bd2bMartyn Welch	if (!(val & 0x00000800)) {
1183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "ca91c042: ca91cx42_VERR_irqhandler DMA Read "
1193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"Error DGCS=%08X\n", val);
12060479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
1213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
1223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return CA91CX42_LINT_VERR;
12360479690af6d559d4202bed139db90323386bd2bMartyn Welch}
12460479690af6d559d4202bed139db90323386bd2bMartyn Welch
12529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_LERR_irqhandler(struct ca91cx42_driver *bridge)
12660479690af6d559d4202bed139db90323386bd2bMartyn Welch{
12760479690af6d559d4202bed139db90323386bd2bMartyn Welch	int val;
12860479690af6d559d4202bed139db90323386bd2bMartyn Welch
12929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	val = ioread32(bridge->base + DGCS);
13060479690af6d559d4202bed139db90323386bd2bMartyn Welch
13160479690af6d559d4202bed139db90323386bd2bMartyn Welch	if (!(val & 0x00000800)) {
1323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "ca91c042: ca91cx42_LERR_irqhandler DMA Read "
1333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"Error DGCS=%08X\n", val);
13460479690af6d559d4202bed139db90323386bd2bMartyn Welch
13560479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
13660479690af6d559d4202bed139db90323386bd2bMartyn Welch
1373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return CA91CX42_LINT_LERR;
13860479690af6d559d4202bed139db90323386bd2bMartyn Welch}
13960479690af6d559d4202bed139db90323386bd2bMartyn Welch
1403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
14129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge,
14229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	int stat)
14360479690af6d559d4202bed139db90323386bd2bMartyn Welch{
1443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int vec, i, serviced = 0;
14529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
14629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
14729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
14829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
14960479690af6d559d4202bed139db90323386bd2bMartyn Welch
15060479690af6d559d4202bed139db90323386bd2bMartyn Welch	for (i = 7; i > 0; i--) {
1513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if (stat & (1 << i)) {
15229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch			vec = ioread32(bridge->base +
1533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch				CA91CX42_V_STATID[i]) & 0xff;
1543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
155c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch			vme_irq_handler(ca91cx42_bridge, i, vec);
1563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
1573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			serviced |= (1 << i);
15860479690af6d559d4202bed139db90323386bd2bMartyn Welch		}
15960479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
1603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
1613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return serviced;
16260479690af6d559d4202bed139db90323386bd2bMartyn Welch}
16360479690af6d559d4202bed139db90323386bd2bMartyn Welch
16429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic irqreturn_t ca91cx42_irqhandler(int irq, void *ptr)
16560479690af6d559d4202bed139db90323386bd2bMartyn Welch{
1663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 stat, enable, serviced = 0;
16729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct vme_bridge *ca91cx42_bridge;
16829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
16960479690af6d559d4202bed139db90323386bd2bMartyn Welch
17029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_bridge = ptr;
17160479690af6d559d4202bed139db90323386bd2bMartyn Welch
17229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
17329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
17429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	enable = ioread32(bridge->base + LINT_EN);
17529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	stat = ioread32(bridge->base + LINT_STAT);
17660479690af6d559d4202bed139db90323386bd2bMartyn Welch
1773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Only look at unmasked interrupts */
1783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	stat &= enable;
1793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
1803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (unlikely(!stat))
1813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return IRQ_NONE;
1823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
1833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & CA91CX42_LINT_DMA)
18429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_DMA_irqhandler(bridge);
1853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
1863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			CA91CX42_LINT_LM3))
18729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_LM_irqhandler(bridge, stat);
1883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & CA91CX42_LINT_MBOX)
18929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_MB_irqhandler(bridge, stat);
1903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & CA91CX42_LINT_SW_IACK)
19129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_IACK_irqhandler(bridge);
1923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & CA91CX42_LINT_VERR)
19329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_VERR_irqhandler(bridge);
1943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & CA91CX42_LINT_LERR)
19529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_LERR_irqhandler(bridge);
1963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 |
1973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 |
1983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 |
1993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			CA91CX42_LINT_VIRQ7))
20029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat);
2013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
2023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Clear serviced interrupts */
20329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(stat, bridge->base + LINT_STAT);
20460479690af6d559d4202bed139db90323386bd2bMartyn Welch
20560479690af6d559d4202bed139db90323386bd2bMartyn Welch	return IRQ_HANDLED;
20660479690af6d559d4202bed139db90323386bd2bMartyn Welch}
20760479690af6d559d4202bed139db90323386bd2bMartyn Welch
20829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge)
20960479690af6d559d4202bed139db90323386bd2bMartyn Welch{
2103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int result, tmp;
2113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct pci_dev *pdev;
21229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
21329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
21429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
21560479690af6d559d4202bed139db90323386bd2bMartyn Welch
2163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Need pdev */
21729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev);
21860479690af6d559d4202bed139db90323386bd2bMartyn Welch
2193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Initialise list for VME bus errors */
22029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	INIT_LIST_HEAD(&(ca91cx42_bridge->vme_errors));
22160479690af6d559d4202bed139db90323386bd2bMartyn Welch
22229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	mutex_init(&(ca91cx42_bridge->irq_mtx));
223c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch
2243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Disable interrupts from PCI to VME */
2253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(0, bridge->base + VINT_EN);
22660479690af6d559d4202bed139db90323386bd2bMartyn Welch
2273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Disable PCI interrupts */
2283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(0, bridge->base + LINT_EN);
2293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Clear Any Pending PCI Interrupts */
2303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
23160479690af6d559d4202bed139db90323386bd2bMartyn Welch
2323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED,
23329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch			driver_name, ca91cx42_bridge);
2343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (result) {
2353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n",
2363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		       pdev->irq);
2373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return result;
23860479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
23960479690af6d559d4202bed139db90323386bd2bMartyn Welch
2403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Ensure all interrupts are mapped to PCI Interrupt 0 */
2413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(0, bridge->base + LINT_MAP0);
2423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(0, bridge->base + LINT_MAP1);
2433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(0, bridge->base + LINT_MAP2);
2443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
2453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Enable DMA, mailbox & LM Interrupts */
2463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 |
2473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK |
2483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA;
2493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
2503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iowrite32(tmp, bridge->base + LINT_EN);
25160479690af6d559d4202bed139db90323386bd2bMartyn Welch
2523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
25360479690af6d559d4202bed139db90323386bd2bMartyn Welch}
25460479690af6d559d4202bed139db90323386bd2bMartyn Welch
25529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
25629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct pci_dev *pdev)
25760479690af6d559d4202bed139db90323386bd2bMartyn Welch{
2583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Disable interrupts from PCI to VME */
25929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0, bridge->base + VINT_EN);
26060479690af6d559d4202bed139db90323386bd2bMartyn Welch
2613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Disable PCI interrupts */
26229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0, bridge->base + LINT_EN);
2633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Clear Any Pending PCI Interrupts */
26429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
26560479690af6d559d4202bed139db90323386bd2bMartyn Welch
2663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	free_irq(pdev->irq, pdev);
2673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
26860479690af6d559d4202bed139db90323386bd2bMartyn Welch
2693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/*
2703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Set up an VME interrupt
2713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */
27229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchvoid ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, int state,
27329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	int sync)
274c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch
2753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
276c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch	struct pci_dev *pdev;
2773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 tmp;
27829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
27929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
28029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
28160479690af6d559d4202bed139db90323386bd2bMartyn Welch
2823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Enable IRQ level */
28329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	tmp = ioread32(bridge->base + LINT_EN);
2843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
285c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch	if (state == 0)
2863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		tmp &= ~CA91CX42_LINT_VIRQ[level];
287c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch	else
288c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch		tmp |= CA91CX42_LINT_VIRQ[level];
28960479690af6d559d4202bed139db90323386bd2bMartyn Welch
29029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(tmp, bridge->base + LINT_EN);
291c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch
292c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch	if ((state == 0) && (sync != 0)) {
2933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		pdev = container_of(ca91cx42_bridge->parent, struct pci_dev,
2943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			dev);
2953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
2963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		synchronize_irq(pdev->irq);
29760479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
29860479690af6d559d4202bed139db90323386bd2bMartyn Welch}
29960479690af6d559d4202bed139db90323386bd2bMartyn Welch
30029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchint ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level,
30129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	int statid)
30260479690af6d559d4202bed139db90323386bd2bMartyn Welch{
3033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 tmp;
30429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
30529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
30629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
30760479690af6d559d4202bed139db90323386bd2bMartyn Welch
3083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Universe can only generate even vectors */
3093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (statid & 1)
3103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
31160479690af6d559d4202bed139db90323386bd2bMartyn Welch
31229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	mutex_lock(&(bridge->vme_int));
31360479690af6d559d4202bed139db90323386bd2bMartyn Welch
31429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	tmp = ioread32(bridge->base + VINT_EN);
31560479690af6d559d4202bed139db90323386bd2bMartyn Welch
3163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Set Status/ID */
31729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(statid << 24, bridge->base + STATID);
3183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
3193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Assert VMEbus IRQ */
3203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	tmp = tmp | (1 << (level + 24));
32129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(tmp, bridge->base + VINT_EN);
32260479690af6d559d4202bed139db90323386bd2bMartyn Welch
3233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Wait for IACK */
32429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	wait_event_interruptible(bridge->iack_queue, 0);
3253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
3263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Return interrupt to low state */
32729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	tmp = ioread32(bridge->base + VINT_EN);
3283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	tmp = tmp & ~(1 << (level + 24));
32929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(tmp, bridge->base + VINT_EN);
3303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
33129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	mutex_unlock(&(bridge->vme_int));
3323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
3333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
33460479690af6d559d4202bed139db90323386bd2bMartyn Welch}
33560479690af6d559d4202bed139db90323386bd2bMartyn Welch
3363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
3373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long vme_base, unsigned long long size,
3383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle)
33960479690af6d559d4202bed139db90323386bd2bMartyn Welch{
34021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	unsigned int i, addr = 0, granularity;
3413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned int temp_ctl = 0;
3423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned int vme_bound, pci_offset;
34329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
34429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
34529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = image->parent->driver_priv;
34660479690af6d559d4202bed139db90323386bd2bMartyn Welch
3473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	i = image->number;
34860479690af6d559d4202bed139db90323386bd2bMartyn Welch
3493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	switch (aspace) {
3503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_A16:
3513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		addr |= CA91CX42_VSI_CTL_VAS_A16;
3523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
3533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_A24:
3543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		addr |= CA91CX42_VSI_CTL_VAS_A24;
3553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
3563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_A32:
3573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		addr |= CA91CX42_VSI_CTL_VAS_A32;
3583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
3593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_USER1:
3603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		addr |= CA91CX42_VSI_CTL_VAS_USER1;
3613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
3623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_USER2:
3633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		addr |= CA91CX42_VSI_CTL_VAS_USER2;
3643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
3653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_A64:
3663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_CRCSR:
3673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_USER3:
3683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_USER4:
3693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	default:
3703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid address space\n");
3713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
3723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
37360479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
37460479690af6d559d4202bed139db90323386bd2bMartyn Welch
3753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/*
3763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * Bound address is a valid address for the window, adjust
3773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * accordingly
3783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
37921e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	vme_bound = vme_base + size;
3803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pci_offset = pci_base - vme_base;
3813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
3823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* XXX Need to check that vme_base, vme_bound and pci_offset aren't
3833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * too big for registers
3843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
3853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
3863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((i == 0) || (i == 4))
3873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		granularity = 0x1000;
3883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	else
3893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		granularity = 0x10000;
3903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
3913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vme_base & (granularity - 1)) {
3923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid VME base alignment\n");
3933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
3943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
3953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vme_bound & (granularity - 1)) {
3963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid VME bound alignment\n");
3973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
3983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
3993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (pci_offset & (granularity - 1)) {
4003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid PCI Offset alignment\n");
4013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
40260479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
40360479690af6d559d4202bed139db90323386bd2bMartyn Welch
4043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Disable while we are mucking around */
40529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]);
4063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~CA91CX42_VSI_CTL_EN;
40729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
40860479690af6d559d4202bed139db90323386bd2bMartyn Welch
4093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup mapping */
41029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]);
41129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]);
41229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]);
4133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX Prefetch stuff currently unsupported */
4153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
4163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeIn->wrPostEnable)
4173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_PWEN;
4183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeIn->prefetchEnable)
4193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_PREN;
4203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeIn->rmwLock)
4213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_LLRMW;
4223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeIn->data64BitCapable)
4233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_LD64EN;
4243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
4253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup address space */
4273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M;
4283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl |= addr;
4293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup cycle types */
4313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M);
4323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_SUPER)
4333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR;
4343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_USER)
4353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV;
4363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_PROG)
4373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM;
4383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_DATA)
4393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA;
4403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Write ctl reg without enable */
44229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
4433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (enabled)
4453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_VSI_CTL_EN;
4463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
44729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
4483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
45060479690af6d559d4202bed139db90323386bd2bMartyn Welch}
45160479690af6d559d4202bed139db90323386bd2bMartyn Welch
4523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled,
4533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long *vme_base, unsigned long long *size,
4543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle)
45560479690af6d559d4202bed139db90323386bd2bMartyn Welch{
4563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned int i, granularity = 0, ctl = 0;
4573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long vme_bound, pci_offset;
45829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
45929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
46029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = image->parent->driver_priv;
4613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	i = image->number;
46360479690af6d559d4202bed139db90323386bd2bMartyn Welch
4643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((i == 0) || (i == 4))
4653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		granularity = 0x1000;
4663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	else
4673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		granularity = 0x10000;
4683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Read Registers */
47029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]);
4713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
47229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	*vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]);
47329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
47429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
4753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*pci_base = (dma_addr_t)vme_base + pci_offset;
4773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*size = (unsigned long long)((vme_bound - *vme_base) + granularity);
4783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*enabled = 0;
4803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*aspace = 0;
4813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*cycle = 0;
4823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_VSI_CTL_EN)
4843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*enabled = 1;
4853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16)
4873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_A16;
4883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24)
4893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_A24;
4903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32)
4913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_A32;
4923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1)
4933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_USER1;
4943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2)
4953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_USER2;
4963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
4973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR)
4983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_SUPER;
4993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV)
5003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_USER;
5013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_VSI_CTL_PGM_PGM)
5023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_PROG;
5033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_VSI_CTL_PGM_DATA)
5043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_DATA;
5053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
5073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
5083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/*
5103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Allocate and map PCI Resource
5113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */
5123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_alloc_resource(struct vme_master_resource *image,
5133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long size)
5143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
5153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long existing_size;
5163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int retval = 0;
5173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct pci_dev *pdev;
51829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct vme_bridge *ca91cx42_bridge;
51929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
52029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_bridge = image->parent;
5213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Find pci_dev container of dev */
5233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ca91cx42_bridge->parent == NULL) {
5243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Dev entry NULL\n");
5253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
5263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
5273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev);
5283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5298fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	existing_size = (unsigned long long)(image->bus_resource.end -
5308fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		image->bus_resource.start);
5313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* If the existing size is OK, return */
5333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (existing_size == (size - 1))
5343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return 0;
5353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (existing_size != 0) {
5373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		iounmap(image->kern_base);
5383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		image->kern_base = NULL;
5398fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		if (image->bus_resource.name != NULL)
5408fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch			kfree(image->bus_resource.name);
5418fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		release_resource(&(image->bus_resource));
5428fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		memset(&(image->bus_resource), 0, sizeof(struct resource));
5433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
5443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5458fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	if (image->bus_resource.name == NULL) {
5468fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
5478fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		if (image->bus_resource.name == NULL) {
5483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			printk(KERN_ERR "Unable to allocate memory for resource"
5493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch				" name\n");
5503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			retval = -ENOMEM;
5513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			goto err_name;
5523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		}
55360479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
5543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5558fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	sprintf((char *)image->bus_resource.name, "%s.%d",
5563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		ca91cx42_bridge->name, image->number);
5573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5588fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	image->bus_resource.start = 0;
5598fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	image->bus_resource.end = (unsigned long)size;
5608fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	image->bus_resource.flags = IORESOURCE_MEM;
5613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = pci_bus_alloc_resource(pdev->bus,
5638fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		&(image->bus_resource), size, size, PCIBIOS_MIN_MEM,
5643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		0, NULL, NULL);
5653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (retval) {
5663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Failed to allocate mem resource for "
5673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"window %d size 0x%lx start 0x%lx\n",
5683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			image->number, (unsigned long)size,
5698fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch			(unsigned long)image->bus_resource.start);
5703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_resource;
57160479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
5723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	image->kern_base = ioremap_nocache(
5748fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		image->bus_resource.start, size);
5753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (image->kern_base == NULL) {
5763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Failed to remap resource\n");
5773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -ENOMEM;
5783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_remap;
57960479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
58060479690af6d559d4202bed139db90323386bd2bMartyn Welch
5813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
5823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iounmap(image->kern_base);
5843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	image->kern_base = NULL;
5853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap:
5868fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	release_resource(&(image->bus_resource));
5873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource:
5888fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	kfree(image->bus_resource.name);
5898fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	memset(&(image->bus_resource), 0, sizeof(struct resource));
5903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_name:
5913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return retval;
5923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
5933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
5943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/*
5954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch * Free and unmap PCI Resource
5964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch */
5973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void ca91cx42_free_resource(struct vme_master_resource *image)
5983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
5993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	iounmap(image->kern_base);
6003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	image->kern_base = NULL;
6018fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	release_resource(&(image->bus_resource));
6028fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	kfree(image->bus_resource.name);
6038fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	memset(&(image->bus_resource), 0, sizeof(struct resource));
6043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
6053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_master_set(struct vme_master_resource *image, int enabled,
6083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long vme_base, unsigned long long size,
6093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
6103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
6113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int retval = 0;
61221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	unsigned int i, granularity = 0;
6133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned int temp_ctl = 0;
6143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long pci_bound, vme_offset, pci_base;
61529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
61629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
61729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = image->parent->driver_priv;
6183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
61921e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	i = image->number;
62021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch
62121e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	if ((i == 0) || (i == 4))
62221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch		granularity = 0x1000;
62321e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	else
62421e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch		granularity = 0x10000;
62521e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch
6263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Verify input data */
62721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	if (vme_base & (granularity - 1)) {
6283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid VME Window alignment\n");
6293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EINVAL;
6303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_window;
6313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
63221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	if (size & (granularity - 1)) {
6333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid VME Window alignment\n");
6343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EINVAL;
6353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_window;
6363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
6373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_lock(&(image->lock));
6393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* XXX We should do this much later, so that we can exit without
6413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 *     needing to redo the mapping...
6423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
6433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/*
6443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * Let's allocate the resource here rather than further up the stack as
6453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * it avoids pushing loads of bus dependant stuff up the stack
6463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
6473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = ca91cx42_alloc_resource(image, size);
6483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (retval) {
6493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		spin_unlock(&(image->lock));
6503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Unable to allocate memory for resource "
6513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"name\n");
6523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -ENOMEM;
6533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_res;
6543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
6553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6568fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch	pci_base = (unsigned long long)image->bus_resource.start;
6573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/*
6593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * Bound address is a valid address for the window, adjust
6603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * according to window granularity.
6613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
66221e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	pci_bound = pci_base + size;
6633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vme_offset = vme_base - pci_base;
6643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Disable while we are mucking around */
66629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]);
6673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~CA91CX42_LSI_CTL_EN;
66829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
6693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX Prefetch stuff currently unsupported */
6713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
6723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeOut->wrPostEnable)
6733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= 0x40000000;
6743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
6753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup cycle types */
6773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M;
6783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_BLT)
6793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT;
6803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_MBLT)
6813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT;
6823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
6833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup data width */
6843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M;
6853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	switch (dwidth) {
6863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_D8:
6873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VDW_D8;
6883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
6893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_D16:
6903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VDW_D16;
6913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
6923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_D32:
6933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VDW_D32;
6943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
6953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_D64:
6963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VDW_D64;
6973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
6983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	default:
6993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		spin_unlock(&(image->lock));
7003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid data width\n");
7013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EINVAL;
7023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_dwidth;
7033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
70460479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
7053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup address space */
7073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M;
7083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	switch (aspace) {
70960479690af6d559d4202bed139db90323386bd2bMartyn Welch	case VME_A16:
7103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VAS_A16;
71160479690af6d559d4202bed139db90323386bd2bMartyn Welch		break;
71260479690af6d559d4202bed139db90323386bd2bMartyn Welch	case VME_A24:
7133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VAS_A24;
71460479690af6d559d4202bed139db90323386bd2bMartyn Welch		break;
71560479690af6d559d4202bed139db90323386bd2bMartyn Welch	case VME_A32:
7163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VAS_A32;
7173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
7183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_CRCSR:
7193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR;
72060479690af6d559d4202bed139db90323386bd2bMartyn Welch		break;
72160479690af6d559d4202bed139db90323386bd2bMartyn Welch	case VME_USER1:
7223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1;
72360479690af6d559d4202bed139db90323386bd2bMartyn Welch		break;
72460479690af6d559d4202bed139db90323386bd2bMartyn Welch	case VME_USER2:
7253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2;
7263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
7273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_A64:
7283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_USER3:
7293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case VME_USER4:
7303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	default:
7313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		spin_unlock(&(image->lock));
7323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		printk(KERN_ERR "Invalid address space\n");
7333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EINVAL;
7343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_aspace;
73560479690af6d559d4202bed139db90323386bd2bMartyn Welch		break;
73660479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
73760479690af6d559d4202bed139db90323386bd2bMartyn Welch
7383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M);
7393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_SUPER)
7403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR;
7413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (cycle & VME_PROG)
7423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM;
74360479690af6d559d4202bed139db90323386bd2bMartyn Welch
7443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup mapping */
74529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]);
74629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]);
74729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]);
7483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Write ctl reg without enable */
75029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
7513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (enabled)
7533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= CA91CX42_LSI_CTL_EN;
7543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
75529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
7563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_unlock(&(image->lock));
7583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
7593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_aspace:
7613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dwidth:
7623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_free_resource(image);
7633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_res:
7643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_window:
7653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return retval;
7663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
7673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint __ca91cx42_master_get(struct vme_master_resource *image, int *enabled,
7693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long *vme_base, unsigned long long *size,
7703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
7713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
7723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned int i, ctl;
7733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long pci_base, pci_bound, vme_offset;
77429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
77529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
77629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = image->parent->driver_priv;
7773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	i = image->number;
7793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
78029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]);
7813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
78229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]);
78329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]);
78429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]);
7853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*vme_base = pci_base + vme_offset;
78721e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	*size = (unsigned long long)(pci_bound - pci_base);
7883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*enabled = 0;
7903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*aspace = 0;
7913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*cycle = 0;
7923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	*dwidth = 0;
7933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_LSI_CTL_EN)
7953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*enabled = 1;
7963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
7973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup address space */
7983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	switch (ctl & CA91CX42_LSI_CTL_VAS_M) {
7993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VAS_A16:
8003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_A16;
8013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VAS_A24:
8033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_A24;
8043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VAS_A32:
8063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_A32;
8073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VAS_CRCSR:
8093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_CRCSR;
8103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VAS_USER1:
8123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_USER1;
8133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VAS_USER2:
8153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*aspace = VME_USER2;
8163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
8183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* XXX Not sure howto check for MBLT */
8203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup cycle types */
8213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_LSI_CTL_VCT_BLT)
8223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_BLT;
8233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	else
8243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_SCT;
8253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR)
8273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_SUPER;
8283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	else
8293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle |= VME_USER;
8303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & CA91CX42_LSI_CTL_PGM_PGM)
8323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle = VME_PROG;
8333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	else
8343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*cycle = VME_DATA;
8353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup data width */
8373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	switch (ctl & CA91CX42_LSI_CTL_VDW_M) {
8383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VDW_D8:
8393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*dwidth = VME_D8;
8403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VDW_D16:
8423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*dwidth = VME_D16;
8433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VDW_D32:
8453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*dwidth = VME_D32;
8463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	case CA91CX42_LSI_CTL_VDW_D64:
8483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		*dwidth = VME_D64;
8493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		break;
8503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
8513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX Prefetch stuff currently unsupported */
8533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
8543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ctl & 0x40000000)
8553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeOut->wrPostEnable = 1;
8563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
8573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
8593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
8603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_master_get(struct vme_master_resource *image, int *enabled,
8623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned long long *vme_base, unsigned long long *size,
8633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
8643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
8653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int retval;
8663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_lock(&(image->lock));
8683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace,
8703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		cycle, dwidth);
8713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_unlock(&(image->lock));
8733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return retval;
8753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
8763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf,
8783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	size_t count, loff_t offset)
8793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
88021e0cf6d2e59e19f77096e73d83157734e7f7782Martyn Welch	ssize_t retval;
88160479690af6d559d4202bed139db90323386bd2bMartyn Welch
8823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_lock(&(image->lock));
88360479690af6d559d4202bed139db90323386bd2bMartyn Welch
8843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count);
8853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = count;
88660479690af6d559d4202bed139db90323386bd2bMartyn Welch
8873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_unlock(&(image->lock));
8883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
8893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return retval;
89060479690af6d559d4202bed139db90323386bd2bMartyn Welch}
89160479690af6d559d4202bed139db90323386bd2bMartyn Welch
8923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf,
8933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	size_t count, loff_t offset)
89460479690af6d559d4202bed139db90323386bd2bMartyn Welch{
8953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int retval = 0;
89660479690af6d559d4202bed139db90323386bd2bMartyn Welch
8973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_lock(&(image->lock));
89860479690af6d559d4202bed139db90323386bd2bMartyn Welch
8993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	memcpy_toio(image->kern_base + offset, buf, (unsigned int)count);
9003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = count;
9013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
9023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	spin_unlock(&(image->lock));
9033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
9043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return retval;
90560479690af6d559d4202bed139db90323386bd2bMartyn Welch}
90660479690af6d559d4202bed139db90323386bd2bMartyn Welch
9074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchint ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
9084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct vme_dma_attr *dest, size_t count)
9094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{
9104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct ca91cx42_dma_entry *entry, *prev;
9114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct vme_dma_pci *pci_attr;
9124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct vme_dma_vme *vme_attr;
9134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	dma_addr_t desc_ptr;
9144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	int retval = 0;
9154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* XXX descriptor must be aligned on 64-bit boundaries */
9174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	entry = (struct ca91cx42_dma_entry *)
9184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL);
9194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (entry == NULL) {
9204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "Failed to allocate memory for dma resource "
9214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch			"structure\n");
9224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		retval = -ENOMEM;
9234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		goto err_mem;
9244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Test descriptor alignment */
9274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if ((unsigned long)&(entry->descriptor) & CA91CX42_DCPP_M) {
9284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk("Descriptor not aligned to 16 byte boundary as "
9294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch			"required: %p\n", &(entry->descriptor));
9304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		retval = -EINVAL;
9314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		goto err_align;
9324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	memset(&(entry->descriptor), 0, sizeof(struct ca91cx42_dma_descriptor));
9354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (dest->type == VME_DMA_VME) {
9374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_L2V;
9384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		vme_attr = (struct vme_dma_vme *)dest->private;
9394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		pci_attr = (struct vme_dma_pci *)src->private;
9404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	} else {
9414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		vme_attr = (struct vme_dma_vme *)src->private;
9424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		pci_attr = (struct vme_dma_pci *)dest->private;
9434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Check we can do fullfill required attributes */
9464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 |
9474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		VME_USER2)) != 0) {
9484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "Unsupported cycle type\n");
9504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		retval = -EINVAL;
9514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		goto err_aspace;
9524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER |
9554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		VME_PROG | VME_DATA)) != 0) {
9564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "Unsupported cycle type\n");
9584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		retval = -EINVAL;
9594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		goto err_cycle;
9604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Check to see if we can fullfill source and destination */
9634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) ||
9644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) {
9654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "Cannot perform transfer with this "
9674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch			"source-destination combination\n");
9684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		retval = -EINVAL;
9694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		goto err_direct;
9704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Setup cycle types */
9734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (vme_attr->cycle & VME_BLT)
9744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT;
9754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Setup data width */
9774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	switch (vme_attr->dwidth) {
9784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_D8:
9794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8;
9804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
9814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_D16:
9824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16;
9834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
9844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_D32:
9854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32;
9864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
9874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_D64:
9884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64;
9894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
9904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	default:
9914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "Invalid data width\n");
9924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		return -EINVAL;
9934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
9944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
9954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Setup address space */
9964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	switch (vme_attr->aspace) {
9974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_A16:
9984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16;
9994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
10004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_A24:
10014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24;
10024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
10034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_A32:
10044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32;
10054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
10064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_USER1:
10074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1;
10084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
10094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	case VME_USER2:
10104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2;
10114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
10124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	default:
10134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "Invalid address space\n");
10144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		return -EINVAL;
10154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		break;
10164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
10174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (vme_attr->cycle & VME_SUPER)
10194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR;
10204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (vme_attr->cycle & VME_PROG)
10214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM;
10224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	entry->descriptor.dtbc = count;
10244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	entry->descriptor.dla = pci_attr->address;
10254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	entry->descriptor.dva = vme_attr->address;
10264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	entry->descriptor.dcpp = CA91CX42_DCPP_NULL;
10274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Add to list */
10294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	list_add_tail(&(entry->list), &(list->entries));
10304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Fill out previous descriptors "Next Address" */
10324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (entry->list.prev != &(list->entries)) {
10334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry,
10344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch			list);
10354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		/* We need the bus address for the pointer */
10364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		desc_ptr = virt_to_bus(&(entry->descriptor));
10374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M;
10384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
10394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	return 0;
10414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_cycle:
10434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_aspace:
10444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_direct:
10454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_align:
10464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	kfree(entry);
10474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welcherr_mem:
10484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	return retval;
10494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch}
10504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchstatic int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge)
10524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{
10534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	u32 tmp;
10544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct ca91cx42_driver *bridge;
10554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
10574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	tmp = ioread32(bridge->base + DGCS);
10594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (tmp & CA91CX42_DGCS_ACT)
10614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		return 0;
10624860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	else
10634860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		return 1;
10644860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch}
10654860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10664860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchint ca91cx42_dma_list_exec(struct vme_dma_list *list)
10674860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{
10684860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct vme_dma_resource *ctrlr;
10694860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct ca91cx42_dma_entry *entry;
10704860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	int retval = 0;
10714860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	dma_addr_t bus_addr;
10724860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	u32 val;
10734860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10744860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct ca91cx42_driver *bridge;
10754860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10764860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	ctrlr = list->parent;
10774860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10784860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	bridge = ctrlr->parent->driver_priv;
10794860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10804860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	mutex_lock(&(ctrlr->mtx));
10814860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10824860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (!(list_empty(&(ctrlr->running)))) {
10834860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		/*
10844860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		 * XXX We have an active DMA transfer and currently haven't
10854860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		 *     sorted out the mechanism for "pending" DMA transfers.
10864860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		 *     Return busy.
10874860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		 */
10884860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		/* Need to add to pending here */
10894860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		mutex_unlock(&(ctrlr->mtx));
10904860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		return -EBUSY;
10914860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	} else {
10924860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		list_add(&(list->list), &(ctrlr->running));
10934860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
10944860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10954860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Get first bus address and write into registers */
10964860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	entry = list_first_entry(&(list->entries), struct ca91cx42_dma_entry,
10974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		list);
10984860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
10994860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	bus_addr = virt_to_bus(&(entry->descriptor));
11004860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11014860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	mutex_unlock(&(ctrlr->mtx));
11024860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11034860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	iowrite32(0, bridge->base + DTBC);
11044860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP);
11054860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11064860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Start the operation */
11074860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	val = ioread32(bridge->base + DGCS);
11084860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11094860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* XXX Could set VMEbus On and Off Counters here */
11104860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M);
11114860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11124860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT |
11134860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR |
11144860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		CA91CX42_DGCS_PERR);
11154860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11164860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	iowrite32(val, bridge->base + DGCS);
11174860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11184860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	val |= CA91CX42_DGCS_GO;
11194860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	iowrite32(val, bridge->base + DGCS);
11214860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11224860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	wait_event_interruptible(bridge->dma_queue,
11234860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		ca91cx42_dma_busy(ctrlr->parent));
11244860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11254860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/*
11264860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	 * Read status register, this register is valid until we kick off a
11274860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	 * new transfer.
11284860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	 */
11294860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	val = ioread32(bridge->base + DGCS);
11304860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11314860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR |
11324860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		CA91CX42_DGCS_PERR)) {
11334860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11344860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		printk(KERN_ERR "ca91c042: DMA Error. DGCS=%08X\n", val);
11354860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		val = ioread32(bridge->base + DCTL);
11364860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
11374860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11384860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* Remove list from running list */
11394860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	mutex_lock(&(ctrlr->mtx));
11404860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	list_del(&(list->list));
11414860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	mutex_unlock(&(ctrlr->mtx));
11424860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11434860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	return retval;
11444860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch}
11464860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11474860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welchint ca91cx42_dma_list_empty(struct vme_dma_list *list)
11484860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch{
11494860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct list_head *pos, *temp;
11504860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	struct ca91cx42_dma_entry *entry;
11514860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11524860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	/* detach and free each entry */
11534860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	list_for_each_safe(pos, temp, &(list->entries)) {
11544860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		list_del(pos);
11554860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		entry = list_entry(pos, struct ca91cx42_dma_entry, list);
11564860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch		kfree(entry);
11574860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	}
11584860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11594860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch	return 0;
11604860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch}
11614860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
11622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/*
11632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * All 4 location monitors reside at the same base - this is therefore a
11642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * system wide configuration.
11652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *
11662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * This does not enable the LM monitor - that should be done when the first
11672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * callback is attached and disabled when the last callback is removed.
11682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */
11692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
11702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	vme_address_t aspace, vme_cycle_t cycle)
11712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{
11722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	u32 temp_base, lm_ctl = 0;
11732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	int i;
11742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	struct ca91cx42_driver *bridge;
11752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	struct device *dev;
11762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
11772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	bridge = lm->parent->driver_priv;
11782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	dev = lm->parent->parent;
11792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
11802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Check the alignment of the location monitor */
11812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	temp_base = (u32)lm_base;
11822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (temp_base & 0xffff) {
11832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		dev_err(dev, "Location monitor must be aligned to 64KB "
11842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch			"boundary");
11852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		return -EINVAL;
11862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
11872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
11882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_lock(&(lm->mtx));
11892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
11902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* If we already have a callback attached, we can't move it! */
11912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	for (i = 0; i < lm->monitors; i++) {
11922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		if (bridge->lm_callback[i] != NULL) {
11932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch			mutex_unlock(&(lm->mtx));
11942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch			dev_err(dev, "Location monitor callback attached, "
11952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch				"can't reset\n");
11962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch			return -EBUSY;
11972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		}
11982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
11992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	switch (aspace) {
12012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	case VME_A16:
12022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_AS_A16;
12032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		break;
12042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	case VME_A24:
12052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_AS_A24;
12062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		break;
12072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	case VME_A32:
12082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_AS_A32;
12092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		break;
12102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	default:
12112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		mutex_unlock(&(lm->mtx));
12122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		dev_err(dev, "Invalid address space\n");
12132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		return -EINVAL;
12142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		break;
12152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
12162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (cycle & VME_SUPER)
12182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_SUPR;
12192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (cycle & VME_USER)
12202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_NPRIV;
12212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (cycle & VME_PROG)
12222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_PGM;
12232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (cycle & VME_DATA)
12242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_DATA;
12252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	iowrite32(lm_base, bridge->base + LM_BS);
12272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	iowrite32(lm_ctl, bridge->base + LM_CTL);
12282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_unlock(&(lm->mtx));
12302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	return 0;
12322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch}
12332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/* Get configuration of the callback monitor and return whether it is enabled
12352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * or disabled.
12362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */
12372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base,
12382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	vme_address_t *aspace, vme_cycle_t *cycle)
12392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{
12402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	u32 lm_ctl, enabled = 0;
12412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	struct ca91cx42_driver *bridge;
12422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	bridge = lm->parent->driver_priv;
12442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_lock(&(lm->mtx));
12462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	*lm_base = (unsigned long long)ioread32(bridge->base + LM_BS);
12482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	lm_ctl = ioread32(bridge->base + LM_CTL);
12492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (lm_ctl & CA91CX42_LM_CTL_EN)
12512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		enabled = 1;
12522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16)
12542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*aspace = VME_A16;
12552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24)
12562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*aspace = VME_A24;
12572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32)
12582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*aspace = VME_A32;
12592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	*cycle = 0;
12612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (lm_ctl & CA91CX42_LM_CTL_SUPR)
12622b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*cycle |= VME_SUPER;
12632b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (lm_ctl & CA91CX42_LM_CTL_NPRIV)
12642b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*cycle |= VME_USER;
12652b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (lm_ctl & CA91CX42_LM_CTL_PGM)
12662b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*cycle |= VME_PROG;
12672b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (lm_ctl & CA91CX42_LM_CTL_DATA)
12682b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		*cycle |= VME_DATA;
12692b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12702b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_unlock(&(lm->mtx));
12712b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12722b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	return enabled;
12732b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch}
12742b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12752b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/*
12762b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Attach a callback to a specific location monitor.
12772b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch *
12782b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Callback will be passed the monitor triggered.
12792b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */
12802b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor,
12812b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	void (*callback)(int))
12822b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{
12832b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	u32 lm_ctl, tmp;
12842b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	struct ca91cx42_driver *bridge;
12852b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	struct device *dev;
12862b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12872b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	bridge = lm->parent->driver_priv;
12882b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	dev = lm->parent->parent;
12892b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12902b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_lock(&(lm->mtx));
12912b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
12922b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Ensure that the location monitor is configured - need PGM or DATA */
12932b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	lm_ctl = ioread32(bridge->base + LM_CTL);
12942b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) {
12952b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		mutex_unlock(&(lm->mtx));
12962b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		dev_err(dev, "Location monitor not properly configured\n");
12972b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		return -EINVAL;
12982b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
12992b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13002b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Check that a callback isn't already attached */
13012b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if (bridge->lm_callback[monitor] != NULL) {
13022b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		mutex_unlock(&(lm->mtx));
13032b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		dev_err(dev, "Existing callback attached\n");
13042b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		return -EBUSY;
13052b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
13062b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13072b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Attach callback */
13082b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	bridge->lm_callback[monitor] = callback;
13092b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13102b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Enable Location Monitor interrupt */
13112b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	tmp = ioread32(bridge->base + LINT_EN);
13122b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	tmp |= CA91CX42_LINT_LM[monitor];
13132b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	iowrite32(tmp, bridge->base + LINT_EN);
13142b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13152b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Ensure that global Location Monitor Enable set */
13162b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) {
13172b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		lm_ctl |= CA91CX42_LM_CTL_EN;
13182b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		iowrite32(lm_ctl, bridge->base + LM_CTL);
13192b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
13202b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13212b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_unlock(&(lm->mtx));
13222b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13232b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	return 0;
13242b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch}
13252b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13262b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch/*
13272b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch * Detach a callback function forn a specific location monitor.
13282b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch */
13292b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welchint ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor)
13302b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch{
13312b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	u32 tmp;
13322b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	struct ca91cx42_driver *bridge;
13332b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13342b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	bridge = lm->parent->driver_priv;
13352b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13362b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_lock(&(lm->mtx));
13372b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13382b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Disable Location Monitor and ensure previous interrupts are clear */
13392b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	tmp = ioread32(bridge->base + LINT_EN);
13402b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	tmp &= ~CA91CX42_LINT_LM[monitor];
13412b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	iowrite32(tmp, bridge->base + LINT_EN);
13422b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13432b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	iowrite32(CA91CX42_LINT_LM[monitor],
13442b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		 bridge->base + LINT_STAT);
13452b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13462b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* Detach callback */
13472b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	bridge->lm_callback[monitor] = NULL;
13482b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13492b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	/* If all location monitors disabled, disable global Location Monitor */
13502b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
13512b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch			CA91CX42_LINT_LM3)) == 0) {
13522b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		tmp = ioread32(bridge->base + LM_CTL);
13532b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		tmp &= ~CA91CX42_LM_CTL_EN;
13542b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch		iowrite32(tmp, bridge->base + LM_CTL);
13552b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	}
13562b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13572b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	mutex_unlock(&(lm->mtx));
13582b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
13592b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch	return 0;
13602b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch}
13612b82beb8c1bc81b3dde69d16cacbc22546681acfMartyn Welch
136229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchint ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge)
136360479690af6d559d4202bed139db90323386bd2bMartyn Welch{
13643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 slot = 0;
136529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
136629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
136729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
136860479690af6d559d4202bed139db90323386bd2bMartyn Welch
136912b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch	if (!geoid) {
137029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		slot = ioread32(bridge->base + VCSR_BS);
137112b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch		slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27);
137212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch	} else
137312b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch		slot = geoid;
137412b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch
13753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return (int)slot;
13763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
13773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
13783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
13793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int __init ca91cx42_init(void)
13803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
13813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return pci_register_driver(&ca91cx42_driver);
13823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
13833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
13843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/*
13853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Configure CR/CSR space
13863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *
13873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Access to the CR/CSR can be configured at power-up. The location of the
13883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * CR/CSR registers in the CR/CSR address space is determined by the boards
13893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * Auto-ID or Geographic address. This function ensures that the window is
13903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * enabled at an offset consistent with the boards geopgraphic address.
13913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */
139229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge,
139329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct pci_dev *pdev)
13943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
13953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	unsigned int crcsr_addr;
13963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int tmp, slot;
139729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
139829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
139929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
14003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
14013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/* XXX We may need to set this somehow as the Universe II does not support
14023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *     geographical addressing.
14033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch */
14043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
14053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vme_slotnum != -1)
140629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		iowrite32(vme_slotnum << 27, bridge->base + VCSR_BS);
14073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
140829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	slot = ca91cx42_slot_get(ca91cx42_bridge);
14093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot);
14103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (slot == 0) {
14113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Slot number is unset, not configuring "
14123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"CR/CSR space\n");
14133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
141460479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
14153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
14163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Allocate mem for CR/CSR image */
141729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
141829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		&(bridge->crcsr_bus));
141929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	if (bridge->crcsr_kernel == NULL) {
14203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR "
14213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"image\n");
14223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -ENOMEM;
142360479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
142460479690af6d559d4202bed139db90323386bd2bMartyn Welch
142529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
142660479690af6d559d4202bed139db90323386bd2bMartyn Welch
14273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	crcsr_addr = slot * (512 * 1024);
142829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO);
142960479690af6d559d4202bed139db90323386bd2bMartyn Welch
143029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	tmp = ioread32(bridge->base + VCSR_CTL);
14313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	tmp |= CA91CX42_VCSR_CTL_EN;
143229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(tmp, bridge->base + VCSR_CTL);
143360479690af6d559d4202bed139db90323386bd2bMartyn Welch
14343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
143560479690af6d559d4202bed139db90323386bd2bMartyn Welch}
143660479690af6d559d4202bed139db90323386bd2bMartyn Welch
143729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welchstatic void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge,
143829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct pci_dev *pdev)
143960479690af6d559d4202bed139db90323386bd2bMartyn Welch{
14403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 tmp;
144129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
144229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
144329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
144460479690af6d559d4202bed139db90323386bd2bMartyn Welch
14453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Turn off CR/CSR space */
144629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	tmp = ioread32(bridge->base + VCSR_CTL);
14473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	tmp &= ~CA91CX42_VCSR_CTL_EN;
144829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(tmp, bridge->base + VCSR_CTL);
144960479690af6d559d4202bed139db90323386bd2bMartyn Welch
14503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Free image */
145129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0, bridge->base + VCSR_TO);
145260479690af6d559d4202bed139db90323386bd2bMartyn Welch
145329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel,
145429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		bridge->crcsr_bus);
14553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
145660479690af6d559d4202bed139db90323386bd2bMartyn Welch
14573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
14583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
14593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int retval, i;
14603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	u32 data;
14613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct list_head *pos = NULL;
146229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct vme_bridge *ca91cx42_bridge;
146329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *ca91cx42_device;
14643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_master_resource *master_image;
14653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_slave_resource *slave_image;
14663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_dma_resource *dma_ctrlr;
14673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_lm_resource *lm;
14683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
14693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* We want to support more than one of each bridge so we need to
14703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * dynamically allocate the bridge structure
14713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
14723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge = kmalloc(sizeof(struct vme_bridge), GFP_KERNEL);
14733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
14743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (ca91cx42_bridge == NULL) {
14753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Failed to allocate memory for device "
14763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"structure\n");
14773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -ENOMEM;
14783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_struct;
14793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
14803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
14813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	memset(ca91cx42_bridge, 0, sizeof(struct vme_bridge));
14823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
148329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_device = kmalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL);
148429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
148529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	if (ca91cx42_device == NULL) {
148629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		dev_err(&pdev->dev, "Failed to allocate memory for device "
148729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch			"structure\n");
148829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		retval = -ENOMEM;
148929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		goto err_driver;
149029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	}
149129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
149229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	memset(ca91cx42_device, 0, sizeof(struct ca91cx42_driver));
149329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
149429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_bridge->driver_priv = ca91cx42_device;
149529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
14963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Enable the device */
14973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = pci_enable_device(pdev);
14983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (retval) {
14993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Unable to enable device\n");
15003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_enable;
15013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Map Registers */
15043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = pci_request_regions(pdev, driver_name);
15053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (retval) {
15063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Unable to reserve resources\n");
15073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_resource;
15083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* map registers in BAR 0 */
151129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0),
15123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		4096);
151329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	if (!ca91cx42_device->base) {
15143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Unable to remap CRG region\n");
15153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EIO;
15163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_remap;
15173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Check to see if the mapping worked out */
152029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF;
15213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (data != PCI_VENDOR_ID_TUNDRA) {
15223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "PCI_ID check failed\n");
15233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EIO;
15243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_test;
15253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Initialize wait queues & mutual exclusion flags */
152829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	init_waitqueue_head(&(ca91cx42_device->dma_queue));
152929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	init_waitqueue_head(&(ca91cx42_device->iack_queue));
153029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	mutex_init(&(ca91cx42_device->vme_int));
153129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	mutex_init(&(ca91cx42_device->vme_rmw));
15323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->parent = &(pdev->dev);
15343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	strcpy(ca91cx42_bridge->name, driver_name);
15353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup IRQ */
15373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = ca91cx42_irq_init(ca91cx42_bridge);
15383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (retval != 0) {
15393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Chip Initialization failed.\n");
15403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_irq;
15413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Add master windows to list */
15443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	INIT_LIST_HEAD(&(ca91cx42_bridge->master_resources));
15453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	for (i = 0; i < CA91C142_MAX_MASTER; i++) {
15463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image = kmalloc(sizeof(struct vme_master_resource),
15473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			GFP_KERNEL);
15483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if (master_image == NULL) {
15493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			dev_err(&pdev->dev, "Failed to allocate memory for "
15503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"master resource structure\n");
15513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			retval = -ENOMEM;
15523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			goto err_master;
15533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		}
15543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->parent = ca91cx42_bridge;
15553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		spin_lock_init(&(master_image->lock));
15563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->locked = 0;
15573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->number = i;
15583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
15593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			VME_CRCSR | VME_USER1 | VME_USER2;
15603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
15613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			VME_SUPER | VME_USER | VME_PROG | VME_DATA;
15623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64;
15638fafb47638012d93134d0ff38adcc5fc661beeb1Martyn Welch		memset(&(master_image->bus_resource), 0,
15643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			sizeof(struct resource));
15653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image->kern_base  = NULL;
15663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_add_tail(&(master_image->list),
15673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			&(ca91cx42_bridge->master_resources));
15683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Add slave windows to list */
15713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	INIT_LIST_HEAD(&(ca91cx42_bridge->slave_resources));
15723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	for (i = 0; i < CA91C142_MAX_SLAVE; i++) {
15733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image = kmalloc(sizeof(struct vme_slave_resource),
15743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			GFP_KERNEL);
15753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if (slave_image == NULL) {
15763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			dev_err(&pdev->dev, "Failed to allocate memory for "
15773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"slave resource structure\n");
15783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			retval = -ENOMEM;
15793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			goto err_slave;
15803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		}
15813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image->parent = ca91cx42_bridge;
15823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		mutex_init(&(slave_image->mtx));
15833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image->locked = 0;
15843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image->number = i;
15853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 |
15863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			VME_USER2;
15873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		/* Only windows 0 and 4 support A16 */
15893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if (i == 0 || i == 4)
15903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			slave_image->address_attr |= VME_A16;
15913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
15923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
15933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			VME_SUPER | VME_USER | VME_PROG | VME_DATA;
15943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_add_tail(&(slave_image->list),
15953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			&(ca91cx42_bridge->slave_resources));
15963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
15974860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
15983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Add dma engines to list */
15993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources));
16003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	for (i = 0; i < CA91C142_MAX_DMA; i++) {
16013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource),
16023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			GFP_KERNEL);
16033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if (dma_ctrlr == NULL) {
16043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			dev_err(&pdev->dev, "Failed to allocate memory for "
16053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			"dma resource structure\n");
16063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			retval = -ENOMEM;
16073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			goto err_dma;
16083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		}
16093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dma_ctrlr->parent = ca91cx42_bridge;
16103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		mutex_init(&(dma_ctrlr->mtx));
16113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dma_ctrlr->locked = 0;
16123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dma_ctrlr->number = i;
16134f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch		dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM |
16144f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch			VME_DMA_MEM_TO_VME;
16153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		INIT_LIST_HEAD(&(dma_ctrlr->pending));
16163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		INIT_LIST_HEAD(&(dma_ctrlr->running));
16173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_add_tail(&(dma_ctrlr->list),
16183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			&(ca91cx42_bridge->dma_resources));
16193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
16204860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch
16213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Add location monitor to list */
16223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources));
16233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL);
16243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (lm == NULL) {
16253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Failed to allocate memory for "
16263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		"location monitor resource structure\n");
16273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -ENOMEM;
16283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_lm;
16293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
16303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	lm->parent = ca91cx42_bridge;
16313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	mutex_init(&(lm->mtx));
16323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	lm->locked = 0;
16333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	lm->number = 1;
16343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	lm->monitors = 4;
16353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_add_tail(&(lm->list), &(ca91cx42_bridge->lm_resources));
16363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
16373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->slave_get = ca91cx42_slave_get;
16383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->slave_set = ca91cx42_slave_set;
16393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->master_get = ca91cx42_master_get;
16403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->master_set = ca91cx42_master_set;
16413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->master_read = ca91cx42_master_read;
16423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->master_write = ca91cx42_master_write;
16433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
16443d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->master_rmw = ca91cx42_master_rmw;
16454860ab74d4d577d21fbfe0da3bd0925f3efc8907Martyn Welch#endif
16463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add;
16473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec;
16483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty;
1649c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch	ca91cx42_bridge->irq_set = ca91cx42_irq_set;
1650c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch	ca91cx42_bridge->irq_generate = ca91cx42_irq_generate;
16513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->lm_set = ca91cx42_lm_set;
16523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->lm_get = ca91cx42_lm_get;
16533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->lm_attach = ca91cx42_lm_attach;
16543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->lm_detach = ca91cx42_lm_detach;
16553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_bridge->slot_get = ca91cx42_slot_get;
16563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
165729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	data = ioread32(ca91cx42_device->base + MISC_CTL);
16583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	dev_info(&pdev->dev, "Board is%s the VME system controller\n",
16593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		(data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not");
166029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	dev_info(&pdev->dev, "Slot ID is %d\n",
166129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		ca91cx42_slot_get(ca91cx42_bridge));
16623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
166329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) {
16643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
16653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		retval = -EINVAL;
16663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
16673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_crcsr;
16683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
166960479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
167060479690af6d559d4202bed139db90323386bd2bMartyn Welch
16713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Need to save ca91cx42_bridge pointer locally in link list for use in
16723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 * ca91cx42_remove()
16733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	 */
16743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	retval = vme_register_bridge(ca91cx42_bridge);
16753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (retval != 0) {
16763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dev_err(&pdev->dev, "Chip Registration failed.\n");
16773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		goto err_reg;
16783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
16793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
168029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	pci_set_drvdata(pdev, ca91cx42_bridge);
168129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
16823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
16833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
16843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vme_unregister_bridge(ca91cx42_bridge);
16853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_reg:
168629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_crcsr_exit(ca91cx42_bridge, pdev);
168770d7aa889f7c107a768d07389998e4fd89a7103dGreg Kroah-Hartman#if 0
16883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_crcsr:
168970d7aa889f7c107a768d07389998e4fd89a7103dGreg Kroah-Hartman#endif
16903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_lm:
16913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
16923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->lm_resources)) {
16933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		lm = list_entry(pos, struct vme_lm_resource, list);
16943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
16953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(lm);
16963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
16973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_dma:
16983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
16993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->dma_resources)) {
17003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
17013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
17023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(dma_ctrlr);
170360479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
17043d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_slave:
17053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
17063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->slave_resources)) {
17073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image = list_entry(pos, struct vme_slave_resource, list);
17083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
17093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(slave_image);
17103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
17113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_master:
17123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
17133d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->master_resources)) {
17143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image = list_entry(pos, struct vme_master_resource,
17153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			list);
17163d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
17173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(master_image);
17183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
17193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
172029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_irq_exit(ca91cx42_device, pdev);
17213d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_irq:
17223d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_test:
172329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iounmap(ca91cx42_device->base);
17243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_remap:
17253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pci_release_regions(pdev);
17263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_resource:
17273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pci_disable_device(pdev);
17283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_enable:
172929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	kfree(ca91cx42_device);
173029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welcherr_driver:
17313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	kfree(ca91cx42_bridge);
17323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welcherr_struct:
17333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return retval;
173460479690af6d559d4202bed139db90323386bd2bMartyn Welch
173560479690af6d559d4202bed139db90323386bd2bMartyn Welch}
173660479690af6d559d4202bed139db90323386bd2bMartyn Welch
17373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchvoid ca91cx42_remove(struct pci_dev *pdev)
173860479690af6d559d4202bed139db90323386bd2bMartyn Welch{
17393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct list_head *pos = NULL;
17403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_master_resource *master_image;
17413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_slave_resource *slave_image;
17423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_dma_resource *dma_ctrlr;
17433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	struct vme_lm_resource *lm;
174429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct ca91cx42_driver *bridge;
174529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev);
174629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
174729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	bridge = ca91cx42_bridge->driver_priv;
174829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch
174960479690af6d559d4202bed139db90323386bd2bMartyn Welch
17503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Turn off Ints */
175129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0, bridge->base + LINT_EN);
17523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
17533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Turn off the windows */
175429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI0_CTL);
175529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI1_CTL);
175629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI2_CTL);
175729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI3_CTL);
175829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI4_CTL);
175929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI5_CTL);
176029848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI6_CTL);
176129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00800000, bridge->base + LSI7_CTL);
176229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI0_CTL);
176329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI1_CTL);
176429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI2_CTL);
176529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI3_CTL);
176629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI4_CTL);
176729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI5_CTL);
176829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI6_CTL);
176929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0x00F00000, bridge->base + VSI7_CTL);
17703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
17713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vme_unregister_bridge(ca91cx42_bridge);
17723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
17733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	ca91cx42_crcsr_exit(pdev);
17743d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
17753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
17763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->lm_resources)) {
17773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		lm = list_entry(pos, struct vme_lm_resource, list);
17783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
17793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(lm);
178060479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
17813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
17823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
17833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->dma_resources)) {
17843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
17853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
17863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(dma_ctrlr);
178760479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
178860479690af6d559d4202bed139db90323386bd2bMartyn Welch
17893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
17903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->slave_resources)) {
17913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		slave_image = list_entry(pos, struct vme_slave_resource, list);
17923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
17933d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(slave_image);
17943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
179560479690af6d559d4202bed139db90323386bd2bMartyn Welch
17963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* resources are stored in link list */
17973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	list_for_each(pos, &(ca91cx42_bridge->master_resources)) {
17983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		master_image = list_entry(pos, struct vme_master_resource,
17993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			list);
18003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		list_del(pos);
18013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		kfree(master_image);
18023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
180360479690af6d559d4202bed139db90323386bd2bMartyn Welch
180429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	ca91cx42_irq_exit(bridge, pdev);
180560479690af6d559d4202bed139db90323386bd2bMartyn Welch
180629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iounmap(bridge->base);
180760479690af6d559d4202bed139db90323386bd2bMartyn Welch
18083d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pci_release_regions(pdev);
180960479690af6d559d4202bed139db90323386bd2bMartyn Welch
18103d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pci_disable_device(pdev);
18113d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
18123d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	kfree(ca91cx42_bridge);
181360479690af6d559d4202bed139db90323386bd2bMartyn Welch}
181460479690af6d559d4202bed139db90323386bd2bMartyn Welch
18153d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchstatic void __exit ca91cx42_exit(void)
181660479690af6d559d4202bed139db90323386bd2bMartyn Welch{
18173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	pci_unregister_driver(&ca91cx42_driver);
18183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
181960479690af6d559d4202bed139db90323386bd2bMartyn Welch
182012b2d5c0895a03e941e7c145d9d23a45908a857bMartyn WelchMODULE_PARM_DESC(geoid, "Override geographical addressing");
182112b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welchmodule_param(geoid, int, 0);
182212b2d5c0895a03e941e7c145d9d23a45908a857bMartyn Welch
18233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge");
18243d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn WelchMODULE_LICENSE("GPL");
182560479690af6d559d4202bed139db90323386bd2bMartyn Welch
18263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_init(ca91cx42_init);
18273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchmodule_exit(ca91cx42_exit);
182860479690af6d559d4202bed139db90323386bd2bMartyn Welch
18293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch/*----------------------------------------------------------------------------
18303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch * STAGING
18313d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch *--------------------------------------------------------------------------*/
18323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
18333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#if 0
183460479690af6d559d4202bed139db90323386bd2bMartyn Welch
18353d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw)
183660479690af6d559d4202bed139db90323386bd2bMartyn Welch{
183760479690af6d559d4202bed139db90323386bd2bMartyn Welch	int temp_ctl = 0;
183860479690af6d559d4202bed139db90323386bd2bMartyn Welch	int tempBS = 0;
183960479690af6d559d4202bed139db90323386bd2bMartyn Welch	int tempBD = 0;
184060479690af6d559d4202bed139db90323386bd2bMartyn Welch	int tempTO = 0;
184160479690af6d559d4202bed139db90323386bd2bMartyn Welch	int vmeBS = 0;
184260479690af6d559d4202bed139db90323386bd2bMartyn Welch	int vmeBD = 0;
184360479690af6d559d4202bed139db90323386bd2bMartyn Welch	int *rmw_pci_data_ptr = NULL;
184460479690af6d559d4202bed139db90323386bd2bMartyn Welch	int *vaDataPtr = NULL;
184560479690af6d559d4202bed139db90323386bd2bMartyn Welch	int i;
184660479690af6d559d4202bed139db90323386bd2bMartyn Welch	vmeOutWindowCfg_t vmeOut;
184760479690af6d559d4202bed139db90323386bd2bMartyn Welch	if (vmeRmw->maxAttempts < 1) {
18483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
184960479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
185060479690af6d559d4202bed139db90323386bd2bMartyn Welch	if (vmeRmw->targetAddrU) {
18513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
185260479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
18533d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Find the PCI address that maps to the desired VME address */
185460479690af6d559d4202bed139db90323386bd2bMartyn Welch	for (i = 0; i < 8; i++) {
185529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		temp_ctl = ioread32(bridge->base +
18563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			CA91CX42_LSI_CTL[i]);
185760479690af6d559d4202bed139db90323386bd2bMartyn Welch		if ((temp_ctl & 0x80000000) == 0) {
185860479690af6d559d4202bed139db90323386bd2bMartyn Welch			continue;
185960479690af6d559d4202bed139db90323386bd2bMartyn Welch		}
186060479690af6d559d4202bed139db90323386bd2bMartyn Welch		memset(&vmeOut, 0, sizeof(vmeOut));
186160479690af6d559d4202bed139db90323386bd2bMartyn Welch		vmeOut.windowNbr = i;
18623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		ca91cx42_get_out_bound(&vmeOut);
186360479690af6d559d4202bed139db90323386bd2bMartyn Welch		if (vmeOut.addrSpace != vmeRmw->addrSpace) {
186460479690af6d559d4202bed139db90323386bd2bMartyn Welch			continue;
186560479690af6d559d4202bed139db90323386bd2bMartyn Welch		}
186629848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		tempBS = ioread32(bridge->base + CA91CX42_LSI_BS[i]);
186729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		tempBD = ioread32(bridge->base + CA91CX42_LSI_BD[i]);
186829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch		tempTO = ioread32(bridge->base + CA91CX42_LSI_TO[i]);
186960479690af6d559d4202bed139db90323386bd2bMartyn Welch		vmeBS = tempBS + tempTO;
187060479690af6d559d4202bed139db90323386bd2bMartyn Welch		vmeBD = tempBD + tempTO;
187160479690af6d559d4202bed139db90323386bd2bMartyn Welch		if ((vmeRmw->targetAddr >= vmeBS) &&
187260479690af6d559d4202bed139db90323386bd2bMartyn Welch		    (vmeRmw->targetAddr < vmeBD)) {
187360479690af6d559d4202bed139db90323386bd2bMartyn Welch			rmw_pci_data_ptr =
187460479690af6d559d4202bed139db90323386bd2bMartyn Welch			    (int *)(tempBS + (vmeRmw->targetAddr - vmeBS));
187560479690af6d559d4202bed139db90323386bd2bMartyn Welch			vaDataPtr =
187660479690af6d559d4202bed139db90323386bd2bMartyn Welch			    (int *)(out_image_va[i] +
187760479690af6d559d4202bed139db90323386bd2bMartyn Welch				    (vmeRmw->targetAddr - vmeBS));
187860479690af6d559d4202bed139db90323386bd2bMartyn Welch			break;
187960479690af6d559d4202bed139db90323386bd2bMartyn Welch		}
188060479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
188160479690af6d559d4202bed139db90323386bd2bMartyn Welch
18823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* If no window - fail. */
188360479690af6d559d4202bed139db90323386bd2bMartyn Welch	if (rmw_pci_data_ptr == NULL) {
18843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
18853d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	}
18863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Setup the RMW registers. */
188729848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(0, bridge->base + SCYC_CTL);
188829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(SWIZZLE(vmeRmw->enableMask), bridge->base + SCYC_EN);
188929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(SWIZZLE(vmeRmw->compareData), bridge->base +
18903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		SCYC_CMP);
189129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(SWIZZLE(vmeRmw->swapData), bridge->base + SCYC_SWP);
189229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32((int)rmw_pci_data_ptr, bridge->base + SCYC_ADDR);
189329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(1, bridge->base + SCYC_CTL);
18943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
18953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* Run the RMW cycle until either success or max attempts. */
189660479690af6d559d4202bed139db90323386bd2bMartyn Welch	vmeRmw->numAttempts = 1;
189760479690af6d559d4202bed139db90323386bd2bMartyn Welch	while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) {
189860479690af6d559d4202bed139db90323386bd2bMartyn Welch
18993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		if ((ioread32(vaDataPtr) & vmeRmw->enableMask) ==
190060479690af6d559d4202bed139db90323386bd2bMartyn Welch		    (vmeRmw->swapData & vmeRmw->enableMask)) {
190160479690af6d559d4202bed139db90323386bd2bMartyn Welch
190229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch			iowrite32(0, bridge->base + SCYC_CTL);
190360479690af6d559d4202bed139db90323386bd2bMartyn Welch			break;
190460479690af6d559d4202bed139db90323386bd2bMartyn Welch
190560479690af6d559d4202bed139db90323386bd2bMartyn Welch		}
190660479690af6d559d4202bed139db90323386bd2bMartyn Welch		vmeRmw->numAttempts++;
190760479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
190860479690af6d559d4202bed139db90323386bd2bMartyn Welch
19093d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	/* If no success, set num Attempts to be greater than max attempts */
191060479690af6d559d4202bed139db90323386bd2bMartyn Welch	if (vmeRmw->numAttempts > vmeRmw->maxAttempts) {
191160479690af6d559d4202bed139db90323386bd2bMartyn Welch		vmeRmw->numAttempts = vmeRmw->maxAttempts + 1;
191260479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
191360479690af6d559d4202bed139db90323386bd2bMartyn Welch
19143d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
191560479690af6d559d4202bed139db90323386bd2bMartyn Welch}
191660479690af6d559d4202bed139db90323386bd2bMartyn Welch
19173d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb)
19183d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
19193d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int temp_ctl = 0;
19203d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int vbto = 0;
192160479690af6d559d4202bed139db90323386bd2bMartyn Welch
192229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	temp_ctl = ioread32(bridge->base + MISC_CTL);
19233d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= 0x00FFFFFF;
192460479690af6d559d4202bed139db90323386bd2bMartyn Welch
19253d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
19263d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vbto = 7;
19273d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	} else if (vmeArb->globalTimeoutTimer > 1024) {
19283d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		return -EINVAL;
19293d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	} else if (vmeArb->globalTimeoutTimer == 0) {
19303d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vbto = 0;
193160479690af6d559d4202bed139db90323386bd2bMartyn Welch	} else {
19323d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vbto = 1;
19333d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer)
19343d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch			vbto += 1;
193560479690af6d559d4202bed139db90323386bd2bMartyn Welch	}
19363d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl |= (vbto << 28);
19373d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19383d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeArb->arbiterMode == VME_PRIORITY_MODE)
19393d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= 1 << 26;
19403d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19413d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeArb->arbiterTimeoutFlag)
19423d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= 2 << 24;
19433d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
194429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + MISC_CTL);
19453d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
19463d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
19473d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19483d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_get_arbiter(vmeArbiterCfg_t *vmeArb)
19493d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
19503d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int temp_ctl = 0;
19513d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int vbto = 0;
19523d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
195329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	temp_ctl = ioread32(bridge->base + MISC_CTL);
19543d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19553d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vbto = (temp_ctl >> 28) & 0xF;
19563d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vbto != 0)
19573d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1)));
19583d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19593d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (temp_ctl & (1 << 26))
19603d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeArb->arbiterMode = VME_PRIORITY_MODE;
19613d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	else
19623d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeArb->arbiterMode = VME_R_ROBIN_MODE;
19633d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19643d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (temp_ctl & (3 << 24))
19653d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeArb->arbiterTimeoutFlag = 1;
19663d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19673d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
19683d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
19693d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19703d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_set_requestor(vmeRequesterCfg_t *vmeReq)
19713d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
19723d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int temp_ctl = 0;
19733d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
197429848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	temp_ctl = ioread32(bridge->base + MAST_CTL);
19753d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl &= 0xFF0FFFFF;
19763d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19773d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeReq->releaseMode == 1)
19783d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= (1 << 20);
19793d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19803d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (vmeReq->fairMode == 1)
19813d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		temp_ctl |= (1 << 21);
19823d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19833d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	temp_ctl |= (vmeReq->requestLevel << 22);
19843d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
198529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	iowrite32(temp_ctl, bridge->base + MAST_CTL);
19863d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
19873d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch}
19883d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19893d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welchint ca91cx42_get_requestor(vmeRequesterCfg_t *vmeReq)
19903d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch{
19913d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	int temp_ctl = 0;
19923d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
199329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch	temp_ctl = ioread32(bridge->base + MAST_CTL);
19943d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19953d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (temp_ctl & (1 << 20))
19963d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeReq->releaseMode = 1;
19973d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
19983d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	if (temp_ctl & (1 << 21))
19993d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch		vmeReq->fairMode = 1;
20003d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
20013d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22;
20023d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
20033d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch	return 0;
200460479690af6d559d4202bed139db90323386bd2bMartyn Welch}
20053d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
20063d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch
20073d0f8bc7517718a4846de6f538ad67a4f7f83239Martyn Welch#endif
2008