From 3d0f8bc7517718a4846de6f538ad67a4f7f83239 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Thu, 27 Aug 2009 17:00:40 +0100 Subject: [PATCH] Staging: vme: Update support for the Universe II VME driver This patch starts the reworking of the vme_ca91cx42.c for the VME core. The driver seems to have only supported the Universe II for a long time, I have no hardware to check to see if it would work on the Universe I. This patch is compile tested with minimal run-time testing. It enables basic support for slave and master windows and interrupts. The master windows have undergone basic run testing. Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/bridges/Kconfig | 7 +- drivers/staging/vme/bridges/vme_ca91cx42.c | 2686 +++++++++++++++------------- drivers/staging/vme/bridges/vme_ca91cx42.h | 748 ++++---- 3 files changed, 1832 insertions(+), 1609 deletions(-) diff --git a/drivers/staging/vme/bridges/Kconfig b/drivers/staging/vme/bridges/Kconfig index 82db2c7..023cceb 100644 --- a/drivers/staging/vme/bridges/Kconfig +++ b/drivers/staging/vme/bridges/Kconfig @@ -1,11 +1,10 @@ comment "VME Bridge Drivers" config VME_CA91CX42 - tristate "Universe I/II" - depends on BROKEN + tristate "Universe II" help - If you say Y here you get support for the Tundra CA91C042 (Universe I) - and CA91C142 (Universe II) VME bridge chips. + If you say Y here you get support for the Tundra CA91C142 + (Universe II) VME bridge chip. config VME_TSI148 tristate "Tempe" diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 37487d6..3d2a84c 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -34,1212 +33,1333 @@ #include "../vme_bridge.h" #include "vme_ca91cx42.h" -extern struct vmeSharedData *vmechip_interboard_data; -extern dma_addr_t vmechip_interboard_datap; -extern const int vmechip_revision; -extern const int vmechip_devid; -extern const int vmechip_irq; -extern int vmechip_irq_overhead_ticks; -extern char *vmechip_baseaddr; -extern const int vme_slotnum; -extern int vme_syscon; -extern unsigned int out_image_va[]; -extern unsigned int vme_irqlog[8][0x100]; - -static int outCTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, - LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL -}; +static int __init ca91cx42_init(void); +static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); +static void ca91cx42_remove(struct pci_dev *); +static void __exit ca91cx42_exit(void); -static int outBS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, - LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS -}; +struct vme_bridge *ca91cx42_bridge; +wait_queue_head_t dma_queue; +wait_queue_head_t iack_queue; +wait_queue_head_t lm_queue; +wait_queue_head_t mbox_queue; -static int outBD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, - LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD -}; - -static int outTO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, - LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO -}; +void (*lm_callback[4])(int); /* Called in interrupt handler, be careful! */ +void *crcsr_kernel; +dma_addr_t crcsr_bus; -static int inCTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, - VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL -}; +struct mutex vme_rmw; /* Only one RMW cycle at a time */ +struct mutex vme_int; /* + * Only one VME interrupt can be + * generated at a time, provide locking + */ +struct mutex vme_irq; /* Locking for VME irq callback configuration */ -static int inBS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, - VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS -}; -static int inBD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, - VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD -}; -static int inTO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, - VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO -}; -static int vmevec[7] = { V1_STATID, V2_STATID, V3_STATID, V4_STATID, - V5_STATID, V6_STATID, V7_STATID -}; +static char driver_name[] = "vme_ca91cx42"; -struct interrupt_counters { - unsigned int acfail; - unsigned int sysfail; - unsigned int sw_int; - unsigned int sw_iack; - unsigned int verr; - unsigned int lerr; - unsigned int lm; - unsigned int mbox; - unsigned int dma; - unsigned int virq[7]; - unsigned int vown; +static struct pci_device_id ca91cx42_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, + { }, }; -extern wait_queue_head_t dma_queue[]; -extern wait_queue_head_t lm_queue; -extern wait_queue_head_t mbox_queue; - -extern int tb_speed; - -unsigned int uni_irq_time; -unsigned int uni_dma_irq_time; -unsigned int uni_lm_event; - -static spinlock_t lm_lock = SPIN_LOCK_UNLOCKED; - -static struct interrupt_counters Interrupt_counters = { 0, 0, - 0, 0, 0, 0, - 0, 0, 0, - {0, 0, 0, 0, 0, 0, 0}, - 0 +static struct pci_driver ca91cx42_driver = { + .name = driver_name, + .id_table = ca91cx42_ids, + .probe = ca91cx42_probe, + .remove = ca91cx42_remove, }; -#define read_register(offset) readl(vmechip_baseaddr + offset) -#define write_register(value,offset) writel(value, vmechip_baseaddr + offset) -#define read_register_word(offset) readw(vmechip_baseaddr + offset) -#define write_register_word(value,offset) writew(value, vmechip_baseaddr + offset) - -int uni_procinfo(char *buf) +static u32 ca91cx42_DMA_irqhandler(void) { - char *p; + wake_up(&dma_queue); - p = buf; + return CA91CX42_LINT_DMA; +} - p += sprintf(p, "\n"); - { - unsigned long misc_ctl; +static u32 ca91cx42_LM_irqhandler(u32 stat) +{ + int i; + u32 serviced = 0; - misc_ctl = read_register(MISC_CTL); - p += sprintf(p, "MISC_CTL:\t\t\t0x%08lx\n", misc_ctl); - p += sprintf(p, "VME Bus Time Out:\t\t"); - switch ((misc_ctl & UNIV_BM_MISC_CTL_VBTO) >> - UNIV_OF_MISC_CTL_VBTO) { - case 0x0: - p += sprintf(p, "Disabled\n"); - break; - case 0x1: - p += sprintf(p, "16 us\n"); - break; - case 0x2: - p += sprintf(p, "32 us\n"); - break; - case 0x3: - p += sprintf(p, "64 us\n"); - break; - case 0x4: - p += sprintf(p, "128 us\n"); - break; - case 0x5: - p += sprintf(p, "256 us\n"); - break; - case 0x6: - p += sprintf(p, "512 us\n"); - break; - case 0x7: - p += sprintf(p, "1024 us\n"); - break; - default: - p += sprintf(p, "Reserved Value, Undefined\n"); + for (i = 0; i < 4; i++) { + if (stat & CA91CX42_LINT_LM[i]) { + /* We only enable interrupts if the callback is set */ + lm_callback[i](i); + serviced |= CA91CX42_LINT_LM[i]; } - p += sprintf(p, "VME Arbitration Time Out:\t"); - switch ((misc_ctl & UNIV_BM_MISC_CTL_VARBTO) >> - UNIV_OF_MISC_CTL_VARBTO) { - case 0x0: - p += sprintf(p, "Disabled"); - break; - case 0x1: - p += sprintf(p, "16 us"); - break; - case 0x2: - p += sprintf(p, "256 us"); - break; - default: - p += sprintf(p, "Reserved Value, Undefined"); - } - if (misc_ctl & UNIV_BM_MISC_CTL_VARB) - p += sprintf(p, ", Priority Arbitration\n"); - else - p += sprintf(p, ", Round Robin Arbitration\n"); - p += sprintf(p, "\n"); - } - - { - unsigned int lmisc; - unsigned int crt; - unsigned int cwt; - - lmisc = read_register(LMISC); - p += sprintf(p, "LMISC:\t\t\t\t0x%08x\n", lmisc); - crt = (lmisc & UNIV_BM_LMISC_CRT) >> UNIV_OF_LMISC_CRT; - cwt = (lmisc & UNIV_BM_LMISC_CWT) >> UNIV_OF_LMISC_CWT; - p += sprintf(p, "Coupled Request Timer:\t\t"); - switch (crt) { - case 0x0: - p += sprintf(p, "Disabled\n"); - break; - case 0x1: - p += sprintf(p, "128 us\n"); - break; - case 0x2: - p += sprintf(p, "256 us\n"); - break; - case 0x3: - p += sprintf(p, "512 us\n"); - break; - case 0x4: - p += sprintf(p, "1024 us\n"); - break; - case 0x5: - p += sprintf(p, "2048 us\n"); - break; - case 0x6: - p += sprintf(p, "4096 us\n"); - break; - default: - p += sprintf(p, "Reserved\n"); - } - p += sprintf(p, "Coupled Window Timer:\t\t"); - switch (cwt) { - case 0x0: - p += sprintf(p, "Disabled\n"); - break; - case 0x1: - p += sprintf(p, "16 PCI Clocks\n"); - break; - case 0x2: - p += sprintf(p, "32 PCI Clocks\n"); - break; - case 0x3: - p += sprintf(p, "64 PCI Clocks\n"); - break; - case 0x4: - p += sprintf(p, "128 PCI Clocks\n"); - break; - case 0x5: - p += sprintf(p, "256 PCI Clocks\n"); - break; - case 0x6: - p += sprintf(p, "512 PCI Clocks\n"); - break; - default: - p += sprintf(p, "Reserved\n"); - } - p += sprintf(p, "\n"); } - { - unsigned int mast_ctl; - mast_ctl = read_register(MAST_CTL); - p += sprintf(p, "MAST_CTL:\t\t\t0x%08x\n", mast_ctl); - { - int retries; + return serviced; +} - retries = ((mast_ctl & UNIV_BM_MAST_CTL_MAXRTRY) - >> UNIV_OF_MAST_CTL_MAXRTRY) * 64; - p += sprintf(p, "Max PCI Master Retries:\t\t"); - if (retries) - p += sprintf(p, "%d\n", retries); - else - p += sprintf(p, "Forever\n"); - } +/* XXX This needs to be split into 4 queues */ +static u32 ca91cx42_MB_irqhandler(int mbox_mask) +{ + wake_up(&mbox_queue); - p += sprintf(p, "Posted Write Transfer Count:\t"); - switch ((mast_ctl & UNIV_BM_MAST_CTL_PWON) >> - UNIV_OF_MAST_CTL_PWON) { - case 0x0: - p += sprintf(p, "128 Bytes\n"); - break; - case 0x1: - p += sprintf(p, "256 Bytes\n"); - break; - case 0x2: - p += sprintf(p, "512 Bytes\n"); - break; - case 0x3: - p += sprintf(p, "1024 Bytes\n"); - break; - case 0x4: - p += sprintf(p, "2048 Bytes\n"); - break; - case 0x5: - p += sprintf(p, "4096 Bytes\n"); - break; - default: - p += sprintf(p, "Undefined\n"); - } + return CA91CX42_LINT_MBOX; +} - p += sprintf(p, "VMEbus Request Level:\t\t"); - switch ((mast_ctl & UNIV_BM_MAST_CTL_VRL) >> - UNIV_OF_MAST_CTL_VRL) { - case 0x0: - p += sprintf(p, "Level 0\n"); - case 0x1: - p += sprintf(p, "Level 1\n"); - case 0x2: - p += sprintf(p, "Level 2\n"); - case 0x3: - p += sprintf(p, "Level 3\n"); - } - p += sprintf(p, "VMEbus Request Mode:\t\t"); - if (mast_ctl & UNIV_BM_MAST_CTL_VRM) - p += sprintf(p, "Fair Request Mode\n"); - else - p += sprintf(p, "Demand Request Mode\n"); - p += sprintf(p, "VMEbus Release Mode:\t\t"); - if (mast_ctl & UNIV_BM_MAST_CTL_VREL) - p += sprintf(p, "Release on Request\n"); - else - p += sprintf(p, "Release when Done\n"); - p += sprintf(p, "VMEbus Ownership Bit:\t\t"); - if (mast_ctl & UNIV_BM_MAST_CTL_VOWN) - p += sprintf(p, "Acquire and hold VMEbus\n"); - else - p += sprintf(p, "Release VMEbus\n"); - p += sprintf(p, "VMEbus Ownership Bit Ack:\t"); - if (mast_ctl & UNIV_BM_MAST_CTL_VOWN_ACK) - p += sprintf(p, "Owning VMEbus\n"); - else - p += sprintf(p, "Not Owning VMEbus\n"); - p += sprintf(p, "\n"); - } - { - unsigned int misc_stat; - - misc_stat = read_register(MISC_STAT); - p += sprintf(p, "MISC_STAT:\t\t\t0x%08x\n", misc_stat); - p += sprintf(p, "Universe BBSY:\t\t\t"); - if (misc_stat & UNIV_BM_MISC_STAT_MYBBSY) - p += sprintf(p, "Negated\n"); - else - p += sprintf(p, "Asserted\n"); - p += sprintf(p, "Transmit FIFO:\t\t\t"); - if (misc_stat & UNIV_BM_MISC_STAT_TXFE) - p += sprintf(p, "Empty\n"); - else - p += sprintf(p, "Not empty\n"); - p += sprintf(p, "Receive FIFO:\t\t\t"); - if (misc_stat & UNIV_BM_MISC_STAT_RXFE) - p += sprintf(p, "Empty\n"); - else - p += sprintf(p, "Not Empty\n"); - p += sprintf(p, "\n"); - } - - p += sprintf(p, "Latency Timer:\t\t\t%02d Clocks\n\n", - (read_register(UNIV_PCI_MISC0) & - UNIV_BM_PCI_MISC0_LTIMER) >> UNIV_OF_PCI_MISC0_LTIMER); - - { - unsigned int lint_en; - unsigned int lint_stat; - - lint_en = read_register(LINT_EN); - lint_stat = read_register(LINT_STAT); - -#define REPORT_IRQ(name,field) \ - p += sprintf(p, (lint_en & UNIV_BM_LINT_##name) ? "Enabled" : "Masked"); \ - p += sprintf(p, ", triggered %d times", Interrupt_counters.field); \ - p += sprintf(p, (lint_stat & UNIV_BM_LINT_##name) ? ", irq now active\n" : "\n"); - p += sprintf(p, "ACFAIL Interrupt:\t\t"); - REPORT_IRQ(ACFAIL, acfail); - p += sprintf(p, "SYSFAIL Interrupt:\t\t"); - REPORT_IRQ(SYSFAIL, sysfail); - p += sprintf(p, "SW_INT Interrupt:\t\t"); - REPORT_IRQ(SW_INT, sw_int); - p += sprintf(p, "SW_IACK Interrupt:\t\t"); - REPORT_IRQ(SW_IACK, sw_iack); - p += sprintf(p, "VERR Interrupt:\t\t\t"); - REPORT_IRQ(VERR, verr); - p += sprintf(p, "LERR Interrupt:\t\t\t"); - REPORT_IRQ(LERR, lerr); - p += sprintf(p, "LM Interrupt:\t\t\t"); - REPORT_IRQ(LM, lm); - p += sprintf(p, "MBOX Interrupt:\t\t\t"); - REPORT_IRQ(MBOX, mbox); - p += sprintf(p, "DMA Interrupt:\t\t\t"); - REPORT_IRQ(DMA, dma); - p += sprintf(p, "VIRQ7 Interrupt:\t\t"); - REPORT_IRQ(VIRQ7, virq[7 - 1]); - p += sprintf(p, "VIRQ6 Interrupt:\t\t"); - REPORT_IRQ(VIRQ6, virq[6 - 1]); - p += sprintf(p, "VIRQ5 Interrupt:\t\t"); - REPORT_IRQ(VIRQ5, virq[5 - 1]); - p += sprintf(p, "VIRQ4 Interrupt:\t\t"); - REPORT_IRQ(VIRQ4, virq[4 - 1]); - p += sprintf(p, "VIRQ3 Interrupt:\t\t"); - REPORT_IRQ(VIRQ3, virq[3 - 1]); - p += sprintf(p, "VIRQ2 Interrupt:\t\t"); - REPORT_IRQ(VIRQ2, virq[2 - 1]); - p += sprintf(p, "VIRQ1 Interrupt:\t\t"); - REPORT_IRQ(VIRQ1, virq[1 - 1]); - p += sprintf(p, "VOWN Interrupt:\t\t\t"); - REPORT_IRQ(VOWN, vown); - p += sprintf(p, "\n"); -#undef REPORT_IRQ - } - { - unsigned long vrai_ctl; - - vrai_ctl = read_register(VRAI_CTL); - if (vrai_ctl & UNIV_BM_VRAI_CTL_EN) { - unsigned int vrai_bs; - - vrai_bs = read_register(VRAI_BS); - p += sprintf(p, - "VME Register Image:\t\tEnabled at VME-Address 0x%x\n", - vrai_bs); - } else - p += sprintf(p, "VME Register Image:\t\tDisabled\n"); - } - { - unsigned int slsi; - - slsi = read_register(SLSI); - if (slsi & UNIV_BM_SLSI_EN) { - /* Not implemented */ - } else { - p += sprintf(p, "Special PCI Slave Image:\tDisabled\n"); - } - } - { - int i; - - for (i = 0; i < (vmechip_revision > 0 ? 8 : 4); i++) { - unsigned int ctl, bs, bd, to, vstart, vend; - - ctl = readl(vmechip_baseaddr + outCTL[i]); - bs = readl(vmechip_baseaddr + outBS[i]); - bd = readl(vmechip_baseaddr + outBD[i]); - to = readl(vmechip_baseaddr + outTO[i]); - - vstart = bs + to; - vend = bd + to; - - p += sprintf(p, "PCI Slave Image %d:\t\t", i); - if (ctl & UNIV_BM_LSI_CTL_EN) { - p += sprintf(p, "Enabled"); - if (ctl & UNIV_BM_LSI_CTL_PWEN) - p += sprintf(p, - ", Posted Write Enabled\n"); - else - p += sprintf(p, "\n"); - p += sprintf(p, - "\t\t\t\tPCI Addresses from 0x%x to 0x%x\n", - bs, bd); - p += sprintf(p, - "\t\t\t\tVME Addresses from 0x%x to 0x%x\n", - vstart, vend); - } else - p += sprintf(p, "Disabled\n"); - } - p += sprintf(p, "\n"); - } - { - int i; - for (i = 0; i < (vmechip_revision > 0 ? 8 : 4); i++) { - unsigned int ctl, bs, bd, to, vstart, vend; - - ctl = readl(vmechip_baseaddr + inCTL[i]); - bs = readl(vmechip_baseaddr + inBS[i]); - bd = readl(vmechip_baseaddr + inBD[i]); - to = readl(vmechip_baseaddr + inTO[i]); - vstart = bs + to; - vend = bd + to; - p += sprintf(p, "VME Slave Image %d:\t\t", i); - if (ctl & UNIV_BM_LSI_CTL_EN) { - p += sprintf(p, "Enabled"); - if (ctl & UNIV_BM_LSI_CTL_PWEN) - p += sprintf(p, - ", Posted Write Enabled\n"); - else - p += sprintf(p, "\n"); - p += sprintf(p, - "\t\t\t\tVME Addresses from 0x%x to 0x%x\n", - bs, bd); - p += sprintf(p, - "\t\t\t\tPCI Addresses from 0x%x to 0x%x\n", - vstart, vend); - } else - p += sprintf(p, "Disabled\n"); - } - } +static u32 ca91cx42_IACK_irqhandler(void) +{ + wake_up(&iack_queue); - return p - buf; + return CA91CX42_LINT_SW_IACK; } -//---------------------------------------------------------------------------- -// uni_bus_error_chk() -//---------------------------------------------------------------------------- -int uni_bus_error_chk(int clrflag) +#if 0 +int ca91cx42_bus_error_chk(int clrflag) { int tmp; - tmp = readl(vmechip_baseaddr + PCI_COMMAND); - if (tmp & 0x08000000) { // S_TA is Set + tmp = ioread32(ca91cx42_bridge->base + PCI_COMMAND); + if (tmp & 0x08000000) { /* S_TA is Set */ if (clrflag) - writel(tmp | 0x08000000, - vmechip_baseaddr + PCI_COMMAND); - return (1); + iowrite32(tmp | 0x08000000, + ca91cx42_bridge->base + PCI_COMMAND); + return 1; } - return (0); -} - -//----------------------------------------------------------------------------- -// Function : DMA_uni_irqhandler -// Inputs : void -// Outputs : void -// Description: Saves DMA completion timestamp and then wakes up DMA queue -//----------------------------------------------------------------------------- -static void DMA_uni_irqhandler(void) -{ - uni_dma_irq_time = uni_irq_time; - wake_up(&dma_queue[0]); + return 0; } +#endif -//----------------------------------------------------------------------------- -// Function : LERR_uni_irqhandler -// Inputs : void -// Outputs : void -// Description: -//----------------------------------------------------------------------------- -static void LERR_uni_irqhandler(void) +static u32 ca91cx42_VERR_irqhandler(void) { int val; - val = readl(vmechip_baseaddr + DGCS); + val = ioread32(ca91cx42_bridge->base + DGCS); if (!(val & 0x00000800)) { - printk(KERN_ERR - "ca91c042: LERR_uni_irqhandler DMA Read Error DGCS=%08X\n", - val); - + printk(KERN_ERR "ca91c042: ca91cx42_VERR_irqhandler DMA Read " + "Error DGCS=%08X\n", val); } + + return CA91CX42_LINT_VERR; } -//----------------------------------------------------------------------------- -// Function : VERR_uni_irqhandler -// Inputs : void -// Outputs : void -// Description: -//----------------------------------------------------------------------------- -static void VERR_uni_irqhandler(void) +static u32 ca91cx42_LERR_irqhandler(void) { int val; - val = readl(vmechip_baseaddr + DGCS); + val = ioread32(ca91cx42_bridge->base + DGCS); if (!(val & 0x00000800)) { - printk(KERN_ERR - "ca91c042: VERR_uni_irqhandler DMA Read Error DGCS=%08X\n", - val); - } - -} + printk(KERN_ERR "ca91c042: ca91cx42_LERR_irqhandler DMA Read " + "Error DGCS=%08X\n", val); -//----------------------------------------------------------------------------- -// Function : MB_uni_irqhandler -// Inputs : void -// Outputs : void -// Description: -//----------------------------------------------------------------------------- -static void MB_uni_irqhandler(int mbox_mask) -{ - if (vmechip_irq_overhead_ticks != 0) { - wake_up(&mbox_queue); } -} -//----------------------------------------------------------------------------- -// Function : LM_uni_irqhandler -// Inputs : void -// Outputs : void -// Description: -//----------------------------------------------------------------------------- -static void LM_uni_irqhandler(int lm_mask) -{ - uni_lm_event = lm_mask; - wake_up(&lm_queue); + return CA91CX42_LINT_LERR; } -//----------------------------------------------------------------------------- -// Function : VIRQ_uni_irqhandler -// Inputs : void -// Outputs : void -// Description: -//----------------------------------------------------------------------------- -static void VIRQ_uni_irqhandler(int virq_mask) + +static u32 ca91cx42_VIRQ_irqhandler(int stat) { - int iackvec, i; + int vec, i, serviced = 0; + void (*call)(int, int, void *); + void *priv_data; for (i = 7; i > 0; i--) { - if (virq_mask & (1 << i)) { - Interrupt_counters.virq[i - 1]++; - iackvec = readl(vmechip_baseaddr + vmevec[i - 1]); - vme_irqlog[i][iackvec]++; + if (stat & (1 << i)) { + vec = ioread32(ca91cx42_bridge->base + + CA91CX42_V_STATID[i]) & 0xff; + + call = ca91cx42_bridge->irq[i - 1].callback[vec].func; + priv_data = + ca91cx42_bridge->irq[i - 1].callback[vec].priv_data; + + if (call != NULL) + call(i, vec, priv_data); + else + printk("Spurilous VME interrupt, level:%x, " + "vector:%x\n", i, vec); + + serviced |= (1 << i); } } + + return serviced; } -//----------------------------------------------------------------------------- -// Function : uni_irqhandler -// Inputs : int irq, void *dev_id, struct pt_regs *regs -// Outputs : void -// Description: -//----------------------------------------------------------------------------- -static irqreturn_t uni_irqhandler(int irq, void *dev_id) +static irqreturn_t ca91cx42_irqhandler(int irq, void *dev_id) { - long stat, enable; + u32 stat, enable, serviced = 0; - if (dev_id != vmechip_baseaddr) + if (dev_id != ca91cx42_bridge->base) return IRQ_NONE; - uni_irq_time = get_tbl(); + enable = ioread32(ca91cx42_bridge->base + LINT_EN); + stat = ioread32(ca91cx42_bridge->base + LINT_STAT); - stat = readl(vmechip_baseaddr + LINT_STAT); - writel(stat, vmechip_baseaddr + LINT_STAT); // Clear all pending ints - enable = readl(vmechip_baseaddr + LINT_EN); - stat = stat & enable; - if (stat & 0x0100) { - Interrupt_counters.dma++; - DMA_uni_irqhandler(); - } - if (stat & 0x0200) { - Interrupt_counters.lerr++; - LERR_uni_irqhandler(); - } - if (stat & 0x0400) { - Interrupt_counters.verr++; - VERR_uni_irqhandler(); - } - if (stat & 0xF0000) { - Interrupt_counters.mbox++; - MB_uni_irqhandler((stat & 0xF0000) >> 16); - } - if (stat & 0xF00000) { - Interrupt_counters.lm++; - LM_uni_irqhandler((stat & 0xF00000) >> 20); - } - if (stat & 0x0000FE) { - VIRQ_uni_irqhandler(stat & 0x0000FE); - } - if (stat & UNIV_BM_LINT_ACFAIL) { - Interrupt_counters.acfail++; - } - if (stat & UNIV_BM_LINT_SYSFAIL) { - Interrupt_counters.sysfail++; - } - if (stat & UNIV_BM_LINT_SW_INT) { - Interrupt_counters.sw_int++; - } - if (stat & UNIV_BM_LINT_SW_IACK) { - Interrupt_counters.sw_iack++; - } - if (stat & UNIV_BM_LINT_VOWN) { - Interrupt_counters.vown++; - } + /* Only look at unmasked interrupts */ + stat &= enable; + + if (unlikely(!stat)) + return IRQ_NONE; + + if (stat & CA91CX42_LINT_DMA) + serviced |= ca91cx42_DMA_irqhandler(); + if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | + CA91CX42_LINT_LM3)) + serviced |= ca91cx42_LM_irqhandler(stat); + if (stat & CA91CX42_LINT_MBOX) + serviced |= ca91cx42_MB_irqhandler(stat); + if (stat & CA91CX42_LINT_SW_IACK) + serviced |= ca91cx42_IACK_irqhandler(); + if (stat & CA91CX42_LINT_VERR) + serviced |= ca91cx42_VERR_irqhandler(); + if (stat & CA91CX42_LINT_LERR) + serviced |= ca91cx42_LERR_irqhandler(); + if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | + CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | + CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | + CA91CX42_LINT_VIRQ7)) + serviced |= ca91cx42_VIRQ_irqhandler(stat); + + /* Clear serviced interrupts */ + iowrite32(stat, ca91cx42_bridge->base + LINT_STAT); return IRQ_HANDLED; } -//----------------------------------------------------------------------------- -// Function : uni_generate_irq -// Description: -//----------------------------------------------------------------------------- -int uni_generate_irq(virqInfo_t * vmeIrq) +static int ca91cx42_irq_init(struct vme_bridge *bridge) { - int timeout; - int looptimeout; + int result, tmp; + struct pci_dev *pdev; - timeout = vmeIrq->waitTime; - if (timeout == 0) { - timeout++; // Wait at least 1 tick... - } - looptimeout = HZ / 20; // try for 1/20 second + /* Need pdev */ + pdev = container_of(bridge->parent, struct pci_dev, dev); - vmeIrq->timeOutFlag = 0; + /* Initialise list for VME bus errors */ + INIT_LIST_HEAD(&(bridge->vme_errors)); - // Validate & setup vector register. - if (vmeIrq->vector & 1) { // Universe can only generate even vectors - return (-EINVAL); - } - writel(vmeIrq->vector << 24, vmechip_baseaddr + STATID); + /* Disable interrupts from PCI to VME */ + iowrite32(0, bridge->base + VINT_EN); - // Assert VMEbus IRQ - writel(1 << (vmeIrq->level + 24), vmechip_baseaddr + VINT_EN); + /* Disable PCI interrupts */ + iowrite32(0, bridge->base + LINT_EN); + /* Clear Any Pending PCI Interrupts */ + iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); - // Wait for syscon to do iack - while (readl(vmechip_baseaddr + VINT_STAT) & - (1 << (vmeIrq->level + 24))) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(looptimeout); - timeout = timeout - looptimeout; - if (timeout <= 0) { - vmeIrq->timeOutFlag = 1; - break; - } + result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, + driver_name, pdev); + if (result) { + dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", + pdev->irq); + return result; } - // Clear VMEbus IRQ bit - writel(0, vmechip_baseaddr + VINT_EN); + /* Ensure all interrupts are mapped to PCI Interrupt 0 */ + iowrite32(0, bridge->base + LINT_MAP0); + iowrite32(0, bridge->base + LINT_MAP1); + iowrite32(0, bridge->base + LINT_MAP2); + + /* Enable DMA, mailbox & LM Interrupts */ + tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | + CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | + CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; + + iowrite32(tmp, bridge->base + LINT_EN); - return (0); + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_set_arbiter -// Description: -//----------------------------------------------------------------------------- -int uni_set_arbiter(vmeArbiterCfg_t * vmeArb) +static void ca91cx42_irq_exit(struct pci_dev *pdev) { - int temp_ctl = 0; - int vbto = 0; + /* Disable interrupts from PCI to VME */ + iowrite32(0, ca91cx42_bridge->base + VINT_EN); - temp_ctl = readl(vmechip_baseaddr + MISC_CTL); - temp_ctl &= 0x00FFFFFF; + /* Disable PCI interrupts */ + iowrite32(0, ca91cx42_bridge->base + LINT_EN); + /* Clear Any Pending PCI Interrupts */ + iowrite32(0x00FFFFFF, ca91cx42_bridge->base + LINT_STAT); - if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) { - vbto = 7; - } else if (vmeArb->globalTimeoutTimer > 1024) { - return (-EINVAL); - } else if (vmeArb->globalTimeoutTimer == 0) { - vbto = 0; - } else { - vbto = 1; - while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer) { - vbto += 1; - } - } - temp_ctl |= (vbto << 28); + free_irq(pdev->irq, pdev); +} - if (vmeArb->arbiterMode == VME_PRIORITY_MODE) { - temp_ctl |= 1 << 26; - } +/* + * Set up an VME interrupt + */ +int ca91cx42_request_irq(int level, int statid, + void (*callback)(int level, int vector, void *priv_data), + void *priv_data) +{ + u32 tmp; - if (vmeArb->arbiterTimeoutFlag) { - temp_ctl |= 2 << 24; + mutex_lock(&(vme_irq)); + + if (ca91cx42_bridge->irq[level - 1].callback[statid].func) { + mutex_unlock(&(vme_irq)); + printk("VME Interrupt already taken\n"); + return -EBUSY; } - writel(temp_ctl, vmechip_baseaddr + MISC_CTL); - return (0); + + ca91cx42_bridge->irq[level - 1].count++; + ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = priv_data; + ca91cx42_bridge->irq[level - 1].callback[statid].func = callback; + + /* Enable IRQ level */ + tmp = ioread32(ca91cx42_bridge->base + LINT_EN); + tmp |= CA91CX42_LINT_VIRQ[level]; + iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); + + mutex_unlock(&(vme_irq)); + + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_get_arbiter -// Description: -//----------------------------------------------------------------------------- -int uni_get_arbiter(vmeArbiterCfg_t * vmeArb) +/* + * Free VME interrupt + */ +void ca91cx42_free_irq(int level, int statid) { - int temp_ctl = 0; - int vbto = 0; + u32 tmp; + struct pci_dev *pdev; - temp_ctl = readl(vmechip_baseaddr + MISC_CTL); + mutex_lock(&(vme_irq)); - vbto = (temp_ctl >> 28) & 0xF; - if (vbto != 0) { - vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1))); - } + ca91cx42_bridge->irq[level - 1].count--; - if (temp_ctl & (1 << 26)) { - vmeArb->arbiterMode = VME_PRIORITY_MODE; - } else { - vmeArb->arbiterMode = VME_R_ROBIN_MODE; - } + /* Disable IRQ level if no more interrupts attached at this level*/ + if (ca91cx42_bridge->irq[level - 1].count == 0) { + tmp = ioread32(ca91cx42_bridge->base + LINT_EN); + tmp &= ~CA91CX42_LINT_VIRQ[level]; + iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); - if (temp_ctl & (3 << 24)) { - vmeArb->arbiterTimeoutFlag = 1; + pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, + dev); + + synchronize_irq(pdev->irq); } - return (0); + + ca91cx42_bridge->irq[level - 1].callback[statid].func = NULL; + ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = NULL; + + mutex_unlock(&(vme_irq)); } -//----------------------------------------------------------------------------- -// Function : uni_set_requestor -// Description: -//----------------------------------------------------------------------------- -int uni_set_requestor(vmeRequesterCfg_t * vmeReq) +int ca91cx42_generate_irq(int level, int statid) { - int temp_ctl = 0; + u32 tmp; - temp_ctl = readl(vmechip_baseaddr + MAST_CTL); - temp_ctl &= 0xFF0FFFFF; + /* Universe can only generate even vectors */ + if (statid & 1) + return -EINVAL; - if (vmeReq->releaseMode == 1) { - temp_ctl |= (1 << 20); - } + mutex_lock(&(vme_int)); - if (vmeReq->fairMode == 1) { - temp_ctl |= (1 << 21); - } + tmp = ioread32(ca91cx42_bridge->base + VINT_EN); - temp_ctl |= (vmeReq->requestLevel << 22); + /* Set Status/ID */ + iowrite32(statid << 24, ca91cx42_bridge->base + STATID); + + /* Assert VMEbus IRQ */ + tmp = tmp | (1 << (level + 24)); + iowrite32(tmp, ca91cx42_bridge->base + VINT_EN); - writel(temp_ctl, vmechip_baseaddr + MAST_CTL); - return (0); + /* Wait for IACK */ + wait_event_interruptible(iack_queue, 0); + + /* Return interrupt to low state */ + tmp = ioread32(ca91cx42_bridge->base + VINT_EN); + tmp = tmp & ~(1 << (level + 24)); + iowrite32(tmp, ca91cx42_bridge->base + VINT_EN); + + mutex_unlock(&(vme_int)); + + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_get_requestor -// Description: -//----------------------------------------------------------------------------- -int uni_get_requestor(vmeRequesterCfg_t * vmeReq) +int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, + dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) { - int temp_ctl = 0; + unsigned int i, addr = 0, granularity = 0; + unsigned int temp_ctl = 0; + unsigned int vme_bound, pci_offset; - temp_ctl = readl(vmechip_baseaddr + MAST_CTL); + i = image->number; - if (temp_ctl & (1 << 20)) { - vmeReq->releaseMode = 1; + switch (aspace) { + case VME_A16: + addr |= CA91CX42_VSI_CTL_VAS_A16; + break; + case VME_A24: + addr |= CA91CX42_VSI_CTL_VAS_A24; + break; + case VME_A32: + addr |= CA91CX42_VSI_CTL_VAS_A32; + break; + case VME_USER1: + addr |= CA91CX42_VSI_CTL_VAS_USER1; + break; + case VME_USER2: + addr |= CA91CX42_VSI_CTL_VAS_USER2; + break; + case VME_A64: + case VME_CRCSR: + case VME_USER3: + case VME_USER4: + default: + printk(KERN_ERR "Invalid address space\n"); + return -EINVAL; + break; } - if (temp_ctl & (1 << 21)) { - vmeReq->fairMode = 1; + /* + * Bound address is a valid address for the window, adjust + * accordingly + */ + vme_bound = vme_base + size - granularity; + pci_offset = pci_base - vme_base; + + /* XXX Need to check that vme_base, vme_bound and pci_offset aren't + * too big for registers + */ + + if ((i == 0) || (i == 4)) + granularity = 0x1000; + else + granularity = 0x10000; + + if (vme_base & (granularity - 1)) { + printk(KERN_ERR "Invalid VME base alignment\n"); + return -EINVAL; + } + if (vme_bound & (granularity - 1)) { + printk(KERN_ERR "Invalid VME bound alignment\n"); + return -EINVAL; + } + if (pci_offset & (granularity - 1)) { + printk(KERN_ERR "Invalid PCI Offset alignment\n"); + return -EINVAL; } - vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22; + /* Disable while we are mucking around */ + temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); + temp_ctl &= ~CA91CX42_VSI_CTL_EN; + iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); - return (0); + /* Setup mapping */ + iowrite32(vme_base, ca91cx42_bridge->base + CA91CX42_VSI_BS[i]); + iowrite32(vme_bound, ca91cx42_bridge->base + CA91CX42_VSI_BD[i]); + iowrite32(pci_offset, ca91cx42_bridge->base + CA91CX42_VSI_TO[i]); + +/* XXX Prefetch stuff currently unsupported */ +#if 0 + if (vmeIn->wrPostEnable) + temp_ctl |= CA91CX42_VSI_CTL_PWEN; + if (vmeIn->prefetchEnable) + temp_ctl |= CA91CX42_VSI_CTL_PREN; + if (vmeIn->rmwLock) + temp_ctl |= CA91CX42_VSI_CTL_LLRMW; + if (vmeIn->data64BitCapable) + temp_ctl |= CA91CX42_VSI_CTL_LD64EN; +#endif + + /* Setup address space */ + temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; + temp_ctl |= addr; + + /* Setup cycle types */ + temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); + if (cycle & VME_SUPER) + temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; + if (cycle & VME_USER) + temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; + if (cycle & VME_PROG) + temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; + if (cycle & VME_DATA) + temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; + + /* Write ctl reg without enable */ + iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); + + if (enabled) + temp_ctl |= CA91CX42_VSI_CTL_EN; + + iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); + + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_set_in_bound -// Description: -//----------------------------------------------------------------------------- -int uni_set_in_bound(vmeInWindowCfg_t * vmeIn) +int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) { - int temp_ctl = 0; + unsigned int i, granularity = 0, ctl = 0; + unsigned long long vme_bound, pci_offset; + + i = image->number; - // Verify input data - if (vmeIn->windowNbr > 7) { - return (-EINVAL); + if ((i == 0) || (i == 4)) + granularity = 0x1000; + else + granularity = 0x10000; + + /* Read Registers */ + ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); + + *vme_base = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BS[i]); + vme_bound = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BD[i]); + pci_offset = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_TO[i]); + + *pci_base = (dma_addr_t)vme_base + pci_offset; + *size = (unsigned long long)((vme_bound - *vme_base) + granularity); + + *enabled = 0; + *aspace = 0; + *cycle = 0; + + if (ctl & CA91CX42_VSI_CTL_EN) + *enabled = 1; + + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) + *aspace = VME_A16; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) + *aspace = VME_A24; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) + *aspace = VME_A32; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) + *aspace = VME_USER1; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) + *aspace = VME_USER2; + + if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) + *cycle |= VME_SUPER; + if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) + *cycle |= VME_USER; + if (ctl & CA91CX42_VSI_CTL_PGM_PGM) + *cycle |= VME_PROG; + if (ctl & CA91CX42_VSI_CTL_PGM_DATA) + *cycle |= VME_DATA; + + return 0; +} + +/* + * Allocate and map PCI Resource + */ +static int ca91cx42_alloc_resource(struct vme_master_resource *image, + unsigned long long size) +{ + unsigned long long existing_size; + int retval = 0; + struct pci_dev *pdev; + + /* Find pci_dev container of dev */ + if (ca91cx42_bridge->parent == NULL) { + printk(KERN_ERR "Dev entry NULL\n"); + return -EINVAL; + } + pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); + + existing_size = (unsigned long long)(image->pci_resource.end - + image->pci_resource.start); + + /* If the existing size is OK, return */ + if (existing_size == (size - 1)) + return 0; + + if (existing_size != 0) { + iounmap(image->kern_base); + image->kern_base = NULL; + if (image->pci_resource.name != NULL) + kfree(image->pci_resource.name); + release_resource(&(image->pci_resource)); + memset(&(image->pci_resource), 0, sizeof(struct resource)); + } + + if (image->pci_resource.name == NULL) { + image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); + if (image->pci_resource.name == NULL) { + printk(KERN_ERR "Unable to allocate memory for resource" + " name\n"); + retval = -ENOMEM; + goto err_name; + } } - if ((vmeIn->vmeAddrU) || (vmeIn->windowSizeU) || (vmeIn->pciAddrU)) { - return (-EINVAL); + + sprintf((char *)image->pci_resource.name, "%s.%d", + ca91cx42_bridge->name, image->number); + + image->pci_resource.start = 0; + image->pci_resource.end = (unsigned long)size; + image->pci_resource.flags = IORESOURCE_MEM; + + retval = pci_bus_alloc_resource(pdev->bus, + &(image->pci_resource), size, size, PCIBIOS_MIN_MEM, + 0, NULL, NULL); + if (retval) { + printk(KERN_ERR "Failed to allocate mem resource for " + "window %d size 0x%lx start 0x%lx\n", + image->number, (unsigned long)size, + (unsigned long)image->pci_resource.start); + goto err_resource; } - if ((vmeIn->vmeAddrL & 0xFFF) || - (vmeIn->windowSizeL & 0xFFF) || (vmeIn->pciAddrL & 0xFFF)) { - return (-EINVAL); + + image->kern_base = ioremap_nocache( + image->pci_resource.start, size); + if (image->kern_base == NULL) { + printk(KERN_ERR "Failed to remap resource\n"); + retval = -ENOMEM; + goto err_remap; } - if (vmeIn->bcastRespond2esst) { - return (-EINVAL); + return 0; + + iounmap(image->kern_base); + image->kern_base = NULL; +err_remap: + release_resource(&(image->pci_resource)); +err_resource: + kfree(image->pci_resource.name); + memset(&(image->pci_resource), 0, sizeof(struct resource)); +err_name: + return retval; +} + +/* + * * Free and unmap PCI Resource + * */ +static void ca91cx42_free_resource(struct vme_master_resource *image) +{ + iounmap(image->kern_base); + image->kern_base = NULL; + release_resource(&(image->pci_resource)); + kfree(image->pci_resource.name); + memset(&(image->pci_resource), 0, sizeof(struct resource)); +} + + +int ca91cx42_master_set(struct vme_master_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, + vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) +{ + int retval = 0; + unsigned int i; + unsigned int temp_ctl = 0; + unsigned long long pci_bound, vme_offset, pci_base; + + /* Verify input data */ + if (vme_base & 0xFFF) { + printk(KERN_ERR "Invalid VME Window alignment\n"); + retval = -EINVAL; + goto err_window; + } + if (size & 0xFFF) { + printk(KERN_ERR "Invalid VME Window alignment\n"); + retval = -EINVAL; + goto err_window; + } + + spin_lock(&(image->lock)); + + /* XXX We should do this much later, so that we can exit without + * needing to redo the mapping... + */ + /* + * Let's allocate the resource here rather than further up the stack as + * it avoids pushing loads of bus dependant stuff up the stack + */ + retval = ca91cx42_alloc_resource(image, size); + if (retval) { + spin_unlock(&(image->lock)); + printk(KERN_ERR "Unable to allocate memory for resource " + "name\n"); + retval = -ENOMEM; + goto err_res; + } + + pci_base = (unsigned long long)image->pci_resource.start; + + /* + * Bound address is a valid address for the window, adjust + * according to window granularity. + */ + pci_bound = pci_base + (size - 0x1000); + vme_offset = vme_base - pci_base; + + i = image->number; + + /* Disable while we are mucking around */ + temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); + temp_ctl &= ~CA91CX42_LSI_CTL_EN; + iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); + +/* XXX Prefetch stuff currently unsupported */ +#if 0 + if (vmeOut->wrPostEnable) + temp_ctl |= 0x40000000; +#endif + + /* Setup cycle types */ + temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; + if (cycle & VME_BLT) + temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; + if (cycle & VME_MBLT) + temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; + + /* Setup data width */ + temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; + switch (dwidth) { + case VME_D8: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; + break; + case VME_D16: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; + break; + case VME_D32: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; + break; + case VME_D64: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; + break; + default: + spin_unlock(&(image->lock)); + printk(KERN_ERR "Invalid data width\n"); + retval = -EINVAL; + goto err_dwidth; + break; } - switch (vmeIn->addrSpace) { - case VME_A64: - case VME_CRCSR: - case VME_USER3: - case VME_USER4: - return (-EINVAL); + + /* Setup address space */ + temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; + switch (aspace) { case VME_A16: - temp_ctl |= 0x00000; + temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; break; case VME_A24: - temp_ctl |= 0x10000; + temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; break; case VME_A32: - temp_ctl |= 0x20000; + temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; + break; + case VME_CRCSR: + temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; break; case VME_USER1: - temp_ctl |= 0x60000; + temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; break; case VME_USER2: - temp_ctl |= 0x70000; + temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; + break; + case VME_A64: + case VME_USER3: + case VME_USER4: + default: + spin_unlock(&(image->lock)); + printk(KERN_ERR "Invalid address space\n"); + retval = -EINVAL; + goto err_aspace; break; } - // Disable while we are mucking around - writel(0x00000000, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); - writel(vmeIn->vmeAddrL, vmechip_baseaddr + inBS[vmeIn->windowNbr]); - writel(vmeIn->vmeAddrL + vmeIn->windowSizeL, - vmechip_baseaddr + inBD[vmeIn->windowNbr]); - writel(vmeIn->pciAddrL - vmeIn->vmeAddrL, - vmechip_baseaddr + inTO[vmeIn->windowNbr]); + temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); + if (cycle & VME_SUPER) + temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; + if (cycle & VME_PROG) + temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; - // Setup CTL register. - if (vmeIn->wrPostEnable) - temp_ctl |= 0x40000000; - if (vmeIn->prefetchEnable) - temp_ctl |= 0x20000000; - if (vmeIn->rmwLock) - temp_ctl |= 0x00000040; - if (vmeIn->data64BitCapable) - temp_ctl |= 0x00000080; - if (vmeIn->userAccessType & VME_USER) - temp_ctl |= 0x00100000; - if (vmeIn->userAccessType & VME_SUPER) - temp_ctl |= 0x00200000; - if (vmeIn->dataAccessType & VME_DATA) - temp_ctl |= 0x00400000; - if (vmeIn->dataAccessType & VME_PROG) - temp_ctl |= 0x00800000; + /* Setup mapping */ + iowrite32(pci_base, ca91cx42_bridge->base + CA91CX42_LSI_BS[i]); + iowrite32(pci_bound, ca91cx42_bridge->base + CA91CX42_LSI_BD[i]); + iowrite32(vme_offset, ca91cx42_bridge->base + CA91CX42_LSI_TO[i]); + + /* Write ctl reg without enable */ + iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); + + if (enabled) + temp_ctl |= CA91CX42_LSI_CTL_EN; + + iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); + + spin_unlock(&(image->lock)); + return 0; + +err_aspace: +err_dwidth: + ca91cx42_free_resource(image); +err_res: +err_window: + return retval; +} + +int __ca91cx42_master_get(struct vme_master_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) +{ + unsigned int i, ctl; + unsigned long long pci_base, pci_bound, vme_offset; + + i = image->number; + + ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); + + pci_base = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]); + vme_offset = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]); + pci_bound = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]); + + *vme_base = pci_base + vme_offset; + *size = (pci_bound - pci_base) + 0x1000; + + *enabled = 0; + *aspace = 0; + *cycle = 0; + *dwidth = 0; + + if (ctl & CA91CX42_LSI_CTL_EN) + *enabled = 1; + + /* Setup address space */ + switch (ctl & CA91CX42_LSI_CTL_VAS_M) { + case CA91CX42_LSI_CTL_VAS_A16: + *aspace = VME_A16; + break; + case CA91CX42_LSI_CTL_VAS_A24: + *aspace = VME_A24; + break; + case CA91CX42_LSI_CTL_VAS_A32: + *aspace = VME_A32; + break; + case CA91CX42_LSI_CTL_VAS_CRCSR: + *aspace = VME_CRCSR; + break; + case CA91CX42_LSI_CTL_VAS_USER1: + *aspace = VME_USER1; + break; + case CA91CX42_LSI_CTL_VAS_USER2: + *aspace = VME_USER2; + break; + } + + /* XXX Not sure howto check for MBLT */ + /* Setup cycle types */ + if (ctl & CA91CX42_LSI_CTL_VCT_BLT) + *cycle |= VME_BLT; + else + *cycle |= VME_SCT; + + if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) + *cycle |= VME_SUPER; + else + *cycle |= VME_USER; + + if (ctl & CA91CX42_LSI_CTL_PGM_PGM) + *cycle = VME_PROG; + else + *cycle = VME_DATA; + + /* Setup data width */ + switch (ctl & CA91CX42_LSI_CTL_VDW_M) { + case CA91CX42_LSI_CTL_VDW_D8: + *dwidth = VME_D8; + break; + case CA91CX42_LSI_CTL_VDW_D16: + *dwidth = VME_D16; + break; + case CA91CX42_LSI_CTL_VDW_D32: + *dwidth = VME_D32; + break; + case CA91CX42_LSI_CTL_VDW_D64: + *dwidth = VME_D64; + break; + } + +/* XXX Prefetch stuff currently unsupported */ +#if 0 + if (ctl & 0x40000000) + vmeOut->wrPostEnable = 1; +#endif + + return 0; +} + +int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) +{ + int retval; + + spin_lock(&(image->lock)); + + retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, + cycle, dwidth); + + spin_unlock(&(image->lock)); + + return retval; +} + +ssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf, + size_t count, loff_t offset) +{ + int retval; - // Write ctl reg without enable - writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + spin_lock(&(image->lock)); - if (vmeIn->windowEnable) - temp_ctl |= 0x80000000; + memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); + retval = count; - writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); - return (0); + spin_unlock(&(image->lock)); + + return retval; } -//----------------------------------------------------------------------------- -// Function : uni_get_in_bound -// Description: -//----------------------------------------------------------------------------- -int uni_get_in_bound(vmeInWindowCfg_t * vmeIn) +ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf, + size_t count, loff_t offset) { - int temp_ctl = 0; + int retval = 0; - // Verify input data - if (vmeIn->windowNbr > 7) { - return (-EINVAL); - } - // Get Window mappings. - vmeIn->vmeAddrL = readl(vmechip_baseaddr + inBS[vmeIn->windowNbr]); - vmeIn->pciAddrL = vmeIn->vmeAddrL + - readl(vmechip_baseaddr + inTO[vmeIn->windowNbr]); - vmeIn->windowSizeL = readl(vmechip_baseaddr + inBD[vmeIn->windowNbr]) - - vmeIn->vmeAddrL; - - temp_ctl = readl(vmechip_baseaddr + inCTL[vmeIn->windowNbr]); - - // Get Control & BUS attributes - if (temp_ctl & 0x40000000) - vmeIn->wrPostEnable = 1; - if (temp_ctl & 0x20000000) - vmeIn->prefetchEnable = 1; - if (temp_ctl & 0x00000040) - vmeIn->rmwLock = 1; - if (temp_ctl & 0x00000080) - vmeIn->data64BitCapable = 1; - if (temp_ctl & 0x00100000) - vmeIn->userAccessType |= VME_USER; - if (temp_ctl & 0x00200000) - vmeIn->userAccessType |= VME_SUPER; - if (temp_ctl & 0x00400000) - vmeIn->dataAccessType |= VME_DATA; - if (temp_ctl & 0x00800000) - vmeIn->dataAccessType |= VME_PROG; - if (temp_ctl & 0x80000000) - vmeIn->windowEnable = 1; - - switch ((temp_ctl & 0x70000) >> 16) { - case 0x0: - vmeIn->addrSpace = VME_A16; - break; - case 0x1: - vmeIn->addrSpace = VME_A24; - break; - case 0x2: - vmeIn->addrSpace = VME_A32; - break; - case 0x6: - vmeIn->addrSpace = VME_USER1; - break; - case 0x7: - vmeIn->addrSpace = VME_USER2; - break; - } + spin_lock(&(image->lock)); - return (0); + memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); + retval = count; + + spin_unlock(&(image->lock)); + + return retval; } -//----------------------------------------------------------------------------- -// Function : uni_set_out_bound -// Description: -//----------------------------------------------------------------------------- -int uni_set_out_bound(vmeOutWindowCfg_t * vmeOut) +int ca91cx42_slot_get(void) { - int temp_ctl = 0; + u32 slot = 0; - // Verify input data - if (vmeOut->windowNbr > 7) { - return (-EINVAL); - } - if ((vmeOut->xlatedAddrU) || (vmeOut->windowSizeU) - || (vmeOut->pciBusAddrU)) { - return (-EINVAL); - } - if ((vmeOut->xlatedAddrL & 0xFFF) || - (vmeOut->windowSizeL & 0xFFF) || (vmeOut->pciBusAddrL & 0xFFF)) { - return (-EINVAL); - } - if (vmeOut->bcastSelect2esst) { - return (-EINVAL); + slot = ioread32(ca91cx42_bridge->base + VCSR_BS); + slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); + return (int)slot; + +} + +static int __init ca91cx42_init(void) +{ + return pci_register_driver(&ca91cx42_driver); +} + +/* + * Configure CR/CSR space + * + * Access to the CR/CSR can be configured at power-up. The location of the + * CR/CSR registers in the CR/CSR address space is determined by the boards + * Auto-ID or Geographic address. This function ensures that the window is + * enabled at an offset consistent with the boards geopgraphic address. + */ +static int ca91cx42_crcsr_init(struct pci_dev *pdev) +{ + unsigned int crcsr_addr; + int tmp, slot; + +/* XXX We may need to set this somehow as the Universe II does not support + * geographical addressing. + */ +#if 0 + if (vme_slotnum != -1) + iowrite32(vme_slotnum << 27, ca91cx42_bridge->base + VCSR_BS); +#endif + slot = ca91cx42_slot_get(); + dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); + if (slot == 0) { + dev_err(&pdev->dev, "Slot number is unset, not configuring " + "CR/CSR space\n"); + return -EINVAL; } - switch (vmeOut->addrSpace) { - case VME_A64: - case VME_USER3: - case VME_USER4: - return (-EINVAL); - case VME_A16: - temp_ctl |= 0x00000; - break; - case VME_A24: - temp_ctl |= 0x10000; - break; - case VME_A32: - temp_ctl |= 0x20000; - break; - case VME_CRCSR: - temp_ctl |= 0x50000; - break; - case VME_USER1: - temp_ctl |= 0x60000; - break; - case VME_USER2: - temp_ctl |= 0x70000; - break; + + /* Allocate mem for CR/CSR image */ + crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, + &crcsr_bus); + if (crcsr_kernel == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " + "image\n"); + return -ENOMEM; } - // Disable while we are mucking around - writel(0x00000000, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); - writel(vmeOut->pciBusAddrL, - vmechip_baseaddr + outBS[vmeOut->windowNbr]); - writel(vmeOut->pciBusAddrL + vmeOut->windowSizeL, - vmechip_baseaddr + outBD[vmeOut->windowNbr]); - writel(vmeOut->xlatedAddrL - vmeOut->pciBusAddrL, - vmechip_baseaddr + outTO[vmeOut->windowNbr]); - - // Sanity check. - if (vmeOut->pciBusAddrL != - readl(vmechip_baseaddr + outBS[vmeOut->windowNbr])) { - printk(KERN_ERR - "ca91c042: out window: %x, failed to configure\n", - vmeOut->windowNbr); - return (-EINVAL); - } - - if (vmeOut->pciBusAddrL + vmeOut->windowSizeL != - readl(vmechip_baseaddr + outBD[vmeOut->windowNbr])) { - printk(KERN_ERR - "ca91c042: out window: %x, failed to configure\n", - vmeOut->windowNbr); - return (-EINVAL); - } - - if (vmeOut->xlatedAddrL - vmeOut->pciBusAddrL != - readl(vmechip_baseaddr + outTO[vmeOut->windowNbr])) { - printk(KERN_ERR - "ca91c042: out window: %x, failed to configure\n", - vmeOut->windowNbr); - return (-EINVAL); - } - // Setup CTL register. - if (vmeOut->wrPostEnable) - temp_ctl |= 0x40000000; - if (vmeOut->userAccessType & VME_SUPER) - temp_ctl |= 0x001000; - if (vmeOut->dataAccessType & VME_PROG) - temp_ctl |= 0x004000; - if (vmeOut->maxDataWidth == VME_D16) - temp_ctl |= 0x00400000; - if (vmeOut->maxDataWidth == VME_D32) - temp_ctl |= 0x00800000; - if (vmeOut->maxDataWidth == VME_D64) - temp_ctl |= 0x00C00000; - if (vmeOut->xferProtocol & (VME_BLT | VME_MBLT)) - temp_ctl |= 0x00000100; + memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); - // Write ctl reg without enable - writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + crcsr_addr = slot * (512 * 1024); + iowrite32(crcsr_bus - crcsr_addr, ca91cx42_bridge->base + VCSR_TO); - if (vmeOut->windowEnable) - temp_ctl |= 0x80000000; + tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL); + tmp |= CA91CX42_VCSR_CTL_EN; + iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL); - writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); - return (0); + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_get_out_bound -// Description: -//----------------------------------------------------------------------------- -int uni_get_out_bound(vmeOutWindowCfg_t * vmeOut) +static void ca91cx42_crcsr_exit(struct pci_dev *pdev) { - int temp_ctl = 0; + u32 tmp; - // Verify input data - if (vmeOut->windowNbr > 7) { - return (-EINVAL); - } - // Get Window mappings. - vmeOut->pciBusAddrL = - readl(vmechip_baseaddr + outBS[vmeOut->windowNbr]); - vmeOut->xlatedAddrL = - vmeOut->pciBusAddrL + readl(vmechip_baseaddr + - outTO[vmeOut->windowNbr]); - vmeOut->windowSizeL = - readl(vmechip_baseaddr + outBD[vmeOut->windowNbr]) - - vmeOut->pciBusAddrL; + /* Turn off CR/CSR space */ + tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL); + tmp &= ~CA91CX42_VCSR_CTL_EN; + iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL); - temp_ctl = readl(vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + /* Free image */ + iowrite32(0, ca91cx42_bridge->base + VCSR_TO); - // Get Control & BUS attributes - if (temp_ctl & 0x40000000) - vmeOut->wrPostEnable = 1; - if (temp_ctl & 0x001000) - vmeOut->userAccessType = VME_SUPER; - else - vmeOut->userAccessType = VME_USER; - if (temp_ctl & 0x004000) - vmeOut->dataAccessType = VME_PROG; - else - vmeOut->dataAccessType = VME_DATA; - if (temp_ctl & 0x80000000) - vmeOut->windowEnable = 1; + pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus); +} - switch ((temp_ctl & 0x00C00000) >> 22) { - case 0: - vmeOut->maxDataWidth = VME_D8; - break; - case 1: - vmeOut->maxDataWidth = VME_D16; - break; - case 2: - vmeOut->maxDataWidth = VME_D32; - break; - case 3: - vmeOut->maxDataWidth = VME_D64; - break; +static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int retval, i; + u32 data; + struct list_head *pos = NULL; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; +#if 0 + struct vme_dma_resource *dma_ctrlr; +#endif + struct vme_lm_resource *lm; + + /* We want to support more than one of each bridge so we need to + * dynamically allocate the bridge structure + */ + ca91cx42_bridge = kmalloc(sizeof(struct vme_bridge), GFP_KERNEL); + + if (ca91cx42_bridge == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for device " + "structure\n"); + retval = -ENOMEM; + goto err_struct; + } + + memset(ca91cx42_bridge, 0, sizeof(struct vme_bridge)); + + /* Enable the device */ + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "Unable to enable device\n"); + goto err_enable; + } + + /* Map Registers */ + retval = pci_request_regions(pdev, driver_name); + if (retval) { + dev_err(&pdev->dev, "Unable to reserve resources\n"); + goto err_resource; + } + + /* map registers in BAR 0 */ + ca91cx42_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0), + 4096); + if (!ca91cx42_bridge->base) { + dev_err(&pdev->dev, "Unable to remap CRG region\n"); + retval = -EIO; + goto err_remap; + } + + /* Check to see if the mapping worked out */ + data = ioread32(ca91cx42_bridge->base + CA91CX42_PCI_ID) & 0x0000FFFF; + if (data != PCI_VENDOR_ID_TUNDRA) { + dev_err(&pdev->dev, "PCI_ID check failed\n"); + retval = -EIO; + goto err_test; + } + + /* Initialize wait queues & mutual exclusion flags */ + /* XXX These need to be moved to the vme_bridge structure */ + init_waitqueue_head(&dma_queue); + init_waitqueue_head(&iack_queue); + mutex_init(&(vme_int)); + mutex_init(&(vme_irq)); + mutex_init(&(vme_rmw)); + + ca91cx42_bridge->parent = &(pdev->dev); + strcpy(ca91cx42_bridge->name, driver_name); + + /* Setup IRQ */ + retval = ca91cx42_irq_init(ca91cx42_bridge); + if (retval != 0) { + dev_err(&pdev->dev, "Chip Initialization failed.\n"); + goto err_irq; + } + + /* Add master windows to list */ + INIT_LIST_HEAD(&(ca91cx42_bridge->master_resources)); + for (i = 0; i < CA91C142_MAX_MASTER; i++) { + master_image = kmalloc(sizeof(struct vme_master_resource), + GFP_KERNEL); + if (master_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "master resource structure\n"); + retval = -ENOMEM; + goto err_master; + } + master_image->parent = ca91cx42_bridge; + spin_lock_init(&(master_image->lock)); + master_image->locked = 0; + master_image->number = i; + master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | + VME_CRCSR | VME_USER1 | VME_USER2; + master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | + VME_SUPER | VME_USER | VME_PROG | VME_DATA; + master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; + memset(&(master_image->pci_resource), 0, + sizeof(struct resource)); + master_image->kern_base = NULL; + list_add_tail(&(master_image->list), + &(ca91cx42_bridge->master_resources)); + } + + /* Add slave windows to list */ + INIT_LIST_HEAD(&(ca91cx42_bridge->slave_resources)); + for (i = 0; i < CA91C142_MAX_SLAVE; i++) { + slave_image = kmalloc(sizeof(struct vme_slave_resource), + GFP_KERNEL); + if (slave_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "slave resource structure\n"); + retval = -ENOMEM; + goto err_slave; + } + slave_image->parent = ca91cx42_bridge; + mutex_init(&(slave_image->mtx)); + slave_image->locked = 0; + slave_image->number = i; + slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | + VME_USER2; + + /* Only windows 0 and 4 support A16 */ + if (i == 0 || i == 4) + slave_image->address_attr |= VME_A16; + + slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | + VME_SUPER | VME_USER | VME_PROG | VME_DATA; + list_add_tail(&(slave_image->list), + &(ca91cx42_bridge->slave_resources)); + } +#if 0 + /* Add dma engines to list */ + INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources)); + for (i = 0; i < CA91C142_MAX_DMA; i++) { + dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), + GFP_KERNEL); + if (dma_ctrlr == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "dma resource structure\n"); + retval = -ENOMEM; + goto err_dma; + } + dma_ctrlr->parent = ca91cx42_bridge; + mutex_init(&(dma_ctrlr->mtx)); + dma_ctrlr->locked = 0; + dma_ctrlr->number = i; + INIT_LIST_HEAD(&(dma_ctrlr->pending)); + INIT_LIST_HEAD(&(dma_ctrlr->running)); + list_add_tail(&(dma_ctrlr->list), + &(ca91cx42_bridge->dma_resources)); + } +#endif + /* Add location monitor to list */ + INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources)); + lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); + if (lm == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "location monitor resource structure\n"); + retval = -ENOMEM; + goto err_lm; + } + lm->parent = ca91cx42_bridge; + mutex_init(&(lm->mtx)); + lm->locked = 0; + lm->number = 1; + lm->monitors = 4; + list_add_tail(&(lm->list), &(ca91cx42_bridge->lm_resources)); + + ca91cx42_bridge->slave_get = ca91cx42_slave_get; + ca91cx42_bridge->slave_set = ca91cx42_slave_set; + ca91cx42_bridge->master_get = ca91cx42_master_get; + ca91cx42_bridge->master_set = ca91cx42_master_set; + ca91cx42_bridge->master_read = ca91cx42_master_read; + ca91cx42_bridge->master_write = ca91cx42_master_write; +#if 0 + ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; + ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; + ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; + ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; +#endif + ca91cx42_bridge->request_irq = ca91cx42_request_irq; + ca91cx42_bridge->free_irq = ca91cx42_free_irq; + ca91cx42_bridge->generate_irq = ca91cx42_generate_irq; +#if 0 + ca91cx42_bridge->lm_set = ca91cx42_lm_set; + ca91cx42_bridge->lm_get = ca91cx42_lm_get; + ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; + ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; +#endif + ca91cx42_bridge->slot_get = ca91cx42_slot_get; + + data = ioread32(ca91cx42_bridge->base + MISC_CTL); + dev_info(&pdev->dev, "Board is%s the VME system controller\n", + (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); + dev_info(&pdev->dev, "Slot ID is %d\n", ca91cx42_slot_get()); + + if (ca91cx42_crcsr_init(pdev)) { + dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); + retval = -EINVAL; +#if 0 + goto err_crcsr; +#endif } - if (temp_ctl & 0x00000100) - vmeOut->xferProtocol = VME_BLT; - else - vmeOut->xferProtocol = VME_SCT; - switch ((temp_ctl & 0x70000) >> 16) { - case 0x0: - vmeOut->addrSpace = VME_A16; - break; - case 0x1: - vmeOut->addrSpace = VME_A24; - break; - case 0x2: - vmeOut->addrSpace = VME_A32; - break; - case 0x5: - vmeOut->addrSpace = VME_CRCSR; - break; - case 0x6: - vmeOut->addrSpace = VME_USER1; - break; - case 0x7: - vmeOut->addrSpace = VME_USER2; - break; + /* Need to save ca91cx42_bridge pointer locally in link list for use in + * ca91cx42_remove() + */ + retval = vme_register_bridge(ca91cx42_bridge); + if (retval != 0) { + dev_err(&pdev->dev, "Chip Registration failed.\n"); + goto err_reg; + } + + return 0; + + vme_unregister_bridge(ca91cx42_bridge); +err_reg: + ca91cx42_crcsr_exit(pdev); +err_crcsr: +err_lm: + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { + lm = list_entry(pos, struct vme_lm_resource, list); + list_del(pos); + kfree(lm); + } +#if 0 +err_dma: + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); + kfree(dma_ctrlr); } +#endif +err_slave: + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); + kfree(slave_image); + } +err_master: + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->master_resources)) { + master_image = list_entry(pos, struct vme_master_resource, + list); + list_del(pos); + kfree(master_image); + } + + ca91cx42_irq_exit(pdev); +err_irq: +err_test: + iounmap(ca91cx42_bridge->base); +err_remap: + pci_release_regions(pdev); +err_resource: + pci_disable_device(pdev); +err_enable: + kfree(ca91cx42_bridge); +err_struct: + return retval; - return (0); } -//----------------------------------------------------------------------------- -// Function : uni_setup_lm -// Description: -//----------------------------------------------------------------------------- -int uni_setup_lm(vmeLmCfg_t * vmeLm) +void ca91cx42_remove(struct pci_dev *pdev) { - int temp_ctl = 0; + struct list_head *pos = NULL; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + struct vme_dma_resource *dma_ctrlr; + struct vme_lm_resource *lm; + int i; - if (vmeLm->addrU) { - return (-EINVAL); + /* Turn off Ints */ + iowrite32(0, ca91cx42_bridge->base + LINT_EN); + + /* Turn off the windows */ + iowrite32(0x00800000, ca91cx42_bridge->base + LSI0_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI1_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI2_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI3_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI4_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI5_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI6_CTL); + iowrite32(0x00800000, ca91cx42_bridge->base + LSI7_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI0_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI1_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI2_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI3_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI4_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI5_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI6_CTL); + iowrite32(0x00F00000, ca91cx42_bridge->base + VSI7_CTL); + + vme_unregister_bridge(ca91cx42_bridge); +#if 0 + ca91cx42_crcsr_exit(pdev); +#endif + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { + lm = list_entry(pos, struct vme_lm_resource, list); + list_del(pos); + kfree(lm); } - switch (vmeLm->addrSpace) { - case VME_A64: - case VME_USER3: - case VME_USER4: - return (-EINVAL); - case VME_A16: - temp_ctl |= 0x00000; - break; - case VME_A24: - temp_ctl |= 0x10000; - break; - case VME_A32: - temp_ctl |= 0x20000; - break; - case VME_CRCSR: - temp_ctl |= 0x50000; - break; - case VME_USER1: - temp_ctl |= 0x60000; - break; - case VME_USER2: - temp_ctl |= 0x70000; - break; + + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); + kfree(dma_ctrlr); } - // Disable while we are mucking around - writel(0x00000000, vmechip_baseaddr + LM_CTL); + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); + kfree(slave_image); + } - writel(vmeLm->addr, vmechip_baseaddr + LM_BS); + /* resources are stored in link list */ + list_for_each(pos, &(ca91cx42_bridge->master_resources)) { + master_image = list_entry(pos, struct vme_master_resource, + list); + list_del(pos); + kfree(master_image); + } - // Setup CTL register. - if (vmeLm->userAccessType & VME_SUPER) - temp_ctl |= 0x00200000; - if (vmeLm->userAccessType & VME_USER) - temp_ctl |= 0x00100000; - if (vmeLm->dataAccessType & VME_PROG) - temp_ctl |= 0x00800000; - if (vmeLm->dataAccessType & VME_DATA) - temp_ctl |= 0x00400000; + ca91cx42_irq_exit(pdev); - uni_lm_event = 0; + iounmap(ca91cx42_bridge->base); - // Write ctl reg and enable - writel(0x80000000 | temp_ctl, vmechip_baseaddr + LM_CTL); - temp_ctl = readl(vmechip_baseaddr + LM_CTL); + pci_release_regions(pdev); - return (0); + pci_disable_device(pdev); + + kfree(ca91cx42_bridge); } -//----------------------------------------------------------------------------- -// Function : uni_wait_lm -// Description: -//----------------------------------------------------------------------------- -int uni_wait_lm(vmeLmCfg_t * vmeLm) +static void __exit ca91cx42_exit(void) { - unsigned long flags; - unsigned int tmp; + pci_unregister_driver(&ca91cx42_driver); +} - spin_lock_irqsave(&lm_lock, flags); - tmp = uni_lm_event; - spin_unlock_irqrestore(&lm_lock, flags); - if (tmp == 0) { - if (vmeLm->lmWait < 10) - vmeLm->lmWait = 10; - interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); - } - writel(0x00000000, vmechip_baseaddr + LM_CTL); - vmeLm->lmEvents = uni_lm_event; +MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); +MODULE_LICENSE("GPL"); - return (0); -} +module_init(ca91cx42_init); +module_exit(ca91cx42_exit); +/*---------------------------------------------------------------------------- + * STAGING + *--------------------------------------------------------------------------*/ + +#if 0 #define SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >> 8) | ((X & 0x0000FF00) << 8) | ((X & 0x000000FF) << 24)) -//----------------------------------------------------------------------------- -// Function : uni_do_rmw -// Description: -//----------------------------------------------------------------------------- -int uni_do_rmw(vmeRmwCfg_t * vmeRmw) +int ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw) { int temp_ctl = 0; int tempBS = 0; @@ -1252,26 +1372,27 @@ int uni_do_rmw(vmeRmwCfg_t * vmeRmw) int i; vmeOutWindowCfg_t vmeOut; if (vmeRmw->maxAttempts < 1) { - return (-EINVAL); + return -EINVAL; } if (vmeRmw->targetAddrU) { - return (-EINVAL); + return -EINVAL; } - // Find the PCI address that maps to the desired VME address + /* Find the PCI address that maps to the desired VME address */ for (i = 0; i < 8; i++) { - temp_ctl = readl(vmechip_baseaddr + outCTL[i]); + temp_ctl = ioread32(ca91cx42_bridge->base + + CA91CX42_LSI_CTL[i]); if ((temp_ctl & 0x80000000) == 0) { continue; } memset(&vmeOut, 0, sizeof(vmeOut)); vmeOut.windowNbr = i; - uni_get_out_bound(&vmeOut); + ca91cx42_get_out_bound(&vmeOut); if (vmeOut.addrSpace != vmeRmw->addrSpace) { continue; } - tempBS = readl(vmechip_baseaddr + outBS[i]); - tempBD = readl(vmechip_baseaddr + outBD[i]); - tempTO = readl(vmechip_baseaddr + outTO[i]); + tempBS = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]); + tempBD = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]); + tempTO = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]); vmeBS = tempBS + tempTO; vmeBD = tempBD + tempTO; if ((vmeRmw->targetAddr >= vmeBS) && @@ -1285,44 +1406,41 @@ int uni_do_rmw(vmeRmwCfg_t * vmeRmw) } } - // If no window - fail. + /* If no window - fail. */ if (rmw_pci_data_ptr == NULL) { - return (-EINVAL); - } - // Setup the RMW registers. - writel(0, vmechip_baseaddr + SCYC_CTL); - writel(SWIZZLE(vmeRmw->enableMask), vmechip_baseaddr + SCYC_EN); - writel(SWIZZLE(vmeRmw->compareData), vmechip_baseaddr + SCYC_CMP); - writel(SWIZZLE(vmeRmw->swapData), vmechip_baseaddr + SCYC_SWP); - writel((int)rmw_pci_data_ptr, vmechip_baseaddr + SCYC_ADDR); - writel(1, vmechip_baseaddr + SCYC_CTL); - - // Run the RMW cycle until either success or max attempts. + return -EINVAL; + } + /* Setup the RMW registers. */ + iowrite32(0, ca91cx42_bridge->base + SCYC_CTL); + iowrite32(SWIZZLE(vmeRmw->enableMask), ca91cx42_bridge->base + SCYC_EN); + iowrite32(SWIZZLE(vmeRmw->compareData), ca91cx42_bridge->base + + SCYC_CMP); + iowrite32(SWIZZLE(vmeRmw->swapData), ca91cx42_bridge->base + SCYC_SWP); + iowrite32((int)rmw_pci_data_ptr, ca91cx42_bridge->base + SCYC_ADDR); + iowrite32(1, ca91cx42_bridge->base + SCYC_CTL); + + /* Run the RMW cycle until either success or max attempts. */ vmeRmw->numAttempts = 1; while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) { - if ((readl(vaDataPtr) & vmeRmw->enableMask) == + if ((ioread32(vaDataPtr) & vmeRmw->enableMask) == (vmeRmw->swapData & vmeRmw->enableMask)) { - writel(0, vmechip_baseaddr + SCYC_CTL); + iowrite32(0, ca91cx42_bridge->base + SCYC_CTL); break; } vmeRmw->numAttempts++; } - // If no success, set num Attempts to be greater than max attempts + /* If no success, set num Attempts to be greater than max attempts */ if (vmeRmw->numAttempts > vmeRmw->maxAttempts) { vmeRmw->numAttempts = vmeRmw->maxAttempts + 1; } - return (0); + return 0; } -//----------------------------------------------------------------------------- -// Function : uniSetupDctlReg -// Description: -//----------------------------------------------------------------------------- int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) { unsigned int dctlreg = 0x80; @@ -1366,11 +1484,11 @@ int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) dctlreg |= 0x00070000; break; - case VME_A64: // not supported in Universe DMA + case VME_A64: /* not supported in Universe DMA */ case VME_CRCSR: case VME_USER3: case VME_USER4: - return (-EINVAL); + return -EINVAL; break; } if (vmeAttr->userAccessType == VME_PROG) { @@ -1383,50 +1501,46 @@ int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) dctlreg |= 0x00000100; } *dctlregreturn = dctlreg; - return (0); + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_start_dma -// Description: -//----------------------------------------------------------------------------- unsigned int -uni_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet * vmeLL) +ca91cx42_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet *vmeLL) { unsigned int val; - // Setup registers as needed for direct or chained. + /* Setup registers as needed for direct or chained. */ if (dgcsreg & 0x8000000) { - writel(0, vmechip_baseaddr + DTBC); - writel((unsigned int)vmeLL, vmechip_baseaddr + DCPP); + iowrite32(0, ca91cx42_bridge->base + DTBC); + iowrite32((unsigned int)vmeLL, ca91cx42_bridge->base + DCPP); } else { #if 0 - printk("Starting: DGCS = %08x\n", dgcsreg); - printk("Starting: DVA = %08x\n", readl(&vmeLL->dva)); - printk("Starting: DLV = %08x\n", readl(&vmeLL->dlv)); - printk("Starting: DTBC = %08x\n", readl(&vmeLL->dtbc)); - printk("Starting: DCTL = %08x\n", readl(&vmeLL->dctl)); + printk(KERN_ERR "Starting: DGCS = %08x\n", dgcsreg); + printk(KERN_ERR "Starting: DVA = %08x\n", + ioread32(&vmeLL->dva)); + printk(KERN_ERR "Starting: DLV = %08x\n", + ioread32(&vmeLL->dlv)); + printk(KERN_ERR "Starting: DTBC = %08x\n", + ioread32(&vmeLL->dtbc)); + printk(KERN_ERR "Starting: DCTL = %08x\n", + ioread32(&vmeLL->dctl)); #endif - // Write registers - writel(readl(&vmeLL->dva), vmechip_baseaddr + DVA); - writel(readl(&vmeLL->dlv), vmechip_baseaddr + DLA); - writel(readl(&vmeLL->dtbc), vmechip_baseaddr + DTBC); - writel(readl(&vmeLL->dctl), vmechip_baseaddr + DCTL); - writel(0, vmechip_baseaddr + DCPP); + /* Write registers */ + iowrite32(ioread32(&vmeLL->dva), ca91cx42_bridge->base + DVA); + iowrite32(ioread32(&vmeLL->dlv), ca91cx42_bridge->base + DLA); + iowrite32(ioread32(&vmeLL->dtbc), ca91cx42_bridge->base + DTBC); + iowrite32(ioread32(&vmeLL->dctl), ca91cx42_bridge->base + DCTL); + iowrite32(0, ca91cx42_bridge->base + DCPP); } - // Start the operation - writel(dgcsreg, vmechip_baseaddr + DGCS); + /* Start the operation */ + iowrite32(dgcsreg, ca91cx42_bridge->base + DGCS); val = get_tbl(); - writel(dgcsreg | 0x8000000F, vmechip_baseaddr + DGCS); - return (val); + iowrite32(dgcsreg | 0x8000000F, ca91cx42_bridge->base + DGCS); + return val; } -//----------------------------------------------------------------------------- -// Function : uni_setup_dma -// Description: -//----------------------------------------------------------------------------- -TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) +TDMA_Cmd_Packet *ca91cx42_setup_dma(vmeDmaPacket_t * vmeDma) { vmeDmaPacket_t *vmeCur; int maxPerPage; @@ -1439,9 +1553,9 @@ TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1; startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0); if (startLL == 0) { - return (startLL); + return startLL; } - // First allocate pages for descriptors and create linked list + /* First allocate pages for descriptors and create linked list */ vmeCur = vmeDma; currentLL = startLL; currentLLcount = 0; @@ -1461,57 +1575,53 @@ TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) vmeCur = vmeCur->pNextPacket; } - // Next fill in information for each descriptor + /* Next fill in information for each descriptor */ vmeCur = vmeDma; currentLL = startLL; while (vmeCur != 0) { if (vmeCur->srcBus == VME_DMA_VME) { - writel(vmeCur->srcAddr, ¤tLL->dva); - writel(vmeCur->dstAddr, ¤tLL->dlv); + iowrite32(vmeCur->srcAddr, ¤tLL->dva); + iowrite32(vmeCur->dstAddr, ¤tLL->dlv); } else { - writel(vmeCur->srcAddr, ¤tLL->dlv); - writel(vmeCur->dstAddr, ¤tLL->dva); + iowrite32(vmeCur->srcAddr, ¤tLL->dlv); + iowrite32(vmeCur->dstAddr, ¤tLL->dva); } uniSetupDctlReg(vmeCur, &dctlreg); - writel(dctlreg, ¤tLL->dctl); - writel(vmeCur->byteCount, ¤tLL->dtbc); + iowrite32(dctlreg, ¤tLL->dctl); + iowrite32(vmeCur->byteCount, ¤tLL->dtbc); currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; vmeCur = vmeCur->pNextPacket; } - // Convert Links to PCI addresses. + /* Convert Links to PCI addresses. */ currentLL = startLL; while (currentLL != 0) { nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp; if (nextLL == 0) { - writel(1, ¤tLL->dcpp); + iowrite32(1, ¤tLL->dcpp); } else { - writel((unsigned int)virt_to_bus(nextLL), + iowrite32((unsigned int)virt_to_bus(nextLL), ¤tLL->dcpp); } currentLL = nextLL; } - // Return pointer to descriptors list - return (startLL); + /* Return pointer to descriptors list */ + return startLL; } -//----------------------------------------------------------------------------- -// Function : uni_free_dma -// Description: -//----------------------------------------------------------------------------- -int uni_free_dma(TDMA_Cmd_Packet * startLL) +int ca91cx42_free_dma(TDMA_Cmd_Packet *startLL) { TDMA_Cmd_Packet *currentLL; TDMA_Cmd_Packet *prevLL; TDMA_Cmd_Packet *nextLL; unsigned int dcppreg; - // Convert Links to virtual addresses. + /* Convert Links to virtual addresses. */ currentLL = startLL; while (currentLL != 0) { - dcppreg = readl(¤tLL->dcpp); + dcppreg = ioread32(¤tLL->dcpp); dcppreg &= ~6; if (dcppreg & 1) { currentLL->dcpp = 0; @@ -1521,7 +1631,7 @@ int uni_free_dma(TDMA_Cmd_Packet * startLL) currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; } - // Free all pages associated with the descriptors. + /* Free all pages associated with the descriptors. */ currentLL = startLL; prevLL = currentLL; while (currentLL != 0) { @@ -1533,15 +1643,11 @@ int uni_free_dma(TDMA_Cmd_Packet * startLL) currentLL = nextLL; } - // Return pointer to descriptors list - return (0); + /* Return pointer to descriptors list */ + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_do_dma -// Description: -//----------------------------------------------------------------------------- -int uni_do_dma(vmeDmaPacket_t * vmeDma) +int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma) { unsigned int dgcsreg = 0; unsigned int dctlreg = 0; @@ -1550,55 +1656,55 @@ int uni_do_dma(vmeDmaPacket_t * vmeDma) vmeDmaPacket_t *curDma; TDMA_Cmd_Packet *dmaLL; - // Sanity check the VME chain. + /* Sanity check the VME chain. */ channel = vmeDma->channel_number; if (channel > 0) { - return (-EINVAL); + return -EINVAL; } curDma = vmeDma; while (curDma != 0) { if (curDma->byteCount == 0) { - return (-EINVAL); + return -EINVAL; } if (curDma->byteCount >= 0x1000000) { - return (-EINVAL); + return -EINVAL; } if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) { - return (-EINVAL); + return -EINVAL; } switch (curDma->srcBus) { case VME_DMA_PCI: if (curDma->dstBus != VME_DMA_VME) { - return (-EINVAL); + return -EINVAL; } break; case VME_DMA_VME: if (curDma->dstBus != VME_DMA_PCI) { - return (-EINVAL); + return -EINVAL; } break; default: - return (-EINVAL); + return -EINVAL; break; } if (uniSetupDctlReg(curDma, &dctlreg) < 0) { - return (-EINVAL); + return -EINVAL; } curDma = curDma->pNextPacket; - if (curDma == vmeDma) { // Endless Loop! - return (-EINVAL); + if (curDma == vmeDma) { /* Endless Loop! */ + return -EINVAL; } } - // calculate control register + /* calculate control register */ if (vmeDma->pNextPacket != 0) { dgcsreg = 0x8000000; } else { dgcsreg = 0; } - for (x = 0; x < 8; x++) { // vme block size + for (x = 0; x < 8; x++) { /* vme block size */ if ((256 << x) >= vmeDma->maxVmeBlockSize) { break; } @@ -1608,7 +1714,7 @@ int uni_do_dma(vmeDmaPacket_t * vmeDma) dgcsreg |= (x << 20); if (vmeDma->vmeBackOffTimer) { - for (x = 1; x < 8; x++) { // vme timer + for (x = 1; x < 8; x++) { /* vme timer */ if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) { break; } @@ -1617,195 +1723,211 @@ int uni_do_dma(vmeDmaPacket_t * vmeDma) x = 7; dgcsreg |= (x << 16); } - // Setup the dma chain - dmaLL = uni_setup_dma(vmeDma); + /*` Setup the dma chain */ + dmaLL = ca91cx42_setup_dma(vmeDma); - // Start the DMA + /* Start the DMA */ if (dgcsreg & 0x8000000) { vmeDma->vmeDmaStartTick = - uni_start_dma(channel, dgcsreg, + ca91cx42_start_dma(channel, dgcsreg, (TDMA_Cmd_Packet *) virt_to_phys(dmaLL)); } else { vmeDma->vmeDmaStartTick = - uni_start_dma(channel, dgcsreg, dmaLL); + ca91cx42_start_dma(channel, dgcsreg, dmaLL); } - wait_event_interruptible(dma_queue[0], - readl(vmechip_baseaddr + DGCS) & 0x800); + wait_event_interruptible(dma_queue, + ioread32(ca91cx42_bridge->base + DGCS) & 0x800); - val = readl(vmechip_baseaddr + DGCS); - writel(val | 0xF00, vmechip_baseaddr + DGCS); + val = ioread32(ca91cx42_bridge->base + DGCS); + iowrite32(val | 0xF00, ca91cx42_bridge->base + DGCS); vmeDma->vmeDmaStatus = 0; - vmeDma->vmeDmaStopTick = uni_dma_irq_time; - if (vmeDma->vmeDmaStopTick < vmeDma->vmeDmaStartTick) { - vmeDma->vmeDmaElapsedTime = - (0xFFFFFFFF - vmeDma->vmeDmaStartTick) + - vmeDma->vmeDmaStopTick; - } else { - vmeDma->vmeDmaElapsedTime = - vmeDma->vmeDmaStopTick - vmeDma->vmeDmaStartTick; - } - vmeDma->vmeDmaElapsedTime -= vmechip_irq_overhead_ticks; - vmeDma->vmeDmaElapsedTime /= (tb_speed / 1000000); if (!(val & 0x00000800)) { vmeDma->vmeDmaStatus = val & 0x700; - printk(KERN_ERR - "ca91c042: DMA Error in DMA_uni_irqhandler DGCS=%08X\n", - val); - val = readl(vmechip_baseaddr + DCPP); + printk(KERN_ERR "ca91c042: DMA Error in ca91cx42_DMA_irqhandler" + " DGCS=%08X\n", val); + val = ioread32(ca91cx42_bridge->base + DCPP); printk(KERN_ERR "ca91c042: DCPP=%08X\n", val); - val = readl(vmechip_baseaddr + DCTL); + val = ioread32(ca91cx42_bridge->base + DCTL); printk(KERN_ERR "ca91c042: DCTL=%08X\n", val); - val = readl(vmechip_baseaddr + DTBC); + val = ioread32(ca91cx42_bridge->base + DTBC); printk(KERN_ERR "ca91c042: DTBC=%08X\n", val); - val = readl(vmechip_baseaddr + DLA); + val = ioread32(ca91cx42_bridge->base + DLA); printk(KERN_ERR "ca91c042: DLA=%08X\n", val); - val = readl(vmechip_baseaddr + DVA); + val = ioread32(ca91cx42_bridge->base + DVA); printk(KERN_ERR "ca91c042: DVA=%08X\n", val); } - // Free the dma chain - uni_free_dma(dmaLL); + /* Free the dma chain */ + ca91cx42_free_dma(dmaLL); - return (0); + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_shutdown -// Description: Put VME bridge in quiescent state. -//----------------------------------------------------------------------------- -void uni_shutdown(void) +int ca91cx42_lm_set(vmeLmCfg_t *vmeLm) { - writel(0, vmechip_baseaddr + LINT_EN); // Turn off Ints - - // Turn off the windows - writel(0x00800000, vmechip_baseaddr + LSI0_CTL); - writel(0x00800000, vmechip_baseaddr + LSI1_CTL); - writel(0x00800000, vmechip_baseaddr + LSI2_CTL); - writel(0x00800000, vmechip_baseaddr + LSI3_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI0_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI1_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI2_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI3_CTL); - if (vmechip_revision >= 2) { - writel(0x00800000, vmechip_baseaddr + LSI4_CTL); - writel(0x00800000, vmechip_baseaddr + LSI5_CTL); - writel(0x00800000, vmechip_baseaddr + LSI6_CTL); - writel(0x00800000, vmechip_baseaddr + LSI7_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI4_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI5_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI6_CTL); - writel(0x00F00000, vmechip_baseaddr + VSI7_CTL); + int temp_ctl = 0; + + if (vmeLm->addrU) + return -EINVAL; + + switch (vmeLm->addrSpace) { + case VME_A64: + case VME_USER3: + case VME_USER4: + return -EINVAL; + case VME_A16: + temp_ctl |= 0x00000; + break; + case VME_A24: + temp_ctl |= 0x10000; + break; + case VME_A32: + temp_ctl |= 0x20000; + break; + case VME_CRCSR: + temp_ctl |= 0x50000; + break; + case VME_USER1: + temp_ctl |= 0x60000; + break; + case VME_USER2: + temp_ctl |= 0x70000; + break; } + + /* Disable while we are mucking around */ + iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL); + + iowrite32(vmeLm->addr, ca91cx42_bridge->base + LM_BS); + + /* Setup CTL register. */ + if (vmeLm->userAccessType & VME_SUPER) + temp_ctl |= 0x00200000; + if (vmeLm->userAccessType & VME_USER) + temp_ctl |= 0x00100000; + if (vmeLm->dataAccessType & VME_PROG) + temp_ctl |= 0x00800000; + if (vmeLm->dataAccessType & VME_DATA) + temp_ctl |= 0x00400000; + + + /* Write ctl reg and enable */ + iowrite32(0x80000000 | temp_ctl, ca91cx42_bridge->base + LM_CTL); + temp_ctl = ioread32(ca91cx42_bridge->base + LM_CTL); + + return 0; } -//----------------------------------------------------------------------------- -// Function : uni_init() -// Description: -//----------------------------------------------------------------------------- -int uni_init(void) +int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm) { - int result; + unsigned long flags; unsigned int tmp; - unsigned int crcsr_addr; - unsigned int irqOverHeadStart; - int overHeadTicks; - - uni_shutdown(); - - // Write to Misc Register - // Set VME Bus Time-out - // Arbitration Mode - // DTACK Enable - tmp = readl(vmechip_baseaddr + MISC_CTL) & 0x0832BFFF; - tmp |= 0x76040000; - writel(tmp, vmechip_baseaddr + MISC_CTL); - if (tmp & 0x20000) { - vme_syscon = 1; - } else { - vme_syscon = 0; - } - - // Clear DMA status log - writel(0x00000F00, vmechip_baseaddr + DGCS); - // Clear and enable error log - writel(0x00800000, vmechip_baseaddr + L_CMDERR); - // Turn off location monitor - writel(0x00000000, vmechip_baseaddr + LM_CTL); - - // Initialize crcsr map - if (vme_slotnum != -1) { - writel(vme_slotnum << 27, vmechip_baseaddr + VCSR_BS); - } - crcsr_addr = readl(vmechip_baseaddr + VCSR_BS) >> 8; - writel((unsigned int)vmechip_interboard_datap - crcsr_addr, - vmechip_baseaddr + VCSR_TO); - if (vme_slotnum != -1) { - writel(0x80000000, vmechip_baseaddr + VCSR_CTL); - } - // Turn off interrupts - writel(0x00000000, vmechip_baseaddr + LINT_EN); // Disable interrupts in the Universe first - writel(0x00FFFFFF, vmechip_baseaddr + LINT_STAT); // Clear Any Pending Interrupts - writel(0x00000000, vmechip_baseaddr + VINT_EN); // Disable interrupts in the Universe first - - result = - request_irq(vmechip_irq, uni_irqhandler, IRQF_SHARED | IRQF_DISABLED, - "VMEBus (ca91c042)", vmechip_baseaddr); - if (result) { - printk(KERN_ERR - "ca91c042: can't get assigned pci irq vector %02X\n", - vmechip_irq); - return (0); - } else { - writel(0x0000, vmechip_baseaddr + LINT_MAP0); // Map all ints to 0 - writel(0x0000, vmechip_baseaddr + LINT_MAP1); // Map all ints to 0 - writel(0x0000, vmechip_baseaddr + LINT_MAP2); // Map all ints to 0 + + spin_lock_irqsave(&lm_lock, flags); + spin_unlock_irqrestore(&lm_lock, flags); + if (tmp == 0) { + if (vmeLm->lmWait < 10) + vmeLm->lmWait = 10; + interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); } + iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL); - // Enable DMA, mailbox, VIRQ & LM Interrupts - if (vme_syscon) - tmp = 0x00FF07FE; - else - tmp = 0x00FF0700; - writel(tmp, vmechip_baseaddr + LINT_EN); + return 0; +} - // Do a quick sanity test of the bridge - if (readl(vmechip_baseaddr + LINT_EN) != tmp) { - return (0); - } - if (readl(vmechip_baseaddr + PCI_CLASS_REVISION) != 0x06800002) { - return (0); - } - for (tmp = 1; tmp < 0x80000000; tmp = tmp << 1) { - writel(tmp, vmechip_baseaddr + SCYC_EN); - writel(~tmp, vmechip_baseaddr + SCYC_CMP); - if (readl(vmechip_baseaddr + SCYC_EN) != tmp) { - return (0); - } - if (readl(vmechip_baseaddr + SCYC_CMP) != ~tmp) { - return (0); - } - } - // do a mail box interrupt to calibrate the interrupt overhead. - irqOverHeadStart = get_tbl(); - writel(0, vmechip_baseaddr + MBOX1); - for (tmp = 0; tmp < 10; tmp++) { - } +int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb) +{ + int temp_ctl = 0; + int vbto = 0; - irqOverHeadStart = get_tbl(); - writel(0, vmechip_baseaddr + MBOX1); - for (tmp = 0; tmp < 10; tmp++) { - } + temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL); + temp_ctl &= 0x00FFFFFF; - overHeadTicks = uni_irq_time - irqOverHeadStart; - if (overHeadTicks > 0) { - vmechip_irq_overhead_ticks = overHeadTicks; + if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) { + vbto = 7; + } else if (vmeArb->globalTimeoutTimer > 1024) { + return -EINVAL; + } else if (vmeArb->globalTimeoutTimer == 0) { + vbto = 0; } else { - vmechip_irq_overhead_ticks = 1; + vbto = 1; + while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer) + vbto += 1; } - return (1); + temp_ctl |= (vbto << 28); + + if (vmeArb->arbiterMode == VME_PRIORITY_MODE) + temp_ctl |= 1 << 26; + + if (vmeArb->arbiterTimeoutFlag) + temp_ctl |= 2 << 24; + + iowrite32(temp_ctl, ca91cx42_bridge->base + MISC_CTL); + return 0; +} + +int ca91cx42_get_arbiter(vmeArbiterCfg_t *vmeArb) +{ + int temp_ctl = 0; + int vbto = 0; + + temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL); + + vbto = (temp_ctl >> 28) & 0xF; + if (vbto != 0) + vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1))); + + if (temp_ctl & (1 << 26)) + vmeArb->arbiterMode = VME_PRIORITY_MODE; + else + vmeArb->arbiterMode = VME_R_ROBIN_MODE; + + if (temp_ctl & (3 << 24)) + vmeArb->arbiterTimeoutFlag = 1; + + return 0; +} + +int ca91cx42_set_requestor(vmeRequesterCfg_t *vmeReq) +{ + int temp_ctl = 0; + + temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL); + temp_ctl &= 0xFF0FFFFF; + + if (vmeReq->releaseMode == 1) + temp_ctl |= (1 << 20); + + if (vmeReq->fairMode == 1) + temp_ctl |= (1 << 21); + + temp_ctl |= (vmeReq->requestLevel << 22); + + iowrite32(temp_ctl, ca91cx42_bridge->base + MAST_CTL); + return 0; +} + +int ca91cx42_get_requestor(vmeRequesterCfg_t *vmeReq) +{ + int temp_ctl = 0; + + temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL); + + if (temp_ctl & (1 << 20)) + vmeReq->releaseMode = 1; + + if (temp_ctl & (1 << 21)) + vmeReq->fairMode = 1; + + vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22; + + return 0; } + + +#endif diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h index 430174d..95a42c2 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.h +++ b/drivers/staging/vme/bridges/vme_ca91cx42.h @@ -4,9 +4,12 @@ * Support for the Tundra Universe 1 and Universe II VME bridge chips * * Author: Tom Armistead - * Updated and maintained by Ajit Prem + * Updated by Ajit Prem * Copyright 2004 Motorola Inc. * + * Further updated by Martyn Welch + * Copyright 2009 GE Fanuc Intelligent Platforms Embedded Systems, Inc. + * * Derived from ca91c042.h by Michael Wyrick * * This program is free software; you can redistribute it and/or modify it @@ -15,180 +18,102 @@ * option) any later version. */ -#ifndef _ca91c042_h -#define _ca91c042_h +#ifndef _CA91CX42_H +#define _CA91CX42_H #ifndef PCI_VENDOR_ID_TUNDRA #define PCI_VENDOR_ID_TUNDRA 0x10e3 #endif -#ifndef PCI_DEVICE_ID_TUNDRA_CA91C042 -#define PCI_DEVICE_ID_TUNDRA_CA91C042 0x0000 +#ifndef PCI_DEVICE_ID_TUNDRA_CA91C142 +#define PCI_DEVICE_ID_TUNDRA_CA91C142 0x0000 #endif -//----------------------------------------------------------------------------- -// Public Functions -//----------------------------------------------------------------------------- -// This is the typedef for a VmeIrqHandler -typedef void (*TirqHandler) (int vmeirq, int vector, void *dev_id, - struct pt_regs * regs); -// This is the typedef for a DMA Transfer Callback function -typedef void (*TDMAcallback) (int status); - -// Returns the PCI baseaddress of the Universe chip -char *Universe_BaseAddr(void); -// Returns the PCI IRQ That the universe is using -int Universe_IRQ(void); - -char *mapvme(unsigned int pci, unsigned int vme, unsigned int size, - int image, int ctl); -void unmapvme(char *ptr, int image); - -// Interrupt Stuff -void enable_vmeirq(unsigned int irq); -void disable_vmeirq(unsigned int irq); -int request_vmeirq(unsigned int irq, TirqHandler); -void free_vmeirq(unsigned int irq); - -// DMA Stuff - -int VME_Bus_Error(void); -int uni_procinfo(char *); - -#define IRQ_VOWN 0x0001 -#define IRQ_VIRQ1 0x0002 -#define IRQ_VIRQ2 0x0004 -#define IRQ_VIRQ3 0x0008 -#define IRQ_VIRQ4 0x0010 -#define IRQ_VIRQ5 0x0020 -#define IRQ_VIRQ6 0x0040 -#define IRQ_VIRQ7 0x0080 -#define IRQ_DMA 0x0100 -#define IRQ_LERR 0x0200 -#define IRQ_VERR 0x0400 -#define IRQ_res 0x0800 -#define IRQ_IACK 0x1000 -#define IRQ_SWINT 0x2000 -#define IRQ_SYSFAIL 0x4000 -#define IRQ_ACFAIL 0x8000 - -// See Page 2-77 in the Universe User Manual -typedef struct { - unsigned int dctl; // DMA Control - unsigned int dtbc; // Transfer Byte Count - unsigned int dlv; // PCI Address - unsigned int res1; // Reserved - unsigned int dva; // Vme Address - unsigned int res2; // Reserved - unsigned int dcpp; // Pointer to Numed Cmd Packet with rPN - unsigned int res3; // Reserved -} TDMA_Cmd_Packet; - /* - * Below here is normaly not used by a user module + * Define the number of each that the CA91C142 supports. */ -#define DMATIMEOUT 2*HZ; - -// Define for the Universe -#define SEEK_SET 0 -#define SEEK_CUR 1 - -#define CONFIG_REG_SPACE 0xA0000000 +#define CA91C142_MAX_MASTER 8 /* Max Master Windows */ +#define CA91C142_MAX_SLAVE 8 /* Max Slave Windows */ +#define CA91C142_MAX_DMA 1 /* Max DMA Controllers */ +#define CA91C142_MAX_MAILBOX 4 /* Max Mail Box registers */ + +/* See Page 2-77 in the Universe User Manual */ +struct ca91cx42_dma_descriptor { + unsigned int dctl; /* DMA Control */ + unsigned int dtbc; /* Transfer Byte Count */ + unsigned int dlv; /* PCI Address */ + unsigned int res1; /* Reserved */ + unsigned int dva; /* Vme Address */ + unsigned int res2; /* Reserved */ + unsigned int dcpp; /* Pointer to Numed Cmd Packet with rPN */ + unsigned int res3; /* Reserved */ +}; + +struct ca91cx42_dma_entry { + struct ca91cx42_dma_descriptor descriptor; + struct list_head list; +}; /* Universe Register Offsets */ /* general PCI configuration registers */ -#define UNIV_PCI_ID 0x000 -#define UNIV_PCI_CSR 0x004 -#define UNIV_PCI_CLASS 0x008 -#define UNIV_BM_PCI_CLASS_BASE 0xFF000000 -#define UNIV_OF_PCI_CLASS_BASE 24 -#define UNIV_BM_PCI_CLASS_SUB 0x00FF0000 -#define UNIV_OF_PCI_CLASS_SUB 16 -#define UNIV_BM_PCI_CLASS_PROG 0x0000FF00 -#define UNIV_OF_PCI_CLASS_PROG 8 -#define UNIV_BM_PCI_CLASS_RID 0x000000FF -#define UNIV_OF_PCI_CLASS_RID 0 - -#define UNIV_OF_PCI_CLASS_RID_UNIVERSE_I 0 -#define UNIV_OF_PCI_CLASS_RID_UNIVERSE_II 1 - -#define UNIV_PCI_MISC0 0x00C -#define UNIV_BM_PCI_MISC0_BISTC 0x80000000 -#define UNIV_BM_PCI_MISC0_SBIST 0x60000000 -#define UNIV_BM_PCI_MISC0_CCODE 0x0F000000 -#define UNIV_BM_PCI_MISC0_MFUNCT 0x00800000 -#define UNIV_BM_PCI_MISC0_LAYOUT 0x007F0000 -#define UNIV_BM_PCI_MISC0_LTIMER 0x0000FF00 -#define UNIV_OF_PCI_MISC0_LTIMER 8 -#define UNIV_PCI_BS 0x010 -#define UNIV_PCI_MISC1 0x03C - -#define UNIV_BM_LSI_CTL_EN 0x80000000 -#define UNIV_BM_LSI_CTL_PWEN 0x40000000 -#define UNIV_BM_LSI_CTL_VDW 0x00C00000 -#define UNIV_OF_LSI_CTL_VDW 22 -#define UNIV_BM_LSI_CTL_VAS 0x00070000 -#define UNIV_OF_LSI_CTL_VAS 16 -#define UNIV_BM_LSI_CTL_PGM 0x0000C000 -#define UNIV_OF_LSI_CTL_PGM 14 -#define UNIV_BM_LSI_CTL_SUPER 0x00003000 -#define UNIV_OF_LSI_CTL_SUPER 12 -#define UNIV_BM_LSI_CTL_VCT 0x00000100 -#define UNIV_BM_LSI_CTL_LAS 0x00000003 -#define UNIV_OF_LSI_CTL_LAS 0 -#define UNIV_BM_LSI_CTL_RESERVED (~ (UNIV_BM_LSI_CTL_EN | UNIV_BM_LSI_CTL_PWEN | UNIV_BM_LSI_CTL_VDW | UNIV_BM_LSI_CTL_VAS | UNIV_BM_LSI_CTL_PGM | UNIV_BM_LSI_CTL_SUPER | UNIV_BM_LSI_CTL_VCT | UNIV_BM_LSI_CTL_LAS)) - -#define PCI_SIZE_8 0x0001 -#define PCI_SIZE_16 0x0002 -#define PCI_SIZE_32 0x0003 - -#define IOCTL_SET_CTL 0xF001 -#define IOCTL_SET_BS 0xF002 -#define IOCTL_SET_BD 0xF003 -#define IOCTL_SET_TO 0xF004 -#define IOCTL_PCI_SIZE 0xF005 -#define IOCTL_SET_MODE 0xF006 -#define IOCTL_SET_WINT 0xF007 // Wait for interrupt before read - -#define LSI0_CTL 0x0100 -#define LSI0_BS 0x0104 -#define LSI0_BD 0x0108 -#define LSI0_TO 0x010C - -#define LSI1_CTL 0x0114 -#define LSI1_BS 0x0118 -#define LSI1_BD 0x011C -#define LSI1_TO 0x0120 - -#define LSI2_CTL 0x0128 -#define LSI2_BS 0x012C -#define LSI2_BD 0x0130 -#define LSI2_TO 0x0134 - -#define LSI3_CTL 0x013C -#define LSI3_BS 0x0140 -#define LSI3_BD 0x0144 -#define LSI3_TO 0x0148 - -#define LSI4_CTL 0x01A0 -#define LSI4_BS 0x01A4 -#define LSI4_BD 0x01A8 -#define LSI4_TO 0x01AC - -#define LSI5_CTL 0x01B4 -#define LSI5_BS 0x01B8 -#define LSI5_BD 0x01BC -#define LSI5_TO 0x01C0 - -#define LSI6_CTL 0x01C8 -#define LSI6_BS 0x01CC -#define LSI6_BD 0x01D0 -#define LSI6_TO 0x01D4 - -#define LSI7_CTL 0x01DC -#define LSI7_BS 0x01E0 -#define LSI7_BD 0x01E4 -#define LSI7_TO 0x01E8 +#define CA91CX42_PCI_ID 0x000 +#define CA91CX42_PCI_CSR 0x004 +#define CA91CX42_PCI_CLASS 0x008 +#define CA91CX42_PCI_MISC0 0x00C +#define CA91CX42_PCI_BS 0x010 +#define CA91CX42_PCI_MISC1 0x03C + +#define LSI0_CTL 0x0100 +#define LSI0_BS 0x0104 +#define LSI0_BD 0x0108 +#define LSI0_TO 0x010C + +#define LSI1_CTL 0x0114 +#define LSI1_BS 0x0118 +#define LSI1_BD 0x011C +#define LSI1_TO 0x0120 + +#define LSI2_CTL 0x0128 +#define LSI2_BS 0x012C +#define LSI2_BD 0x0130 +#define LSI2_TO 0x0134 + +#define LSI3_CTL 0x013C +#define LSI3_BS 0x0140 +#define LSI3_BD 0x0144 +#define LSI3_TO 0x0148 + +#define LSI4_CTL 0x01A0 +#define LSI4_BS 0x01A4 +#define LSI4_BD 0x01A8 +#define LSI4_TO 0x01AC + +#define LSI5_CTL 0x01B4 +#define LSI5_BS 0x01B8 +#define LSI5_BD 0x01BC +#define LSI5_TO 0x01C0 + +#define LSI6_CTL 0x01C8 +#define LSI6_BS 0x01CC +#define LSI6_BD 0x01D0 +#define LSI6_TO 0x01D4 + +#define LSI7_CTL 0x01DC +#define LSI7_BS 0x01E0 +#define LSI7_BD 0x01E4 +#define LSI7_TO 0x01E8 + +static const int CA91CX42_LSI_CTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, + LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL }; + +static const int CA91CX42_LSI_BS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, + LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS }; + +static const int CA91CX42_LSI_BD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, + LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD }; + +static const int CA91CX42_LSI_TO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, + LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO }; #define SCYC_CTL 0x0170 #define SCYC_ADDR 0x0174 @@ -196,24 +121,7 @@ typedef struct { #define SCYC_CMP 0x017C #define SCYC_SWP 0x0180 #define LMISC 0x0184 -#define UNIV_BM_LMISC_CRT 0xF0000000 -#define UNIV_OF_LMISC_CRT 28 -#define UNIV_BM_LMISC_CWT 0x0F000000 -#define UNIV_OF_LMISC_CWT 24 #define SLSI 0x0188 -#define UNIV_BM_SLSI_EN 0x80000000 -#define UNIV_BM_SLSI_PWEN 0x40000000 -#define UNIV_BM_SLSI_VDW 0x00F00000 -#define UNIV_OF_SLSI_VDW 20 -#define UNIV_BM_SLSI_PGM 0x0000F000 -#define UNIV_OF_SLSI_PGM 12 -#define UNIV_BM_SLSI_SUPER 0x00000F00 -#define UNIV_OF_SLSI_SUPER 8 -#define UNIV_BM_SLSI_BS 0x000000F6 -#define UNIV_OF_SLSI_BS 2 -#define UNIV_BM_SLSI_LAS 0x00000003 -#define UNIV_OF_SLSI_LAS 0 -#define UNIV_BM_SLSI_RESERVED 0x3F0F0000 #define L_CMDERR 0x018C #define LAERR 0x0190 @@ -225,154 +133,109 @@ typedef struct { #define DGCS 0x0220 #define D_LLUE 0x0224 -#define LINT_EN 0x0300 -#define UNIV_BM_LINT_ACFAIL 0x00008000 -#define UNIV_BM_LINT_SYSFAIL 0x00004000 -#define UNIV_BM_LINT_SW_INT 0x00002000 -#define UNIV_BM_LINT_SW_IACK 0x00001000 -#define UNIV_BM_LINT_VERR 0x00000400 -#define UNIV_BM_LINT_LERR 0x00000200 -#define UNIV_BM_LINT_DMA 0x00000100 -#define UNIV_BM_LINT_LM 0x00F00000 -#define UNIV_BM_LINT_MBOX 0x000F0000 -#define UNIV_BM_LINT_VIRQ 0x000000FE -#define UNIV_BM_LINT_VIRQ7 0x00000080 -#define UNIV_BM_LINT_VIRQ6 0x00000040 -#define UNIV_BM_LINT_VIRQ5 0x00000020 -#define UNIV_BM_LINT_VIRQ4 0x00000010 -#define UNIV_BM_LINT_VIRQ3 0x00000008 -#define UNIV_BM_LINT_VIRQ2 0x00000004 -#define UNIV_BM_LINT_VIRQ1 0x00000002 -#define UNIV_BM_LINT_VOWN 0x00000001 -#define LINT_STAT 0x0304 -#define LINT_MAP0 0x0308 -#define LINT_MAP1 0x030C -#define VINT_EN 0x0310 -#define VINT_STAT 0x0314 -#define VINT_MAP0 0x0318 -#define VINT_MAP1 0x031C -#define STATID 0x0320 -#define V1_STATID 0x0324 -#define V2_STATID 0x0328 -#define V3_STATID 0x032C -#define V4_STATID 0x0330 -#define V5_STATID 0x0334 -#define V6_STATID 0x0338 -#define V7_STATID 0x033C -#define LINT_MAP2 0x0340 -#define VINT_MAP2 0x0344 - -#define MBOX0 0x0348 -#define MBOX1 0x034C -#define MBOX2 0x0350 -#define MBOX3 0x0354 -#define SEMA0 0x0358 -#define SEMA1 0x035C - -#define MAST_CTL 0x0400 -#define UNIV_BM_MAST_CTL_MAXRTRY 0xF0000000 -#define UNIV_OF_MAST_CTL_MAXRTRY 28 -#define UNIV_BM_MAST_CTL_PWON 0x0F000000 -#define UNIV_OF_MAST_CTL_PWON 24 -#define UNIV_BM_MAST_CTL_VRL 0x00C00000 -#define UNIV_OF_MAST_CTL_VRL 22 -#define UNIV_BM_MAST_CTL_VRM 0x00200000 -#define UNIV_BM_MAST_CTL_VREL 0x00100000 -#define UNIV_BM_MAST_CTL_VOWN 0x00080000 -#define UNIV_BM_MAST_CTL_VOWN_ACK 0x00040000 -#define UNIV_BM_MAST_CTL_PABS 0x00001000 -#define UNIV_BM_MAST_CTL_BUS_NO 0x0000000F -#define UNIV_OF_MAST_CTL_BUS_NO 0 - -#define MISC_CTL 0x0404 -#define UNIV_BM_MISC_CTL_VBTO 0xF0000000 -#define UNIV_OF_MISC_CTL_VBTO 28 -#define UNIV_BM_MISC_CTL_VARB 0x04000000 -#define UNIV_BM_MISC_CTL_VARBTO 0x03000000 -#define UNIV_OF_MISC_CTL_VARBTO 24 -#define UNIV_BM_MISC_CTL_SW_LRST 0x00800000 -#define UNIV_BM_MISC_CTL_SW_SRST 0x00400000 -#define UNIV_BM_MISC_CTL_BI 0x00100000 -#define UNIV_BM_MISC_CTL_ENGBI 0x00080000 -#define UNIV_BM_MISC_CTL_RESCIND 0x00040000 -#define UNIV_BM_MISC_CTL_SYSCON 0x00020000 -#define UNIV_BM_MISC_CTL_V64AUTO 0x00010000 -#define UNIV_BM_MISC_CTL_RESERVED 0x0820FFFF - -#define MISC_STAT 0x0408 -#define UNIV_BM_MISC_STAT_ENDIAN 0x80000000 -#define UNIV_BM_MISC_STAT_LCLSIZE 0x40000000 -#define UNIV_BM_MISC_STAT_DY4AUTO 0x08000000 -#define UNIV_BM_MISC_STAT_MYBBSY 0x00200000 -#define UNIV_BM_MISC_STAT_DY4DONE 0x00080000 -#define UNIV_BM_MISC_STAT_TXFE 0x00040000 -#define UNIV_BM_MISC_STAT_RXFE 0x00020000 -#define UNIV_BM_MISC_STAT_DY4AUTOID 0x0000FF00 -#define UNIV_OF_MISC_STAT_DY4AUTOID 8 - -#define USER_AM 0x040C - -#define VSI0_CTL 0x0F00 -#define VSI0_BS 0x0F04 -#define VSI0_BD 0x0F08 -#define VSI0_TO 0x0F0C - -#define VSI1_CTL 0x0F14 -#define VSI1_BS 0x0F18 -#define VSI1_BD 0x0F1C -#define VSI1_TO 0x0F20 - -#define VSI2_CTL 0x0F28 -#define VSI2_BS 0x0F2C -#define VSI2_BD 0x0F30 -#define VSI2_TO 0x0F34 - -#define VSI3_CTL 0x0F3C -#define VSI3_BS 0x0F40 -#define VSI3_BD 0x0F44 -#define VSI3_TO 0x0F48 - -#define LM_CTL 0x0F64 -#define LM_BS 0x0F68 - -#define VRAI_CTL 0x0F70 -#define UNIV_BM_VRAI_CTL_EN 0x80000000 -#define UNIV_BM_VRAI_CTL_PGM 0x00C00000 -#define UNIV_OF_VRAI_CTL_PGM 22 -#define UNIV_BM_VRAI_CTL_SUPER 0x00300000 -#define UNIV_OF_VRAI_CTL_SUPER 20 -#define UNIV_BM_VRAI_CTL_VAS 0x00030000 -#define UNIV_OF_VRAI_CTL_VAS 16 - -#define VRAI_BS 0x0F74 -#define VCSR_CTL 0x0F80 -#define VCSR_TO 0x0F84 -#define V_AMERR 0x0F88 +#define LINT_EN 0x0300 +#define LINT_STAT 0x0304 +#define LINT_MAP0 0x0308 +#define LINT_MAP1 0x030C +#define VINT_EN 0x0310 +#define VINT_STAT 0x0314 +#define VINT_MAP0 0x0318 +#define VINT_MAP1 0x031C +#define STATID 0x0320 + +#define V1_STATID 0x0324 +#define V2_STATID 0x0328 +#define V3_STATID 0x032C +#define V4_STATID 0x0330 +#define V5_STATID 0x0334 +#define V6_STATID 0x0338 +#define V7_STATID 0x033C + +static const int CA91CX42_V_STATID[8] = { 0, V1_STATID, V2_STATID, V3_STATID, + V4_STATID, V5_STATID, V6_STATID, + V7_STATID }; + +#define LINT_MAP2 0x0340 +#define VINT_MAP2 0x0344 + +#define MBOX0 0x0348 +#define MBOX1 0x034C +#define MBOX2 0x0350 +#define MBOX3 0x0354 +#define SEMA0 0x0358 +#define SEMA1 0x035C + +#define MAST_CTL 0x0400 +#define MISC_CTL 0x0404 +#define MISC_STAT 0x0408 +#define USER_AM 0x040C + +#define VSI0_CTL 0x0F00 +#define VSI0_BS 0x0F04 +#define VSI0_BD 0x0F08 +#define VSI0_TO 0x0F0C + +#define VSI1_CTL 0x0F14 +#define VSI1_BS 0x0F18 +#define VSI1_BD 0x0F1C +#define VSI1_TO 0x0F20 + +#define VSI2_CTL 0x0F28 +#define VSI2_BS 0x0F2C +#define VSI2_BD 0x0F30 +#define VSI2_TO 0x0F34 + +#define VSI3_CTL 0x0F3C +#define VSI3_BS 0x0F40 +#define VSI3_BD 0x0F44 +#define VSI3_TO 0x0F48 + +#define LM_CTL 0x0F64 +#define LM_BS 0x0F68 + +#define VRAI_CTL 0x0F70 + +#define VRAI_BS 0x0F74 +#define VCSR_CTL 0x0F80 +#define VCSR_TO 0x0F84 +#define V_AMERR 0x0F88 #define VAERR 0x0F8C -#define VSI4_CTL 0x0F90 -#define VSI4_BS 0x0F94 -#define VSI4_BD 0x0F98 -#define VSI4_TO 0x0F9C +#define VSI4_CTL 0x0F90 +#define VSI4_BS 0x0F94 +#define VSI4_BD 0x0F98 +#define VSI4_TO 0x0F9C + +#define VSI5_CTL 0x0FA4 +#define VSI5_BS 0x0FA8 +#define VSI5_BD 0x0FAC +#define VSI5_TO 0x0FB0 + +#define VSI6_CTL 0x0FB8 +#define VSI6_BS 0x0FBC +#define VSI6_BD 0x0FC0 +#define VSI6_TO 0x0FC4 + +#define VSI7_CTL 0x0FCC +#define VSI7_BS 0x0FD0 +#define VSI7_BD 0x0FD4 +#define VSI7_TO 0x0FD8 + +static const int CA91CX42_VSI_CTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, + VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL }; -#define VSI5_CTL 0x0FA4 -#define VSI5_BS 0x0FA8 -#define VSI5_BD 0x0FAC -#define VSI5_TO 0x0FB0 +static const int CA91CX42_VSI_BS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, + VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS }; -#define VSI6_CTL 0x0FB8 -#define VSI6_BS 0x0FBC -#define VSI6_BD 0x0FC0 -#define VSI6_TO 0x0FC4 +static const int CA91CX42_VSI_BD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, + VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD }; -#define VSI7_CTL 0x0FCC -#define VSI7_BS 0x0FD0 -#define VSI7_BD 0x0FD4 -#define VSI7_TO 0x0FD8 +static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, + VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO }; -#define VCSR_CLR 0x0FF4 -#define VCSR_SET 0x0FF8 -#define VCSR_BS 0x0FFC +#define VCSR_CLR 0x0FF4 +#define VCSR_SET 0x0FF8 +#define VCSR_BS 0x0FFC // DMA General Control/Status Register DGCS (0x220) // 32-24 || GO | STOPR | HALTR | 0 || CHAIN | 0 | 0 | 0 || @@ -400,4 +263,243 @@ typedef struct { // 0110 = 512 // 0111 = 1024 -#endif /* _ca91c042_h */ +/* + * PCI Class Register + * offset 008 + */ +#define CA91CX42_BM_PCI_CLASS_BASE 0xFF000000 +#define CA91CX42_OF_PCI_CLASS_BASE 24 +#define CA91CX42_BM_PCI_CLASS_SUB 0x00FF0000 +#define CA91CX42_OF_PCI_CLASS_SUB 16 +#define CA91CX42_BM_PCI_CLASS_PROG 0x0000FF00 +#define CA91CX42_OF_PCI_CLASS_PROG 8 +#define CA91CX42_BM_PCI_CLASS_RID 0x000000FF +#define CA91CX42_OF_PCI_CLASS_RID 0 + +#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_I 0 +#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_II 1 + +/* + * PCI Misc Register + * offset 00C + */ +#define CA91CX42_BM_PCI_MISC0_BISTC 0x80000000 +#define CA91CX42_BM_PCI_MISC0_SBIST 0x60000000 +#define CA91CX42_BM_PCI_MISC0_CCODE 0x0F000000 +#define CA91CX42_BM_PCI_MISC0_MFUNCT 0x00800000 +#define CA91CX42_BM_PCI_MISC0_LAYOUT 0x007F0000 +#define CA91CX42_BM_PCI_MISC0_LTIMER 0x0000FF00 +#define CA91CX42_OF_PCI_MISC0_LTIMER 8 + + +/* + * LSI Control Register + * offset 100 + */ +#define CA91CX42_LSI_CTL_EN (1<<31) +#define CA91CX42_LSI_CTL_PWEN (1<<30) + +#define CA91CX42_LSI_CTL_VDW_M (3<<22) +#define CA91CX42_LSI_CTL_VDW_D8 0 +#define CA91CX42_LSI_CTL_VDW_D16 (1<<22) +#define CA91CX42_LSI_CTL_VDW_D32 (1<<23) +#define CA91CX42_LSI_CTL_VDW_D64 (3<<22) + +#define CA91CX42_LSI_CTL_VAS_M (7<<16) +#define CA91CX42_LSI_CTL_VAS_A16 0 +#define CA91CX42_LSI_CTL_VAS_A24 (1<<16) +#define CA91CX42_LSI_CTL_VAS_A32 (1<<17) +#define CA91CX42_LSI_CTL_VAS_CRCSR (5<<16) +#define CA91CX42_LSI_CTL_VAS_USER1 (3<<17) +#define CA91CX42_LSI_CTL_VAS_USER2 (7<<16) + +#define CA91CX42_LSI_CTL_PGM_M (1<<14) +#define CA91CX42_LSI_CTL_PGM_DATA 0 +#define CA91CX42_LSI_CTL_PGM_PGM (1<<14) + +#define CA91CX42_LSI_CTL_SUPER_M (1<<12) +#define CA91CX42_LSI_CTL_SUPER_NPRIV 0 +#define CA91CX42_LSI_CTL_SUPER_SUPR (1<<12) + +#define CA91CX42_LSI_CTL_VCT_M (1<<8) +#define CA91CX42_LSI_CTL_VCT_BLT (1<<8) +#define CA91CX42_LSI_CTL_VCT_MBLT (1<<8) +#define CA91CX42_LSI_CTL_LAS (1<<0) + + +/* + * LMISC Register + * offset 184 + */ +#define CA91CX42_BM_LMISC_CRT 0xF0000000 +#define CA91CX42_OF_LMISC_CRT 28 +#define CA91CX42_BM_LMISC_CWT 0x0F000000 +#define CA91CX42_OF_LMISC_CWT 24 + +/* + * SLSI Register + * offset 188 + */ +#define CA91CX42_BM_SLSI_EN 0x80000000 +#define CA91CX42_BM_SLSI_PWEN 0x40000000 +#define CA91CX42_BM_SLSI_VDW 0x00F00000 +#define CA91CX42_OF_SLSI_VDW 20 +#define CA91CX42_BM_SLSI_PGM 0x0000F000 +#define CA91CX42_OF_SLSI_PGM 12 +#define CA91CX42_BM_SLSI_SUPER 0x00000F00 +#define CA91CX42_OF_SLSI_SUPER 8 +#define CA91CX42_BM_SLSI_BS 0x000000F6 +#define CA91CX42_OF_SLSI_BS 2 +#define CA91CX42_BM_SLSI_LAS 0x00000003 +#define CA91CX42_OF_SLSI_LAS 0 +#define CA91CX42_BM_SLSI_RESERVED 0x3F0F0000 + +/* + * PCI Interrupt Enable Register + * offset 300 + */ +#define CA91CX42_LINT_LM3 0x00800000 +#define CA91CX42_LINT_LM2 0x00400000 +#define CA91CX42_LINT_LM1 0x00200000 +#define CA91CX42_LINT_LM0 0x00100000 +#define CA91CX42_LINT_MBOX3 0x00080000 +#define CA91CX42_LINT_MBOX2 0x00040000 +#define CA91CX42_LINT_MBOX1 0x00020000 +#define CA91CX42_LINT_MBOX0 0x00010000 +#define CA91CX42_LINT_ACFAIL 0x00008000 +#define CA91CX42_LINT_SYSFAIL 0x00004000 +#define CA91CX42_LINT_SW_INT 0x00002000 +#define CA91CX42_LINT_SW_IACK 0x00001000 + +#define CA91CX42_LINT_VERR 0x00000400 +#define CA91CX42_LINT_LERR 0x00000200 +#define CA91CX42_LINT_DMA 0x00000100 +#define CA91CX42_LINT_VIRQ7 0x00000080 +#define CA91CX42_LINT_VIRQ6 0x00000040 +#define CA91CX42_LINT_VIRQ5 0x00000020 +#define CA91CX42_LINT_VIRQ4 0x00000010 +#define CA91CX42_LINT_VIRQ3 0x00000008 +#define CA91CX42_LINT_VIRQ2 0x00000004 +#define CA91CX42_LINT_VIRQ1 0x00000002 +#define CA91CX42_LINT_VOWN 0x00000001 + +static const int CA91CX42_LINT_VIRQ[] = { 0, CA91CX42_LINT_VIRQ1, + CA91CX42_LINT_VIRQ2, CA91CX42_LINT_VIRQ3, + CA91CX42_LINT_VIRQ4, CA91CX42_LINT_VIRQ5, + CA91CX42_LINT_VIRQ6, CA91CX42_LINT_VIRQ7 }; + +#define CA91CX42_LINT_MBOX 0x000F0000 + +static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1, + CA91CX42_LINT_LM2, CA91CX42_LINT_LM3 }; + +/* + * MAST_CTL Register + * offset 400 + */ +#define CA91CX42_BM_MAST_CTL_MAXRTRY 0xF0000000 +#define CA91CX42_OF_MAST_CTL_MAXRTRY 28 +#define CA91CX42_BM_MAST_CTL_PWON 0x0F000000 +#define CA91CX42_OF_MAST_CTL_PWON 24 +#define CA91CX42_BM_MAST_CTL_VRL 0x00C00000 +#define CA91CX42_OF_MAST_CTL_VRL 22 +#define CA91CX42_BM_MAST_CTL_VRM 0x00200000 +#define CA91CX42_BM_MAST_CTL_VREL 0x00100000 +#define CA91CX42_BM_MAST_CTL_VOWN 0x00080000 +#define CA91CX42_BM_MAST_CTL_VOWN_ACK 0x00040000 +#define CA91CX42_BM_MAST_CTL_PABS 0x00001000 +#define CA91CX42_BM_MAST_CTL_BUS_NO 0x0000000F +#define CA91CX42_OF_MAST_CTL_BUS_NO 0 + +/* + * MISC_CTL Register + * offset 404 + */ +#define CA91CX42_MISC_CTL_VBTO 0xF0000000 +#define CA91CX42_MISC_CTL_VARB 0x04000000 +#define CA91CX42_MISC_CTL_VARBTO 0x03000000 +#define CA91CX42_MISC_CTL_SW_LRST 0x00800000 +#define CA91CX42_MISC_CTL_SW_SRST 0x00400000 +#define CA91CX42_MISC_CTL_BI 0x00100000 +#define CA91CX42_MISC_CTL_ENGBI 0x00080000 +#define CA91CX42_MISC_CTL_RESCIND 0x00040000 +#define CA91CX42_MISC_CTL_SYSCON 0x00020000 +#define CA91CX42_MISC_CTL_V64AUTO 0x00010000 +#define CA91CX42_MISC_CTL_RESERVED 0x0820FFFF + +#define CA91CX42_OF_MISC_CTL_VARBTO 24 +#define CA91CX42_OF_MISC_CTL_VBTO 28 + +/* + * MISC_STAT Register + * offset 408 + */ +#define CA91CX42_BM_MISC_STAT_ENDIAN 0x80000000 +#define CA91CX42_BM_MISC_STAT_LCLSIZE 0x40000000 +#define CA91CX42_BM_MISC_STAT_DY4AUTO 0x08000000 +#define CA91CX42_BM_MISC_STAT_MYBBSY 0x00200000 +#define CA91CX42_BM_MISC_STAT_DY4DONE 0x00080000 +#define CA91CX42_BM_MISC_STAT_TXFE 0x00040000 +#define CA91CX42_BM_MISC_STAT_RXFE 0x00020000 +#define CA91CX42_BM_MISC_STAT_DY4AUTOID 0x0000FF00 +#define CA91CX42_OF_MISC_STAT_DY4AUTOID 8 + +/* + * VSI Control Register + * offset F00 + */ +#define CA91CX42_VSI_CTL_EN (1<<31) +#define CA91CX42_VSI_CTL_PWEN (1<<30) +#define CA91CX42_VSI_CTL_PREN (1<<29) + +#define CA91CX42_VSI_CTL_PGM_M (3<<22) +#define CA91CX42_VSI_CTL_PGM_DATA (1<<22) +#define CA91CX42_VSI_CTL_PGM_PGM (1<<23) + +#define CA91CX42_VSI_CTL_SUPER_M (3<<20) +#define CA91CX42_VSI_CTL_SUPER_NPRIV (1<<20) +#define CA91CX42_VSI_CTL_SUPER_SUPR (1<<21) + +#define CA91CX42_VSI_CTL_VAS_M (7<<16) +#define CA91CX42_VSI_CTL_VAS_A16 0 +#define CA91CX42_VSI_CTL_VAS_A24 (1<<16) +#define CA91CX42_VSI_CTL_VAS_A32 (1<<17) +#define CA91CX42_VSI_CTL_VAS_USER1 (3<<17) +#define CA91CX42_VSI_CTL_VAS_USER2 (7<<16) + +#define CA91CX42_VSI_CTL_LD64EN (1<<7) +#define CA91CX42_VSI_CTL_LLRMW (1<<6) + +#define CA91CX42_VSI_CTL_LAS_M (3<<0) +#define CA91CX42_VSI_CTL_LAS_PCI_MS 0 +#define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0) +#define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1) + +/* + * VRAI_CTL Register + * offset F70 + */ +#define CA91CX42_BM_VRAI_CTL_EN 0x80000000 +#define CA91CX42_BM_VRAI_CTL_PGM 0x00C00000 +#define CA91CX42_OF_VRAI_CTL_PGM 22 +#define CA91CX42_BM_VRAI_CTL_SUPER 0x00300000 +#define CA91CX42_OF_VRAI_CTL_SUPER 20 +#define CA91CX42_BM_VRAI_CTL_VAS 0x00030000 +#define CA91CX42_OF_VRAI_CTL_VAS 16 + +/* VCSR_CTL Register + * offset F80 + */ +#define CA91CX42_VCSR_CTL_EN (1<<31) + +#define CA91CX42_VCSR_CTL_LAS_M (3<<0) +#define CA91CX42_VCSR_CTL_LAS_PCI_MS 0 +#define CA91CX42_VCSR_CTL_LAS_PCI_IO (1<<0) +#define CA91CX42_VCSR_CTL_LAS_PCI_CONF (1<<1) + +/* VCSR_BS Register + * offset FFC + */ +#define CA91CX42_VCSR_BS_SLOT_M (0x1F<<27) + +#endif /* _CA91CX42_H */ -- 2.7.4