^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Support for the Tundra TSI148 VME-PCI Bridge Chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Martyn Welch <martyn.welch@ge.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Based on work by Tom Armistead and Ajit Prem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2004 Motorola Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/byteorder/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/vme.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "../vme_bridge.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "vme_tsi148.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int tsi148_probe(struct pci_dev *, const struct pci_device_id *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void tsi148_remove(struct pci_dev *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Module parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static bool err_chk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int geoid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static const char driver_name[] = "vme_tsi148";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct pci_device_id tsi148_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MODULE_DEVICE_TABLE(pci, tsi148_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static struct pci_driver tsi148_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .name = driver_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .id_table = tsi148_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .probe = tsi148_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .remove = tsi148_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void reg_join(unsigned int high, unsigned int low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned long long *variable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *variable = (unsigned long long)high << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *variable |= (unsigned long long)low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void reg_split(unsigned long long variable, unsigned int *high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned int *low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *low = (unsigned int)variable & 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *high = (unsigned int)(variable >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Wakes up DMA queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int channel_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 serviced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (channel_mask & TSI148_LCSR_INTS_DMA0S) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) wake_up(&bridge->dma_queue[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) serviced |= TSI148_LCSR_INTC_DMA0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (channel_mask & TSI148_LCSR_INTS_DMA1S) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) wake_up(&bridge->dma_queue[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) serviced |= TSI148_LCSR_INTC_DMA1C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return serviced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * Wake up location monitor queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 serviced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (stat & TSI148_LCSR_INTS_LMS[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* We only enable interrupts if the callback is set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) bridge->lm_callback[i](bridge->lm_data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) serviced |= TSI148_LCSR_INTC_LMC[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return serviced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Wake up mail box queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * XXX This functionality is not exposed up though API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static u32 tsi148_MB_irqhandler(struct vme_bridge *tsi148_bridge, u32 stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 serviced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (stat & TSI148_LCSR_INTS_MBS[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) val = ioread32be(bridge->base + TSI148_GCSR_MBOX[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev_err(tsi148_bridge->parent, "VME Mailbox %d received"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ": 0x%x\n", i, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) serviced |= TSI148_LCSR_INTC_MBC[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return serviced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * Display error & status message when PERR (PCI) exception interrupt occurs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static u32 tsi148_PERR_irqhandler(struct vme_bridge *tsi148_bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) dev_err(tsi148_bridge->parent, "PCI Exception at address: 0x%08x:%08x, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "attributes: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ioread32be(bridge->base + TSI148_LCSR_EDPAU),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ioread32be(bridge->base + TSI148_LCSR_EDPAL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ioread32be(bridge->base + TSI148_LCSR_EDPAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dev_err(tsi148_bridge->parent, "PCI-X attribute reg: %08x, PCI-X split "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) "completion reg: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ioread32be(bridge->base + TSI148_LCSR_EDPXA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ioread32be(bridge->base + TSI148_LCSR_EDPXS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return TSI148_LCSR_INTC_PERRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Save address and status when VME error interrupt occurs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int error_addr_high, error_addr_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned long long error_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u32 error_attrib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int error_am;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) error_am = (error_attrib & TSI148_LCSR_VEAT_AM_M) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) reg_join(error_addr_high, error_addr_low, &error_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* Check for exception register overflow (we have lost error data) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (error_attrib & TSI148_LCSR_VEAT_VEOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dev_err(tsi148_bridge->parent, "VME Bus Exception Overflow "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) "Occurred\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (err_chk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) vme_bus_error_handler(tsi148_bridge, error_addr, error_am);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_err(tsi148_bridge->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) "VME Bus Error at address: 0x%llx, attributes: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) error_addr, error_attrib);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Clear Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return TSI148_LCSR_INTC_VERRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Wake up IACK queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) wake_up(&bridge->iack_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return TSI148_LCSR_INTC_IACKC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Calling VME bus interrupt callback if provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) u32 stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int vec, i, serviced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) for (i = 7; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (stat & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * Note: Even though the registers are defined as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * 32-bits in the spec, we only want to issue 8-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * IACK cycles on the bus, read from offset 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) vme_irq_handler(tsi148_bridge, i, vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) serviced |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return serviced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * Top level interrupt handler. Clears appropriate interrupt status bits and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * then calls appropriate sub handler(s).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static irqreturn_t tsi148_irqhandler(int irq, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u32 stat, enable, serviced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) tsi148_bridge = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* Determine which interrupts are unmasked and set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) enable = ioread32be(bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) stat = ioread32be(bridge->base + TSI148_LCSR_INTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Only look at unmasked interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) stat &= enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (unlikely(!stat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* Call subhandlers as appropriate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* DMA irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) serviced |= tsi148_DMA_irqhandler(bridge, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Location monitor irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) serviced |= tsi148_LM_irqhandler(bridge, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Mail box irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) serviced |= tsi148_MB_irqhandler(tsi148_bridge, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* PCI bus error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (stat & TSI148_LCSR_INTS_PERRS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) serviced |= tsi148_PERR_irqhandler(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* VME bus error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (stat & TSI148_LCSR_INTS_VERRS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) serviced |= tsi148_VERR_irqhandler(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* IACK irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (stat & TSI148_LCSR_INTS_IACKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) serviced |= tsi148_IACK_irqhandler(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* VME bus irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) TSI148_LCSR_INTS_IRQ1S))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Clear serviced interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int tsi148_irq_init(struct vme_bridge *tsi148_bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pdev = to_pci_dev(tsi148_bridge->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) result = request_irq(pdev->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) tsi148_irqhandler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) driver_name, tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) dev_err(tsi148_bridge->parent, "Can't get assigned pci irq "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) "vector %02X\n", pdev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* Enable and unmask interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) tmp = TSI148_LCSR_INTEO_DMA1EO | TSI148_LCSR_INTEO_DMA0EO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) TSI148_LCSR_INTEO_MB3EO | TSI148_LCSR_INTEO_MB2EO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) TSI148_LCSR_INTEO_MB1EO | TSI148_LCSR_INTEO_MB0EO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) TSI148_LCSR_INTEO_IACKEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* This leaves the following interrupts masked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * TSI148_LCSR_INTEO_VIEEO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * TSI148_LCSR_INTEO_SYSFLEO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * TSI148_LCSR_INTEO_ACFLEO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Don't enable Location Monitor interrupts here - they will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * enabled when the location monitors are properly configured and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * a callback has been attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * TSI148_LCSR_INTEO_LM0EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * TSI148_LCSR_INTEO_LM1EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * TSI148_LCSR_INTEO_LM2EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * TSI148_LCSR_INTEO_LM3EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* Don't enable VME interrupts until we add a handler, else the board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * will respond to it and we don't want that unless it knows how to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * properly deal with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * TSI148_LCSR_INTEO_IRQ7EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * TSI148_LCSR_INTEO_IRQ6EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * TSI148_LCSR_INTEO_IRQ5EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * TSI148_LCSR_INTEO_IRQ4EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * TSI148_LCSR_INTEO_IRQ3EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * TSI148_LCSR_INTEO_IRQ2EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * TSI148_LCSR_INTEO_IRQ1EO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static void tsi148_irq_exit(struct vme_bridge *tsi148_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct tsi148_driver *bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* Turn off interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Clear all interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* Detach interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) free_irq(pdev->irq, tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * Check to see if an IACk has been received, return true (1) or false (0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int tsi148_iack_received(struct tsi148_driver *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) tmp = ioread32be(bridge->base + TSI148_LCSR_VICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (tmp & TSI148_LCSR_VICR_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * Configure VME interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int state, int sync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* We need to do the ordering differently for enabling and disabling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (state == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (sync != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) pdev = to_pci_dev(tsi148_bridge->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) synchronize_irq(pdev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * Generate a VME bus interrupt at the requested level & vector. Wait for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * interrupt to be acked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int statid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) mutex_lock(&bridge->vme_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* Read VICR register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) tmp = ioread32be(bridge->base + TSI148_LCSR_VICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* Set Status/ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) (statid & TSI148_LCSR_VICR_STID_M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* Assert VMEbus IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) tmp = tmp | TSI148_LCSR_VICR_IRQL[level];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* XXX Consider implementing a timeout? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) wait_event_interruptible(bridge->iack_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) tsi148_iack_received(bridge));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) mutex_unlock(&bridge->vme_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * Initialize a slave window with the requested attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long long vme_base, unsigned long long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) dma_addr_t pci_base, u32 aspace, u32 cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) unsigned int i, addr = 0, granularity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) unsigned int temp_ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) unsigned int vme_base_low, vme_base_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) unsigned int vme_bound_low, vme_bound_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) unsigned int pci_offset_low, pci_offset_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long long vme_bound, pci_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) tsi148_bridge = image->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) i = image->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) switch (aspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) case VME_A16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) granularity = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) addr |= TSI148_LCSR_ITAT_AS_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case VME_A24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) granularity = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) addr |= TSI148_LCSR_ITAT_AS_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) case VME_A32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) granularity = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) addr |= TSI148_LCSR_ITAT_AS_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case VME_A64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) granularity = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) addr |= TSI148_LCSR_ITAT_AS_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) dev_err(tsi148_bridge->parent, "Invalid address space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* Convert 64-bit variables to 2x 32-bit variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) reg_split(vme_base, &vme_base_high, &vme_base_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * Bound address is a valid address for the window, adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) vme_bound = vme_base + size - granularity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) reg_split(vme_bound, &vme_bound_high, &vme_bound_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) pci_offset = (unsigned long long)pci_base - vme_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) reg_split(pci_offset, &pci_offset_high, &pci_offset_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (vme_base_low & (granularity - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) dev_err(tsi148_bridge->parent, "Invalid VME base alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (vme_bound_low & (granularity - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) dev_err(tsi148_bridge->parent, "Invalid VME bound alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (pci_offset_low & (granularity - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_err(tsi148_bridge->parent, "Invalid PCI Offset "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) "alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* Disable while we are mucking around */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) TSI148_LCSR_OFFSET_ITAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) temp_ctl &= ~TSI148_LCSR_ITAT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) TSI148_LCSR_OFFSET_ITAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* Setup mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) TSI148_LCSR_OFFSET_ITSAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) TSI148_LCSR_OFFSET_ITSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) TSI148_LCSR_OFFSET_ITEAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) TSI148_LCSR_OFFSET_ITEAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) TSI148_LCSR_OFFSET_ITOFU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) TSI148_LCSR_OFFSET_ITOFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* Setup 2eSST speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case VME_2eSST160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case VME_2eSST267:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_267;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case VME_2eSST320:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* Setup cycle types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) temp_ctl &= ~(0x1F << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (cycle & VME_BLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) temp_ctl |= TSI148_LCSR_ITAT_BLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (cycle & VME_MBLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) temp_ctl |= TSI148_LCSR_ITAT_MBLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (cycle & VME_2eVME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) temp_ctl |= TSI148_LCSR_ITAT_2eVME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (cycle & VME_2eSST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) temp_ctl |= TSI148_LCSR_ITAT_2eSST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (cycle & VME_2eSSTB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) temp_ctl |= TSI148_LCSR_ITAT_2eSSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Setup address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) temp_ctl &= ~TSI148_LCSR_ITAT_AS_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) temp_ctl |= addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) temp_ctl &= ~0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (cycle & VME_SUPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) temp_ctl |= TSI148_LCSR_ITAT_SUPR ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (cycle & VME_USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) temp_ctl |= TSI148_LCSR_ITAT_NPRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (cycle & VME_PROG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) temp_ctl |= TSI148_LCSR_ITAT_PGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (cycle & VME_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) temp_ctl |= TSI148_LCSR_ITAT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* Write ctl reg without enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) TSI148_LCSR_OFFSET_ITAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) temp_ctl |= TSI148_LCSR_ITAT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) TSI148_LCSR_OFFSET_ITAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * Get slave window configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) unsigned long long *vme_base, unsigned long long *size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) dma_addr_t *pci_base, u32 *aspace, u32 *cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) unsigned int i, granularity = 0, ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) unsigned int vme_base_low, vme_base_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) unsigned int vme_bound_low, vme_bound_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) unsigned int pci_offset_low, pci_offset_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) unsigned long long vme_bound, pci_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) bridge = image->parent->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) i = image->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* Read registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) TSI148_LCSR_OFFSET_ITAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) TSI148_LCSR_OFFSET_ITSAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) TSI148_LCSR_OFFSET_ITSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) TSI148_LCSR_OFFSET_ITEAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) TSI148_LCSR_OFFSET_ITEAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) TSI148_LCSR_OFFSET_ITOFU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) TSI148_LCSR_OFFSET_ITOFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* Convert 64-bit variables to 2x 32-bit variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) reg_join(vme_base_high, vme_base_low, vme_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) reg_join(vme_bound_high, vme_bound_low, &vme_bound);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) reg_join(pci_offset_high, pci_offset_low, &pci_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) *pci_base = (dma_addr_t)(*vme_base + pci_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) *enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) *aspace = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) *cycle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (ctl & TSI148_LCSR_ITAT_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) *enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) granularity = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) *aspace |= VME_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) granularity = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) *aspace |= VME_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) granularity = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) *aspace |= VME_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) granularity = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) *aspace |= VME_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* Need granularity before we set the size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) *size = (unsigned long long)((vme_bound - *vme_base) + granularity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) *cycle |= VME_2eSST160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) *cycle |= VME_2eSST267;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *cycle |= VME_2eSST320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (ctl & TSI148_LCSR_ITAT_BLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *cycle |= VME_BLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (ctl & TSI148_LCSR_ITAT_MBLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) *cycle |= VME_MBLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (ctl & TSI148_LCSR_ITAT_2eVME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) *cycle |= VME_2eVME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (ctl & TSI148_LCSR_ITAT_2eSST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) *cycle |= VME_2eSST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (ctl & TSI148_LCSR_ITAT_2eSSTB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) *cycle |= VME_2eSSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (ctl & TSI148_LCSR_ITAT_SUPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) *cycle |= VME_SUPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ctl & TSI148_LCSR_ITAT_NPRIV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *cycle |= VME_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (ctl & TSI148_LCSR_ITAT_PGM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) *cycle |= VME_PROG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (ctl & TSI148_LCSR_ITAT_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) *cycle |= VME_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * Allocate and map PCI Resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int tsi148_alloc_resource(struct vme_master_resource *image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) unsigned long long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) unsigned long long existing_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) tsi148_bridge = image->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) pdev = to_pci_dev(tsi148_bridge->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) existing_size = (unsigned long long)(image->bus_resource.end -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) image->bus_resource.start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* If the existing size is OK, return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if ((size != 0) && (existing_size == (size - 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (existing_size != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) iounmap(image->kern_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) image->kern_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) kfree(image->bus_resource.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) release_resource(&image->bus_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) memset(&image->bus_resource, 0, sizeof(image->bus_resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* Exit here if size is zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (!image->bus_resource.name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!image->bus_resource.name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) goto err_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) image->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) image->bus_resource.start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) image->bus_resource.end = (unsigned long)size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) image->bus_resource.flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) retval = pci_bus_alloc_resource(pdev->bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) &image->bus_resource, size, 0x10000, PCIBIOS_MIN_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) dev_err(tsi148_bridge->parent, "Failed to allocate mem "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) "resource for window %d size 0x%lx start 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) image->number, (unsigned long)size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) (unsigned long)image->bus_resource.start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) goto err_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) image->kern_base = ioremap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) image->bus_resource.start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!image->kern_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) dev_err(tsi148_bridge->parent, "Failed to remap resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto err_remap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) err_remap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) release_resource(&image->bus_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) err_resource:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) kfree(image->bus_resource.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) memset(&image->bus_resource, 0, sizeof(image->bus_resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) err_name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * Free and unmap PCI Resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static void tsi148_free_resource(struct vme_master_resource *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) iounmap(image->kern_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) image->kern_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) release_resource(&image->bus_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) kfree(image->bus_resource.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) memset(&image->bus_resource, 0, sizeof(image->bus_resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * Set the attributes of an outbound window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static int tsi148_master_set(struct vme_master_resource *image, int enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) unsigned long long vme_base, unsigned long long size, u32 aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) u32 cycle, u32 dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) unsigned int temp_ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) unsigned int pci_base_low, pci_base_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) unsigned int pci_bound_low, pci_bound_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) unsigned int vme_offset_low, vme_offset_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) unsigned long long pci_bound, vme_offset, pci_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) struct pci_bus_region region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) tsi148_bridge = image->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) pdev = to_pci_dev(tsi148_bridge->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* Verify input data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (vme_base & 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dev_err(tsi148_bridge->parent, "Invalid VME Window "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) "alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) goto err_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if ((size == 0) && (enabled != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) dev_err(tsi148_bridge->parent, "Size must be non-zero for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) "enabled windows\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) goto err_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) spin_lock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Let's allocate the resource here rather than further up the stack as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * it avoids pushing loads of bus dependent stuff up the stack. If size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * is zero, any existing resource will be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) retval = tsi148_alloc_resource(image, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) dev_err(tsi148_bridge->parent, "Unable to allocate memory for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) "resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) goto err_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) pci_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) pci_bound = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) vme_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) pcibios_resource_to_bus(pdev->bus, ®ion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) &image->bus_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) pci_base = region.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * Bound address is a valid address for the window, adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * according to window granularity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) pci_bound = pci_base + (size - 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) vme_offset = vme_base - pci_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /* Convert 64-bit variables to 2x 32-bit variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) reg_split(pci_base, &pci_base_high, &pci_base_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) reg_split(pci_bound, &pci_bound_high, &pci_bound_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) reg_split(vme_offset, &vme_offset_high, &vme_offset_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (pci_base_low & 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) dev_err(tsi148_bridge->parent, "Invalid PCI base alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) goto err_gran;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (pci_bound_low & 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dev_err(tsi148_bridge->parent, "Invalid PCI bound alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) goto err_gran;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (vme_offset_low & 0xFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev_err(tsi148_bridge->parent, "Invalid VME Offset "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) "alignment\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) goto err_gran;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) i = image->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /* Disable while we are mucking around */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) TSI148_LCSR_OFFSET_OTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) temp_ctl &= ~TSI148_LCSR_OTAT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) TSI148_LCSR_OFFSET_OTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Setup 2eSST speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) case VME_2eSST160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) case VME_2eSST267:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_267;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) case VME_2eSST320:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* Setup cycle types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (cycle & VME_BLT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) temp_ctl |= TSI148_LCSR_OTAT_TM_BLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (cycle & VME_MBLT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) temp_ctl |= TSI148_LCSR_OTAT_TM_MBLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (cycle & VME_2eVME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) temp_ctl |= TSI148_LCSR_OTAT_TM_2eVME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (cycle & VME_2eSST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (cycle & VME_2eSSTB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) dev_warn(tsi148_bridge->parent, "Currently not setting "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) "Broadcast Select Registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* Setup data width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) temp_ctl &= ~TSI148_LCSR_OTAT_DBW_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) switch (dwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case VME_D16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) temp_ctl |= TSI148_LCSR_OTAT_DBW_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case VME_D32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) temp_ctl |= TSI148_LCSR_OTAT_DBW_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) dev_err(tsi148_bridge->parent, "Invalid data width\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) goto err_dwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* Setup address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) temp_ctl &= ~TSI148_LCSR_OTAT_AMODE_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) switch (aspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) case VME_A16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) temp_ctl |= TSI148_LCSR_OTAT_AMODE_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case VME_A24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) temp_ctl |= TSI148_LCSR_OTAT_AMODE_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) case VME_A32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) temp_ctl |= TSI148_LCSR_OTAT_AMODE_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) case VME_A64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) temp_ctl |= TSI148_LCSR_OTAT_AMODE_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) case VME_CRCSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) temp_ctl |= TSI148_LCSR_OTAT_AMODE_CRCSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) case VME_USER1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case VME_USER2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) case VME_USER3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) case VME_USER4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dev_err(tsi148_bridge->parent, "Invalid address space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) goto err_aspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) temp_ctl &= ~(3<<4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (cycle & VME_SUPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) temp_ctl |= TSI148_LCSR_OTAT_SUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (cycle & VME_PROG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) temp_ctl |= TSI148_LCSR_OTAT_PGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* Setup mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) TSI148_LCSR_OFFSET_OTSAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) TSI148_LCSR_OFFSET_OTSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) TSI148_LCSR_OFFSET_OTEAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) TSI148_LCSR_OFFSET_OTEAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) TSI148_LCSR_OFFSET_OTOFU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) TSI148_LCSR_OFFSET_OTOFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /* Write ctl reg without enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) TSI148_LCSR_OFFSET_OTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) temp_ctl |= TSI148_LCSR_OTAT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) TSI148_LCSR_OFFSET_OTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) err_aspace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) err_dwidth:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) err_gran:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) tsi148_free_resource(image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) err_res:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) err_window:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * Set the attributes of an outbound window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * XXX Not parsing prefetch information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) static int __tsi148_master_get(struct vme_master_resource *image, int *enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) u32 *cycle, u32 *dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) unsigned int i, ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) unsigned int pci_base_low, pci_base_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) unsigned int pci_bound_low, pci_bound_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) unsigned int vme_offset_low, vme_offset_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) unsigned long long pci_base, pci_bound, vme_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) bridge = image->parent->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) i = image->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) TSI148_LCSR_OFFSET_OTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) TSI148_LCSR_OFFSET_OTSAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) TSI148_LCSR_OFFSET_OTSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) TSI148_LCSR_OFFSET_OTEAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) TSI148_LCSR_OFFSET_OTEAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) TSI148_LCSR_OFFSET_OTOFU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) TSI148_LCSR_OFFSET_OTOFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* Convert 64-bit variables to 2x 32-bit variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) reg_join(pci_base_high, pci_base_low, &pci_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) reg_join(pci_bound_high, pci_bound_low, &pci_bound);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) reg_join(vme_offset_high, vme_offset_low, &vme_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) *vme_base = pci_base + vme_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) *size = (unsigned long long)(pci_bound - pci_base) + 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) *enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) *aspace = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) *cycle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) *dwidth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (ctl & TSI148_LCSR_OTAT_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) *enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* Setup address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) *aspace |= VME_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) *aspace |= VME_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) *aspace |= VME_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) *aspace |= VME_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_CRCSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) *aspace |= VME_CRCSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) *aspace |= VME_USER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) *aspace |= VME_USER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) *aspace |= VME_USER3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) *aspace |= VME_USER4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /* Setup 2eSST speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) *cycle |= VME_2eSST160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) *cycle |= VME_2eSST267;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) *cycle |= VME_2eSST320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /* Setup cycle types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_SCT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) *cycle |= VME_SCT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_BLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) *cycle |= VME_BLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_MBLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) *cycle |= VME_MBLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eVME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) *cycle |= VME_2eVME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) *cycle |= VME_2eSST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSSTB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) *cycle |= VME_2eSSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (ctl & TSI148_LCSR_OTAT_SUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) *cycle |= VME_SUPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) *cycle |= VME_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (ctl & TSI148_LCSR_OTAT_PGM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) *cycle |= VME_PROG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) *cycle |= VME_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* Setup data width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) *dwidth = VME_D16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) *dwidth = VME_D32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static int tsi148_master_get(struct vme_master_resource *image, int *enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) u32 *cycle, u32 *dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) spin_lock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) retval = __tsi148_master_get(image, enabled, vme_base, size, aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) cycle, dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) size_t count, loff_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int retval, enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) unsigned long long vme_base, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) u32 aspace, cycle, dwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct vme_error_handler *handler = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) void __iomem *addr = image->kern_base + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) unsigned int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) unsigned int count32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) tsi148_bridge = image->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) spin_lock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (err_chk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) &cycle, &dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) handler = vme_register_error_handler(tsi148_bridge, aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) vme_base + offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (!handler) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /* The following code handles VME address alignment. We cannot use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * memcpy_xxx here because it may cut data transfers in to 8-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) * cycles when D16 or D32 cycles are required on the VME bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * On the other hand, the bridge itself assures that the maximum data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * cycle configured for the transfer is used and splits it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) * automatically for non-aligned addresses, so we don't want the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) * overhead of needlessly forcing small transfers for the entire cycle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if ((uintptr_t)addr & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) *(u8 *)buf = ioread8(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) done += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (done == count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if ((uintptr_t)(addr + done) & 0x2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if ((count - done) < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) *(u8 *)(buf + done) = ioread8(addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) done += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) *(u16 *)(buf + done) = ioread16(addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) done += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) count32 = (count - done) & ~0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) while (done < count32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) *(u32 *)(buf + done) = ioread32(addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) done += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if ((count - done) & 0x2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) *(u16 *)(buf + done) = ioread16(addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) done += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if ((count - done) & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) *(u8 *)(buf + done) = ioread8(addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) done += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) retval = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (err_chk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (handler->num_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) dev_err(image->parent->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) "First VME read error detected an at address 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) handler->first_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) retval = handler->first_error - (vme_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) vme_unregister_error_handler(handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) size_t count, loff_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) int retval = 0, enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) unsigned long long vme_base, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) u32 aspace, cycle, dwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) void __iomem *addr = image->kern_base + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) unsigned int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) unsigned int count32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct vme_error_handler *handler = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) tsi148_bridge = image->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) spin_lock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (err_chk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) &cycle, &dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) handler = vme_register_error_handler(tsi148_bridge, aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) vme_base + offset, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (!handler) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) /* Here we apply for the same strategy we do in master_read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * function in order to assure the correct cycles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if ((uintptr_t)addr & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) iowrite8(*(u8 *)buf, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) done += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (done == count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if ((uintptr_t)(addr + done) & 0x2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if ((count - done) < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) iowrite8(*(u8 *)(buf + done), addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) done += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) iowrite16(*(u16 *)(buf + done), addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) done += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) count32 = (count - done) & ~0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) while (done < count32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) iowrite32(*(u32 *)(buf + done), addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) done += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if ((count - done) & 0x2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) iowrite16(*(u16 *)(buf + done), addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) done += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if ((count - done) & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) iowrite8(*(u8 *)(buf + done), addr + done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) done += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) retval = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * Writes are posted. We need to do a read on the VME bus to flush out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * all of the writes before we check for errors. We can't guarantee
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * that reading the data we have just written is safe. It is believed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * that there isn't any read, write re-ordering, so we can read any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * location in VME space, so lets read the Device ID from the tsi148's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * own registers as mapped into CR/CSR space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * We check for saved errors in the written address range/space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (err_chk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) ioread16(bridge->flush_image->kern_base + 0x7F000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (handler->num_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) dev_warn(tsi148_bridge->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) "First VME write error detected an at address 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) handler->first_error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) retval = handler->first_error - (vme_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) vme_unregister_error_handler(handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * Perform an RMW cycle on the VME bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * Requires a previously configured master window, returns final value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) static unsigned int tsi148_master_rmw(struct vme_master_resource *image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) unsigned int mask, unsigned int compare, unsigned int swap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) loff_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) unsigned long long pci_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) unsigned int pci_addr_high, pci_addr_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) u32 tmp, result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) bridge = image->parent->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) /* Find the PCI address that maps to the desired VME address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) i = image->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* Locking as we can only do one of these at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) mutex_lock(&bridge->vme_rmw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) /* Lock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) spin_lock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) TSI148_LCSR_OFFSET_OTSAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) TSI148_LCSR_OFFSET_OTSAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) reg_join(pci_addr_high, pci_addr_low, &pci_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) /* Configure registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) /* Enable RMW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) tmp |= TSI148_LCSR_VMCTRL_RMWEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /* Kick process off with a read to the required address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) result = ioread32be(image->kern_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) /* Disable RMW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) tmp &= ~TSI148_LCSR_VMCTRL_RMWEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) spin_unlock(&image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) mutex_unlock(&bridge->vme_rmw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) static int tsi148_dma_set_vme_src_attributes(struct device *dev, __be32 *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) u32 aspace, u32 cycle, u32 dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) val = be32_to_cpu(*attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /* Setup 2eSST speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) case VME_2eSST160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) val |= TSI148_LCSR_DSAT_2eSSTM_160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) case VME_2eSST267:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) val |= TSI148_LCSR_DSAT_2eSSTM_267;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) case VME_2eSST320:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) val |= TSI148_LCSR_DSAT_2eSSTM_320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) /* Setup cycle types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (cycle & VME_SCT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) val |= TSI148_LCSR_DSAT_TM_SCT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (cycle & VME_BLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) val |= TSI148_LCSR_DSAT_TM_BLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (cycle & VME_MBLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) val |= TSI148_LCSR_DSAT_TM_MBLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (cycle & VME_2eVME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) val |= TSI148_LCSR_DSAT_TM_2eVME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) if (cycle & VME_2eSST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) val |= TSI148_LCSR_DSAT_TM_2eSST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (cycle & VME_2eSSTB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) dev_err(dev, "Currently not setting Broadcast Select "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) "Registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) val |= TSI148_LCSR_DSAT_TM_2eSSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) /* Setup data width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) switch (dwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) case VME_D16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) val |= TSI148_LCSR_DSAT_DBW_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) case VME_D32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) val |= TSI148_LCSR_DSAT_DBW_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) dev_err(dev, "Invalid data width\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* Setup address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) switch (aspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) case VME_A16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) val |= TSI148_LCSR_DSAT_AMODE_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) case VME_A24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) val |= TSI148_LCSR_DSAT_AMODE_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) case VME_A32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) val |= TSI148_LCSR_DSAT_AMODE_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) case VME_A64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) val |= TSI148_LCSR_DSAT_AMODE_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) case VME_CRCSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) val |= TSI148_LCSR_DSAT_AMODE_CRCSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) case VME_USER1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) val |= TSI148_LCSR_DSAT_AMODE_USER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) case VME_USER2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) val |= TSI148_LCSR_DSAT_AMODE_USER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) case VME_USER3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) val |= TSI148_LCSR_DSAT_AMODE_USER3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) case VME_USER4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) val |= TSI148_LCSR_DSAT_AMODE_USER4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) dev_err(dev, "Invalid address space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (cycle & VME_SUPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) val |= TSI148_LCSR_DSAT_SUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (cycle & VME_PROG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) val |= TSI148_LCSR_DSAT_PGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) *attr = cpu_to_be32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) static int tsi148_dma_set_vme_dest_attributes(struct device *dev, __be32 *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) u32 aspace, u32 cycle, u32 dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) val = be32_to_cpu(*attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) /* Setup 2eSST speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) case VME_2eSST160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) val |= TSI148_LCSR_DDAT_2eSSTM_160;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) case VME_2eSST267:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) val |= TSI148_LCSR_DDAT_2eSSTM_267;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) case VME_2eSST320:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) val |= TSI148_LCSR_DDAT_2eSSTM_320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) /* Setup cycle types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (cycle & VME_SCT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) val |= TSI148_LCSR_DDAT_TM_SCT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (cycle & VME_BLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) val |= TSI148_LCSR_DDAT_TM_BLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (cycle & VME_MBLT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) val |= TSI148_LCSR_DDAT_TM_MBLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (cycle & VME_2eVME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) val |= TSI148_LCSR_DDAT_TM_2eVME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (cycle & VME_2eSST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) val |= TSI148_LCSR_DDAT_TM_2eSST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (cycle & VME_2eSSTB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) dev_err(dev, "Currently not setting Broadcast Select "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) "Registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) val |= TSI148_LCSR_DDAT_TM_2eSSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) /* Setup data width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) switch (dwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) case VME_D16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) val |= TSI148_LCSR_DDAT_DBW_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) case VME_D32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) val |= TSI148_LCSR_DDAT_DBW_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) dev_err(dev, "Invalid data width\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) /* Setup address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) switch (aspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) case VME_A16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) val |= TSI148_LCSR_DDAT_AMODE_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) case VME_A24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) val |= TSI148_LCSR_DDAT_AMODE_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) case VME_A32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) val |= TSI148_LCSR_DDAT_AMODE_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) case VME_A64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) val |= TSI148_LCSR_DDAT_AMODE_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) case VME_CRCSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) val |= TSI148_LCSR_DDAT_AMODE_CRCSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) case VME_USER1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) val |= TSI148_LCSR_DDAT_AMODE_USER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) case VME_USER2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) val |= TSI148_LCSR_DDAT_AMODE_USER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) case VME_USER3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) val |= TSI148_LCSR_DDAT_AMODE_USER3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) case VME_USER4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) val |= TSI148_LCSR_DDAT_AMODE_USER4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) dev_err(dev, "Invalid address space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (cycle & VME_SUPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) val |= TSI148_LCSR_DDAT_SUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) if (cycle & VME_PROG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) val |= TSI148_LCSR_DDAT_PGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) *attr = cpu_to_be32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) * Add a link list descriptor to the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) * Note: DMA engine expects the DMA descriptor to be big endian.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) static int tsi148_dma_list_add(struct vme_dma_list *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) struct tsi148_dma_entry *entry, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) u32 address_high, address_low, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) struct vme_dma_pattern *pattern_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) struct vme_dma_pci *pci_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) struct vme_dma_vme *vme_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) tsi148_bridge = list->parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) /* Descriptor must be aligned on 64-bit boundaries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) entry = kmalloc(sizeof(*entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) goto err_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) /* Test descriptor alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) if ((unsigned long)&entry->descriptor & 0x7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) dev_err(tsi148_bridge->parent, "Descriptor not aligned to 8 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) "byte boundary as required: %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) &entry->descriptor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) goto err_align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) /* Given we are going to fill out the structure, we probably don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * need to zero it, but better safe than sorry for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) memset(&entry->descriptor, 0, sizeof(entry->descriptor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) /* Fill out source part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) switch (src->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) case VME_DMA_PATTERN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) pattern_attr = src->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) entry->descriptor.dsal = cpu_to_be32(pattern_attr->pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) val = TSI148_LCSR_DSAT_TYP_PAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) /* Default behaviour is 32 bit pattern */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (pattern_attr->type & VME_DMA_PATTERN_BYTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) val |= TSI148_LCSR_DSAT_PSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) /* It seems that the default behaviour is to increment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) val |= TSI148_LCSR_DSAT_NIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) entry->descriptor.dsat = cpu_to_be32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) case VME_DMA_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) pci_attr = src->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) reg_split((unsigned long long)pci_attr->address, &address_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) &address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) entry->descriptor.dsau = cpu_to_be32(address_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) entry->descriptor.dsal = cpu_to_be32(address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) case VME_DMA_VME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) vme_attr = src->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) reg_split((unsigned long long)vme_attr->address, &address_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) &address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) entry->descriptor.dsau = cpu_to_be32(address_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) entry->descriptor.dsal = cpu_to_be32(address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_VME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) retval = tsi148_dma_set_vme_src_attributes(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) tsi148_bridge->parent, &entry->descriptor.dsat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) goto err_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) dev_err(tsi148_bridge->parent, "Invalid source type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) goto err_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) /* Assume last link - this will be over-written by adding another */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) entry->descriptor.dnlau = cpu_to_be32(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) entry->descriptor.dnlal = cpu_to_be32(TSI148_LCSR_DNLAL_LLA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) /* Fill out destination part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) switch (dest->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) case VME_DMA_PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) pci_attr = dest->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) reg_split((unsigned long long)pci_attr->address, &address_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) &address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) entry->descriptor.ddau = cpu_to_be32(address_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) entry->descriptor.ddal = cpu_to_be32(address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) case VME_DMA_VME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) vme_attr = dest->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) reg_split((unsigned long long)vme_attr->address, &address_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) &address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) entry->descriptor.ddau = cpu_to_be32(address_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) entry->descriptor.ddal = cpu_to_be32(address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_VME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) retval = tsi148_dma_set_vme_dest_attributes(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) tsi148_bridge->parent, &entry->descriptor.ddat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) goto err_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) dev_err(tsi148_bridge->parent, "Invalid destination type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) goto err_dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) /* Fill out count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) entry->descriptor.dcnt = cpu_to_be32((u32)count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) /* Add to list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) list_add_tail(&entry->list, &list->entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) entry->dma_handle = dma_map_single(tsi148_bridge->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) &entry->descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) sizeof(entry->descriptor),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (dma_mapping_error(tsi148_bridge->parent, entry->dma_handle)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) dev_err(tsi148_bridge->parent, "DMA mapping error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) goto err_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) /* Fill out previous descriptors "Next Address" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) if (entry->list.prev != &list->entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) reg_split((unsigned long long)entry->dma_handle, &address_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) &address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) prev = list_entry(entry->list.prev, struct tsi148_dma_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) prev->descriptor.dnlau = cpu_to_be32(address_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) prev->descriptor.dnlal = cpu_to_be32(address_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) err_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) err_dest:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) err_source:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) err_align:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) err_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) * Check to see if the provided DMA channel is busy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) TSI148_LCSR_OFFSET_DSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (tmp & TSI148_LCSR_DSTA_BSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) * Execute a previously generated link list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) * XXX Need to provide control register configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) static int tsi148_dma_list_exec(struct vme_dma_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) struct vme_dma_resource *ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) int channel, retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) struct tsi148_dma_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) u32 bus_addr_high, bus_addr_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) u32 val, dctlreg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) ctrlr = list->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) tsi148_bridge = ctrlr->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) mutex_lock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) channel = ctrlr->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (!list_empty(&ctrlr->running)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) * XXX We have an active DMA transfer and currently haven't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) * sorted out the mechanism for "pending" DMA transfers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) * Return busy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /* Need to add to pending here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) mutex_unlock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) list_add(&list->list, &ctrlr->running);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) /* Get first bus address and write into registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) entry = list_first_entry(&list->entries, struct tsi148_dma_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) mutex_unlock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) reg_split(entry->dma_handle, &bus_addr_high, &bus_addr_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) iowrite32be(bus_addr_high, bridge->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) iowrite32be(bus_addr_low, bridge->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) dctlreg = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) TSI148_LCSR_OFFSET_DCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) /* Start the operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) retval = wait_event_interruptible(bridge->dma_queue[channel],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) tsi148_dma_busy(ctrlr->parent, channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) iowrite32be(dctlreg | TSI148_LCSR_DCTL_ABT, bridge->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) /* Wait for the operation to abort */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) wait_event(bridge->dma_queue[channel],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) tsi148_dma_busy(ctrlr->parent, channel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) retval = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) * Read status register, this register is valid until we kick off a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) * new transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) TSI148_LCSR_OFFSET_DSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) if (val & TSI148_LCSR_DSTA_VBE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) dev_err(tsi148_bridge->parent, "DMA Error. DSTA=%08X\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) /* Remove list from running list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) mutex_lock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) list_del(&list->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) mutex_unlock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) * Clean up a previously generated link list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) * We have a separate function, don't assume that the chain can't be reused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) static int tsi148_dma_list_empty(struct vme_dma_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) struct list_head *pos, *temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) struct tsi148_dma_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) struct vme_bridge *tsi148_bridge = list->parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) /* detach and free each entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) list_for_each_safe(pos, temp, &list->entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) entry = list_entry(pos, struct tsi148_dma_entry, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) dma_unmap_single(tsi148_bridge->parent, entry->dma_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) * All 4 location monitors reside at the same base - this is therefore a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * system wide configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) * This does not enable the LM monitor - that should be done when the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) * callback is attached and disabled when the last callback is removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) u32 aspace, u32 cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) u32 lm_base_high, lm_base_low, lm_ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) tsi148_bridge = lm->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) /* If we already have a callback attached, we can't move it! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) for (i = 0; i < lm->monitors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if (bridge->lm_callback[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) dev_err(tsi148_bridge->parent, "Location monitor "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) "callback attached, can't reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) switch (aspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) case VME_A16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) lm_ctl |= TSI148_LCSR_LMAT_AS_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) case VME_A24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) lm_ctl |= TSI148_LCSR_LMAT_AS_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) case VME_A32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) lm_ctl |= TSI148_LCSR_LMAT_AS_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) case VME_A64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) lm_ctl |= TSI148_LCSR_LMAT_AS_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) dev_err(tsi148_bridge->parent, "Invalid address space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) if (cycle & VME_SUPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) lm_ctl |= TSI148_LCSR_LMAT_SUPR ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) if (cycle & VME_USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) lm_ctl |= TSI148_LCSR_LMAT_NPRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) if (cycle & VME_PROG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) lm_ctl |= TSI148_LCSR_LMAT_PGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) if (cycle & VME_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) lm_ctl |= TSI148_LCSR_LMAT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) reg_split(lm_base, &lm_base_high, &lm_base_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) /* Get configuration of the callback monitor and return whether it is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) * or disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) static int tsi148_lm_get(struct vme_lm_resource *lm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) unsigned long long *lm_base, u32 *aspace, u32 *cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) bridge = lm->parent->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) reg_join(lm_base_high, lm_base_low, lm_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (lm_ctl & TSI148_LCSR_LMAT_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) *aspace |= VME_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) *aspace |= VME_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) *aspace |= VME_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) *aspace |= VME_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) if (lm_ctl & TSI148_LCSR_LMAT_SUPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) *cycle |= VME_SUPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) if (lm_ctl & TSI148_LCSR_LMAT_NPRIV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) *cycle |= VME_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (lm_ctl & TSI148_LCSR_LMAT_PGM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) *cycle |= VME_PROG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) if (lm_ctl & TSI148_LCSR_LMAT_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) *cycle |= VME_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) return enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) * Attach a callback to a specific location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) * Callback will be passed the monitor triggered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) static int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) void (*callback)(void *), void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) u32 lm_ctl, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) tsi148_bridge = lm->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) /* Ensure that the location monitor is configured - need PGM or DATA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) dev_err(tsi148_bridge->parent, "Location monitor not properly "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) "configured\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) /* Check that a callback isn't already attached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) if (bridge->lm_callback[monitor]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) dev_err(tsi148_bridge->parent, "Existing callback attached\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) /* Attach callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) bridge->lm_callback[monitor] = callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) bridge->lm_data[monitor] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) /* Enable Location Monitor interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) tmp |= TSI148_LCSR_INTEN_LMEN[monitor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) tmp |= TSI148_LCSR_INTEO_LMEO[monitor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) /* Ensure that global Location Monitor Enable set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) lm_ctl |= TSI148_LCSR_LMAT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) * Detach a callback function forn a specific location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) static int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) u32 lm_en, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) bridge = lm->parent->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) /* Disable Location Monitor and ensure previous interrupts are clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) iowrite32be(TSI148_LCSR_INTC_LMC[monitor],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) bridge->base + TSI148_LCSR_INTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) /* Detach callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) bridge->lm_callback[monitor] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) bridge->lm_data[monitor] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) /* If all location monitors disabled, disable global Location Monitor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) tmp &= ~TSI148_LCSR_LMAT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) * Determine Geographical Addressing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) static int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) u32 slot = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) if (!geoid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) slot = slot & TSI148_LCSR_VSTAT_GA_M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) slot = geoid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) return (int)slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) static void *tsi148_alloc_consistent(struct device *parent, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) dma_addr_t *dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) /* Find pci_dev container of dev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) pdev = to_pci_dev(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) return pci_alloc_consistent(pdev, size, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) static void tsi148_free_consistent(struct device *parent, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) void *vaddr, dma_addr_t dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) /* Find pci_dev container of dev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) pdev = to_pci_dev(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) pci_free_consistent(pdev, size, vaddr, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) * Configure CR/CSR space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) * Access to the CR/CSR can be configured at power-up. The location of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) * CR/CSR registers in the CR/CSR address space is determined by the boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) * Auto-ID or Geographic address. This function ensures that the window is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) * enabled at an offset consistent with the boards geopgraphic address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) * Each board has a 512kB window, with the highest 4kB being used for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) * boards registers, this means there is a fix length 508kB window which must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) * be mapped onto PCI memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) u32 cbar, crat, vstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) u32 crcsr_bus_high, crcsr_bus_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) /* Allocate mem for CR/CSR image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) &bridge->crcsr_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) if (!bridge->crcsr_kernel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) dev_err(tsi148_bridge->parent, "Failed to allocate memory for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) "CR/CSR image\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) /* Ensure that the CR/CSR is configured at the correct offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) cbar = ioread32be(bridge->base + TSI148_CBAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) vstat = tsi148_slot_get(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (cbar != vstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) cbar = vstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) dev_info(tsi148_bridge->parent, "Setting CR/CSR offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) iowrite32be(cbar<<3, bridge->base + TSI148_CBAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) crat = ioread32be(bridge->base + TSI148_LCSR_CRAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) if (crat & TSI148_LCSR_CRAT_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) iowrite32be(crat | TSI148_LCSR_CRAT_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) bridge->base + TSI148_LCSR_CRAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) /* If we want flushed, error-checked writes, set up a window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) * over the CR/CSR registers. We read from here to safely flush
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) * through VME writes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) if (err_chk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) retval = tsi148_master_set(bridge->flush_image, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) (vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) VME_D16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) dev_err(tsi148_bridge->parent, "Configuring flush image"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) " failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) static void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) u32 crat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) /* Turn off CR/CSR space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) crat = ioread32be(bridge->base + TSI148_LCSR_CRAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) iowrite32be(crat & ~TSI148_LCSR_CRAT_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) bridge->base + TSI148_LCSR_CRAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) /* Free image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) iowrite32be(0, bridge->base + TSI148_LCSR_CROU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) iowrite32be(0, bridge->base + TSI148_LCSR_CROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) bridge->crcsr_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) int retval, i, master_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) struct list_head *pos = NULL, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) struct vme_bridge *tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) struct tsi148_driver *tsi148_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) struct vme_master_resource *master_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) struct vme_slave_resource *slave_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) struct vme_dma_resource *dma_ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) /* If we want to support more than one of each bridge, we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) * dynamically generate this so we get one per device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) tsi148_bridge = kzalloc(sizeof(*tsi148_bridge), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) if (!tsi148_bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) goto err_struct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) vme_init_bridge(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) tsi148_device = kzalloc(sizeof(*tsi148_device), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) if (!tsi148_device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) goto err_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) tsi148_bridge->driver_priv = tsi148_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) /* Enable the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) retval = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) dev_err(&pdev->dev, "Unable to enable device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) goto err_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) /* Map Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) retval = pci_request_regions(pdev, driver_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) dev_err(&pdev->dev, "Unable to reserve resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) goto err_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) /* map registers in BAR 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) tsi148_device->base = ioremap(pci_resource_start(pdev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) if (!tsi148_device->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) dev_err(&pdev->dev, "Unable to remap CRG region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) goto err_remap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) /* Check to see if the mapping worked out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) if (data != PCI_VENDOR_ID_TUNDRA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) dev_err(&pdev->dev, "CRG region check failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) goto err_test;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) /* Initialize wait queues & mutual exclusion flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) init_waitqueue_head(&tsi148_device->dma_queue[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) init_waitqueue_head(&tsi148_device->dma_queue[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) init_waitqueue_head(&tsi148_device->iack_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) mutex_init(&tsi148_device->vme_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) mutex_init(&tsi148_device->vme_rmw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) tsi148_bridge->parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) strcpy(tsi148_bridge->name, driver_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) /* Setup IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) retval = tsi148_irq_init(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) if (retval != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) dev_err(&pdev->dev, "Chip Initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) /* If we are going to flush writes, we need to read from the VME bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) * We need to do this safely, thus we read the devices own CR/CSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) * register. To do this we must set up a window in CR/CSR space and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) * hence have one less master window resource available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) master_num = TSI148_MAX_MASTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) if (err_chk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) master_num--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) tsi148_device->flush_image =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) kmalloc(sizeof(*tsi148_device->flush_image),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) if (!tsi148_device->flush_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) goto err_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) tsi148_device->flush_image->parent = tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) spin_lock_init(&tsi148_device->flush_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) tsi148_device->flush_image->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) tsi148_device->flush_image->number = master_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) memset(&tsi148_device->flush_image->bus_resource, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) sizeof(tsi148_device->flush_image->bus_resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) tsi148_device->flush_image->kern_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) /* Add master windows to list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) for (i = 0; i < master_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) master_image = kmalloc(sizeof(*master_image), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) if (!master_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) goto err_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) master_image->parent = tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) spin_lock_init(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) master_image->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) master_image->number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) master_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) VME_USER3 | VME_USER4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) VME_PROG | VME_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) master_image->width_attr = VME_D16 | VME_D32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) memset(&master_image->bus_resource, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) sizeof(master_image->bus_resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) master_image->kern_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) list_add_tail(&master_image->list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) &tsi148_bridge->master_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) /* Add slave windows to list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) for (i = 0; i < TSI148_MAX_SLAVE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) slave_image = kmalloc(sizeof(*slave_image), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) if (!slave_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) goto err_slave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) slave_image->parent = tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) mutex_init(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) slave_image->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) slave_image->number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) VME_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) VME_PROG | VME_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) list_add_tail(&slave_image->list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) &tsi148_bridge->slave_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) /* Add dma engines to list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) for (i = 0; i < TSI148_MAX_DMA; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) dma_ctrlr = kmalloc(sizeof(*dma_ctrlr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) if (!dma_ctrlr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) goto err_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) dma_ctrlr->parent = tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) mutex_init(&dma_ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) dma_ctrlr->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) dma_ctrlr->number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) VME_DMA_PATTERN_TO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) INIT_LIST_HEAD(&dma_ctrlr->pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) INIT_LIST_HEAD(&dma_ctrlr->running);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) list_add_tail(&dma_ctrlr->list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) &tsi148_bridge->dma_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) /* Add location monitor to list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) lm = kmalloc(sizeof(*lm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (!lm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) goto err_lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) lm->parent = tsi148_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) mutex_init(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) lm->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) lm->number = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) lm->monitors = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) list_add_tail(&lm->list, &tsi148_bridge->lm_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) tsi148_bridge->slave_get = tsi148_slave_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) tsi148_bridge->slave_set = tsi148_slave_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) tsi148_bridge->master_get = tsi148_master_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) tsi148_bridge->master_set = tsi148_master_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) tsi148_bridge->master_read = tsi148_master_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) tsi148_bridge->master_write = tsi148_master_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) tsi148_bridge->master_rmw = tsi148_master_rmw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) tsi148_bridge->dma_list_add = tsi148_dma_list_add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) tsi148_bridge->dma_list_exec = tsi148_dma_list_exec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) tsi148_bridge->dma_list_empty = tsi148_dma_list_empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) tsi148_bridge->irq_set = tsi148_irq_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) tsi148_bridge->irq_generate = tsi148_irq_generate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) tsi148_bridge->lm_set = tsi148_lm_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) tsi148_bridge->lm_get = tsi148_lm_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) tsi148_bridge->lm_attach = tsi148_lm_attach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) tsi148_bridge->lm_detach = tsi148_lm_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) tsi148_bridge->slot_get = tsi148_slot_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) tsi148_bridge->alloc_consistent = tsi148_alloc_consistent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) tsi148_bridge->free_consistent = tsi148_free_consistent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) dev_info(&pdev->dev, "Board is%s the VME system controller\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) (data & TSI148_LCSR_VSTAT_SCONS) ? "" : " not");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) if (!geoid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) dev_info(&pdev->dev, "VME geographical address is %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) data & TSI148_LCSR_VSTAT_GA_M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) dev_info(&pdev->dev, "VME geographical address is set to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) geoid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) dev_info(&pdev->dev, "VME Write and flush and error check is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) err_chk ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) retval = tsi148_crcsr_init(tsi148_bridge, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) goto err_crcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) retval = vme_register_bridge(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) if (retval != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) dev_err(&pdev->dev, "Chip Registration failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) goto err_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) pci_set_drvdata(pdev, tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) /* Clear VME bus "board fail", and "power-up reset" lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) data &= ~TSI148_LCSR_VSTAT_BRDFL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) data |= TSI148_LCSR_VSTAT_CPURST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) err_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) tsi148_crcsr_exit(tsi148_bridge, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) err_crcsr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) err_lm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) list_for_each_safe(pos, n, &tsi148_bridge->lm_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) lm = list_entry(pos, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) kfree(lm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) err_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) list_for_each_safe(pos, n, &tsi148_bridge->dma_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) kfree(dma_ctrlr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) err_slave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) list_for_each_safe(pos, n, &tsi148_bridge->slave_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) slave_image = list_entry(pos, struct vme_slave_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) kfree(slave_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) err_master:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) list_for_each_safe(pos, n, &tsi148_bridge->master_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) master_image = list_entry(pos, struct vme_master_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) kfree(master_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) tsi148_irq_exit(tsi148_bridge, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) err_test:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) iounmap(tsi148_device->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) err_remap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) err_resource:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) err_enable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) kfree(tsi148_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) err_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) kfree(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) err_struct:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) static void tsi148_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) struct list_head *pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) struct list_head *tmplist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) struct vme_master_resource *master_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) struct vme_slave_resource *slave_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) struct vme_dma_resource *dma_ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) struct tsi148_driver *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) bridge = tsi148_bridge->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) dev_dbg(&pdev->dev, "Driver is being unloaded.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) * Shutdown all inbound and outbound windows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) TSI148_LCSR_OFFSET_ITAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) TSI148_LCSR_OFFSET_OTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) * Shutdown Location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) iowrite32be(0, bridge->base + TSI148_LCSR_LMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) * Shutdown CRG map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) * Clear error status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) * Remove VIRQ interrupt (if any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) * Map all Interrupts to PCI INTA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) tsi148_irq_exit(tsi148_bridge, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) vme_unregister_bridge(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) tsi148_crcsr_exit(tsi148_bridge, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) list_for_each_safe(pos, tmplist, &tsi148_bridge->dma_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) kfree(dma_ctrlr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) list_for_each_safe(pos, tmplist, &tsi148_bridge->slave_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) slave_image = list_entry(pos, struct vme_slave_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) kfree(slave_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) /* resources are stored in link list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) list_for_each_safe(pos, tmplist, &tsi148_bridge->master_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) master_image = list_entry(pos, struct vme_master_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) list_del(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) kfree(master_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) iounmap(bridge->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) kfree(tsi148_bridge->driver_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) kfree(tsi148_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) module_pci_driver(tsi148_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) module_param(err_chk, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) MODULE_PARM_DESC(geoid, "Override geographical addressing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) module_param(geoid, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) MODULE_LICENSE("GPL");