/** * @file * @ingroup cchip * @brief Companion Chip PCI board driver */ /* * GR-701 (Companion Chip) PCI board driver * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* #define DEBUG #define DEBUG_IRQS */ #define BOARD_INFO /*#define PRINT_SPURIOUS*/ /* AT697 Register MAP */ static LEON_Register_Map *regs = (LEON_Register_Map *)0x80000000; /* initializes interrupt management for companionship board */ void cchip1_irq_init(void); /* register interrupt handler (called from drivers) */ void cchip1_set_isr(void *handler, int irqno, void *arg); #define READ_REG(address) _READ_REG((unsigned int)address) static __inline__ unsigned int _READ_REG(unsigned int addr) { unsigned int tmp; __asm__ ("lda [%1]1, %0 " : "=r"(tmp) : "r"(addr) ); return tmp; } /* PCI bride reg layout on AMBA side */ typedef struct { unsigned int bar0; unsigned int bar1; unsigned int bar2; unsigned int bar3; unsigned int bar4;/* 0x10 */ unsigned int unused[4*3-1]; unsigned int ambabars[1]; /* 0x40 */ } amba_bridge_regs; /* PCI bride reg layout on PCI side */ typedef struct { unsigned int bar0; unsigned int bar1; unsigned int bar2; unsigned int bar3; unsigned int bar4; /* 0x10 */ unsigned int ilevel; unsigned int ipend; unsigned int iforce; unsigned int istatus; unsigned int iclear; unsigned int imask; } pci_bridge_regs; typedef struct { pci_bridge_regs *pcib; amba_bridge_regs *ambab; /* AT697 PCI */ unsigned int bars[5]; int bus, dev, fun; /* AMBA bus */ struct ambapp_bus amba_bus; struct ambapp_mmap amba_maps[2]; /* FT AHB SRAM */ int ftsram_size; /* kb */ unsigned int ftsram_start; unsigned int ftsram_end; } cchip1; cchip1 cc1; int init_pcif(void){ unsigned int com1; int i,bus,dev,fun; pci_bridge_regs *pcib; amba_bridge_regs *ambab; struct ambapp_bus *abus; if ( BSP_pciFindDevice(0x1AC8, 0x0701, 0, &bus, &dev, &fun) == 0 ) { ; }else if (BSP_pciFindDevice(0x16E3, 0x0210, 0, &bus, &dev, &fun) == 0) { ; } else { /* didn't find any Companionship board on the PCI bus. */ return -1; } /* found Companionship PCI board, Set it up: */ pci_read_config_dword(bus, dev, fun, 0x10, &cc1.bars[0]); pci_read_config_dword(bus, dev, fun, 0x14, &cc1.bars[1]); pci_read_config_dword(bus, dev, fun, 0x18, &cc1.bars[2]); pci_read_config_dword(bus, dev, fun, 0x1c, &cc1.bars[3]); pci_read_config_dword(bus, dev, fun, 0x20, &cc1.bars[4]); #ifdef DEBUG for(i=0; i<5; i++){ printk("PCI: BAR%d: 0x%x\n\r",i,cc1.bars[i]); } #endif /* Set up PCI ==> AMBA */ pcib = (void *)cc1.bars[0]; pcib->bar0 = 0xfc000000; /* pcib->bar1 = 0xff000000;*/ #ifdef BOARD_INFO printk("Found CCHIP1 Board at 0x%lx\n\r",(unsigned int)pcib); #endif /* AMBA MAP cc1.bars[1] (in CPU) ==> 0xf0000000(remote amba address) */ cc1.amba_maps[0].size = 0x04000000; cc1.amba_maps[0].local_adr = cc1.bars[1]; cc1.amba_maps[0].remote_adr = 0xfc000000; /* Mark end of table */ cc1.amba_maps[1].size=0; cc1.amba_maps[1].local_adr = 0; cc1.amba_maps[1].remote_adr = 0; /* Enable I/O and Mem accesses */ pci_read_config_dword(bus, dev, fun, 0x4, &com1); com1 |= 0x3; pci_write_config_dword(bus, dev, fun, 0x4, com1); pci_read_config_dword(bus, dev, fun, 0x4, &com1); /* Set up AMBA Masters ==> PCI */ ambab = (void *)(cc1.bars[1]+0x400); #ifdef DEBUG printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",0,ambab->bar0,pcib->bar0); printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",1,ambab->bar1,pcib->bar1); printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",2,ambab->bar2,pcib->bar2); #endif ambab->ambabars[0] = 0x40000000; /* 0xe0000000(AMBA) ==> 0x40000000(PCI) ==> 0x40000000(AT697 AMBA) */ /* Scan bus for AMBA devices */ abus = &cc1.amba_bus; memset(abus,0,sizeof(*abus)); ambapp_scan(abus, cc1.bars[1]+0x3f00000, NULL, &cc1.amba_maps[0]); /* Init all msters, max 16 */ for(i=1; i<16; i++) { ambab->ambabars[i] = 0x40000000; if (READ_REG(&ambab->ambabars[i]) != 0x40000000) break; } /* Enable PCI Master */ pci_read_config_dword(bus, dev, fun, 0x4, &com1); com1 |= 0x4; pci_write_config_dword(bus, dev, fun, 0x4, com1); pci_read_config_dword(bus, dev, fun, 0x4, &com1); cc1.pcib = pcib; cc1.ambab = ambab; cc1.bus = bus; cc1.dev = dev; cc1.fun = fun; return 0; } #ifndef GAISLER_FTAHBRAM #define GAISLER_FTAHBRAM 0x50 #endif int init_onboard_sram(void){ struct ambapp_ahb_info ahb; struct ambapp_apb_info apb; unsigned int conf, size; /* Find SRAM controller * 1. AHB slave interface * 2. APB slave interface */ if ( ambapp_find_apbslv(&cc1.amba_bus, VENDOR_GAISLER, GAISLER_FTAHBRAM, &apb) != 1 ){ printk("On Board FT SRAM not found (APB)\n"); return -1; } if ( ambapp_find_ahbslv(&cc1.amba_bus, VENDOR_GAISLER, GAISLER_FTAHBRAM, &ahb) != 1 ){ printk("On Board FT SRAM not found (AHB)\n"); return -1; } /* We have found the controller. * Get it going. * * Get size of SRAM */ conf = *(unsigned int *)apb.start; size = (conf >>10) & 0x7; /* 2^x kb */ cc1.ftsram_size = 1<PIO_Direction &= ~(1<<7); regs->PIO_Interrupt = 0x87; /* level sensitive */ /* Set up irq controller (mask all IRQs) */ cc1.pcib->imask = 0x0000; cc1.pcib->ipend = 0; cc1.pcib->iclear = 0xffff; cc1.pcib->iforce = 0; cc1.pcib->ilevel = 0x0; memset(int_handlers,0,sizeof(int_handlers)); /* Reset spurious counter */ cchip1_spurious_cnt = 0; /* Register interrupt handler */ set_vector(cchip1_interrupt_dispatcher,LEON_TRAP_TYPE(CCHIP_IRQ),1); } void cchip1_set_isr(void *handler, int irqno, void *arg){ int_handlers[irqno].handler = handler; int_handlers[irqno].arg = arg; #ifdef DEBUG printk("Registering IRQ %d to 0x%lx(%d,0x%lx)\n\r",irqno,(unsigned int)handler,irqno,(unsigned int)arg); #endif cc1.pcib->imask |= 1<ipend); unsigned int (*handler)(int irqno, void *arg); unsigned int clr = pending; int irq=1; if ( !pending ){ #ifdef PRINT_SPURIOUS printk("Spurious IRQ %d: %d\n",v,cchip1_spurious_cnt); #endif cchip1_spurious_cnt++; return; } #ifdef DEBUG_IRQS printk("CCIRQ: 0x%x\n",(unsigned int)pending); #endif /* IRQ 0 doesn't exist */ irq=1; pending = pending>>1; while ( pending ){ if ( (pending & 1) && (handler=int_handlers[irq].handler) ){ handler(irq,int_handlers[irq].arg); } irq++; pending = pending>>1; } cc1.pcib->iclear = clr; /*LEON_Clear_interrupt( brd->irq );*/ }