/* remap the zero-based PCI IO spaces of both hoses to a single * address space * * This must be called AFTER to BSP_pci_initialize() */ /* * Authorship * ---------- * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was * created by Till Straumann , 2005-2007, * Stanford Linear Accelerator Center, Stanford University. * * Acknowledgement of sponsorship * ------------------------------ * The 'beatnik' BSP was produced by * the Stanford Linear Accelerator Center, Stanford University, * under Contract DE-AC03-76SFO0515 with the Department of Energy. * * Government disclaimer of liability * ---------------------------------- * Neither the United States nor the United States Department of Energy, * nor any of their employees, makes any warranty, express or implied, or * assumes any legal liability or responsibility for the accuracy, * completeness, or usefulness of any data, apparatus, product, or process * disclosed, or represents that its use would not infringe privately owned * rights. * * Stanford disclaimer of liability * -------------------------------- * Stanford University makes no representations or warranties, express or * implied, nor assumes any liability for the use of this software. * * Stanford disclaimer of copyright * -------------------------------- * Stanford University, owner of the copyright, hereby disclaims its * copyright and all other rights in this software. Hence, anyone may * freely use it for any purpose without restriction. * * Maintenance of notices * ---------------------- * In the interest of clarity regarding the origin and status of this * SLAC software, this and all the preceding Stanford University notices * are to remain affixed to any copy or derivative of this software made * or distributed by the recipient and are to be affixed to any copy of * software made or distributed by the recipient that contains a copy or * derivative of this software. * * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 */ #include #include #include #include #include #include #include #include "pci_io_remap.h" static int fixup_irq_line(int bus, int slot, int fun, void *uarg) { unsigned char line; pci_read_config_byte( bus, slot, fun, PCI_INTERRUPT_LINE, &line); if ( line < BSP_IRQ_GPP_0 ) { pci_write_config_byte( bus, slot, fun, PCI_INTERRUPT_LINE, line + BSP_IRQ_GPP_0 ); } return 0; } void BSP_motload_pci_fixup(void) { uint32_t b0,b1,r0,r1,lim,dis; /* MotLoad on the mvme5500 and mvme6100 configures the PCI * busses nicely, i.e., the values read from the memory address * space BARs by means of PCI config cycles directly reflect the * CPU memory map. Thus, the presence of two hoses is already hidden. * * Unfortunately, all PCI I/O addresses are 'zero-based' i.e., * a hose-specific base address would have to be added to * the values read from config space. * * We fix this here so I/O BARs also reflect the CPU memory map. * * Furthermore, the mvme5500 uses * f000.0000 * ..f07f.ffff for PCI-0 / hose0 * * and * * f080.0000 * ..f0ff.0000 for PCI-1 / hose 0 * * whereas the mvme6100 does it the other way round... */ b0 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Low_Decode) ); b1 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Low_Decode) ); r0 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap) ); r1 = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap) ); switch ( BSP_getDiscoveryVersion(0) ) { case MV_64360: /* In case of the MV64360 the 'limit' is actually a 'size'! * Disable by setting special bits in the 'BAR disable reg'. */ dis = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL) ); /* disable PCI0 I/O and PCI1 I/O */ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL), dis | (1<<9) | (1<<14) ); /* remap busses on hose 0; if the remap register was already set, assume * that someone else [such as the bootloader] already performed the fixup */ if ( (b0 & 0xffff) && 0 == (r0 & 0xffff) ) { rtems_pci_io_remap( 0, BSP_pci_hose1_bus_base, (b0 & 0xffff)<<16 ); out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap), (b0 & 0xffff) ); } /* remap busses on hose 1 */ if ( (b1 & 0xffff) && 0 == (r1 & 0xffff) ) { rtems_pci_io_remap( BSP_pci_hose1_bus_base, pci_bus_count(), (b1 & 0xffff)<<16 ); out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap), (b1 & 0xffff) ); } /* re-enable */ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + MV_64360_BASE_ADDR_DISBL), dis ); break; case GT_64260_A: case GT_64260_B: if ( (b0 & 0xfff) && 0 == (r0 & 0xfff) ) { /* base are only 12 bits */ /* switch window off by setting the limit < base */ lim = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode) ); out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode), 0 ); /* remap busses on hose 0 */ rtems_pci_io_remap( 0, BSP_pci_hose1_bus_base, (b0 & 0xfff)<<20 ); /* BTW: it seems that writing the base register also copies the * value into the 'remap' register automatically (??) */ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_Remap), (b0 & 0xfff) ); /* re-enable */ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI0_IO_High_Decode), lim ); } if ( (b1 & 0xfff) && 0 == (r1 & 0xfff) ) { /* base are only 12 bits */ /* switch window off by setting the limit < base */ lim = in_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode) ); out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode), 0 ); /* remap busses on hose 1 */ rtems_pci_io_remap( BSP_pci_hose1_bus_base, pci_bus_count(), (b1 & 0xfff)<<20 ); out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_Remap), (b1 & 0xfff) ); /* re-enable */ out_le32( (volatile uint32_t*)(BSP_MV64x60_BASE + GT_PCI1_IO_High_Decode), lim ); } break; default: rtems_panic("Unknown discovery version; switch in file: "__FILE__" not implemented (yet)"); break; /* never get here */ } /* Fixup the IRQ lines; the mvme6100 maps them nicely into our scheme, i.e., GPP * interrupts start at 64 upwards * * The mvme5500 is apparently initialized differently :-(. GPP interrupts start at 0 * Since all PCI interrupts are wired to GPP we simply check for a value < 64 and * reprogram the interrupt line register. */ BSP_pciScan(0, fixup_irq_line, 0); }