diff --git a/BaS_gcc/bas.lk.in b/BaS_gcc/bas.lk.in index 4adf6b6..6b2c8df 100644 --- a/BaS_gcc/bas.lk.in +++ b/BaS_gcc/bas.lk.in @@ -36,6 +36,7 @@ SECTIONS #endif /* MACHINE_FIREBEE */ OBJDIR/wait.o(.text) OBJDIR/exceptions.o(.text) + OBJDIR/interrupts.o(.text) OBJDIR/illegal_instruction.o(.text) OBJDIR/supervisor.o(.text) OBJDIR/mmu.o(.text) diff --git a/BaS_gcc/include/interrupts.h b/BaS_gcc/include/interrupts.h index a12eb84..e671732 100644 --- a/BaS_gcc/include/interrupts.h +++ b/BaS_gcc/include/interrupts.h @@ -77,4 +77,5 @@ #define INT_SOURCE_GPT0 62 // GPT0 timer interrupt +extern int register_interrupt_handler(uint8_t priority, uint8_t intr, void (*func)()); #endif /* _INTERRUPTS_H_ */ diff --git a/BaS_gcc/sources/interrupts.c b/BaS_gcc/sources/interrupts.c index c396810..a529149 100644 --- a/BaS_gcc/sources/interrupts.c +++ b/BaS_gcc/sources/interrupts.c @@ -27,36 +27,39 @@ #include "bas_utils.h" #include "interrupts.h" -extern uint8_t _rtl_vbr[]; -#define VBR ((uint32_t **) &_rtl_vbr[0]) +extern uint32_t rt_vbr[]; +#define VBR rt_vbr /* - * register an interrupt handler at the Coldfire interrupt controller and add the handler to the interrupt vector table + * register an interrupt handler at the Coldfire interrupt controller and add the handler to + * the interrupt vector table */ -int register_handler(uint8_t priority, uint8_t intr, void (*func)()) +int register_interrupt_handler(uint8_t priority, uint8_t source, void (*func)()) { int i; uint8_t level = 0b01111111; - uint32_t **adr = VBR; + uint32_t **adr = &VBR[0]; - intr &= 63; + source &= 63; priority &= 7; - if (intr <= 0) + if (source <= 0) return -1; for (i = 1; i < 64; i++) - if (i != intr) + { + if (i != source) { if ((MCF_INTC_ICR(i) & 7) == priority) CLEAR_BIT_NO(level, (MCF_INTC_ICR(i) >> 3) & 7); } + } - for (i = 0; 1 < 7; i++) + for (i = 0; i <= 7; i++) if (level & (1 << i)) break; - if (i >= 7) + if (i > 7) return -1; /* @@ -64,39 +67,35 @@ int register_handler(uint8_t priority, uint8_t intr, void (*func)()) */ __asm__ volatile ( "move.w sr,d0\n\t" - "move.w d0,-(sp) \n\t" + "move.w d0,srsave \n\t" "move.w #0x2700,sr\n\t" + " .data\n\t" + "srsave: ds.w 1\n\t" + " .text\n\t" : : - : "sp","d0","memory" + : "d0","memory" ); - if (intr < 32) - CLEAR_BIT(MCF_INTC_IMRL, (1 << intr)); + if (source < 32) + CLEAR_BIT(MCF_INTC_IMRL, (1 << source)); else - CLEAR_BIT(MCF_INTC_IMRH, (1 << (intr - 32))); + CLEAR_BIT(MCF_INTC_IMRH, (1 << (source - 32))); - MCF_INTC_ICR(intr) = MCF_INTC_ICR_IP(priority) | MCF_INTC_ICR_IL(i); + MCF_INTC_ICR(source) = MCF_INTC_ICR_IP(priority) | MCF_INTC_ICR_IL(i); - adr[64 + intr] = (uint32_t *) func; /* first 64 vectors are system exceptions */ + adr[64 + source] = (uint32_t *) func; /* first 64 vectors are system exceptions */ /* * Return the saved priority level */ __asm__ volatile ( - "move.w (sp)+,d2\n\t" + "move.w srsave,d2\n\t" "move.w d2,sr\n\t" : : - : "sp","d2","memory" + : "d2","memory" ); return 0; } - -__attribute__((interrupt)) void pci_arb_interrupt(void) -{ - xprintf("XLBARB slave error interrupt\r\n"); - MCF_XLB_XARB_SR |= ~MCF_XLB_XARB_SR_SEA; -} - diff --git a/BaS_gcc/sources/pci.c b/BaS_gcc/sources/pci.c index 839936e..48bf5dd 100644 --- a/BaS_gcc/sources/pci.c +++ b/BaS_gcc/sources/pci.c @@ -30,6 +30,7 @@ #include "bas_printf.h" #include "bas_string.h" #include "util.h" +#include "interrupts.h" #include "wait.h" #define pci_config_wait() wait(10000); /* FireBee USB not properly detected otherwise */ @@ -173,7 +174,7 @@ uint32_t pci_read_config_longword(int32_t handle, int offset) value = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */ /* finish PCI configuration access special cycle (allow regular PCI accesses) */ - MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; + //MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; pci_config_wait(); @@ -222,7 +223,7 @@ int32_t pci_write_config_longword(int32_t handle, int offset, uint32_t value) pci_config_wait(); /* finish configuration space access cycle */ - MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; + //MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; pci_config_wait(); return PCI_SUCCESSFUL; @@ -345,8 +346,8 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) struct pci_rd *descriptors; int i; uint32_t value; - static uint32_t mem_address = 0; - static uint32_t io_address = 0; + static uint32_t mem_address = PCI_MEMORY_OFFSET; + static uint32_t io_address = PCI_IO_OFFSET; /* determine pci handle from bus, device + function number */ handle = PCI_HANDLE(bus, device, function); @@ -372,7 +373,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) /* * write all bits of BAR[i] */ - pci_write_config_longword(handle, 0x10 + i, 0xffffffff); + pci_write_config_longword(handle, PCIBAR0 + i, 0xffffffff); /* * read back value to see which bits have been set @@ -390,7 +391,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) { /* adjust base address to card's alignment requirements */ int size = ~(address & 0xfffffff0) + 1; - xprintf("device 0x%x: BAR[%d] requests %d kBytes of memory\r\n", handle, i, size / 1024); + xprintf("device 0x%x: BAR[%d] requests %d bytes of memory\r\n", handle, i, size); /* calculate a valid map adress with alignment requirements */ address = (mem_address + size - 1) & ~(size - 1); @@ -399,17 +400,17 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) pci_write_config_longword(handle, PCIBAR0 + i, swpl(address)); /* read it back, just to be sure */ - value = swpl(pci_read_config_longword(handle, PCIBAR0 + i)); + value = swpl(pci_read_config_longword(handle, PCIBAR0 + i)) & ~1; xprintf("set PCIBAR%d on device 0x%02x to 0x%08x\r\n", i, handle, value); /* fill resource descriptor */ rd->next = sizeof(struct pci_rd); - rd->flags = 0 | FLG_8BIT | FLG_16BIT | FLG_32BIT; + rd->flags = 0 | FLG_32BIT | FLG_16BIT | FLG_8BIT | 2; /* little endian, lane swapped */ rd->start = address; rd->length = size; - rd->offset = PCI_MEMORY_OFFSET; + rd->offset = 0; rd->dmaoffset = 0; /* adjust memory adress for next turn */ @@ -421,7 +422,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) else if (IS_PCI_IO_BAR(value)) /* same as above for I/O resources */ { int size = ~(address & 0xfffffffc) + 1; - xprintf("device 0x%x: BAR[%d] requests %d bytes of memory\r\n", handle, i, size); + xprintf("device 0x%x: BAR[%d] requests %d bytes of I/O space\r\n", handle, i, size); address = (io_address + size - 1) & ~(size - 1); pci_write_config_longword(handle, PCIBAR0 + i, swpl(address)); @@ -431,9 +432,9 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) i, handle, value); rd->next = sizeof(struct pci_rd); - rd->flags = FLG_IO | FLG_8BIT | FLG_16BIT | FLG_32BIT | 1; + rd->flags = FLG_IO | FLG_8BIT | FLG_16BIT | FLG_32BIT | 2; rd->start = address; - rd->offset = PCI_IO_OFFSET; + rd->offset = 0; rd->length = size; rd->dmaoffset = 0; @@ -451,13 +452,29 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) * enable device finally */ value = swpl(pci_read_config_longword(handle, PCICSR)); - value |= 0xffff035f; + xprintf("device 0x%02x PCICSR = 0x%08x\r\n", handle, value); + value = 0xffff0146; pci_write_config_longword(handle, PCICSR, swpl(value)); value = swpl(pci_read_config_longword(handle, PCICSR)); xprintf("device 0x%02x PCICSR = 0x%08x\r\n", handle, value); } +static void pci_bridge_config(uint16_t bus, uint16_t device, uint16_t function) +{ + int32_t handle; + + if (function != 0) + { + xprintf("trying to configure a multi-function bridge. Cancelled\r\n"); + return; + } + handle = PCI_HANDLE(bus, device, function); + pci_write_config_longword(handle, PCIBAR0, 0x40000000); + pci_write_config_longword(handle, PCIBAR1, 0x0); + pci_write_config_longword(handle, PCICSR, 0x146); +} + /* * scan PCI bus and display devices found. Create a handle for each device and call pci_device_config() for it */ @@ -494,6 +511,12 @@ void pci_scan(void) PCI_DEVICE_FROM_HANDLE(handle), PCI_FUNCTION_FROM_HANDLE(handle)); } + else + { + pci_bridge_config(PCI_BUS_FROM_HANDLE(handle), + PCI_DEVICE_FROM_HANDLE(handle), + PCI_FUNCTION_FROM_HANDLE(handle)); + } handle = pci_find_device(0x0, 0xFFFF, ++index); } @@ -545,9 +568,30 @@ void init_xlbus_arbiter(void) MCF_XLB_XARB_BUSTO = 0xffffff; } + +__attribute__((interrupt)) void pci_arb_interrupt(void) +{ + xprintf("XLBARB slave error interrupt\r\n"); + MCF_XLB_XARB_SR |= ~MCF_XLB_XARB_SR_SEA; +} + +__attribute__((interrupt)) void xlb_pci_interrupt(void) +{ + xprintf("XLBPCI interrupt\r\n"); +} + void init_pci(void) { - xprintf("initializing PCI bridge:"); + int res; + + xprintf("initializing PCI bridge:\r\n"); + + res = register_interrupt_handler(0, INT_SOURCE_PCIARB, pci_arb_interrupt); + xprintf("registered interrupt handler for PCI arbiter: %s\r\n", + (res < 0 ? "failed" : "succeeded")); + register_interrupt_handler(0, INT_SOURCE_XLBPCI, xlb_pci_interrupt); + xprintf("registered interrupt handler for XLB PCI: %s\r\n", + (res < 0 ? "failed" : "succeeded")); init_eport(); init_xlbus_arbiter(); @@ -556,7 +600,7 @@ void init_pci(void) * setup the PCI arbiter */ MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI /* internal master priority: high */ - | MCF_PCIARB_PACR_EXTMPRI(0x1F) /* external master priority: high */ + | MCF_PCIARB_PACR_EXTMPRI(0x4) /* external master priority: high */ | MCF_PCIARB_PACR_INTMINTEN /* enable "internal master broken" interrupt */ | MCF_PCIARB_PACR_EXTMINTEN(0x1F); /* enable "external master broken" interrupt */ @@ -591,7 +635,9 @@ void init_pci(void) /* initiator window 0 base / translation adress register */ MCF_PCI_PCIIW0BTAR = (PCI_MEMORY_OFFSET | (((PCI_MEMORY_SIZE - 1) >> 8) & 0xffff0000)) - | PCI_MEMORY_OFFSET >> 16; + | ((PCI_MEMORY_OFFSET >> 16) & 0xff00); + + xprintf("PCIIW0BTAR=0x%08x\r\n", MCF_PCI_PCIIW0BTAR); /* initiator window 1 base / translation adress register */ MCF_PCI_PCIIW1BTAR = (PCI_IO_OFFSET | ((PCI_IO_SIZE - 1) >> 8)) & 0xffff0000; @@ -600,11 +646,14 @@ void init_pci(void) MCF_PCI_PCIIW2BTAR = 0L; /* not used */ /* initiator window configuration register */ - MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE | MCF_PCI_PCIIWCR_WINCTRL1_IO; + MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE | + MCF_PCI_PCIIWCR_WINCTRL1_IO | + MCF_PCI_PCIIWCR_WINCTRL0_E | + MCF_PCI_PCIIWCR_WINCTRL1_E; /* initialize target control register */ MCF_PCI_PCIBAR0 = 0x40000000; /* 256 kB window */ - MCF_PCI_PCITBATR0 = (uint32_t) &_MBAR[0] + MCF_PCI_PCITBATR0_EN; /* target base address translation register 0 */ + MCF_PCI_PCITBATR0 = (uint32_t) &_MBAR[0] | MCF_PCI_PCITBATR0_EN; /* target base address translation register 0 */ MCF_PCI_PCIBAR1 = 0; /* 1GB window */ MCF_PCI_PCITBATR1 = MCF_PCI_PCITBATR1_EN; @@ -627,4 +676,6 @@ void init_pci(void) xprintf("PCIGSCR=0x%08x, PCISCR=0x%08x\r\n", MCF_PCI_PCIGSCR, MCF_PCI_PCISCR); MCF_PCI_PCISCR |= 0xffff035f; /* clear all error flags */ xprintf("PCIGSCR=0x%08x, PCISCR=0x%08x\r\n", MCF_PCI_PCIGSCR, MCF_PCI_PCISCR); + + xprintf("XARB_SR=0x%08x\r\n", MCF_XLB_XARB_SR); } diff --git a/BaS_gcc/sources/sysinit.c b/BaS_gcc/sources/sysinit.c index b48679c..b5ca71b 100644 --- a/BaS_gcc/sources/sysinit.c +++ b/BaS_gcc/sources/sysinit.c @@ -260,7 +260,7 @@ void init_serial(void) MCF_PSC3_PSCCR = 0x05; #endif /* MACHINE_FIREBEE */ - MCF_INTC_ICR32 = 0x3F; //MAXIMALE PRIORITY/**********/ + //MCF_INTC_ICR32 = 0x3F; //MAXIMALE PRIORITY/**********/ xprintf("\r\nserial interfaces initialization: finished\r\n"); }